// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Nef_3/include/CGAL/Nef_3/SNC_intersection.h $ // $Id: SNC_intersection.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Michael Seel // Peter Hachenberger #ifndef CGAL_SNC_INTERSECTION_H #define CGAL_SNC_INTERSECTION_H #include #include #undef CGAL_NEF_DEBUG #define CGAL_NEF_DEBUG 37 #include namespace CGAL { template < class Node, class Object> struct Project_shalfedge_point { typedef Node argument_type; typedef Object result_type; Object& operator()( Node& x) const { return x.source()->source()->point(); /* a Point_3& reference must be returned by D.point() */ } const Object& operator()( const Node& x) const { return x.source()->source()->point(); /* a Point_3& reference must be returned by D.point() */ } }; template class SNC_intersection : public SNC_const_decorator { // TODO: granados: is it really necessary to inherit from the decorator? typedef SNC_structure_ SNC_structure; typedef SNC_intersection Self; typedef SNC_const_decorator Base; // typedef SNC_const_decorator SNC_const_decorator; typedef typename SNC_structure::SHalfedge SHalfedge; typedef typename SNC_structure::Halfedge_handle Halfedge_handle; typedef typename SNC_structure::Halffacet_const_handle Halffacet_const_handle; typedef typename SNC_structure::SHalfedge_const_handle SHalfedge_const_handle; typedef typename SNC_structure::SHalfloop_const_handle SHalfloop_const_handle; typedef typename SNC_structure::SHalfedge_around_facet_const_circulator SHalfedge_around_facet_const_circulator; typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; #ifdef CGAL_NEF3_FACET_WITH_BOX typedef typename SNC_structure::Partial_facet Partial_facet; #endif typedef typename SNC_structure::Point_3 Point_3; typedef typename SNC_structure::Vector_3 Vector_3; typedef typename SNC_structure::Segment_3 Segment_3; typedef typename SNC_structure::Line_3 Line_3; typedef typename SNC_structure::Ray_3 Ray_3; typedef typename SNC_structure::Plane_3 Plane_3; typedef typename SNC_structure::Triangle_3 Triangle_3; public: SNC_intersection() : Base() {} SNC_intersection(const SNC_structure& W) : Base(W) {} bool does_contain_internally(const Segment_3& s, const Point_3& p) const { if(!are_strictly_ordered_along_line (s.source(), p, s.target())) return false; if(!s.supporting_line().has_on(p)) return false; return true; } bool does_contain_internally( Halffacet_const_handle f, const Point_3& p, bool check_has_on = true) const { if(check_has_on && !f->plane().has_on(p)) return false; return (locate_point_in_halffacet( p, f) == CGAL::ON_BOUNDED_SIDE); } #ifdef CGAL_NEF3_FACET_WITH_BOX bool does_contain_internally( Partial_facet& pf, const Point_3& p) const { CGAL_NEF_TRACEN("does point lie in partial facet" << p); // pf.debug(); if( !pf.f->plane().has_on(p)) return false; return (locate_point_in_halffacet( p, pf) == CGAL::ON_BOUNDED_SIDE); } #endif bool does_contain_on_boundary( Halffacet_const_handle f, const Point_3& p) const { typedef Project_shalfedge_point < SHalfedge, const Point_3> Project; typedef Circulator_project < SHalfedge_around_facet_const_circulator, Project, const Point_3&, const Point_3*> Circulator; Halffacet_cycle_const_iterator fc = f->facet_cycles_begin(); CGAL_assertion(fc.is_shalfedge()); if (fc.is_shalfedge() ) { SHalfedge_const_handle se(fc); SHalfedge_around_facet_const_circulator hfc(se); Circulator c(hfc), cp(c), cend(c); do { c++; CGAL_NEF_TRACEN("contained on edge "<facet_cycles_end(); ++fc; CGAL_For_all(fc, fe) { if (fc.is_shalfloop() ) { SHalfloop_const_handle l(fc); CGAL_NEF_TRACEN("isolated point on "<incident_sface()->center_vertex()->point()<<"? "); if( l->incident_sface()->center_vertex()->point() == p) return true; } else if (fc.is_shalfedge() ) { SHalfedge_const_handle se(fc); SHalfedge_around_facet_const_circulator hfc(se); Circulator c(hfc), cp(c), cend(c); do { c++; CGAL_NEF_TRACEN("contained on edge "< Intersection triangle - ray"); CGAL_NEF_TRACEN(" -> Ray: "< Triangle: "< intersection point: "< Intersection triangle - segment"); CGAL_NEF_TRACEN(" -> Segment: "< Triangle: "< intersection point: "< Intersection facet - ray"); Plane_3 h( f->plane()); CGAL_NEF_TRACEN("-> facet's plane: " << h); CGAL_NEF_TRACEN("-> a point on the plane: " << h.point()); CGAL_NEF_TRACEN("-> ray: " << ray); CGAL_assertion(!ray.is_degenerate()); if(checkHasOn) { if(h.has_on(ray.source())) return false; } else CGAL_assertion(!h.has_on(ray.source())); Object o = intersection( h, ray); if( !CGAL::assign( p, o)) return false; CGAL_NEF_TRACEN( "-> intersection point: " << p ); CGAL_NEF_TRACEN( "-> point in facet interior? "< Intersection facet - ray"); Plane_3 h( pf.f->plane()); CGAL_NEF_TRACEN("-> facet's plane: " << h); CGAL_NEF_TRACEN("-> a point on the plane: " << h.point()); CGAL_NEF_TRACEN("-> ray: " << ray); CGAL_assertion(!ray.is_degenerate()); if( h.has_on( ray.source())) /* no possible internal intersection */ return false; Object o = intersection( h, ray); if( !CGAL::assign( p, o)) return false; CGAL_NEF_TRACEN( "-> intersection point: " << p ); // CGAL_NEF_TRACEN( "-> point in facet interior? "< Intersection facet - segment"); Plane_3 h( f->plane()); CGAL_NEF_TRACEN("-> facet's plane: " << h); CGAL_NEF_TRACEN("-> a point on the plane: " << h.point()); CGAL_NEF_TRACEN("-> segment: " << seg); CGAL_assertion(!seg.is_degenerate()); if( h.has_on( seg.source()) || h.has_on(seg.target())) /* no possible internal intersection */ return false; return does_intersect(seg, f, p); } bool does_intersect(const Segment_3& seg, Halffacet_const_handle f, Point_3& p) const { Plane_3 h( f->plane()); Object o = intersection( h, seg); if( !CGAL::assign( p, o)) return false; CGAL_NEF_TRACEN( "-> intersection point: " << p ); CGAL_NEF_TRACEN( "-> point in facet interior? "< Intersection partial facet - segment"); Plane_3 h( pf.f->plane()); CGAL_NEF_TRACEN("-> facet's plane: " << h); CGAL_NEF_TRACEN("-> a point on the plane: " << h.point()); CGAL_NEF_TRACEN("-> segment: " << seg); CGAL_assertion(!seg.is_degenerate()); if( h.has_on( seg.source()) || h.has_on(seg.target())) /* no possible internal intersection */ return false; Object o = intersection( h, seg); if( !CGAL::assign( p, o)) return false; CGAL_NEF_TRACEN( "-> intersection point: " << p ); // CGAL_NEF_TRACEN( "-> point in facet interior? "<plane()); typedef Project_shalfedge_point < SHalfedge, const Point_3> Project; typedef Circulator_project < SHalfedge_around_facet_const_circulator, Project, const Point_3&, const Point_3*> Circulator; typedef Container_from_circulator Container; Plane_3 h(f->plane()); CGAL_assertion(h.has_on(p)); Halffacet_cycle_const_iterator fc = f->facet_cycles_begin(); Bounded_side outer_bound_pos(CGAL::ON_BOUNDARY); if (fc.is_shalfedge() ) { SHalfedge_const_handle se(fc); SHalfedge_around_facet_const_circulator hfc(se); Circulator c(hfc); Container ct(c); CGAL_assertion( !is_empty_range(ct.begin(), ct.end())); outer_bound_pos = bounded_side_3(ct.begin(), ct.end(), p, h); } else CGAL_error_msg( "is facet first cycle a SHalfloop?"); if( outer_bound_pos != CGAL::ON_BOUNDED_SIDE ) return outer_bound_pos; /* The point p is not in the relative interior of the outer face cycle so it is not necesary to know the possition of p with respect to the inner face cycles */ Halffacet_cycle_const_iterator fe = f->facet_cycles_end(); ++fc; if( fc == fe ) return outer_bound_pos; Bounded_side inner_bound_pos(CGAL::ON_BOUNDARY); CGAL_For_all(fc, fe) { if (fc.is_shalfloop() ) { SHalfloop_const_handle l(fc); if(l->incident_sface()->center_vertex()->point() == p ) inner_bound_pos = CGAL::ON_BOUNDARY; else inner_bound_pos = CGAL::ON_UNBOUNDED_SIDE; } else if (fc.is_shalfedge() ) { SHalfedge_const_handle se(fc); SHalfedge_around_facet_const_circulator hfc(se); Circulator c(hfc); Container ct(c); CGAL_assertion( !is_empty_range(ct.begin(), ct.end())); inner_bound_pos = bounded_side_3( ct.begin(), ct.end(), p, h.opposite()); } else CGAL_error_msg( "Damn wrong handle."); if( inner_bound_pos != CGAL::ON_UNBOUNDED_SIDE ) return opposite(inner_bound_pos); /* At this point the point p belongs to relative interior of the facet's outer cycle, and its possition is completely known when it belongs to the clousure of any inner cycle */ } return CGAL::ON_BOUNDED_SIDE; } #ifdef CGAL_NEF3_FACET_WITH_BOX Bounded_side locate_point_in_halffacet( const Point_3& p, Partial_facet pf) const { if(p.x() < pf.f->b.min_coord(0) || p.x() > pf.f->b.max_coord(0) || p.y() < pf.f->b.min_coord(1) || p.y() > pf.f->b.max_coord(1) || p.z() < pf.f->b.min_coord(2) || p.z() > pf.f->b.max_coord(2)) return CGAL::ON_UNBOUNDED_SIDE; typedef Project_shalfedge_point < SHalfedge, Point_3> Project; typedef Circulator_project < SHalfedge_around_facet_const_circulator, Project, const Point_3&, const Point_3*> Circulator; typedef Container_from_circulator Container; typedef typename Partial_facet::Outer_cycle_iterator Outer_cycle_iterator; typedef typename Partial_facet::Inner_cycle_iterator Inner_cycle_iterator; typedef typename Partial_facet::Isolated_vertex_iterator Isolated_vertex_iterator; Plane_3 h(pf.f->plane()); CGAL_assertion(h.has_on(p)); Bounded_side outer_bound_pos(CGAL::ON_BOUNDED_SIDE); Outer_cycle_iterator oc = pf.outer_cycles_begin(); while(oc != pf.outer_cycles_end() && outer_bound_pos == CGAL::ON_BOUNDED_SIDE) { if(oc->first == oc->second) { SHalfedge_around_facet_const_circulator hfc(oc->first); Circulator c(hfc); Container ct(c); CGAL_assertion( !is_empty_range(ct.begin(), ct.end())); outer_bound_pos = bounded_side_3(ct.begin(), ct.end(), p, h); } else { outer_bound_pos = bounded_side_3(Circulator(SHalfedge_around_facet_const_circulator(oc->first)), Circulator(SHalfedge_around_facet_const_circulator(oc->second)), p, h); } ++oc; } if(outer_bound_pos != CGAL::ON_BOUNDED_SIDE ) return outer_bound_pos; Bounded_side inner_bound_pos(CGAL::ON_UNBOUNDED_SIDE); Inner_cycle_iterator ic = pf.inner_cycles_begin(); while(ic != pf.inner_cycles_end() && inner_bound_pos == CGAL::ON_UNBOUNDED_SIDE) { if(ic->first == ic->second) { SHalfedge_around_facet_const_circulator hfc(ic->first); Circulator c(hfc); Container ct(c); CGAL_assertion( !is_empty_range(ct.begin(), ct.end())); inner_bound_pos = bounded_side_3(ct.begin(), ct.end(), p, h); } else { inner_bound_pos = bounded_side_3(Circulator(SHalfedge_around_facet_const_circulator(ic->first)), Circulator(SHalfedge_around_facet_const_circulator(ic->second)), p, h); } ++ic; } if(inner_bound_pos != CGAL::ON_UNBOUNDED_SIDE ) return opposite(inner_bound_pos); Isolated_vertex_iterator iv = pf.isolated_vertices_begin(); while(iv != pf.isolated_vertices_end()) { if(*iv == p) return CGAL::ON_BOUNDARY; ++iv; } return CGAL::ON_BOUNDED_SIDE; } #endif }; // SNC_intersection } //namespace CGAL #endif //CGAL_SNC_INTERSECTION_H