package org.mt4j.components.visibleComponents.shapes;
import java.util.ArrayList;
import java.util.List;
import org.mt4j.AbstractMTApplication;
import org.mt4j.components.css.util.CSSHelper;
import org.mt4j.components.css.util.CSSStylableComponent;
import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.opengl.GluTrianglulator;
import processing.core.PApplet;
/**
* This class is used to display non-simple polygons like concave polygons, polygons with wholes or more than only 1 contour
* since MTPolygon can only handle convex polygons.
* <br><br>Note: calls to setVertices() will be more expensive here since a triangulation algorithm is used to split the contours
* up into triangles.
* <br>Note: we should only provide 2D vertices (all vertices with the same z value) to not confuse the triangulation algorithm
* <br>Note: setGeometryInfo() should never be called directly on this class since the geometry has to first be calculated
* from the specified vertices. Use setVertices() instead if you want to change the shape.
*/
public class MTComplexPolygon extends MTTriangleMesh implements CSSStylableComponent{
/** The Constant WINDING_RULE_ODD. */
public static final int WINDING_RULE_ODD = GluTrianglulator.WINDING_RULE_ODD;
/** The Constant WINDING_RULE_NONZERO. */
public static final int WINDING_RULE_NONZERO = GluTrianglulator.WINDING_RULE_NONZERO;
//TODO override the intersection/containspoint methods to only use outline?
//-> else we do expensive checks against each triangle
/**
* Instantiates a new mT complex polygon with only one contour.
*
* @param app the app
* @param vertices the vertices
*/
public MTComplexPolygon(PApplet app, Vertex[] vertices) {
super(app, new GeometryInfo(app, new Vertex[]{}), false);
this.setVertices(vertices);
this.setNoStroke(false);
// /*
if (app instanceof AbstractMTApplication) {
this.mtApp = (AbstractMTApplication)app;
this.cssHelper = new CSSHelper(this, mtApp);
if (this.mtApp.getCssStyleManager().isGloballyEnabled()) {
this.enableCSS();
}
}
// */
}
/**
* Instantiates a new mT complex polygon using multiple contours and the ODD winding rule.
* So if a second contour is inside of the first contour, the second contour would cut a hole into the first one.
*
* @param app the app
* @param contours the contours
*/
public MTComplexPolygon(PApplet app, List<Vertex[]> contours) {
this(app, contours, GluTrianglulator.WINDING_RULE_ODD);
}
/**
* Instantiates a new mT complex polygon using multiple contours and the specified winding rule.
* So if a second contour is inside of the first contour, the second contour would cut a hole into the first one.
* @param app the app
* @param contours the contours
* @param windingRule the winding rule
*/
public MTComplexPolygon(PApplet app, List<Vertex[]> contours, int windingRule) {
super(app, new GeometryInfo(app, new Vertex[]{}), false);
this.setVertices(contours, windingRule);
this.setNoStroke(false);
// /*
if (app instanceof AbstractMTApplication) {
this.mtApp = (AbstractMTApplication)app;
this.cssHelper = new CSSHelper(this, mtApp);
if (this.mtApp.getCssStyleManager().isGloballyEnabled()) {
this.enableCSS();
}
}
// */
}
/**
* Sets the vertices.
*
* @param contours the contours
* @param windingRule the winding rule
*/
public void setVertices(List<Vertex[]> contours, int windingRule) {
this.setOutlineContours(contours);
GluTrianglulator triangulator = new GluTrianglulator(getRenderer());
List<Vertex> tris = triangulator.tesselate(contours, windingRule);
triangulator.deleteTess();
super.setVertices(tris.toArray(new Vertex[tris.size()]));
}
/* (non-Javadoc)
* @see org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh#setVertices(org.mt4j.util.math.Vertex[])
*/
@Override
public void setVertices(Vertex[] vertices) {
List<Vertex[]> contours = new ArrayList<Vertex[]>();
contours.add(vertices);
this.setOutlineContours(contours);
GluTrianglulator triangulator = new GluTrianglulator(getRenderer());
Vertex[] tris = triangulator.tesselate(vertices);
triangulator.deleteTess();
super.setVertices(tris);
}
// /*
//CSS Stuff
/** The mt app. */
private AbstractMTApplication mtApp;
/** The css styled. */
private boolean cssStyled = false;
/** The css helper. */
private CSSHelper cssHelper;
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#isCSSStyled()
*/
public boolean isCSSStyled() {
return cssStyled;
}
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#enableCSS()
*/
public void enableCSS() {
if (mtApp != null && cssHelper != null) {
cssStyled = true;
}
applyStyleSheet();
}
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#disableCSS()
*/
public void disableCSS() {
cssStyled = false;
}
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#applyStyleSheet()
*/
public void applyStyleSheet() {
//Custom behaviour goes here..
if (cssStyled && mtApp != null && cssHelper != null) {
cssHelper.applyStyleSheet(this);
}
}
/** The css force disabled. */
private boolean cssForceDisabled = false;
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#isCssForceDisabled()
*/
public boolean isCssForceDisabled() {
return cssForceDisabled;
}
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#setCssForceDisable(boolean)
*/
public void setCssForceDisable(boolean cssForceDisabled) {
this.cssForceDisabled = cssForceDisabled;
}
/* (non-Javadoc)
* @see org.mt4j.components.css.util.CSSStylableComponent#getCssHelper()
*/
public CSSHelper getCssHelper() {
return this.cssHelper;
}
// */
}