diff --git a/Convex_hull_3/doc/Convex_hull_3/CGAL/Convex_hull_traits_3.h b/Convex_hull_3/doc/Convex_hull_3/CGAL/Convex_hull_traits_3.h index 8ba87fd6ed1..c03fa746511 100644 --- a/Convex_hull_3/doc/Convex_hull_3/CGAL/Convex_hull_traits_3.h +++ b/Convex_hull_3/doc/Convex_hull_3/CGAL/Convex_hull_traits_3.h @@ -98,6 +98,11 @@ unspecified_type Has_on_positive_side_3; /*! +*/ +unspecified_type Has_on_negative_side_3; + +/*! + */ unspecified_type Less_signed_distance_to_plane_3; diff --git a/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h b/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h index 9b857d2165c..e4d4af444c1 100644 --- a/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h +++ b/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h @@ -84,6 +84,13 @@ Predicate object type that provides `q` is on the positive side of the halfspace `h`. */ typedef unspecified_type Has_on_positive_side_3; + + /*! + Predicate object type that provides + `bool operator()(Plane_3 h, Point_3 q)`, which determines if the point + `q` is on the negative side of the halfspace `h`. + */ + typedef unspecified_type Has_on_negative_side_3; /*! Predicate object type that provides diff --git a/Convex_hull_3/include/CGAL/Convex_hull_traits_3.h b/Convex_hull_3/include/CGAL/Convex_hull_traits_3.h index caa065b2b58..1df55294e3f 100644 --- a/Convex_hull_3/include/CGAL/Convex_hull_traits_3.h +++ b/Convex_hull_3/include/CGAL/Convex_hull_traits_3.h @@ -95,6 +95,23 @@ public: typedef bool result_type; }; + +template +class Point_triple_has_on_negative_side_3 { + +public: + typedef typename K::Point_3 Point_3; + typedef Point_triple Plane_3; + bool + operator()( const Plane_3& pl, const Point_3& p) const + { + typename K::Orientation_3 o; + return ( o(pl.p(), pl.q(), pl.r(), p) == CGAL::NEGATIVE); + } + + typedef bool result_type; +}; + template class Point_triple_construct_orthogonal_vector_3 { @@ -167,6 +184,8 @@ struct GT3_for_CH3 { template struct Convex_hull_traits_base_3 { typedef Point_triple_has_on_positive_side_3 Has_on_positive_side_3; + typedef Point_triple_has_on_negative_side_3 Has_on_negative_side_3; + typedef Point_triple_less_signed_distance_to_plane_3 Less_signed_distance_to_plane_3; @@ -180,6 +199,13 @@ struct Convex_hull_traits_base_3{ Point_triple_converter, Point_triple_converter > Has_on_positive_side_3; + + typedef Filtered_predicate< + Point_triple_has_on_negative_side_3< typename R_::Exact_kernel_rt >, + Point_triple_has_on_negative_side_3< typename R_::Approximate_kernel >, + Point_triple_converter, + Point_triple_converter + > Has_on_negative_side_3; typedef Filtered_predicate< Point_triple_less_signed_distance_to_plane_3< typename R_::Exact_kernel_rt >, @@ -230,6 +256,8 @@ class Convex_hull_traits_3 : typedef typename Convex_hull_traits_base_3 ::Has_on_positive_side_3 Has_on_positive_side_3; + typedef typename Convex_hull_traits_base_3 + ::Has_on_negative_side_3 Has_on_negative_side_3; typedef typename Convex_hull_traits_base_3 ::Less_signed_distance_to_plane_3 Less_signed_distance_to_plane_3; @@ -289,6 +317,10 @@ class Convex_hull_traits_3 : Has_on_positive_side_3 has_on_positive_side_3_object() const { return Has_on_positive_side_3(); } + + Has_on_negative_side_3 + has_on_negative_side_3_object() const + { return Has_on_negative_side_3(); } Oriented_side_3 oriented_side_3_object() const diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index 732893b58bb..e73e6b10286 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -358,8 +358,8 @@ find_visible_set(TDS_2& tds, typedef typename Traits::Plane_3 Plane_3; typedef typename TDS_2::Face_handle Face_handle; typedef typename TDS_2::Vertex_handle Vertex_handle; - typename Traits::Has_on_positive_side_3 has_on_positive_side = - traits.has_on_positive_side_3_object(); + typename Traits::Has_on_negative_side_3 has_on_negative_side = + traits.has_on_negative_side_3_object(); std::vector vertices; vertices.reserve(10); @@ -387,7 +387,7 @@ find_visible_set(TDS_2& tds, f->info() = VISITED; Plane_3 plane(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); int ind = f->index(*vis_it); - if ( has_on_positive_side(plane, point) ){ // is visible + if ( !has_on_negative_side(plane, point) ){ // is visible visible.push_back(f); Vertex_handle vh = f->vertex(ind); if(vh->info() == 0){ vertices.push_back(vh); vh->info() = VISITED;} @@ -717,6 +717,56 @@ ch_quickhull_polyhedron_3(std::list& points, } +template +void init_iterators(P3_iterator& minx, + P3_iterator& maxx, + P3_iterator& miny, + const P3_iterator& start, + const Point_3_list& points) +{ + P3_iterator it = start; + for(; it != points.end(); ++it){ + if(it->x() < minx->x()) minx = it; + else if(it->x() == minx->x()) + { + if(it->y() < minx->y()) minx = it; + else if(it->y() == minx->y()) + { + if(it->z() < minx->z()) minx = it; + } + } + } + it = start; + for(; it != points.end(); ++it){ + if(it == minx ) + continue; + if(it->x() > maxx->x()) maxx = it; + else if(it->x() == maxx->x()) + { + if(it->y() > maxx->y()) maxx = it; + else if(it->y() == maxx->y()) + { + if(it->z() > maxx->z()) maxx = it; + } + } + } + it = start; + for(; it != points.end(); ++it){ + if(it == minx || it == maxx) + continue; + if(it->y() < miny->y()) miny = it; + else if(it->y() == miny->y()) + { + if(it->x() > miny->x()) miny = it; + else if(it->x() == miny->x()) + { + if(it->z() < miny->z()) miny = it; + } + } + } +} + } } //namespace internal::Convex_hull_3 @@ -810,13 +860,7 @@ convex_hull_3(InputIterator first, InputIterator beyond, Polyhedron P; P3_iterator minx, maxx, miny, it; - minx = maxx = miny = it = points.begin(); - ++it; - for(; it != points.end(); ++it){ - if(it->x() < minx->x()) minx = it; - if(it->x() > maxx->x()) maxx = it; - if(it->y() < miny->y()) miny = it; - } + internal::Convex_hull_3::init_iterators(minx, maxx, miny, it, points); if(! collinear(*minx, *maxx, *miny) ){ internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); } else { @@ -893,8 +937,20 @@ void convex_hull_3(InputIterator first, InputIterator beyond, clear(polyhedron); // result will be a polyhedron - internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, - polyhedron, traits); + P3_iterator minx, maxx, miny, it; + minx = maxx = miny = it = points.begin(); + ++it; + + + //take extreme points to begin with. + internal::Convex_hull_::init_iterators(minx, maxx, miny, it, points); + if(! collinear(*minx, *maxx, *miny) ){ + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, minx, maxx, miny, + polyhedron, traits); + } else {//to do : this case leads to bad init a risk of non minimal convex hull + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, + polyhedron, traits); + } } diff --git a/Convex_hull_3/test/Convex_hull_3/convex_hull_traits_3_fp_bug.cpp b/Convex_hull_3/test/Convex_hull_3/convex_hull_traits_3_fp_bug.cpp index 7eb9d41e1bd..3ca7be941c2 100644 --- a/Convex_hull_3/test/Convex_hull_3/convex_hull_traits_3_fp_bug.cpp +++ b/Convex_hull_3/test/Convex_hull_3/convex_hull_traits_3_fp_bug.cpp @@ -1,10 +1,14 @@ #include +#include #include #include +#include +#include #include #include typedef CGAL::Epick K; +typedef CGAL::Epeck EK; int main() { @@ -18,8 +22,20 @@ int main() CGAL::Polyhedron_3 r; CGAL::convex_hull_3(pointset.begin(), pointset.end(), r); - assert(r.size_of_vertices()==82); + + CGAL::Polyhedron_3 s; + CGAL::copy_face_graph(r,s); + assert(CGAL::is_strongly_convex_3(s)); + + CGAL::Cartesian_converter to_EK; + CGAL::Side_of_triangle_mesh, EK> sotm(s); + + + BOOST_FOREACH(K::Point_3 p, pointset) + { + assert(sotm(to_EK(p)) != CGAL::ON_UNBOUNDED_SIDE); + } return 0; }