diff --git a/Packages/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h b/Packages/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h index 868800d08c3..a1b8a0c167b 100644 --- a/Packages/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h +++ b/Packages/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h @@ -1,192 +1,454 @@ -// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org); you may redistribute it under -// the terms of the Q Public License version 1.0. -// See the file LICENSE.QPL distributed with CGAL. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $Source$ -// $Revision$ $Date$ -// $Name$ -// -// Author(s) : Michael Seel -// Miguel Granados -// Susan Hert -// Lutz Kettner -//#ifndef CGAL_SNC_POINT_LOCATOR_H -#ifdef CGAL_NEF3_DEPRECATED_CLASS -#error funcionality now provided by SNC_ray_shoter.h -#define CGAL_SNC_POINT_LOCATOR_H +#line 7 "point_locator.nw" +#ifndef SNC_POINT_LOCATOR_H +#define SNC_POINT_LOCATOR_H #include -#include -#include -#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); + +#define CGAL_for_each( i, C) for( i = C.begin(); i != C.end(); ++i) +// TODO: find out the CGAL replacement for this macro and remove it CGAL_BEGIN_NAMESPACE -template -class SNC_point_locator : public SNC_decorator -{ +template +class SNC_point_locator +{ + class Intersection_call_back; + typedef SNC_point_locator Self; + typedef typename SNC_structure::Object_handle Object_handle; + typedef typename SNC_structure::Vertex_handle Vertex_handle; + typedef typename SNC_structure::Halfedge_handle Halfedge_handle; + typedef typename SNC_structure::Halffacet_handle Halffacet_handle; + typedef typename SNC_structure::Point_3 Point_3; + typedef typename SNC_structure::Segment_3 Segment_3; + typedef typename SNC_structure::Ray_3 Ray_3; public: - typedef SNC_ SNC_structure; - typedef SNC_point_locator Self; - typedef CGAL::SNC_decorator Base; - typedef CGAL::SNC_constructor SNC_constructor; - typedef CGAL::SNC_FM_decorator FM_decorator; - typedef CGAL::SNC_SM_decorator SM_decorator; - typedef CGAL::SNC_SM_point_locator SM_point_locator; + 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 Self* copy() const = 0; + virtual bool update( Unique_hash_map& V, + Unique_hash_map& E, + Unique_hash_map& F) = 0; + virtual ~SNC_point_locator() {}; +}; -#define USING(t) typedef typename Base::t t - USING(Vertex_iterator); USING(Vertex_handle); - USING(Halfedge_iterator); USING(Halfedge_handle); - USING(Halffacet_iterator); USING(Halffacet_handle); - USING(Volume_iterator); USING(Volume_handle); - USING(SVertex_iterator); USING(SVertex_handle); - USING(SHalfedge_iterator); USING(SHalfedge_handle); - USING(SHalfloop_iterator); USING(SHalfloop_handle); - USING(SFace_iterator); USING(SFace_handle); +template +class SNC_point_locator_by_spatial_subdivision : + public SNC_point_locator, + public SNC_decorator +{ + typedef SNC_decorator Base; + typedef SNC_point_locator SNC_point_locator; + typedef SNC_decorator SNC_decorator; + typedef SNC_point_locator_by_spatial_subdivision Self; + typedef SNC_SM_decorator SM_decorator; + typedef SNC_intersection SNC_intersection; + + typedef typename CGAL::SNC_k3_tree_traits K3_tree_traits; + typedef typename CGAL::K3_tree K3_tree; + typedef K3_tree SNC_candidate_provider; + + 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; + + #define USING(t) typedef typename SNC_structure::t t USING(Object_handle); - USING(SObject_handle); - USING(SFace_cycle_iterator); - USING(Halffacet_cycle_iterator); - USING(Shell_entry_iterator); - USING(SHalfedge_around_facet_circulator); + 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(Plane_3); - USING(Vector_3); - USING(Line_3); - USING(Sphere_point); - USING(Sphere_segment); - USING(Sphere_circle); - USING(Mark); -#undef USING - typedef void* GenPtr; + USING(Ray_3); + USING(Direction_3); + #undef USING - SNC_point_locator(SNC_structure& W) : Base(W) {} + bool initialized; - typename SNC_::Object_handle locate(const Point_3& p) const; - typename SNC_::Halffacet_handle get_facet_below(const Vertex_handle& vi) - const; - - void shorten(Segment_3& s, const Point_3& p) const - { s = Segment_3(s.source(),p); } - - bool contains_internally(const Segment_3& s, const Point_3& p) const - { CGAL_nef3_assertion(s.has_on(p)); - CGAL::Comparison_result r1 = compare_xyz(s.source(),p); - CGAL::Comparison_result r2 = compare_xyz(s.target(),p); - return (r1 == opposite(r2)); +public: + SNC_point_locator_by_spatial_subdivision() : initialized(false) {} + virtual void initialize(SNC_structure* W) { + CGAL_assertion( W != NULL); + Base::initialize(W); + initialized = true; + Object_list objects; + Vertex_iterator v; + Halfedge_iterator e; + Halffacet_iterator f; + CGAL_nef3_forall_vertices( v, *sncp()) + objects.push_back(Object_handle(Vertex_handle(v))); + CGAL_nef3_forall_edges( e, *sncp()) + objects.push_back(Object_handle(Halfedge_handle(e))); + CGAL_nef3_forall_facets( f, *sncp()) + objects.push_back(Object_handle(Halffacet_handle(f))); + candidate_provider = new SNC_candidate_provider(objects); + _TRACEN(*candidate_provider); } - bool do_intersect(const Segment_3& s, - Halfedge_handle e, - Point_3& p) const - { CGAL::Object o = CGAL::intersection(Line_3(s),Line_3(segment(e))); - if ( !CGAL::assign(p,o) ) return false; - CGAL::Oriented_side os1 = h.oriented_side(s.source()); - CGAL::Oriented_side os2 = h.oriented_side(s.target()); - return (os1 == CGAL::opposite(os2)); + virtual Self* clone() const { + return new Self; + } + /* + virtual Self* copy() const { + CGAL_assertion( initialized); + Self *pl_copy = new Self; + pl_copy->initialize(sncp()); + return pl_copy; + } + */ + virtual bool update( Unique_hash_map& V, + Unique_hash_map& E, + Unique_hash_map& F) { + CGAL_assertion( initialized); + _TRACEN( *candidate_provider); + bool updated = candidate_provider->update( V, E, F); + _TRACEN( *candidate_provider); + return updated; + } + virtual ~SNC_point_locator_by_spatial_subdivision() { + CGAL_assertion( initialized); + delete candidate_provider; } - bool do_intersect(const Segment_3& s, - Halffacet_handle f, - Point_3& p) const - { Plane_3 h(plane(f)); - CGAL::Object o = CGAL::intersection(h, Line_3(s)); - if ( !CGAL::assign(p,o) ) return false; - CGAL::Oriented_side os1 = h.oriented_side(s.source()); - CGAL::Oriented_side os2 = h.oriented_side(s.target()); - return (os1 == CGAL::opposite(os2)); + virtual Object_handle shoot(const Ray_3& ray) const { + 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)) // TODO: hide the node + continue; + if( !hit || + has_smaller_distance_to_point( ray.source(), q, end_of_seg)) { + end_of_seg = 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; + if( !hit || + has_smaller_distance_to_point( ray.source(), q, end_of_seg)) { + end_of_seg = q; + result = Object_handle(f); + hit = true; + _TRACEN("the facet becomes the new hit object"); + } + } + } + else + CGAL_nef3_assertion_msg( 0, "wrong handle"); + } + if(!hit) + ++objects_iterator; + } + return result; } + virtual Object_handle locate( const Point_3& p) const { + CGAL_assertion( initialized); + _TRACEN( "locate "<objects_around_point(p); + Object_list_iterator o; + CGAL_for_each( o, candidates) { + if( assign( v, *o)) { + if ( p == point(v)) { + _TRACEN("found on vertex"< + // TODO: here, the vertex to choose should be contained in the same cell + // where the query point is located, or, if there is not vertex on the + // cell, then the volume containing the cell should be available in the + // tree structure and so immediately reported + _TRACEN("shooting ray to determine the volume"); + Ray_3 r( p, Direction_3( -1, 0, 0)); + return Object_handle(determine_volume(r)); + } + virtual void intersect_with_edges( Halfedge_handle e0, + const typename SNC_point_locator::Intersection_call_back& call_back) const { + CGAL_assertion( initialized); + _TRACEN( "intersecting edge: "<<&*e0<<' '<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<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 "< -typename SNC_::Object_handle -SNC_point_locator::locate(const Point_3& p) const +private: + Volume_handle determine_volume( const Ray_3& ray) const { + Halffacet_handle f_below; + Object_handle o = shoot(ray); + Vertex_handle v; + Halfedge_handle e; + Halffacet_handle f; + if( assign( v, o)) { + _TRACEN("vertex hit, obtaining volume..."); + f_below = get_visible_facet( v, ray); + if( f_below != Halffacet_handle()) + return volume(f_below); + SM_decorator SD(v); // now, the vertex has no incident facets + CGAL_nef3_assertion( SD.number_of_sfaces() == 1); + return volume(SD.sfaces_begin()); + } + else if( assign( e, o)) { + _TRACEN("edge hit, obtaining volume..."); + f_below = get_visible_facet( e, ray); + if( f_below != Halffacet_handle()) + return volume(f_below); + SM_decorator SD(source(e)); // now, the edge has no incident facets + CGAL_nef3_assertion(SD.is_isolated(e)); + return volume(sface(e)); + } + else if( assign( f, o)) { + _TRACEN("facet hit, obtaining volume..."); + f_below = get_visible_facet(f, ray); + CGAL_nef3_assertion( f_below != Halffacet_handle()); + return volume(f_below); + } + return Base(*this).volumes_begin(); // TODO: Comment this hack! + } + +private: + SNC_candidate_provider* candidate_provider; + SNC_intersection is; +}; + +template +class SNC_point_locator_naive : + public SNC_ray_shooter, + public SNC_point_locator { - if ( number_of_vertices() == 0 ) return Object_handle(); - // now not empty: + typedef SNC_ray_shooter Base; + typedef SNC_point_locator_naive Self; + typedef SNC_point_locator SNC_point_locator; + typedef SNC_intersection SNC_intersection; + typedef typename SNC_structure::Object_handle Object_handle; + typedef typename SNC_structure::Point_3 Point_3; + typedef typename SNC_structure::Segment_3 Segment_3; + typedef typename SNC_structure::Ray_3 Ray_3; + typedef typename SNC_structure::Vertex_handle Vertex_handle; + typedef typename SNC_structure::Halfedge_handle Halfedge_handle; + typedef typename SNC_structure::Halffacet_handle Halffacet_handle; + typedef typename SNC_structure::Vertex_iterator Vertex_iterator; + typedef typename SNC_structure::Halfedge_iterator Halfedge_iterator; + typedef typename SNC_structure::Halffacet_iterator Halffacet_iterator; - Vertex_iterator v; - CGAL_nef3_forall_vertices(v,*sncp()) - if ( p == point(v) ) return Object_handle(v); + bool initialized; - Halfedge_iterator e; - CGAL_nef3_forall_edges(e,*sncp()) - if ( segment(e).constains(p) ) return Object_handle(e); - - Halffacet_iterator f; - CGAL_nef3_forall_halffacets(f,*sncp()) { // nur ufacets - FM_decorator D(f); - if ( D.facet_contains(p) ) return Object_handle(f); - } - // now not contained in any boundary object: - - Segment_3 s(p, point(vertices_begin())), so(s.opposite()); - Object_handle closest(vertices_begin()); - CGAL_nef3_forall_vertices(v,*sncp()) - if ( s.has_on(point(v)) ) - { shorten(s,point(v)); closest=Object_handle(v); } - CGAL_nef3_forall_edges(e,*sncp()) { - Point_3 q; - if ( do_intersect(s,e,q) ) - { shorten(s,q); closest=Object_handle(e); } - } - CGAL_nef3_forall_halffacets(f,*sncp()) { - Point_3 q; - if ( do_intersect(s,f,q) ) - { shorten(s,q); closest=Object_handle(f); } +public: + SNC_point_locator_naive() : initialized(false) {} + virtual void initialize(SNC_structure* W) { + CGAL_assertion( W != NULL); + Base::initialize(W); + initialized = true; } - // now closest holds the closest boundary object that - // contains the point s.target() : + virtual Self* clone() const { + return new Self; + } + /* + virtual Self* copy() const { + CGAL_assertion( initialized); + Self *pl_copy = new Self; + pl_copy->initialize(sncp()); + return pl_copy; + } + */ + virtual bool update( Unique_hash_map& V, + Unique_hash_map& E, + Unique_hash_map& F) { + CGAL_assertion( initialized); + return false; + } - if ( CGAL::assign(v,closest) ) { - SM_point_locator L(v); - Sphere_point pl(so.direction()); - SObject_handle o = L.locate(pl); - SFace_handle f; - if ( !CGAL::assign(f,o) ) CGAL_nef3_assertion_msg(0,"Must be sface."); - /* v is the closest object and therefore the view towards p must - be an sface */ - return Object_handle(volume(f)); - } else if ( CGAL::assign(e,closest) ) { - SNC_constructor C(*sncp()); - Vertex_handle v_tmp = C.create_from_edge(e,s.target()); - SM_point_locator L(v_tmp); - Sphere_point pl(so.direction()); - SObject_handle o = L.locate(pl); - SFace_handle f; - if ( !CGAL::assign(f,o) ) CGAL_nef3_assertion_msg(0,"Must be sface."); - /* e is the closest object and therefore the view towards p must - be an sface */ - return Object_handle(volume(f)); - } else if ( CGAL::assign(f,closest) ) { - // sideness correction necessary: - if ( plane(f).has_on_negative_side(p) ) f = twin(f); - CGAL_nef3_assertion( plane(f).has_on_positive_side(p) ); - return Object_handle(volume(f)); - } else CGAL_nef3_assertion_msg(0,"damn generic handles."); - return Object_handle(); // never reached -} + virtual ~SNC_point_locator_naive() {} + + Object_handle locate(const Point_3& p) const { + CGAL_assertion( initialized); + return Base::locate(p); + } + Object_handle shoot(const Ray_3& r) const { + CGAL_assertion( initialized); + return Base::shoot(r); + } + + void intersect_with_edges( Halfedge_handle e0, + const typename SNC_point_locator::Intersection_call_back& call_back) const { + CGAL_assertion( initialized); + TRACEN( "intersecting edge: "<