/// <summary> /// Creates a new front triangle and legalize it /// </summary> /// /// <param name="tcx"></param> /// <param name="point"></param> /// <param name="node"></param> private static AdvancingFrontNode newFrontTriangle(DTSweepContext tcx, TriangulationPoint point, AdvancingFrontNode node) { AdvancingFrontNode newNode; DelaunayTriangle triangle; triangle = new DelaunayTriangle(point, node.point, node.next.point); triangle.markNeighbor(node.triangle); tcx.addToList(triangle); newNode = new AdvancingFrontNode(point); newNode.next = node.next; newNode.prev = node; node.next.prev = newNode; node.next = newNode; tcx.addNode(newNode); // XXX: BST if (tcx.isDebugEnabled()) { tcx.getDebugContext().setActiveNode(newNode); } if (!legalize(tcx, triangle)) { tcx.mapTriangleToNodes(triangle); } return(newNode); }
/// <summary> /// Exhaustive search to update neighbor pointers /// </summary> /// <param name="t">triangle</param> public void markNeighbor(DelaunayTriangle t) { if (t.contains(points[1], points[2])) { neighbors[0] = t; t.markNeighbor(points[1], points[2], this); } else if (t.contains(points[0], points[2])) { neighbors[1] = t; t.markNeighbor(points[0], points[2], this); } else if (t.contains(points[0], points[1])) { neighbors[2] = t; t.markNeighbor(points[0], points[1], this); } else { logger.Error("markNeighbor failed"); } }
/// <summary> /// Adds a triangle to the advancing front to fill a hole. /// </summary> /// /// <param name="tcx"></param> /// <param name="node">middle node, that is the bottom of the hole</param> /// private static void fill(DTSweepContext tcx, AdvancingFrontNode node) { DelaunayTriangle triangle = new DelaunayTriangle(node.prev.point, node.point, node.next.point); // TODO: should copy the cEdge value from neighbor triangles // for now cEdge values are copied during the legalize triangle.markNeighbor(node.prev.triangle); triangle.markNeighbor(node.triangle); tcx.addToList(triangle); // Update the advancing front node.prev.next = node.next; node.next.prev = node.prev; tcx.removeNode(node); // If it was legalized the triangle has already been mapped if (!legalize(tcx, triangle)) { tcx.mapTriangleToNodes(triangle); } }
/// <summary> /// Rotates a triangle pair one vertex CW /// <code> /// n2 n2 /// P +-----+ P +-----+ /// | t /| |\ t | /// | / | | \ | /// n1| / |n3 n1| \ |n3 /// | / | after CW | \ | /// |/ oT | | oT \| /// +-----+ oP +-----+ /// n4 n4 /// </code> /// </summary> private static void rotateTrianglePair(DelaunayTriangle t, TriangulationPoint p, DelaunayTriangle ot, TriangulationPoint op) { DelaunayTriangle n1, n2, n3, n4; n1 = t.neighborCCW(p); n2 = t.neighborCW(p); n3 = ot.neighborCCW(op); n4 = ot.neighborCW(op); bool ce1, ce2, ce3, ce4; ce1 = t.getConstrainedEdgeCCW(p); ce2 = t.getConstrainedEdgeCW(p); ce3 = ot.getConstrainedEdgeCCW(op); ce4 = ot.getConstrainedEdgeCW(op); bool de1, de2, de3, de4; de1 = t.getDelunayEdgeCCW(p); de2 = t.getDelunayEdgeCW(p); de3 = ot.getDelunayEdgeCCW(op); de4 = ot.getDelunayEdgeCW(op); t.legalize(p, op); ot.legalize(op, p); // Remap dEdge ot.setDelunayEdgeCCW(p, de1); t.setDelunayEdgeCW(p, de2); t.setDelunayEdgeCCW(op, de3); ot.setDelunayEdgeCW(op, de4); // Remap cEdge ot.setConstrainedEdgeCCW(p, ce1); t.setConstrainedEdgeCW(p, ce2); t.setConstrainedEdgeCCW(op, ce3); ot.setConstrainedEdgeCW(op, ce4); // Remap neighbors // XXX: might optimize the markNeighbor by keeping track of // what side should be assigned to what neighbor after the // rotation. Now mark neighbor does lots of testing to find // the right side. t.clearNeighbors(); ot.clearNeighbors(); if (n1 != null) { ot.markNeighbor(n1); } if (n2 != null) { t.markNeighbor(n2); } if (n3 != null) { t.markNeighbor(n3); } if (n4 != null) { ot.markNeighbor(n4); } t.markNeighbor(ot); }