void handleDual(Ray_2 r, Iso_rectangle_2 crect, std::vector<PointList>& polylines) { std::cerr << "ray" << std::endl; // str << r; Object_2 o = CGAL::intersection(crect, r); Segment_2 seg; Point_2 pnt; if (assign(seg, o)) { std::cerr << "ray -> segment" << std::endl; Point_2 ss = seg.source(); Point_2 st = seg.target(); PointList points; points.push_back(ss); points.push_back(st); polylines.push_back(points); } else if (assign(pnt, o)){ std::cerr << "ray -> point" << std::endl; // no use for points } else { std::cerr << "ray -> ?" << std::endl; std::cerr << r.source() << " " << r.point(1) << std::endl; } }
int voronoi_tessellation(TreeNode &tn) { assert(tn.region.is_convex()); // tn.regionは凸であることを前提 assert(tn.children.size() >= 2); PD2 pd2; std::list<TreeNode>::iterator cit; for (cit = tn.children.begin(); cit != tn.children.end(); ++cit) { cit->face = pd2.insert(cit->p); cit->region = Polygon_2(); // 全部初期化しておく } assert( pd2.is_valid() ); PD2::Delaunay_graph dg = pd2.dual(); PD2::Delaunay_graph::Finite_vertices_iterator vit; for (vit = dg.finite_vertices_begin(); vit != dg.finite_vertices_end(); ++vit) { // tn.regionとintersectする。Ray/Lineは切り取られてSegmentとなる。 PD2::Delaunay_graph::Edge_circulator eci = dg.incident_edges(vit); PD2::Delaunay_graph::Edge_circulator ece = eci; std::set<Point_2> point_set; if (eci != NULL) { Polygon_2::Vertex_iterator pvit; do { Line_2 l; Ray_2 r; Segment_2 s; if (!dg.is_infinite(eci)) { CGAL::Object o = dg.dual(eci); if (CGAL::assign(s, o)) { // std::cout << "Segment: (" << s.source().x() << ", " << s.source().y() << ") (" << s.target().x() << ", " << s.target().y() << ")" << std::endl; if (tn.region.bounded_side(s.source()) != CGAL::ON_UNBOUNDED_SIDE) { point_set.insert(s.source()); } if (tn.region.bounded_side(s.target()) != CGAL::ON_UNBOUNDED_SIDE) { point_set.insert(s.target()); } Polygon_2::Edge_const_iterator eit; for (eit = tn.region.edges_begin(); eit != tn.region.edges_end(); ++eit) { CGAL::Object obj = CGAL::intersection(*eit, s); Point_2 p; Segment_2 seg; if (CGAL::assign(p, obj)) { point_set.insert(p); } else if (CGAL::assign(seg, obj)) { assert(false); } } } if (CGAL::assign(r, o)) { // std::cout << "Ray: (" << r.source().x() << ", " << r.source().y() << ") " << r << std::endl; if (tn.region.bounded_side(r.source()) != CGAL::ON_UNBOUNDED_SIDE) { point_set.insert(r.source()); } Polygon_2::Edge_const_iterator eit; for (eit = tn.region.edges_begin(); eit != tn.region.edges_end(); ++eit) { CGAL::Object obj = CGAL::intersection(*eit, r); Point_2 p; Segment_2 seg; if (CGAL::assign(p, obj)) { point_set.insert(p); } else if (CGAL::assign(seg, obj)) { assert(false); } } } if (CGAL::assign(l, o)) { // std::cout << "Line: (" << l.point(0).x() << ", " << l.point(0).y() << ") (" << l.direction().dx() << ", " << l.direction().dy() << ")" << std::endl; Polygon_2::Edge_const_iterator eit; for (eit = tn.region.edges_begin(); eit != tn.region.edges_end(); ++eit) { CGAL::Object obj = CGAL::intersection(*eit, l); Point_2 p; Segment_2 seg; if (CGAL::assign(p, obj)) { point_set.insert(p); } else if (CGAL::assign(seg, obj)) { assert(false); } } } } // infinite } while (++eci != ece); // tn.regionのpolygon中の点で、領域内のものをぜんぶ入れる for (pvit = tn.region.vertices_begin(); pvit != tn.region.vertices_end(); ++pvit) { /* // NOTE: locateはちょっとバグってるみたい。 // 代わりに、距離が最短な点を探す。 // NOTE: バグってないかも。代替ロジックでも問題が出た。 PD2::Locate_result lr = pd2.locate(*pvit); if (PD2::Vertex_handle *v = boost::get<PD2::Vertex_handle>(&lr)) { // 交わってるはず assert(false); } elsentersection if (PD2::Halfedge_handle *e = boost::get<Halfedge_handle>(&lr)) { // 交わってるはず assert(false); } else if (PD2::Face_handle *f = boost::get<Face_handle>(&lr)) { // 今対象としている点の領域だったら、追加 if ((*f)->dual()->point() == vit->point()) { point_set.insert(*pvit); } } */ // tn.regionの頂点と子供の頂点とのpower distanceを // すべて計算し、着目している子供に属するかを調べる cit = tn.children.begin(); Weighted_point_2 cp = cit->p; ++cit; for (; cit != tn.children.end(); ++cit) { if (CGAL::compare_power_distance(cp, cit->p, *pvit) == CGAL::LARGER) { cp = cit->p; } } if (cp == vit->point()) { // std::cout << "RegionPoint: (" << pvit->x() << ", " << pvit->y() << ")" << std::endl; point_set.insert(*pvit); } } assert(point_set.size() != 1 && point_set.size() != 2); } // 対応する子供を見つける for (cit = tn.children.begin(); cit != tn.children.end(); ++cit) { if (vit->point() == cit->p) { // 自前でのソートが面倒なのでconvex hullを求めてPolygonを作る。 CGAL::ch_graham_andrew(point_set.begin(), point_set.end(), std::inserter(cit->region, cit->region.vertices_begin())); assert(point_set.size() == 0 || cit->region.size() > 0); assert(point_set.size() == cit->region.size()); // 頂点の数あってるはず assert(cit->region.area() <= tn.region.area()); } } } return 0; }