Edge* Subdivision::Locate(const Point2d& x) // Returns an edge e, s.t. either x is on e, or e is an edge of // a triangle containing x. The search starts from startingEdge // and proceeds in the general direction of x. Based on the // pseudocode in Guibas and Stolfi (1985) p.121. { Edge* e = startingEdge; while (TRUE) { if (x == e->Org2d() || x == e->Dest2d()) return e; else if (RightOf(x, e)) e = e->Sym(); else if (!RightOf(x, e->Onext())) e = e->Onext(); else if (!RightOf(x, e->Dprev())) e = e->Dprev(); else return e; } }
Edge *Subdivision::locate(const Vec2& x, Edge *start) { Edge *e = start; double t = triArea(x, e->Dest(), e->Org()); if (t>0) { // x is to the right of edge e t = -t; e = e->Sym(); } while (true) { Edge *eo = e->Onext(); Edge *ed = e->Dprev(); double to = triArea(x, eo->Dest(), eo->Org()); double td = triArea(x, ed->Dest(), ed->Org()); if (td>0) // x is below ed if (to>0 || to==0 && t==0) {// x is interior, or origin endpoint startingEdge = e; return e; } else { // x is below ed, below eo t = to; e = eo; } else // x is on or above ed if (to>0) // x is above eo if (td==0 && t==0) { // x is destination endpoint startingEdge = e; return e; } else { // x is on or above ed and above eo t = td; e = ed; } else // x is on or below eo if (t==0 && !leftOf(eo->Dest(), e)) // x on e but subdiv. is to right e = e->Sym(); else if (rand()&1) { // x is on or above ed and t = to; // on or below eo; step randomly e = eo; } else { t = td; e = ed; } } }
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; }