bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { // To legalize a triangle we start by finding if any of the three edges // violate the Delaunay condition for (int i = 0; i < 3; i++) { if (t.delaunay_edge[i]) continue; Triangle* ot = t.GetNeighbor(i); if (ot) { Point* p = t.GetPoint(i); Point* op = ot->OppositePoint(t, *p); int oi = ot->Index(op); // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) // then we should not try to legalize if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { t.constrained_edge[i] = ot->constrained_edge[oi]; continue; } bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); if (inside) { // Lets mark this shared edge as Delaunay t.delaunay_edge[i] = true; ot->delaunay_edge[oi] = true; // Lets rotate shared edge one vertex CW to legalize it RotateTrianglePair(t, *p, *ot, *op); // We now got one valid Delaunay Edge shared by two triangles // This gives us 4 new edges to check for Delaunay // Make sure that triangle to node mapping is done only one time for a specific triangle bool not_legalized = !Legalize(tcx, t); if (not_legalized) { tcx.MapTriangleToNodes(t); } not_legalized = !Legalize(tcx, *ot); if (not_legalized) tcx.MapTriangleToNodes(*ot); // Reset the Delaunay edges, since they only are valid Delaunay edges // until we add a new triangle or point. // XXX: need to think about this. Can these edges be tried after we // return to previous recursive level? t.delaunay_edge[i] = false; ot->delaunay_edge[oi] = false; // If triangle have been legalized no need to check the other edges since // the recursive legalization will handles those so we can end here. return true; } } } return false; }
void SweepContext::MapTriangleToNodes(Triangle& t) { for (int i = 0; i < 3; i++) { if (!t.GetNeighbor(i)) { Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); if (n) n->triangle = &t; } } }
void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes) { (void) nodes; // Initial triangle Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); map_.push_back(triangle); af_head_ = new Node(*triangle->GetPoint(1), *triangle); af_middle_ = new Node(*triangle->GetPoint(0), *triangle); af_tail_ = new Node(*triangle->GetPoint(2)); front_ = new AdvancingFront(*af_head_, *af_tail_); // TODO: More intuitive if head is middles next and not previous? // so swap head and tail af_head_->next = af_middle_; af_middle_->next = af_tail_; af_middle_->prev = af_head_; af_tail_->prev = af_middle_; }