// ============================================================================ // // Copyright (c) 2001 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------------- // // release : $CGAL_Revision $ // release_date : $CGAL_Date $ // // file : include/CGAL/convexity_check_3.h // package : $CGAL_Package: Convex_hull_3 $ // maintainer : Susan Hert // chapter : Convex Hulls and Extreme Points // // revision : $Revision$ // revision_date : $Date$ // // author(s) : Susan Hert // : Amol Prakash // // coordinator : MPI (Susan Hert ) // // implementation: functions for testing validity of convex hulls // ============================================================================ #ifndef CGAL_CONVEXITY_CHECK_3_H #define CGAL_CONVEXITY_CHECK_3_H #include namespace CGAL { template bool is_locally_convex(Facet_handle f_hdl, const Traits& traits) { // This function checks if all the faces around facet *f_hdl form part of // the convex hull typedef typename Facet_handle::value_type Facet; typedef typename Facet::Halfedge_around_facet_circulator Halfedge_circ; typedef typename Traits::Point_3 Point_3; typename Traits::Has_on_positive_side_3 has_on_positive_side = traits.has_on_positive_side_3_object(); Halfedge_circ h_circ = (*f_hdl).facet_begin(); do { // Take the point on the other facet not shared by this facet Point_3 point= h_circ->opposite()->next()->vertex()->point(); // Point must be on the plane or on the negative side if (has_on_positive_side((*f_hdl).plane(), point)) return false; h_circ++; } while ( h_circ != (*f_hdl).facet_begin()); return true; } // Pre: equations of facet planes have been computed template bool is_strongly_convex_3(Polyhedron& P, const Traits& traits) { typedef typename Polyhedron::Facet_iterator Facet_iterator; typedef typename Polyhedron::Vertex_iterator Vertex_iterator; typedef typename Traits::Point_3 Point_3; typedef typename Traits::Ray_3 Ray_3; typedef typename Traits::Triangle_3 Triangle_3; if (P.vertices_begin() == P.vertices_end()) return false; Facet_iterator f_it; for ( f_it = P.facets_begin(); f_it != P.facets_end(); ++f_it) if (!is_locally_convex(f_it, traits)) return false; // Check 2: see if a point interior to the hull is actually on the same // side of each facet of P typename Traits::Coplanar_3 coplanar = traits.coplanar_3_object(); Vertex_iterator v_it = P.vertices_begin(); Point_3 p; Point_3 q; Point_3 r; Point_3 s; // First take 3 arbitrary points p = v_it->point(); v_it++; q = v_it->point(); v_it++; r = v_it->point(); v_it++; // three vertices that form a single (triangular) facet if (v_it == P.vertices_end()) return P.facets_begin() != P.facets_end(); // Now take 4th point s.t. it's not coplaner with them while (v_it != P.vertices_end() && coplanar(p, q, r, (*v_it).point())) v_it++; // if no such point, all are coplanar so it is not strongly convex if( v_it == P.vertices_end() ) return false; s = (*v_it).point(); // else construct a point inside the polyhedron typename Traits::Construct_centroid_3 construct_centroid = traits.construct_centroid_3_object(); Point_3 inside_pt = construct_centroid(p,q,r,s); typename Traits::Oriented_side_3 oriented_side = traits.oriented_side_3_object(); f_it = P.facets_begin(); Oriented_side side = oriented_side(f_it->plane(), inside_pt); // the point inside should not be on the facet plane if (side == ON_ORIENTED_BOUNDARY) return false; // now make sure this point that is inside the polyhedron is on the same // side of each facet for (f_it++; f_it != P.facets_end(); f_it++) { if ( oriented_side(f_it->plane(), inside_pt) != side ) return false; } // Check 3 : see if a ray from the interior point to a point in the // middle of one of the facets intersects any other facets typename Traits::Construct_ray_3 construct_ray = traits.construct_ray_3_object(); typename Traits::Construct_triangle_3 construct_triangle = traits.construct_triangle_3_object(); typename Traits::Intersect_3 intersect = traits.intersect_3_object(); typename Traits::Has_on_3 has_on = traits.has_on_3_object(); f_it = P.facets_begin(); Point_3 facet_pt = construct_centroid(f_it->halfedge()->opposite()->vertex()->point(), f_it->halfedge()->vertex()->point(), f_it->halfedge()->next()->vertex()->point()); Ray_3 ray = construct_ray(inside_pt, facet_pt); Point_3 i_point; Point_3 i_ray; for ( ++f_it ; f_it != P.facets_end(); f_it++) { Object obj = intersection(f_it->plane(), ray); if (assign(i_point, obj)) // ray may intersect facet plane but not facet { Triangle_3 facet_tri = construct_triangle(f_it->halfedge()->opposite()->vertex()->point(), f_it->halfedge()->vertex()->point(), f_it->halfedge()->next()->vertex()->point()); if (has_on(facet_tri, i_point)) return false; } else if (assign(i_ray, obj)) // ray should not lie on a facet plane return false; } return true; } template bool CGAL_is_strongly_convex_3(Polyhedron& P, Point_3*) { return is_strongly_convex_3(P, R()); } template bool is_strongly_convex_3(Polyhedron& P) { typedef typename Polyhedron::Point_3 Point_3; return CGAL_is_strongly_convex_3(P, reinterpret_cast(0)); } template bool all_points_inside( ForwardIterator first, ForwardIterator last, Polyhedron& P, const Traits& traits) { typedef typename Polyhedron::Facet_iterator Facet_iterator; typename Traits::Has_on_positive_side_3 has_on_positive_side = traits.has_on_positive_side_3_object(); for (ForwardIterator p_it = first; p_it != last; p_it++) { Facet_iterator f_it; for (f_it = P.facets_begin(); f_it != P.facets_end(); f_it++) { if (has_on_positive_side(f_it->plane(),*p_it)) return false; } } return true; } } // namespace CGAL #endif // CGAL_CONVEXITY_CHECK_3_H