@ \subsection {Point location on the SNC structure} This implementation of the point location and ray shooting for the SNC structure differs from the previous one (e.g. the naive implementation) in that it supports the candidates provider interface for performing ray shooting and point location. <>= #ifndef SNC_POINT_LOCATOR_H #define SNC_POINT_LOCATOR_H #include #include #include #include #include #include #include #include // #include // #include #undef _DEBUG #define _DEBUG 509 #include #undef _TRACEN #define _TRACEN(msg) TRACEN( "SNC_point_locator: " << msg); // TODO: find out the proper CGAL replacement for this macro and remove it #define CGAL_for_each( i, C) for( i = C.begin(); i != C.end(); ++i) // #define TIMER(instruction) instruction #define TIMER(instruction) // #define CLOG(t) std::clog <<" "< class SNC_point_locator { public: class Intersection_call_back; typedef SNC_point_locator Self; protected: char version_[64]; // time for construction, point location, ray shooting and intersection test mutable Timer ct_t, pl_t, rs_t, it_t; public: #define USING(t) typedef typename SNC_structure::t t USING(Object_handle); USING(Vertex_handle); USING(Halfedge_handle); USING(Halffacet_handle); USING(Halffacet_triangle_handle); USING(Volume_handle); USING(Vertex_iterator); USING(Halfedge_iterator); USING(Halffacet_iterator); USING(Point_3); USING(Segment_3); USING(Ray_3); USING(Vector_3); USING(Triangle_3); USING(Aff_transformation_3); #undef USING const char* version() { return version_; } virtual Object_handle locate(const Point_3& p) const = 0; virtual Object_handle shoot(const Ray_3& s) const = 0; virtual void intersect_with_edges( Halfedge_handle edge, const Intersection_call_back& call_back) const = 0; virtual void intersect_with_facets( Halfedge_handle edge, const Intersection_call_back& call_back) const = 0; class Intersection_call_back { public: virtual void operator()( Halfedge_handle edge, Object_handle object, const Point_3& intersection_point) const = 0; }; virtual void initialize(SNC_structure* W) = 0; virtual Self* clone() const = 0; virtual void transform(const Aff_transformation_3& t) = 0; //virtual bool update( Unique_hash_map& V, // Unique_hash_map& E, // Unique_hash_map& F) = 0; virtual ~SNC_point_locator() { CLOG(""); CLOG("construction_time: "< class SNC_point_locator_by_spatial_subdivision : public SNC_point_locator, public SNC_decorator { typedef SNC_decorator Base; typedef SNC_decorator SNC_decorator; typedef SNC_point_locator SNC_point_locator; typedef SNC_point_locator_by_spatial_subdivision Self; typedef typename SNC_structure::Sphere_map Sphere_map; typedef SM_decorator SM_decorator; typedef SNC_intersection SNC_intersection; typedef typename SNC_structure::Kernel Kernel; public: typedef typename CGAL::SNC_k3_tree_traits K3_tree_traits; typedef typename CGAL::K3_tree K3_tree; typedef K3_tree SNC_candidate_provider; #define USING(t) typedef typename SNC_point_locator::t t USING(Object_handle); USING(Vertex_handle); USING(Halfedge_handle); USING(Halffacet_handle); USING(Halffacet_triangle_handle); USING(Vertex_iterator); USING(Halfedge_iterator); USING(Halffacet_iterator); USING(Volume_handle); USING(Point_3); USING(Segment_3); USING(Ray_3); USING(Vector_3); USING(Triangle_3); USING(Aff_transformation_3); #undef USING typedef typename SNC_candidate_provider::Object_list Object_list; typedef typename Object_list::iterator Object_list_iterator; typedef typename SNC_candidate_provider::Objects_along_ray Objects_along_ray; typedef typename Objects_along_ray::Iterator Objects_along_ray_iterator; public: SNC_point_locator_by_spatial_subdivision() : initialized(false), candidate_provider(0) {} virtual void initialize(SNC_structure* W) { TIMER(ct_t.start()); strcpy( version_, "Point Locator by Spatial Subdivision (tm)"); #ifdef CGAL_NEF3_TRIANGULATE_FACETS CLOG(version()<<" (with triangulated facets)"); #else CLOG(version()); #endif CGAL_assertion( W != NULL); Base::initialize(W); initialized = true; Object_list objects; Vertex_iterator v; Halfedge_iterator e; Halffacet_iterator f; CGAL_forall_vertices( v, *sncp()) objects.push_back(Object_handle(Vertex_handle(v))); CGAL_forall_edges( e, *sncp()) objects.push_back(Object_handle(Halfedge_handle(e))); CGAL_forall_facets( f, *sncp()) { #ifdef CGAL_NEF3_TRIANGULATE_FACETS typedef typename std::list Triangles; typedef typename Triangles::const_iterator Triangles_iterator; typedef Polygon_triangulation_traits_2 Triangulation_traits; Triangles triangles; triangulate_facet ( f, std::back_inserter(triangles), Triangulation_traits()); for( Triangles_iterator ti = triangles.begin(); ti != triangles.end(); ++ti) { Halffacet_triangle_handle th( f, *ti); objects.push_back(Object_handle(th)); CGAL_assertion( assign( th, *(--objects.end()))); CGAL_assertion( th.get_triangle() == *ti); } #else objects.push_back(Object_handle(Halffacet_handle(f))); #endif // CGAL_NEF3_TRIANGULATE_FACETS } candidate_provider = new SNC_candidate_provider(objects); //_TRACEN(*candidate_provider); TIMER(ct_t.stop()); } virtual Self* clone() const { return new Self; } virtual void transform(const Aff_transformation_3& t) { candidate_provider->transform(t); } virtual bool update( Unique_hash_map& V, Unique_hash_map& E, Unique_hash_map& F) { TIMER(ct_t.start()); CGAL_assertion( initialized); bool updated = candidate_provider->update( V, E, F); TIMER(ct_t.stop()); return updated; } virtual ~SNC_point_locator_by_spatial_subdivision() { CGAL_warning( initialized); // required? delete candidate_provider; } virtual Object_handle shoot(const Ray_3& ray) const { TIMER(rs_t.start()); CGAL_assertion( initialized); _TRACEN( "shooting: "<objects_along_ray(ray); Objects_along_ray_iterator objects_iterator = objects.begin(); while( !hit && objects_iterator != objects.end()) { Object_list candidates = *objects_iterator; Object_list_iterator o; CGAL_for_each( o, candidates) { if( assign( v, *o)) { _TRACEN("trying vertex on "<is_point_on_cell( q, objects_iterator)); if( !candidate_provider->is_point_on_cell( q, objects_iterator)) continue; eor = q; result = Object_handle(e); hit = true; _TRACEN("the edge becomes the new hit object"); } } else if( assign( f, *o)) { Point_3 q; _TRACEN("trying facet with on plane "<is_point_on_cell( q, objects_iterator)); if( !candidate_provider->is_point_on_cell( q, objects_iterator)) continue; eor = q; result = Object_handle(f); hit = true; _TRACEN("the facet becomes the new hit object"); } } else if( assign( t, *o)) { Point_3 q; Triangle_3 tr = t.get_triangle(); _TRACEN("trying triangle "<is_point_on_cell(q,objects_iterator)); if( !candidate_provider->is_point_on_cell( q, objects_iterator)) continue; eor = q; result = Object_handle(Halffacet_handle(t)); hit = true; _TRACEN("the facet becomes the new hit object"); } } else CGAL_assertion_msg( 0, "wrong handle"); } if(!hit) ++objects_iterator; } TIMER(rs_t.stop()); return result; } virtual Object_handle locate( const Point_3& p) const { TIMER(pl_t.start()); CGAL_assertion( initialized); _TRACEN( "locate "<objects_around_point(p); Object_list_iterator o = candidates.begin(); bool found = false; while( !found && o != candidates.end()) { if( assign( v, *o)) { if ( p == point(v)) { _TRACEN("found on vertex "<objects_around_segment(s); CGAL_for_each( o, objects) { if( assign( v, *o)) { /* do nothing */ } else if( assign( e, *o)) { Point_3 q; if( is.does_intersect_internally( s, segment(e), q)) { q = normalized(q); call_back( e0, Object_handle(e), q); _TRACEN("edge intersects edge "<<' '<<&*e< f_mark(false); #endif // CGAL_NEF3_TRIANGULATE_FACETS Segment_3 s(segment(e0)); Vertex_handle v; Halfedge_handle e; Halffacet_handle f; Halffacet_triangle_handle t; Object_list_iterator o; Object_list objects = candidate_provider->objects_around_segment(s); CGAL_for_each( o, objects) { if( assign( v, *o)) { /* do nothing */ } else if( assign( e, *o)) { /* do nothing */ } else if( assign( f, *o)) { Point_3 q; if( is.does_intersect_internally( s, f, q) ) { q = normalized(q); call_back( e0, Object_handle(f), q); _TRACEN("edge intersects facet on plane "< triangulation; }; template class SNC_point_locator_naive : public SNC_ray_shooter, public SNC_point_locator { typedef SNC_ray_shooter Base; typedef SNC_point_locator_naive Self; typedef SNC_point_locator SNC_point_locator; typedef SNC_intersection SNC_intersection; public: #define USING(t) typedef typename SNC_point_locator::t t USING(Object_handle); USING(Vertex_handle); USING(Halfedge_handle); USING(Halffacet_handle); USING(Volume_handle); USING(Vertex_iterator); USING(Halfedge_iterator); USING(Halffacet_iterator); USING(Point_3); USING(Segment_3); USING(Ray_3); USING(Triangle_3); #undef USING public: SNC_point_locator_naive() : initialized(false) {} virtual void initialize(SNC_structure* W) { TIMER(ct_t.start()); strcpy( version_, "Naive Point Locator (tm)"); CLOG(version()); CGAL_assertion( W != NULL); Base::initialize(W); initialized = true; TIMER(ct_t.stop()); } virtual Self* clone() const { return new Self; } virtual bool update( Unique_hash_map& V, Unique_hash_map& E, Unique_hash_map& F) { TIMER(ct_t.start()); CGAL_assertion( initialized); TIMER(ct_t.stop()); return false; } virtual ~SNC_point_locator_naive() {} virtual Object_handle locate(const Point_3& p) const { TIMER(pl_t.start()); CGAL_assertion( initialized); TIMER(pl_t.stop()); return Base::locate(p); } virtual Object_handle shoot(const Ray_3& r) const { TIMER(rs_t.start()); CGAL_assertion( initialized); TIMER(rs_t.stop()); return Base::shoot(r); } virtual void intersect_with_edges( Halfedge_handle e0, const typename SNC_point_locator::Intersection_call_back& call_back) const { TIMER(it_t.start()); CGAL_assertion( initialized); TRACEN( "intersecting edge: "<