Fix Convex_hull_3 so it becomes minimal.

This commit is contained in:
Maxime Gimeno 2018-07-12 16:42:21 +02:00
parent 156c9e7c47
commit c945d27dc2
5 changed files with 129 additions and 13 deletions

View File

@ -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;

View File

@ -85,6 +85,13 @@ Predicate object type that provides
*/
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
a constructor taking a single `Point_3` object and

View File

@ -95,6 +95,23 @@ public:
typedef bool result_type;
};
template <class K>
class Point_triple_has_on_negative_side_3 {
public:
typedef typename K::Point_3 Point_3;
typedef Point_triple<K> 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 K, class OldK>
class Point_triple_construct_orthogonal_vector_3
{
@ -167,6 +184,8 @@ struct GT3_for_CH3 {
template <class R_, class Has_filtered_predicates_tag /* = Tag_false */>
struct Convex_hull_traits_base_3 {
typedef Point_triple_has_on_positive_side_3<R_> Has_on_positive_side_3;
typedef Point_triple_has_on_negative_side_3<R_> Has_on_negative_side_3;
typedef Point_triple_less_signed_distance_to_plane_3<R_>
Less_signed_distance_to_plane_3;
@ -181,6 +200,13 @@ struct Convex_hull_traits_base_3<R_, Tag_true>{
Point_triple_converter<R_,typename R_::Approximate_kernel>
> 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<R_,typename R_::Exact_kernel_rt>,
Point_triple_converter<R_,typename R_::Approximate_kernel>
> Has_on_negative_side_3;
typedef Filtered_predicate<
Point_triple_less_signed_distance_to_plane_3< typename R_::Exact_kernel_rt >,
Point_triple_less_signed_distance_to_plane_3< typename R_::Approximate_kernel >,
@ -230,6 +256,8 @@ class Convex_hull_traits_3 :
typedef typename Convex_hull_traits_base_3<R_, Has_filtered_predicates_tag>
::Has_on_positive_side_3 Has_on_positive_side_3;
typedef typename Convex_hull_traits_base_3<R_, Has_filtered_predicates_tag>
::Has_on_negative_side_3 Has_on_negative_side_3;
typedef typename Convex_hull_traits_base_3<R_, Has_filtered_predicates_tag>
::Less_signed_distance_to_plane_3 Less_signed_distance_to_plane_3;
@ -290,6 +318,10 @@ class Convex_hull_traits_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
{ return Oriented_side_3(); }

View File

@ -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<Vertex_handle> 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<typename Traits::Point_3>& points,
}
template <class P3_iterator,
class Point_3_list>
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
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);
}
}

View File

@ -1,10 +1,14 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Side_of_triangle_mesh.h>
#include <CGAL/convexity_check_3.h>
#include <fstream>
#include <cassert>
typedef CGAL::Epick K;
typedef CGAL::Epeck EK;
int main()
{
@ -18,8 +22,20 @@ int main()
CGAL::Polyhedron_3<K> r;
CGAL::convex_hull_3(pointset.begin(), pointset.end(), r);
assert(r.size_of_vertices()==82);
CGAL::Polyhedron_3<EK> s;
CGAL::copy_face_graph(r,s);
assert(CGAL::is_strongly_convex_3(s));
CGAL::Cartesian_converter<K, EK> to_EK;
CGAL::Side_of_triangle_mesh<CGAL::Polyhedron_3<EK>, EK> sotm(s);
BOOST_FOREACH(K::Point_3 p, pointset)
{
assert(sotm(to_EK(p)) != CGAL::ON_UNBOUNDED_SIDE);
}
return 0;
}