Edge * splitFace(Face *fl, Vertex *v1, Vertex *v2) { Face *fr = new Face(); //cout << " split vertices: " << v1->p << "-" << v2->p << endl; Edge *a = v1->getEdge(); Edge *b = v2->getEdge(); Edge *c = Edge::makeEdge(v1, v2, fl, fr); while (a->Left() != fl) { a = a->Onext(); } while (b->Left() != fl) { b = b->Onext(); } Edge::splice(a, c); Edge::splice(b, c->Sym()); Edge *cIter = c->Lnext(); while (cIter != c) { cIter->setLeft(fl); cIter = cIter->Lnext(); } cIter = c->Rnext(); while (cIter != c) { cIter->setRight(fr); cIter = cIter->Rnext(); } return c; }
// // s is a spoke pointing OUT from x // void Subdivision::optimize(Vec2& x, Edge *s) { Edge *start_spoke = s; Edge *spoke = s; do { Edge *e = spoke->Lnext(); Edge *t = e->Oprev(); if( isInterior(e) && shouldSwap(x, e) ) swap(e); else { spoke = spoke->Onext(); if( spoke == start_spoke ) break; } } while( true ); // // Now, update all the triangles spoke = start_spoke; do { Edge *e = spoke->Lnext(); Triangle *t = e->Lface(); if( t ) t->update(*this); spoke = spoke->Onext(); } while( spoke != start_spoke ); }
void Swap(Edge* e) // Essentially turns edge e counterclockwise inside its enclosing // quadrilateral. The data pointers are modified accordingly. { Edge* a = e->Oprev(); Edge* b = e->Sym()->Oprev(); Splice(e, a); Splice(e->Sym(), b); Splice(e, a->Lnext()); Splice(e->Sym(), b->Lnext()); e->EndPoints(a->Dest(), b->Dest()); }
int getFaceOrder(Edge *e, vector<Vertex>& pts) { int count = 1; Edge *iter = e->Lnext(); if (iter->Left() == NULL) { return -1; } if (iter == NULL) { cout << "Erro: ponteiro next == NULL\n"; return -1; } pts.clear(); pts.push_back(*e->Orig()); while (iter != e && count < 100) { count++; pts.push_back(*iter->Orig()); iter = iter->Lnext(); } if (count == 100) { cout << "Erro: loop infinito\n"; return -1; } return count; }
void Subdivision::swap(Edge *e) { Triangle *f1 = e->Lface(); Triangle *f2 = e->Sym()->Lface(); Edge *a = e->Oprev(); Edge *b = e->Sym()->Oprev(); splice(e, a); splice(e->Sym(), b); splice(e, a->Lnext()); splice(e->Sym(), b->Lnext()); e->EndPoints(a->Dest(), b->Dest()); f1->reshape(e); f2->reshape(e->Sym()); }
void Cell::setOrbitLeft(Edge *edge, Face *left) { assert(edge != 0); assert(left != 0); // traverse the Lnext orbit of _edge_, setting the left face of each edge to // _left_ Edge *scan = edge; do { scan->setLeft(left); scan = scan->Lnext(); } while (scan != edge); }
Point getFaceCentroid(Face *f) { int count = 1; Point p(-1,-1); if (f == NULL) return p; Edge *e = f->getEdge(); Edge *iter = e->Lnext(); p = e->Orig()->p; while (iter != e) { Point np = iter->Orig()->p; p += np; count++; iter = iter->Lnext(); } p.x /= count; p.y /= count; return p; }
Edge *Cell::getOrbitOrg(Edge *edge, Vertex *org) { assert(edge != 0); assert(org != 0); // traverse the Lnext orbit of _edge_ looking for an edge whose origin is // _org_ Edge *scan = edge; do { if (scan->Org() == org) { return scan; } scan = scan->Lnext(); } while (scan != edge); return 0; }
void Subdivision::InsertSite(const Point2d& x) // Inserts a new point into a subdivision representing a Delaunay // triangulation, and fixes the affected edges so that the result // is still a Delaunay triangulation. This is based on the // pseudocode from Guibas and Stolfi (1985) p.120, with slight // modifications and a bug fix. { Edge* e = Locate(x); if ((x == e->Org2d()) || (x == e->Dest2d())) // point is already in return; else if (OnEdge(x, e)) { e = e->Oprev(); DeleteEdge(e->Onext()); } // Connect the new point to the vertices of the containing // triangle (or quadrilateral, if the new point fell on an // existing edge.) Edge* base = MakeEdge(); base->EndPoints(e->Org(), new Point2d(x)); Splice(base, e); startingEdge = base; do { base = Connect(e, base->Sym()); e = base->Oprev(); } while (e->Lnext() != startingEdge); // Examine suspect edges to ensure that the Delaunay condition // is satisfied. do { Edge* t = e->Oprev(); if (RightOf(t->Dest2d(), e) && InCircle(e->Org2d(), t->Dest2d(), e->Dest2d(), x)) { Swap(e); e = e->Oprev(); } else if (e->Onext() == startingEdge) // no more suspect edges return; else // pop a suspect edge e = e->Onext()->Lprev(); } while (TRUE); }
int getFaceOrder(Edge *e) { int count = 1; Edge *iter = e->Lnext(); if (iter->Left() == NULL) { return -1; } if (iter == NULL) { cout << "Erro: ponteiro next == NULL\n"; return -1; } while (iter != e && count < 100) { count++; iter = iter->Lnext(); } if (count == 100) { cout << "Erro: loop infinito\n"; return -1; } return count; }
int main() { using cgl::Point2d; using cgl::Edge; using cgl::make_edge; // Point2d *a = new Point2d(0.0, 0.0); // 0 // Point2d *b = new Point2d(1.0, 0.0); // 1 // Point2d *c = new Point2d(1.0, 1.0); // 2 // Point2d *d = new Point2d(0.0, 1.0); // 3 Edge *ea = make_edge(0, 1); Edge *eb = make_edge(ea->Dest(), 2); Edge *ec = make_edge(eb->Dest(), 3); Edge *ed = make_edge(ec->Dest(), 0); Edge *ee = make_edge(eb->Dest(), ea->Org()); // Connect eb to ea->Dest() splice(ea->Sym(), eb); // Connect ec to eb->Dest() splice(eb->Sym(), ec); // Connect ed to ec->Sym() and ea splice(ec->Sym(), ed); splice(ed->Sym(), ea); // Connect ee to ec and ea -- this is equivalent to Delaunay::connect splice(ee, eb->Lnext()); splice(ee->Sym(), ea); // Traverse the convex hull if (ea->Dnext() != eb->Sym()) { std::cerr << "Error: ea->Dnext() != eb->Sym()" << std::endl; return 1; } if (eb->Dnext() != ec->Sym()) { std::cerr << "Error: eb->Dnext() != ec->Sym()" << std::endl; return 1; } if (ec->Dnext() != ed->Sym()) { std::cerr << "Error: ec->Dnext() != ed->Sym()" << std::endl; return 1; } if (ed->Dprev() != ee) { std::cerr << "Error: ed->Dprev() != ee" << std::endl; return 1; } // Cross linkage -- test algebra // Rot / invRot if (ee->Rot()->Org() != ed->invRot()->Org()) { std::cerr << "Error: ee->Rot()->Org() != ed->invRot()->Org()" << std::endl; return 1; } // Sym if (ee->Sym()->Org() != 0) { std::cerr << "Error: ee->Sym()->Org() != a" << std::endl; return 1; } // Onext if (ee->Onext() != eb->Sym()) { std::cerr << "Error: ee->Onext() != eb->Sym()" << std::endl; return 1; } // Oprev if (ee->Oprev() != ec) { std::cerr << "Error: ee->Oprev() != ec" << std::endl; return 1; } // Dnext if (ee->Dnext() != ed) { std::cerr << "Error: ee->Dnext() != ed" << std::endl; return 1; } // Dprev if (ee->Dprev() != ea->Sym()) { std::cerr << "Error: ee->Dprev() != ea->Sym()" << std::endl; return 1; } // Lnext if (ee->Lnext() != ea) { std::cerr << "Error: ee->Lnext() != ea" << std::endl; return 1; } // Lprev if (ee->Lprev() != eb) { std::cerr << "Error: ee->Lprev() != eb" << std::endl; return 1; } // Rnext if (ee->Rnext() != ec->Sym()) { std::cerr << "Error: ee->Rnext() != ec->Sym()" << std::endl; return 1; } // Rprev if (ee->Rprev() != ed->Sym()) { std::cerr << "Error: ee->Rprev() != ed->Sym()" << std::endl; return 1; } // Org / Dest if (ed->Org() != 3) { std::cerr << "Error: ed->Org() != d" << std::endl; return 1; } if (ed->Dest() != 0) { std::cerr << "Error: ed->Dest() != a" << std::endl; return 1; } if (ee->Org() != 2) { std::cerr << "Error: ee->Org() != c" << std::endl; return 1; } if (ee->Dest() != 0) { std::cerr << "Error: ee->Dest() != a" << std::endl; return 1; } // Let the system clean up the memory return 0; }