void ArrPolyIpelet::protected_run(int fn){ if (fn==1) { show_help(); return; } X_monotone_list output_curves; Curve_list input_curves; //Argt std::list<Segment_2> sg_list; std::list<Circle_2> cir_list; std::list<Polygon_2> pol_list; std::list<Circular_arc_2> arc_list; read_active_objects( CGAL::dispatch_or_drop_output<Polygon_2,Circle_2,Segment_2,Circular_arc_2>( std::back_inserter(pol_list), std::back_inserter(cir_list), std::back_inserter(sg_list), std::back_inserter(arc_list) ), true,true ); for (std::list<Polygon_2>::iterator it=pol_list.begin();it!=pol_list.end();++it) for(Polygon_2::Edge_const_iterator edge_it=it->edges_begin();edge_it!=it->edges_end();++edge_it) input_curves.push_back(Curve_2(edge_it->point(0),edge_it->point(1))); for (std::list<Segment_2>::iterator it=sg_list.begin();it!=sg_list.end();++it) input_curves.push_back(Curve_2(it->point(0),it->point(1))); for (std::list<Circle_2>::iterator it=cir_list.begin();it!=cir_list.end();++it) input_curves.push_back(Curve_2(it->center(),sqrt(CGAL::to_double(it->squared_radius())))); for (std::list<Circular_arc_2>::iterator it=arc_list.begin();it!=arc_list.end();++it) input_curves.push_back( Curve_2( std::get<0>(*it).center(), sqrt(CGAL::to_double(std::get<0>(*it).squared_radius())), std::get<3>(*it), Traits::Point_2(std::get<1>(*it).x(),std::get<1>(*it).y()), Traits::Point_2(std::get<2>(*it).x(),std::get<2>(*it).y()) ) ); Traits T; CGAL::compute_subcurves(input_curves.begin(),input_curves.end(),std::back_inserter(output_curves),false,T); for (X_monotone_list::iterator it=output_curves.begin();it!=output_curves.end();++it){ Point_2 S(CGAL::to_double(it->source().x()),CGAL::to_double(it->source().y())); Point_2 T(CGAL::to_double(it->target().x()),CGAL::to_double(it->target().y())); if (it->is_linear ()) draw_in_ipe(Segment_2(S,T)); if (it->is_circular()) draw_in_ipe(Circular_arc_2(it->supporting_circle(),S,T,it->supporting_circle().orientation())); } return; }
// This routine checks whether a poylgon can be inserted into a block such that the interior of the polygon does not at all overlap with used space // in the block. We COULD do this using boolean operations (E.g. is the intersection of the used block space and our polygon empty?) but we do NOT want // to. Why? Time to do a boolean op is a function of BOTH polygons, and in a lot of cases the block will be HUGELY complex (imagine a giant forest expanse // with lots of crap already inserted into it) and our test block will be TINY (a quad). In this case, we get better performance by doing a piece-wise per-side // test. // Side note: using the bulk locator totally violates this principle...we will probably need to replace it with a walk location strategy. // So we use the zone utility to see what we'll hit as we go along our edges. bool can_insert_into_block( Block_2& block, const Polygon_2& bounds) { // Run a bulk location on the entire block...TBD: there may be blocks where sweeping is worse than marching. // Anyway, we get a bunch of pairs of the locate point and the actual part of the arrangement we hit. vector<pair<Point_2, CGAL::Object> > pts; CGAL::locate(block, bounds.vertices_begin(), bounds.vertices_end(), back_inserter(pts)); // Quick check: if ANY of our points are inside a non empty face, we are by definition hosed. // We can see this now just from the location data. Block_2::Face_const_handle ff; for(int n = 0; n < pts.size(); ++n) if(CGAL::assign(ff,pts[n].second)) if(ff->data().usage != usage_Empty) return false; for(int n = 0; n < pts.size(); ++n) { // We are now going to go through each side and do a zone test. This will check whether it is // either running along a full area or crashing through it. int m = (n+1)%pts.size(); check_block_visitor v; v.cv = Block_2::X_monotone_curve_2(Segment_2(pts[n].first, pts[m].first)); CGAL::Arrangement_zone_2<Block_2,check_block_visitor> zone(block, &v); if(v.cv.is_directed_right()) zone.init_with_hint(v.cv,pts[n].second); else zone.init_with_hint(v.cv,pts[m].second); zone.compute_zone(); if(!v.ok) return false; } return true; }
Segment_2 project_2(const Segment_3& s) { return Segment_2(s.source().point_2(), s.target().point_2()); }
void triangulate(const Polygon_2& polygon, Cut_iter cuts_begin, Cut_iter cuts_end, const boost::unordered_map<Point_3, boost::unordered_set<Segment_3_undirected> >& point2edges, Out_iter triangles) { typedef CGAL::Triangulation_vertex_base_2<Kernel> Vb; typedef CGAL::Triangulation_vertex_base_with_info_2<Point_3, Kernel, Vb> Info; typedef CGAL::Constrained_triangulation_face_base_2<Kernel> Fb; typedef CGAL::Triangulation_data_structure_2<Info,Fb> TDS; typedef CGAL::Exact_predicates_tag Itag; typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel, TDS, Itag> CDT; typedef CDT::Vertex_handle Vertex_handle; static log4cplus::Logger logger = log4cplus::Logger::getInstance("polygon_utils"); Polygon_2 p(polygon); LOG4CPLUS_TRACE(logger, "Triangulating " << pp(p)); if (p.size() < 3) return; bool vertical = is_vertical(p); if (vertical) { LOG4CPLUS_TRACE(logger, "Polygon is vertical. Rotating."); p = yz_swap_neg(p); } bool reverse = !p.is_counterclockwise_oriented(); if (reverse) p.reverse_orientation(); CDT cdt; boost::unordered_map<Point_3, Vertex_handle> point2handle; for (Polygon_2::Vertex_iterator it = p.vertices_begin(); it != p.vertices_end(); ++it) { Vertex_handle h = cdt.insert(*it); point2handle[*it] = h; h->info() = *it;//it->z(); } Polygon_2::Vertex_circulator start = p.vertices_circulator(); Polygon_2::Vertex_circulator c = start; Polygon_2::Vertex_circulator n = c; ++n; do { Vertex_handle ch = point2handle[*c];//cdt.insert(*c); Vertex_handle nh = point2handle[*n];//cdt.insert(*n); // ch->info() = c->z(); // nh->info() = n->z(); // cdt.insert_constraint(*c, *n); cdt.insert_constraint(ch, nh); ++c; ++n; } while (c != start); for (Cut_iter c_it = cuts_begin; c_it != cuts_end; ++c_it) { Polyline_2 cut = *c_it; LOG4CPLUS_TRACE(logger, "Adding cut: " << pp(cut)); if (vertical) cut = yz_swap_neg(cut); for (Polyline_2::const_iterator c = cut.begin(); c != cut.end(); ++c) { Polyline_2::const_iterator n = c; ++n; if (n != cut.end()) { const Point_3& cp = *c; const Point_3& np = *n; if (point2handle.find(cp) == point2handle.end()) { Vertex_handle h = cdt.insert(cp); point2handle[cp] = h; h->info() = cp;//cp.z(); } if (point2handle.find(np) == point2handle.end()) { Vertex_handle h = cdt.insert(np); point2handle[np] = h; h->info() = np;//np.z(); } Vertex_handle ch = point2handle[*c];//cdt.insert(*c); Vertex_handle nh = point2handle[*n];//cdt.insert(*n); // ch->info() = c->z(); // nh->info() = n->z(); // cdt.insert_constraint(*c, *n); cdt.insert_constraint(ch, nh); LOG4CPLUS_TRACE(logger, " " << pp(Segment_2(*c, *n))); } } } // Loop through the triangulation and store the vertices of each triangle for (CDT::Finite_faces_iterator ffi = cdt.finite_faces_begin(); ffi != cdt.finite_faces_end(); ++ffi) { Triangle t; Point_3 center = centroid(ffi->vertex(0)->info(), ffi->vertex(1)->info(), ffi->vertex(2)->info()); if (p.has_on_bounded_side(center) && is_legal(ffi->vertex(0)->info(), ffi->vertex(1)->info(), ffi->vertex(2)->info(), point2edges)) { for (int i = 0; i < 3; ++i) { int idx = reverse ? 2-i : i; if (!vertical) { // Point_3 p(ffi->vertex(i)->point()); // p = Point_3(p.x(), p.y(), ffi->vertex(i)->info()); Point_3 p(ffi->vertex(i)->info()); t[idx] = p; } else { // Point_3 p(ffi->vertex(i)->point()); // p = Point_3(p.x(), p.y(), ffi->vertex(i)->info()); Point_3 p(ffi->vertex(i)->info()); t[idx] = yz_swap_pos(p); } } LOG4CPLUS_TRACE(logger, "Adding tile: " << pp_tri(t)); *triangles++ = t; } } }
void SubSelectIpelet::protected_run(int fn) { if (fn==2) { show_help(); return; } std::list<Circle_2> cir_list; std::list<Polygon_2> pol_list; Iso_rectangle_2 bbox= read_active_objects( CGAL::dispatch_or_drop_output<Polygon_2,Circle_2>( std::back_inserter(pol_list), std::back_inserter(cir_list) ) ); if (fn==0 && pol_list.size()!=2){ print_error_message("You must select exactly two polygons"); return; } std::list<double> r_offsets; for (std::list<Circle_2>::iterator it=cir_list.begin();it!=cir_list.end();++it) r_offsets.push_back(sqrt(CGAL::to_double(it->squared_radius()))); IpeMatrix tfm (1,0,0,1,-CGAL::to_double(bbox.min().x()),-CGAL::to_double(bbox.min().y())); for (std::list<Polygon_2>::iterator it=pol_list.begin();it!=pol_list.end();++it) if(!it->is_simple()){ print_error_message("Polygon(s) must be simple"); } if (fn==0){ Polygon_2 polygon1=*pol_list.begin(); Polygon_2 polygon2=*++pol_list.begin(); Polygon_with_holes_2 sum = minkowski_sum_2 (polygon1, polygon2); std::list<Point_2> LP; for (Polygon_2::iterator it=sum.outer_boundary().vertices_begin();it!= sum.outer_boundary().vertices_end();++it) LP.push_back(*it); draw_polyline_in_ipe(LP.begin(),LP.end(),true,false,false); for (Polygon_with_holes_2::Hole_const_iterator poly_it = sum.holes_begin(); poly_it != sum.holes_end(); ++poly_it){ LP.clear(); for (Polygon_2::iterator it=poly_it->vertices_begin();it!= poly_it->vertices_end();++it) LP.push_back(*it); draw_polyline_in_ipe(LP.begin(),LP.end(),true,false,false); } create_polygon_with_holes(true); transform_selected_objects_(tfm); } else{ if (r_offsets.size()==0) r_offsets.push_back(10); for (std::list<Polygon_2>::iterator it_pol=pol_list.begin();it_pol!=pol_list.end();++it_pol){ for(std::list<double>::iterator it=r_offsets.begin();it!=r_offsets.end();++it){ Offset_polygon_with_holes_2 offset=approximated_offset_2 (*it_pol, *it, 0.0001); std::list<Segment_2> LS; for( Offset_polygon_2::Curve_iterator itt=offset.outer_boundary().curves_begin(); itt!=offset.outer_boundary().curves_end();++itt){ Point_2 S=Point_2(CGAL::to_double(itt->source().x()),CGAL::to_double(itt->source().y())); Point_2 T=Point_2(CGAL::to_double(itt->target().x()),CGAL::to_double(itt->target().y())); if (itt->is_linear ()) LS.push_back(Segment_2(S,T)); if (itt->is_circular()) draw_in_ipe(Circular_arc_2(itt->supporting_circle(),S,T,itt->supporting_circle().orientation())); } draw_in_ipe(LS.begin(),LS.end()); } } } }
void Cone_spanners_ipelet::protected_run(int fn) { std::vector<Point_2> lst; int number_of_cones; switch (fn){ case 0: case 1: case 2: case 3: case 4: case 5: case 6: { std::vector<Point_2> points_read; read_active_objects( CGAL::dispatch_or_drop_output<Point_2>(std::back_inserter(points_read)) ); if (points_read.empty()) { print_error_message("No mark selected"); return; } for(std::vector<Point_2>::iterator it = points_read.begin(); it != points_read.end(); it++) { if(std::find(points_read.begin(), it, *it) == it) { lst.push_back(*it); } } int ret_val; boost::tie(ret_val,number_of_cones)=request_value_from_user<int>("Enter the number of cones"); if (ret_val < 0) { print_error_message("Incorrect value"); return; } if(number_of_cones < 2) { print_error_message("The number of cones must be larger than 1!"); return; } break; } case 7: show_help(); return; } if(fn >= 0 && fn <= 5) { CGAL::Cones_selected cones_selected = CGAL::ALL_CONES; if(fn == 2 || fn == 3) cones_selected = CGAL::EVEN_CONES; else if(fn == 4 || fn == 5) cones_selected = CGAL::ODD_CONES; Graph g; switch (fn){ case 0: case 2: case 4: { CGAL::Construct_theta_graph_2<Kernel, Graph> theta(number_of_cones, Direction_2(1,0), cones_selected); theta(lst.begin(), lst.end(), g); break; } case 1: case 3: case 5: { CGAL::Construct_yao_graph_2<Kernel, Graph> yao(number_of_cones, Direction_2(1,0), cones_selected); yao(lst.begin(), lst.end(), g); break; } } boost::graph_traits<Graph>::edge_iterator ei, ei_end; for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { boost::graph_traits<Graph>::edge_descriptor e = *ei; boost::graph_traits<Graph>::vertex_descriptor u = source(e, g); boost::graph_traits<Graph>::vertex_descriptor v = target(e, g); draw_in_ipe(Segment_2(g[u], g[v])); } group_selected_objects_(); } else if(fn == 6) { CGAL::Compute_cone_boundaries_2<Kernel> cones; std::vector<Direction_2> directions(number_of_cones); cones(number_of_cones, Direction_2(1,0), directions.begin()); for(std::vector<Point_2>::iterator it = lst.begin(); it != lst.end(); it++) { for(std::vector<Direction_2>::iterator dir = directions.begin(); dir != directions.end(); dir++) { draw_in_ipe(Segment_2(*it,*it + 100*dir->to_vector())); } group_selected_objects_(); get_IpePage()->deselectAll(); } } }