summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/graph/curve/tess
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-04-08 21:35:34 +0200
committerSven Gothel <[email protected]>2011-04-08 21:35:34 +0200
commit324b85b0cc688f85a91e84b0b6d6a0378a79bea3 (patch)
treea5acbe1630d879e80ec66c6c3a72623431c57632 /src/jogl/classes/jogamp/graph/curve/tess
parente104e42ba9ecda8c4094bf4b183105a6ab719da5 (diff)
Fix TAB: Replace all TAB with 4 spaces
Diffstat (limited to 'src/jogl/classes/jogamp/graph/curve/tess')
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java80
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java160
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/HEdge.java190
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/Loop.java668
4 files changed, 549 insertions, 549 deletions
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
index 5dae296e5..a0d1923a9 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
@@ -33,49 +33,49 @@ import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Vertex;
public class GraphOutline {
- final private Outline outline;
- final private ArrayList<GraphVertex> controlpoints = new ArrayList<GraphVertex>(3);
-
- public GraphOutline(){
- this.outline = new Outline();
- }
-
- /**Create a control polyline of control vertices
- * the curve pieces can be identified by onCurve flag
- * of each cp the control polyline is open by default
- */
- public GraphOutline(Outline ol){
- this.outline = ol;
- ArrayList<Vertex> vertices = this.outline.getVertices();
- for(Vertex v:vertices){
- this.controlpoints.add(new GraphVertex(v));
- }
- }
+ final private Outline outline;
+ final private ArrayList<GraphVertex> controlpoints = new ArrayList<GraphVertex>(3);
+
+ public GraphOutline(){
+ this.outline = new Outline();
+ }
+
+ /**Create a control polyline of control vertices
+ * the curve pieces can be identified by onCurve flag
+ * of each cp the control polyline is open by default
+ */
+ public GraphOutline(Outline ol){
+ this.outline = ol;
+ ArrayList<Vertex> vertices = this.outline.getVertices();
+ for(Vertex v:vertices){
+ this.controlpoints.add(new GraphVertex(v));
+ }
+ }
- public Outline getOutline() {
- return outline;
- }
+ public Outline getOutline() {
+ return outline;
+ }
- /*public void setOutline(Outline<T> outline) {
- this.outline = outline;
- }*/
-
+ /*public void setOutline(Outline<T> outline) {
+ this.outline = outline;
+ }*/
+
- public ArrayList<GraphVertex> getGraphPoint() {
- return controlpoints;
- }
-
- public ArrayList<Vertex> getPoints() {
- return outline.getVertices();
- }
+ public ArrayList<GraphVertex> getGraphPoint() {
+ return controlpoints;
+ }
+
+ public ArrayList<Vertex> getPoints() {
+ return outline.getVertices();
+ }
- /*public void setControlpoints(ArrayList<GraphPoint<T>> controlpoints) {
- this.controlpoints = controlpoints;
- }*/
+ /*public void setControlpoints(ArrayList<GraphPoint<T>> controlpoints) {
+ this.controlpoints = controlpoints;
+ }*/
- public void addVertex(GraphVertex v) {
- controlpoints.add(v);
- outline.addVertex(v.getPoint());
- }
-
+ public void addVertex(GraphVertex v) {
+ controlpoints.add(v);
+ outline.addVertex(v.getPoint());
+ }
+
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
index b9f95a0e7..5efe57c28 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphVertex.java
@@ -32,89 +32,89 @@ import java.util.ArrayList;
import com.jogamp.graph.geom.Vertex;
public class GraphVertex {
- private Vertex point;
- private ArrayList<HEdge> edges = null;
- private boolean boundaryContained = false;
-
- public GraphVertex(Vertex point) {
- this.point = point;
- }
+ private Vertex point;
+ private ArrayList<HEdge> edges = null;
+ private boolean boundaryContained = false;
+
+ public GraphVertex(Vertex point) {
+ this.point = point;
+ }
- public Vertex getPoint() {
- return point;
- }
-
- public float getX(){
- return point.getX();
- }
-
- public float getY(){
- return point.getY();
- }
-
- public float getZ(){
- return point.getZ();
- }
- public float[] getCoord() {
- return point.getCoord();
- }
+ public Vertex getPoint() {
+ return point;
+ }
+
+ public float getX(){
+ return point.getX();
+ }
+
+ public float getY(){
+ return point.getY();
+ }
+
+ public float getZ(){
+ return point.getZ();
+ }
+ public float[] getCoord() {
+ return point.getCoord();
+ }
- public void setPoint(Vertex point) {
- this.point = point;
- }
+ public void setPoint(Vertex point) {
+ this.point = point;
+ }
- public ArrayList<HEdge> getEdges() {
- return edges;
- }
+ public ArrayList<HEdge> getEdges() {
+ return edges;
+ }
- public void setEdges(ArrayList<HEdge> edges) {
- this.edges = edges;
- }
-
- public void addEdge(HEdge edge){
- if(edges == null){
- edges = new ArrayList<HEdge>();
- }
- edges.add(edge);
- }
- public void removeEdge(HEdge edge){
- if(edges == null)
- return;
- edges.remove(edge);
- if(edges.size() == 0){
- edges = null;
- }
- }
- public HEdge findNextEdge(GraphVertex nextVert){
- for(HEdge e:edges){
- if(e.getNext().getGraphPoint() == nextVert){
- return e;
- }
- }
- return null;
- }
- public HEdge findBoundEdge(){
- for(HEdge e:edges){
- if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){
- return e;
- }
- }
- return null;
- }
- public HEdge findPrevEdge(GraphVertex prevVert){
- for(HEdge e:edges){
- if(e.getPrev().getGraphPoint() == prevVert){
- return e;
- }
- }
- return null;
- }
-
- public boolean isBoundaryContained() {
- return boundaryContained;
- }
+ public void setEdges(ArrayList<HEdge> edges) {
+ this.edges = edges;
+ }
+
+ public void addEdge(HEdge edge){
+ if(edges == null){
+ edges = new ArrayList<HEdge>();
+ }
+ edges.add(edge);
+ }
+ public void removeEdge(HEdge edge){
+ if(edges == null)
+ return;
+ edges.remove(edge);
+ if(edges.size() == 0){
+ edges = null;
+ }
+ }
+ public HEdge findNextEdge(GraphVertex nextVert){
+ for(HEdge e:edges){
+ if(e.getNext().getGraphPoint() == nextVert){
+ return e;
+ }
+ }
+ return null;
+ }
+ public HEdge findBoundEdge(){
+ for(HEdge e:edges){
+ if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){
+ return e;
+ }
+ }
+ return null;
+ }
+ public HEdge findPrevEdge(GraphVertex prevVert){
+ for(HEdge e:edges){
+ if(e.getPrev().getGraphPoint() == prevVert){
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public boolean isBoundaryContained() {
+ return boundaryContained;
+ }
- public void setBoundaryContained(boolean boundaryContained) {
- this.boundaryContained = boundaryContained;
- }
+ public void setBoundaryContained(boolean boundaryContained) {
+ this.boundaryContained = boundaryContained;
+ }
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java b/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
index d1bcc6e17..4d29a81f3 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/HEdge.java
@@ -32,99 +32,99 @@ import com.jogamp.graph.geom.Triangle;
public class HEdge {
- public static int BOUNDARY = 3;
- public static int INNER = 1;
- public static int HOLE = 2;
-
- private GraphVertex vert;
- private HEdge prev = null;
- private HEdge next = null;
- private HEdge sibling = null;
- private int type = BOUNDARY;
- private Triangle triangle = null;
-
- public HEdge(GraphVertex vert, int type) {
- this.vert = vert;
- this.type = type;
- }
-
- public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) {
- this.vert = vert;
- this.prev = prev;
- this.next = next;
- this.sibling = sibling;
- this.type = type;
- }
-
- public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, Triangle triangle) {
- this.vert = vert;
- this.prev = prev;
- this.next = next;
- this.sibling = sibling;
- this.type = type;
- this.triangle = triangle;
- }
-
- public GraphVertex getGraphPoint() {
- return vert;
- }
-
- public void setVert(GraphVertex vert) {
- this.vert = vert;
- }
-
- public HEdge getPrev() {
- return prev;
- }
-
- public void setPrev(HEdge prev) {
- this.prev = prev;
- }
-
- public HEdge getNext() {
- return next;
- }
-
- public void setNext(HEdge next) {
- this.next = next;
- }
-
- public HEdge getSibling() {
- return sibling;
- }
-
- public void setSibling(HEdge sibling) {
- this.sibling = sibling;
- }
-
- public int getType() {
- return type;
- }
-
- public void setType(int type) {
- this.type = type;
- }
-
- public Triangle getTriangle() {
- return triangle;
- }
-
- public void setTriangle(Triangle triangle) {
- this.triangle = triangle;
- }
-
- public static <T extends Vertex> void connect(HEdge first, HEdge next){
- first.setNext(next);
- next.setPrev(first);
- }
-
- public static <T extends Vertex> void makeSiblings(HEdge first, HEdge second){
- first.setSibling(second);
- second.setSibling(first);
- }
-
- public boolean vertexOnCurveVertex(){
- return vert.getPoint().isOnCurve();
- }
-
+ public static int BOUNDARY = 3;
+ public static int INNER = 1;
+ public static int HOLE = 2;
+
+ private GraphVertex vert;
+ private HEdge prev = null;
+ private HEdge next = null;
+ private HEdge sibling = null;
+ private int type = BOUNDARY;
+ private Triangle triangle = null;
+
+ public HEdge(GraphVertex vert, int type) {
+ this.vert = vert;
+ this.type = type;
+ }
+
+ public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) {
+ this.vert = vert;
+ this.prev = prev;
+ this.next = next;
+ this.sibling = sibling;
+ this.type = type;
+ }
+
+ public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, Triangle triangle) {
+ this.vert = vert;
+ this.prev = prev;
+ this.next = next;
+ this.sibling = sibling;
+ this.type = type;
+ this.triangle = triangle;
+ }
+
+ public GraphVertex getGraphPoint() {
+ return vert;
+ }
+
+ public void setVert(GraphVertex vert) {
+ this.vert = vert;
+ }
+
+ public HEdge getPrev() {
+ return prev;
+ }
+
+ public void setPrev(HEdge prev) {
+ this.prev = prev;
+ }
+
+ public HEdge getNext() {
+ return next;
+ }
+
+ public void setNext(HEdge next) {
+ this.next = next;
+ }
+
+ public HEdge getSibling() {
+ return sibling;
+ }
+
+ public void setSibling(HEdge sibling) {
+ this.sibling = sibling;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public Triangle getTriangle() {
+ return triangle;
+ }
+
+ public void setTriangle(Triangle triangle) {
+ this.triangle = triangle;
+ }
+
+ public static <T extends Vertex> void connect(HEdge first, HEdge next){
+ first.setNext(next);
+ next.setPrev(first);
+ }
+
+ public static <T extends Vertex> void makeSiblings(HEdge first, HEdge second){
+ first.setSibling(second);
+ second.setSibling(first);
+ }
+
+ public boolean vertexOnCurveVertex(){
+ return vert.getPoint().isOnCurve();
+ }
+
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
index fd7736a20..9e29d3973 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
@@ -36,338 +36,338 @@ import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.math.VectorUtil;
public class Loop {
- private HEdge root = null;
- private AABBox box = new AABBox();
- private GraphOutline initialOutline = null;
-
- public Loop(GraphOutline polyline, int direction){
- initialOutline = polyline;
- this.root = initFromPolyline(initialOutline, direction);
- }
-
- public HEdge getHEdge(){
- return root;
- }
-
- public Triangle cut(boolean delaunay){
- if(isSimplex()){
- Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(),
- root.getNext().getNext().getGraphPoint().getPoint());
- t.setVerticesBoundary(checkVerticesBoundary(root));
- return t;
- }
- HEdge prev = root.getPrev();
- HEdge next1 = root.getNext();
-
- HEdge next2 = findClosestValidNeighbor(next1.getNext(), delaunay);
- if(next2 == null){
- root = root.getNext();
- return null;
- }
-
- GraphVertex v1 = root.getGraphPoint();
- GraphVertex v2 = next1.getGraphPoint();
- GraphVertex v3 = next2.getGraphPoint();
-
- HEdge v3Edge = new HEdge(v3, HEdge.INNER);
-
- HEdge.connect(v3Edge, root);
- HEdge.connect(next1, v3Edge);
-
- HEdge v3EdgeSib = v3Edge.getSibling();
- if(v3EdgeSib == null){
- v3EdgeSib = new HEdge(v3Edge.getNext().getGraphPoint(), HEdge.INNER);
- HEdge.makeSiblings(v3Edge, v3EdgeSib);
- }
-
- HEdge.connect(prev, v3EdgeSib);
- HEdge.connect(v3EdgeSib, next2);
-
- Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root);
- this.root = next2;
- return t;
- }
-
- public boolean isSimplex(){
- return (root.getNext().getNext().getNext() == root);
- }
-
- /**Create a connected list of half edges (loop)
- * from the boundary profile
- * @param direction requested winding of edges (CCW or CW)
- */
- private HEdge initFromPolyline(GraphOutline outline, int direction){
- ArrayList<GraphVertex> vertices = outline.getGraphPoint();
-
- if(vertices.size()<3) {
- throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size());
- }
- boolean isCCW = VectorUtil.ccw(vertices.get(0).getPoint(), vertices.get(1).getPoint(),
- vertices.get(2).getPoint());
- boolean invert = isCCW && (direction == VectorUtil.CW);
-
- HEdge firstEdge = null;
- HEdge lastEdge = null;
- int index =0;
- int max = vertices.size();
-
- int edgeType = HEdge.BOUNDARY;
- if(invert){
- index = vertices.size() -1;
- max = -1;
- edgeType = HEdge.HOLE;
- }
-
- while(index != max){
- GraphVertex v1 = vertices.get(index);
- box.resize(v1.getX(), v1.getY(), v1.getZ());
-
- HEdge edge = new HEdge(v1, edgeType);
-
- v1.addEdge(edge);
- if(lastEdge != null){
- lastEdge.setNext(edge);
- edge.setPrev(lastEdge);
- }
- else{
- firstEdge = edge;
- }
-
- if(!invert){
- if(index == vertices.size()-1){
- edge.setNext(firstEdge);
- firstEdge.setPrev(edge);
- }
- }
- else if (index == 0){
- edge.setNext(firstEdge);
- firstEdge.setPrev(edge);
- }
-
- lastEdge = edge;
-
- if(!invert){
- index++;
- }
- else{
- index--;
- }
- }
- return firstEdge;
- }
-
- public void addConstraintCurve(GraphOutline polyline) {
- // GraphOutline outline = new GraphOutline(polyline);
- /**needed to generate vertex references.*/
- initFromPolyline(polyline, VectorUtil.CW);
-
- GraphVertex v3 = locateClosestVertex(polyline);
- HEdge v3Edge = v3.findBoundEdge();
- HEdge v3EdgeP = v3Edge.getPrev();
- HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER);
-
- HEdge.connect(root.getPrev(), crossEdge);
- HEdge.connect(crossEdge, v3Edge);
-
- HEdge crossEdgeSib = crossEdge.getSibling();
- if(crossEdgeSib == null) {
- crossEdgeSib = new HEdge(crossEdge.getNext().getGraphPoint(), HEdge.INNER);
- HEdge.makeSiblings(crossEdge, crossEdgeSib);
- }
-
- HEdge.connect(v3EdgeP, crossEdgeSib);
- HEdge.connect(crossEdgeSib, root);
- }
-
- /** Locates the vertex and update the loops root
- * to have (root + vertex) as closest pair
- * @param polyline the control polyline
- * to search for closestvertices
- * @return the vertex that is closest to the newly set root Hedge.
- */
- private GraphVertex locateClosestVertex(GraphOutline polyline) {
- HEdge closestE = null;
- GraphVertex closestV = null;
-
- float minDistance = Float.MAX_VALUE;
- boolean inValid = false;
- ArrayList<GraphVertex> initVertices = initialOutline.getGraphPoint();
- ArrayList<GraphVertex> vertices = polyline.getGraphPoint();
-
- for(int i=0; i< initVertices.size()-1; i++){
- GraphVertex v = initVertices.get(i);
- GraphVertex nextV = initVertices.get(i+1);
- for(GraphVertex cand:vertices){
- float distance = VectorUtil.computeLength(v.getCoord(), cand.getCoord());
- if(distance < minDistance){
- for (GraphVertex vert:vertices){
- if(vert == v || vert == nextV || vert == cand)
- continue;
- inValid = VectorUtil.inCircle(v.getPoint(), nextV.getPoint(),
- cand.getPoint(), vert.getPoint());
- if(inValid){
- break;
- }
- }
- if(!inValid){
- closestV = cand;
- minDistance = distance;
- closestE = v.findBoundEdge();
- }
- }
-
- }
- }
-
- if(closestE != null){
- root = closestE;
- }
-
- return closestV;
- }
-
- private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) {
- HEdge next = root.getNext();
-
- if(!VectorUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
- edge.getGraphPoint().getPoint())){
- return null;
- }
-
- HEdge candEdge = edge;
- boolean inValid = false;
-
- if(delaunay){
- Vertex cand = candEdge.getGraphPoint().getPoint();
- HEdge e = candEdge.getNext();
- while (e != candEdge){
- if(e.getGraphPoint() == root.getGraphPoint()
- || e.getGraphPoint() == next.getGraphPoint()
- || e.getGraphPoint().getPoint() == cand){
- e = e.getNext();
- continue;
- }
- inValid = VectorUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
- cand, e.getGraphPoint().getPoint());
- if(inValid){
- break;
- }
- e = e.getNext();
- }
- }
- if(!inValid){
- return candEdge;
- }
- return null;
- }
-
- /** Create a triangle from the param vertices only if
- * the triangle is valid. IE not outside region.
- * @param v1 vertex 1
- * @param v2 vertex 2
- * @param v3 vertex 3
- * @param root and edge of this triangle
- * @return the triangle iff it satisfies, null otherwise
- */
- private Triangle createTriangle(Vertex v1, Vertex v2, Vertex v3, HEdge rootT){
- Triangle t = new Triangle(v1, v2, v3);
- t.setVerticesBoundary(checkVerticesBoundary(rootT));
- return t;
- }
-
- private boolean[] checkVerticesBoundary(HEdge rootT) {
- boolean[] boundary = new boolean[3];
- HEdge e1 = rootT;
- HEdge e2 = rootT.getNext();
- HEdge e3 = rootT.getNext().getNext();
-
- if(e1.getGraphPoint().isBoundaryContained()){
- boundary[0] = true;
- }
- if(e2.getGraphPoint().isBoundaryContained()){
- boundary[1] = true;
- }
- if(e3.getGraphPoint().isBoundaryContained()){
- boundary[2] = true;
- }
- return boundary;
- }
-
-
- /** Check if vertex inside the Loop
- * @param vertex the Vertex
- * @return true if the vertex is inside, false otherwise
- */
- public boolean checkInside(Vertex vertex) {
- if(!box.contains(vertex.getX(), vertex.getY(), vertex.getZ())){
- return false;
- }
-
- float[] center = box.getCenter();
-
- int hits = 0;
- HEdge current = root;
- HEdge next = root.getNext();
- while(next!= root){
- if(current.getType() == HEdge.INNER || next.getType() == HEdge.INNER){
- current = next;
- next = current.getNext();
- continue;
- }
- Vertex vert1 = current.getGraphPoint().getPoint();
- Vertex vert2 = next.getGraphPoint().getPoint();
-
- /** The ray is P0+s*D0, where P0 is the ray origin, D0 is a direction vector and s >= 0.
- * The segment is P1+t*D1, where P1 and P1+D1 are the endpoints, and 0 <= t <= 1.
- * perp(x,y) = (y,-x).
- * if Dot(perp(D1),D0) is not zero,
- * s = Dot(perp(D1),P1-P0)/Dot(perp(D1),D0)
- * t = Dot(perp(D0),P1-P0)/Dot(perp(D1),D0)
- */
-
- float[] d0 = new float[]{center[0] - vertex.getX(), center[1]-vertex.getY(),
- center[2]-vertex.getZ()};
- float[] d1 = {vert2.getX() - vert1.getX(), vert2.getY() - vert1.getY(),
- vert2.getZ() - vert1.getZ()};
-
- float[] prep_d1 = {d1[1],-1*d1[0], d1[2]};
- float[] prep_d0 = {d0[1],-1*d0[0], d0[2]};
-
- float[] p0p1 = new float[]{vert1.getX() - vertex.getX(), vert1.getY() - vertex.getY(),
- vert1.getZ() - vertex.getZ()};
-
- float dotD1D0 = VectorUtil.dot(prep_d1, d0);
- if(dotD1D0 == 0){
- /** ray parallel to segment */
- current = next;
- next = current.getNext();
- continue;
- }
-
- float s = VectorUtil.dot(prep_d1,p0p1)/dotD1D0;
- float t = VectorUtil.dot(prep_d0,p0p1)/dotD1D0;
-
- if(s >= 0 && t >= 0 && t<= 1){
- hits++;
- }
- current = next;
- next = current.getNext();
- }
-
- if(hits % 2 != 0){
- /** check if hit count is even */
- return true;
- }
- return false;
- }
-
- public int computeLoopSize(){
- int size = 0;
- HEdge e = root;
- do{
- size++;
- e = e.getNext();
- }while(e != root);
- return size;
- }
+ private HEdge root = null;
+ private AABBox box = new AABBox();
+ private GraphOutline initialOutline = null;
+
+ public Loop(GraphOutline polyline, int direction){
+ initialOutline = polyline;
+ this.root = initFromPolyline(initialOutline, direction);
+ }
+
+ public HEdge getHEdge(){
+ return root;
+ }
+
+ public Triangle cut(boolean delaunay){
+ if(isSimplex()){
+ Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(),
+ root.getNext().getNext().getGraphPoint().getPoint());
+ t.setVerticesBoundary(checkVerticesBoundary(root));
+ return t;
+ }
+ HEdge prev = root.getPrev();
+ HEdge next1 = root.getNext();
+
+ HEdge next2 = findClosestValidNeighbor(next1.getNext(), delaunay);
+ if(next2 == null){
+ root = root.getNext();
+ return null;
+ }
+
+ GraphVertex v1 = root.getGraphPoint();
+ GraphVertex v2 = next1.getGraphPoint();
+ GraphVertex v3 = next2.getGraphPoint();
+
+ HEdge v3Edge = new HEdge(v3, HEdge.INNER);
+
+ HEdge.connect(v3Edge, root);
+ HEdge.connect(next1, v3Edge);
+
+ HEdge v3EdgeSib = v3Edge.getSibling();
+ if(v3EdgeSib == null){
+ v3EdgeSib = new HEdge(v3Edge.getNext().getGraphPoint(), HEdge.INNER);
+ HEdge.makeSiblings(v3Edge, v3EdgeSib);
+ }
+
+ HEdge.connect(prev, v3EdgeSib);
+ HEdge.connect(v3EdgeSib, next2);
+
+ Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root);
+ this.root = next2;
+ return t;
+ }
+
+ public boolean isSimplex(){
+ return (root.getNext().getNext().getNext() == root);
+ }
+
+ /**Create a connected list of half edges (loop)
+ * from the boundary profile
+ * @param direction requested winding of edges (CCW or CW)
+ */
+ private HEdge initFromPolyline(GraphOutline outline, int direction){
+ ArrayList<GraphVertex> vertices = outline.getGraphPoint();
+
+ if(vertices.size()<3) {
+ throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size());
+ }
+ boolean isCCW = VectorUtil.ccw(vertices.get(0).getPoint(), vertices.get(1).getPoint(),
+ vertices.get(2).getPoint());
+ boolean invert = isCCW && (direction == VectorUtil.CW);
+
+ HEdge firstEdge = null;
+ HEdge lastEdge = null;
+ int index =0;
+ int max = vertices.size();
+
+ int edgeType = HEdge.BOUNDARY;
+ if(invert){
+ index = vertices.size() -1;
+ max = -1;
+ edgeType = HEdge.HOLE;
+ }
+
+ while(index != max){
+ GraphVertex v1 = vertices.get(index);
+ box.resize(v1.getX(), v1.getY(), v1.getZ());
+
+ HEdge edge = new HEdge(v1, edgeType);
+
+ v1.addEdge(edge);
+ if(lastEdge != null){
+ lastEdge.setNext(edge);
+ edge.setPrev(lastEdge);
+ }
+ else{
+ firstEdge = edge;
+ }
+
+ if(!invert){
+ if(index == vertices.size()-1){
+ edge.setNext(firstEdge);
+ firstEdge.setPrev(edge);
+ }
+ }
+ else if (index == 0){
+ edge.setNext(firstEdge);
+ firstEdge.setPrev(edge);
+ }
+
+ lastEdge = edge;
+
+ if(!invert){
+ index++;
+ }
+ else{
+ index--;
+ }
+ }
+ return firstEdge;
+ }
+
+ public void addConstraintCurve(GraphOutline polyline) {
+ // GraphOutline outline = new GraphOutline(polyline);
+ /**needed to generate vertex references.*/
+ initFromPolyline(polyline, VectorUtil.CW);
+
+ GraphVertex v3 = locateClosestVertex(polyline);
+ HEdge v3Edge = v3.findBoundEdge();
+ HEdge v3EdgeP = v3Edge.getPrev();
+ HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER);
+
+ HEdge.connect(root.getPrev(), crossEdge);
+ HEdge.connect(crossEdge, v3Edge);
+
+ HEdge crossEdgeSib = crossEdge.getSibling();
+ if(crossEdgeSib == null) {
+ crossEdgeSib = new HEdge(crossEdge.getNext().getGraphPoint(), HEdge.INNER);
+ HEdge.makeSiblings(crossEdge, crossEdgeSib);
+ }
+
+ HEdge.connect(v3EdgeP, crossEdgeSib);
+ HEdge.connect(crossEdgeSib, root);
+ }
+
+ /** Locates the vertex and update the loops root
+ * to have (root + vertex) as closest pair
+ * @param polyline the control polyline
+ * to search for closestvertices
+ * @return the vertex that is closest to the newly set root Hedge.
+ */
+ private GraphVertex locateClosestVertex(GraphOutline polyline) {
+ HEdge closestE = null;
+ GraphVertex closestV = null;
+
+ float minDistance = Float.MAX_VALUE;
+ boolean inValid = false;
+ ArrayList<GraphVertex> initVertices = initialOutline.getGraphPoint();
+ ArrayList<GraphVertex> vertices = polyline.getGraphPoint();
+
+ for(int i=0; i< initVertices.size()-1; i++){
+ GraphVertex v = initVertices.get(i);
+ GraphVertex nextV = initVertices.get(i+1);
+ for(GraphVertex cand:vertices){
+ float distance = VectorUtil.computeLength(v.getCoord(), cand.getCoord());
+ if(distance < minDistance){
+ for (GraphVertex vert:vertices){
+ if(vert == v || vert == nextV || vert == cand)
+ continue;
+ inValid = VectorUtil.inCircle(v.getPoint(), nextV.getPoint(),
+ cand.getPoint(), vert.getPoint());
+ if(inValid){
+ break;
+ }
+ }
+ if(!inValid){
+ closestV = cand;
+ minDistance = distance;
+ closestE = v.findBoundEdge();
+ }
+ }
+
+ }
+ }
+
+ if(closestE != null){
+ root = closestE;
+ }
+
+ return closestV;
+ }
+
+ private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) {
+ HEdge next = root.getNext();
+
+ if(!VectorUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
+ edge.getGraphPoint().getPoint())){
+ return null;
+ }
+
+ HEdge candEdge = edge;
+ boolean inValid = false;
+
+ if(delaunay){
+ Vertex cand = candEdge.getGraphPoint().getPoint();
+ HEdge e = candEdge.getNext();
+ while (e != candEdge){
+ if(e.getGraphPoint() == root.getGraphPoint()
+ || e.getGraphPoint() == next.getGraphPoint()
+ || e.getGraphPoint().getPoint() == cand){
+ e = e.getNext();
+ continue;
+ }
+ inValid = VectorUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
+ cand, e.getGraphPoint().getPoint());
+ if(inValid){
+ break;
+ }
+ e = e.getNext();
+ }
+ }
+ if(!inValid){
+ return candEdge;
+ }
+ return null;
+ }
+
+ /** Create a triangle from the param vertices only if
+ * the triangle is valid. IE not outside region.
+ * @param v1 vertex 1
+ * @param v2 vertex 2
+ * @param v3 vertex 3
+ * @param root and edge of this triangle
+ * @return the triangle iff it satisfies, null otherwise
+ */
+ private Triangle createTriangle(Vertex v1, Vertex v2, Vertex v3, HEdge rootT){
+ Triangle t = new Triangle(v1, v2, v3);
+ t.setVerticesBoundary(checkVerticesBoundary(rootT));
+ return t;
+ }
+
+ private boolean[] checkVerticesBoundary(HEdge rootT) {
+ boolean[] boundary = new boolean[3];
+ HEdge e1 = rootT;
+ HEdge e2 = rootT.getNext();
+ HEdge e3 = rootT.getNext().getNext();
+
+ if(e1.getGraphPoint().isBoundaryContained()){
+ boundary[0] = true;
+ }
+ if(e2.getGraphPoint().isBoundaryContained()){
+ boundary[1] = true;
+ }
+ if(e3.getGraphPoint().isBoundaryContained()){
+ boundary[2] = true;
+ }
+ return boundary;
+ }
+
+
+ /** Check if vertex inside the Loop
+ * @param vertex the Vertex
+ * @return true if the vertex is inside, false otherwise
+ */
+ public boolean checkInside(Vertex vertex) {
+ if(!box.contains(vertex.getX(), vertex.getY(), vertex.getZ())){
+ return false;
+ }
+
+ float[] center = box.getCenter();
+
+ int hits = 0;
+ HEdge current = root;
+ HEdge next = root.getNext();
+ while(next!= root){
+ if(current.getType() == HEdge.INNER || next.getType() == HEdge.INNER){
+ current = next;
+ next = current.getNext();
+ continue;
+ }
+ Vertex vert1 = current.getGraphPoint().getPoint();
+ Vertex vert2 = next.getGraphPoint().getPoint();
+
+ /** The ray is P0+s*D0, where P0 is the ray origin, D0 is a direction vector and s >= 0.
+ * The segment is P1+t*D1, where P1 and P1+D1 are the endpoints, and 0 <= t <= 1.
+ * perp(x,y) = (y,-x).
+ * if Dot(perp(D1),D0) is not zero,
+ * s = Dot(perp(D1),P1-P0)/Dot(perp(D1),D0)
+ * t = Dot(perp(D0),P1-P0)/Dot(perp(D1),D0)
+ */
+
+ float[] d0 = new float[]{center[0] - vertex.getX(), center[1]-vertex.getY(),
+ center[2]-vertex.getZ()};
+ float[] d1 = {vert2.getX() - vert1.getX(), vert2.getY() - vert1.getY(),
+ vert2.getZ() - vert1.getZ()};
+
+ float[] prep_d1 = {d1[1],-1*d1[0], d1[2]};
+ float[] prep_d0 = {d0[1],-1*d0[0], d0[2]};
+
+ float[] p0p1 = new float[]{vert1.getX() - vertex.getX(), vert1.getY() - vertex.getY(),
+ vert1.getZ() - vertex.getZ()};
+
+ float dotD1D0 = VectorUtil.dot(prep_d1, d0);
+ if(dotD1D0 == 0){
+ /** ray parallel to segment */
+ current = next;
+ next = current.getNext();
+ continue;
+ }
+
+ float s = VectorUtil.dot(prep_d1,p0p1)/dotD1D0;
+ float t = VectorUtil.dot(prep_d0,p0p1)/dotD1D0;
+
+ if(s >= 0 && t >= 0 && t<= 1){
+ hits++;
+ }
+ current = next;
+ next = current.getNext();
+ }
+
+ if(hits % 2 != 0){
+ /** check if hit count is even */
+ return true;
+ }
+ return false;
+ }
+
+ public int computeLoopSize(){
+ int size = 0;
+ HEdge e = root;
+ do{
+ size++;
+ e = e.getNext();
+ }while(e != root);
+ return size;
+ }
}