/** Iterate through all polygon nodes and remove small local self-intersections **/ private static Node cureLocalIntersections(Node startNode, final List<Triangle> tessellation) { Node node = startNode; Node nextNode; do { nextNode = node.next; Node a = node.previous; Node b = nextNode.next; // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) if (isVertexEquals(a, b) == false && isIntersectingPolygon(a, a.getX(), a.getY(), b.getX(), b.getY()) == false && linesIntersect(a.getX(), a.getY(), node.getX(), node.getY(), nextNode.getX(), nextNode.getY(), b.getX(), b.getY()) && isLocallyInside(a, b) && isLocallyInside(b, a)) { // Return the triangulated vertices to the tessellation tessellation.add(new Triangle(a, node, b)); // remove two nodes involved removeNode(node); removeNode(node.next); node = startNode = b; } node = node.next; } while (node != startNode); return node; }
Node p = outerNode; double qx = Double.NEGATIVE_INFINITY; final double hx = holeNode.getX(); final double hy = holeNode.getY(); Node connection = null; final double x = p.getX() + (hy - p.getY()) * (p.next.getX() - p.getX()) / (p.next.getY() - p.getY()); if (x <= hx && x > qx) { qx = x; if (hy == p.next.getY()) return p.next; connection = p.getX() < p.next.getX() ? p : p.next; final double mx = connection.getX(); final double my = connection.getY(); double tanMin = Double.POSITIVE_INFINITY; if (hx >= p.getX() && p.getX() >= mx && hx != p.getX() && pointInEar(p.getX(), p.getY(), hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy)) { tan = Math.abs(hy - p.getY()) / (hx - p.getX()); // tangential if ((tan < tanMin || (tan == tanMin && p.getX() > connection.getX())) && isLocallyInside(p, holeNode)) { connection = p; tanMin = tan;
&& n != null && Long.compareUnsigned(n.morton, maxZ) <= 0) { if (p.idx != ear.previous.idx && p.idx != ear.next.idx && pointInEar(p.getX(), p.getY(), ear.previous.getX(), ear.previous.getY(), ear.getX(), ear.getY(), ear.next.getX(), ear.next.getY()) && area(p.previous.getX(), p.previous.getY(), p.getX(), p.getY(), p.next.getX(), p.next.getY()) >= 0) return false; p = p.previousZ; pointInEar(n.getX(), n.getY(), ear.previous.getX(), ear.previous.getY(), ear.getX(), ear.getY(), ear.next.getX(), ear.next.getY()) && area(n.previous.getX(), n.previous.getY(), n.getX(), n.getY(), n.next.getX(), n.next.getY()) >= 0) return false; n = n.nextZ; && pointInEar(p.getX(), p.getY(), ear.previous.getX(), ear.previous.getY(), ear.getX(), ear.getY(), ear.next.getX(), ear.next.getY()) && area(p.previous.getX(), p.previous.getY(), p.getX(), p.getY(), p.next.getX(), p.next.getY()) >= 0) { return false; Long.compareUnsigned(n.morton, maxZ) <= 0) { if (n.idx != ear.previous.idx && n.idx != ear.next.idx && pointInEar(n.getX(), n.getY(), ear.previous.getX(), ear.previous.getY(), ear.getX(), ear.getY(), ear.next.getX(), ear.next.getY()) && area(n.previous.getX(), n.previous.getY(), n.getX(), n.getY(), n.next.getX(), n.next.getY()) >= 0) { return false;
/** Determine whether the middle point of a polygon diagonal is contained within the polygon */ private static boolean middleInsert(final Node start, final double x0, final double y0, final double x1, final double y1) { Node node = start; Node nextNode; boolean lIsInside = false; final double lDx = (x0 + x1) / 2.0f; final double lDy = (y0 + y1) / 2.0f; do { nextNode = node.next; if (node.getY() > lDy != nextNode.getY() > lDy && lDx < (nextNode.getX() - node.getX()) * (lDy - node.getY()) / (nextNode.getY() - node.getY()) + node.getX()) { lIsInside = !lIsInside; } node = node.next; } while (node != start); return lIsInside; }
/** Finds the left-most hole of a polygon ring. **/ private static Node fetchLeftmost(final Node start) { Node node = start; Node leftMost = start; do { // Determine if the current node possesses a lesser X position. if (node.getX() < leftMost.getX()) { // Maintain a reference to this Node. leftMost = node; } // Progress the search to the next node in the doubly-linked list. node = node.next; } while (node != start); // Return the node with the smallest X value. return leftMost; }
/** Determines whether a polygon node forms a valid ear with adjacent nodes. **/ private static boolean isEar(final Node ear, final boolean mortonOptimized) { if (mortonOptimized == true) { return mortonIsEar(ear); } // make sure there aren't other points inside the potential ear Node node = ear.next.next; while (node != ear.previous) { if (pointInEar(node.getX(), node.getY(), ear.previous.getX(), ear.previous.getY(), ear.getX(), ear.getY(), ear.next.getX(), ear.next.getY()) && area(node.previous.getX(), node.previous.getY(), node.getX(), node.getY(), node.next.getX(), node.next.getY()) >= 0) { return false; } node = node.next; } return true; }
/** Determines if two point vertices are equal. **/ private static boolean isVertexEquals(final Node a, final double x, final double y) { return a.getX() == x && a.getY() == y; }
/** Determines if two point vertices are equal. **/ private static boolean isVertexEquals(final Node a, final Node b) { return isVertexEquals(a, b.getX(), b.getY()); }
/** Determines if the diagonal of a polygon is intersecting with any polygon elements. **/ private static boolean isIntersectingPolygon(final Node start, final double x0, final double y0, final double x1, final double y1) { Node node = start; Node nextNode; do { nextNode = node.next; if(isVertexEquals(node, x0, y0) == false && isVertexEquals(node, x1, y1) == false) { if (linesIntersect(node.getX(), node.getY(), nextNode.getX(), nextNode.getY(), x0, y0, x1, y1)) { return true; } } node = nextNode; } while (node != start); return false; }
private static boolean isLocallyInside(final Node a, final Node b) { // if a is cw if (area(a.previous.getX(), a.previous.getY(), a.getX(), a.getY(), a.next.getX(), a.next.getY()) < 0) { return area(a.getX(), a.getY(), b.getX(), b.getY(), a.next.getX(), a.next.getY()) >= 0 && area(a.getX(), a.getY(), a.previous.getX(), a.previous.getY(), b.getX(), b.getY()) >= 0; } // ccw return area(a.getX(), a.getY(), b.getX(), b.getY(), a.previous.getX(), a.previous.getY()) < 0 || area(a.getX(), a.getY(), a.next.getX(), a.next.getY(), b.getX(), b.getY()) < 0; }
/** Determines whether a diagonal between two polygon nodes lies within a polygon interior. * (This determines the validity of the ray.) **/ private static boolean isValidDiagonal(final Node a, final Node b) { return a.next.idx != b.idx && a.previous.idx != b.idx && isIntersectingPolygon(a, a.getX(), a.getY(), b.getX(), b.getY()) == false && isLocallyInside(a, b) && isLocallyInside(b, a) && middleInsert(a, a.getX(), a.getY(), b.getX(), b.getY()); }