add include files for the demo

This commit is contained in:
Sébastien Loriot 2012-07-11 16:21:54 +00:00
parent b72b9a69fd
commit e2e155fdb4
10 changed files with 5856 additions and 0 deletions

9
.gitattributes vendored
View File

@ -3279,6 +3279,15 @@ Polyhedron/examples/Polyhedron/corner.off -text svneol=unset#application/octet-s
Polyhedron/examples/Polyhedron/corner_with_hole.off -text svneol=unset#application/octet-stream
Polyhedron/examples/Polyhedron/corner_with_sharp_edge.off -text svneol=unset#application/octet-stream
Polyhedron/examples/Polyhedron/cross.off -text svneol=unset#application/octet-stream
Polyhedron/include/CGAL/corefinement_operations.h -text
Polyhedron/include/CGAL/internal/corefinement/Combinatorial_map_for_corefinement.h -text
Polyhedron/include/CGAL/internal/corefinement/Polyhedron_constness_types.h -text
Polyhedron/include/CGAL/internal/corefinement/Polyhedron_subset_extraction.h -text
Polyhedron/include/CGAL/internal/corefinement/intersection_coplanar_triangles_3.h -text
Polyhedron/include/CGAL/internal/corefinement/intersection_triangle_segment_3.h -text
Polyhedron/include/CGAL/internal/corefinement/intersection_triangle_segment_3_coplanar.h -text
Polyhedron/include/CGAL/intersection_of_Polyhedra_3.h -text
Polyhedron/include/CGAL/intersection_of_Polyhedra_3_refinement_visitor.h -text
Polynomial/doc_tex/Polynomial/Polynomial.png -text
Polynomial/doc_tex/Polynomial_ref/PolynomialTraits_d_ConstructCoefficientConstIteratorRange.tex -text
Polynomial/doc_tex/Polynomial_ref/PolynomialTraits_d_ConstructInnermostCoefficientConstIteratorRange.tex -text

View File

@ -0,0 +1,485 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_COREFINEMENT_OPERATIONS_H
#define CGAL_COREFINEMENT_OPERATIONS_H
#include <CGAL/intersection_of_Polyhedra_3.h>
#include <CGAL/intersection_of_Polyhedra_3_refinement_visitor.h>
namespace CGAL{
/** \cond */
namespace internal{
template <class HDS>
class Import_volume_as_polyhedron : public CGAL::Modifier_base<HDS> {
typedef typename HDS::Halfedge_handle Halfedge_handle;
typedef typename HDS::Vertex_handle Vertex_handle;
typedef typename HDS::Face_handle Face_handle;
typedef typename HDS::Vertex Vertex;
typedef typename HDS::Halfedge Halfedge;
typedef typename HDS::Face Face;
//data members
Face_handle current_face;
std::vector< typename Vertex::Point > points;
unsigned nb_edges;
std::vector<CGAL::cpp0x::tuple<unsigned,unsigned,unsigned> > faces;
typename HDS::Halfedge::Base*
unlock_halfedge(Halfedge_handle h){
return static_cast<typename HDS::Halfedge::Base*>(&(*h));
}
typename HDS::Face::Base*
unlock_face(Face_handle f){
return static_cast<typename HDS::Face::Base*>(&(*f));
}
public:
//to import each piece individually
template <class Combinatorial_map_3>
Import_volume_as_polyhedron(const Combinatorial_map_3& map,typename Combinatorial_map_3::Dart_const_handle dart):nb_edges(0)
{
typedef Combinatorial_map_3 CMap;
typedef std::map<const typename Vertex::Point*,unsigned int> Vertex_map;
Vertex_map vertex_map;
unsigned int index=0;
//recover all the vertices in the current volumeiterator over all the point
//map the vertex to the index of the point in the vector
for (typename CMap::template One_dart_per_incident_cell_const_range<0,3>::const_iterator
it=map.template one_dart_per_incident_cell<0,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<0,3>(dart).end();
it!=itend; ++it)
{
points.push_back(it->template attribute<0>()->point());
vertex_map.insert(std::make_pair(&it->template attribute<0>()->point(),index++));
}
//count the number of edges
nb_edges+=map.template one_dart_per_incident_cell<1,3>(dart).size();
//recover one dart per face
for (typename CMap::template One_dart_per_incident_cell_const_range<2,3>::const_iterator
it=map.template one_dart_per_incident_cell<2,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<2,3>(dart).end();
it!=itend; ++it)
{
//warning: the convention used into a polyhedron is that the normal
// of a triangle indicates the outside of the object; thus
// we need to reverse the orientation of the faces of the
// combinatorial map.
unsigned int i=vertex_map[&it->template attribute<0>()->point()];
unsigned int j=vertex_map[&it->beta(0)->template attribute<0>()->point()];
unsigned int k=vertex_map[&it->beta(1)->template attribute<0>()->point()];
faces.push_back(CGAL::cpp0x::make_tuple(i,j,k));
}
}
//for intersection and symetric difference
template <class Combinatorial_map_3,class Iterator>
Import_volume_as_polyhedron(const Combinatorial_map_3& map,
Iterator dart_begin,
Iterator dart_end):nb_edges(0)
{
typedef Combinatorial_map_3 CMap;
typedef std::map<const typename Vertex::Point*,unsigned int> Vertex_map;
Vertex_map vertex_map;
unsigned int index=0;
for (Iterator it=dart_begin;it!=dart_end;++it)
{
typename Combinatorial_map_3::Dart_const_handle dart=*it;
//recover all the vertices in the current volumeiterator over all the point
//map the vertex to the index of the point in the vector
for (typename CMap::template One_dart_per_incident_cell_const_range<0,3>::const_iterator
it=map.template one_dart_per_incident_cell<0,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<0,3>(dart).end();
it!=itend; ++it)
{
if ( vertex_map.insert(std::make_pair(&it->template attribute<0>()->point(),index)).second )
{
points.push_back(it->template attribute<0>()->point());
++index;
}
}
//count the number of edges
nb_edges+=map.template one_dart_per_incident_cell<1,3>(dart).size();
//recover one dart per face
for (typename CMap::template One_dart_per_incident_cell_const_range<2,3>::const_iterator
it=map.template one_dart_per_incident_cell<2,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<2,3>(dart).end();
it!=itend; ++it)
{
//warning: the convention used into a polyhedron is that the normal
// of a triangle indicates the outside of the object; thus
// we need to reverse the orientation of the faces of the
// combinatorial map.
unsigned int i=vertex_map[&it->template attribute<0>()->point()];
unsigned int j=vertex_map[&it->beta(0)->template attribute<0>()->point()];
unsigned int k=vertex_map[&it->beta(1)->template attribute<0>()->point()];
faces.push_back(CGAL::cpp0x::make_tuple(i,j,k));
}
}
}
//for union : use the inverse of the complementary
template <class Combinatorial_map_3,class Iterator>
Import_volume_as_polyhedron(const Combinatorial_map_3& map,
Iterator dart_begin,
Iterator dart_end,bool):nb_edges(0)
{
typedef Combinatorial_map_3 CMap;
typedef std::map<const typename Vertex::Point*,unsigned int> Vertex_map;
Vertex_map vertex_map;
unsigned int index=0;
for (Iterator it=dart_begin;it!=dart_end;++it)
{
typename Combinatorial_map_3::Dart_const_handle dart=*it;
//recover all the vertices in the current volumeiterator over all the point
//map the vertex to the index of the point in the vector
for (typename CMap::template One_dart_per_incident_cell_const_range<0,3>::const_iterator
it=map.template one_dart_per_incident_cell<0,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<0,3>(dart).end();
it!=itend; ++it)
{
if (vertex_map.insert(std::make_pair(&it->template attribute<0>()->point(),index)).second )
{
points.push_back(it->template attribute<0>()->point());
++index;
}
}
//count the number of edges
nb_edges+=map.template one_dart_per_incident_cell<1,3>(dart).size();
//recover one dart per face
for (typename CMap::template One_dart_per_incident_cell_const_range<2,3>::const_iterator
it=map.template one_dart_per_incident_cell<2,3>(dart).begin(),
itend=map.template one_dart_per_incident_cell<2,3>(dart).end();
it!=itend; ++it)
{
//warning: the convention used into a polyhedron is that the normal
// of a triangle indicates the outside of the object; thus
// we need to reverse the orientation of the faces of the
// combinatorial map. Since to get the complementary we
// also need to reverse the orientation, we finally do
// not change it.
unsigned int i=vertex_map[&it->template attribute<0>()->point()];
unsigned int j=vertex_map[&it->beta(1)->template attribute<0>()->point()];
unsigned int k=vertex_map[&it->beta(0)->template attribute<0>()->point()];
faces.push_back(CGAL::cpp0x::make_tuple(i,j,k));
}
}
}
void operator()( HDS& hds)
{
CGAL::Polyhedron_incremental_builder_3<HDS> B(hds, true);
B.begin_surface( points.size(), faces.size(),2*nb_edges);
//insert vertices
for (typename std::vector<typename Vertex::Point>::iterator it=points.begin();it!=points.end();++it)
B.add_vertex(*it);
//create faces
for (std::vector<CGAL::cpp0x::tuple<unsigned,unsigned,unsigned> >::iterator it=faces.begin();it!=faces.end();++it)
{
B.begin_facet();
B.add_vertex_to_facet(CGAL::cpp0x::get<0>(*it));
B.add_vertex_to_facet(CGAL::cpp0x::get<1>(*it));
B.add_vertex_to_facet(CGAL::cpp0x::get<2>(*it));
B.end_facet();
}
B.end_surface();
}
};
}
/** \endcond */
/*! \class Polyhedron_corefinement corefinement_operations.h CGAL/corefinement_operations.h
* Function object to compute the decomposition of the space induced by two polyhedra.
* @tparam Polyhedron must be an instantiation of CGAL::Polyhedron_3<Traits>.
* @tparam Kernel must be a CGAL Kernel compatible with the underlying kernel of Polyhedron.
*/
template <class Polyhedron,class Kernel=typename Polyhedron::Traits::Kernel>
class Polyhedron_corefinement
{
typedef internal::Import_volume_as_polyhedron<typename Polyhedron::HalfedgeDS> Volume_import_modifier;
public:
/** Enumeration of the different feature tags, listing all kind of space decomposition the functor can compute given two input polyhedra P and Q.*/
enum Boolean_operation_tag
{
Join_tag=1, /*!< the union of P and Q. */
Intersection_tag=2, /*!< the intersection of P and Q. */
P_minus_Q_tag=4, /*!< P minus Q. */
Q_minus_P_tag=8, /*!< Q minus P. */
Parts_of_P_tag=32, /*!< decomposition of the volume bounded by P induced by Q. */
Parts_of_Q_tag=64, /*!< decomposition of the volume bounded by Q induced by P. */
Decomposition_tag=16 /*!< Both decompositions of P and Q. */
};
/**
* This computes different polyhedra according to the value of features.
* Each input polyhedron is expected to bound a volume: the volume is bounded by the surface polyhedron with facet
* normals pointing outside the volume. Each facet is supposed to be counterclockwise oriented, that is its vertex
* sequence (induced by halfedges) is seen counterclockwise from the side of the facet pointed by its normal. If one or
* both polyhedra are not closed, the algorithm will end up correctly if each intersection polyline separates each surface
* in two components. In that case for each triangle of each surface path boundary, the interior of the volume is considered
* to be on the side opposite of that pointed by it normals (but the orientation must be consistent on each patch).
* the surface the volume bounded by an open surface is considered to be an infinite volume above
* or below the surface (the side not pointed by normal vectors).
* @tparam Polyline_output_iterator must be an output iterator of std::vector<Kernel::Point_3>.
* @tparam Polyhedron_ptr_and_type_output_iterator an output iterator of std::pair<Polyhedron*,int>.
* @param P is the first input triangulated polyhedron. Note that a reference is taken and P will be updated to contain the 1D intersection between the two surfaces P and Q.
* @param Q is the first input triangulated polyhedron. Note that a reference is taken and Q will be updated to contain the 1D intersection between the two surfaces P and Q.
* @param polyline_output is an output iterator that collects intersection polylines between P and Q.
* @param poly_output is an output iterator that collects output polyhedra. Note that each polyhedron is allocated within this function (thus must be explicitly deleted when no longer used). The integer is a feature tag corresponding to the volume represented by the polyhedron of the pair.
* @param features is an integer indicating what polyhedra the function must compute. If several kind of polyhedra are expected, feature tags must be combined by |. For example if features = Polyhedron_corefinement<Polyhedron,Kernel>::Join_tag | Polyhedron_corefinement<Polyhedron,Kernel>::Intersection_tag, then poly_output will collect two polyhedra, the union and the intersection of P and Q.
*/
template <class Polyline_output_iterator,class Polyhedron_ptr_and_type_output_iterator>
void operator()( Polyhedron& P, Polyhedron& Q,
Polyline_output_iterator polyline_output,
Polyhedron_ptr_and_type_output_iterator poly_output,
int features) const
{
typedef CGAL::Node_visitor_refine_polyhedra<Polyhedron> Split_visitor;
Split_visitor visitor;
CGAL::Intersection_of_Polyhedra_3<Polyhedron,
Kernel,
Split_visitor> polyline_intersections(visitor);
polyline_intersections(P, Q, polyline_output);
typedef typename Split_visitor::Combinatorial_map_3 Combinatorial_map_3;
typedef typename Split_visitor::Volume_info Volume_info;
typedef typename Combinatorial_map_3::Dart_const_handle Dart_const_handle;
const typename Split_visitor::Combinatorial_map_3& final_map=visitor.combinatorial_map();
typename Combinatorial_map_3::template One_dart_per_cell_const_range<3> cell_range=final_map.template one_dart_per_cell<3>();
std::list<Dart_const_handle> intersection;
std::list<Dart_const_handle> union_;
std::list<Dart_const_handle> P_minus_Q;
std::list<Dart_const_handle> Q_minus_P;
for (typename Combinatorial_map_3::template One_dart_per_cell_const_range<3>::const_iterator
it = cell_range.begin(), it_end= cell_range.end();
it!= it_end;
++it )
{
const Volume_info& info=it->template attribute<3>()->info();
std::size_t inside_size=info.inside.size();
std::size_t outside_size=info.outside.size();
if ( inside_size + outside_size != 2){
std::cerr << "Error: One volume cannot be represented using a polyhedron. Aborted.\n";
break;
}
switch (outside_size)
{
case 2:
if (features & Join_tag) union_.push_back(it);
break;
case 0:
if (features & Intersection_tag) intersection.push_back(it);
break;
default:
if ( *info.inside.begin() == &P )
{ if (features & P_minus_Q_tag) P_minus_Q.push_back(it); }
else
{ if (features & Q_minus_P_tag) Q_minus_P.push_back(it); }
}
if ( features&Decomposition_tag )
{
Volume_import_modifier modifier(final_map,it);
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++ = std::make_pair( new_poly,static_cast<int>(Decomposition_tag) );
}
if ( features&Parts_of_P_tag && info.inside.find(&P)!=info.inside.end() )
{
Volume_import_modifier modifier(final_map,it);
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++ = std::make_pair( new_poly,static_cast<int>(Parts_of_P_tag) );
}
if ( features&Parts_of_Q_tag && info.inside.find(&Q)!=info.inside.end() )
{
Volume_import_modifier modifier(final_map,it);
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++ = std::make_pair( new_poly,static_cast<int>(Parts_of_Q_tag) );
}
}
if (!intersection.empty())
{
Volume_import_modifier modifier(final_map,intersection.begin(),intersection.end());
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++=std::make_pair( new_poly,static_cast<int>(Intersection_tag) );
}
if (!P_minus_Q.empty())
{
Volume_import_modifier modifier(final_map,P_minus_Q.begin(),P_minus_Q.end());
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++=std::make_pair( new_poly,static_cast<int>(P_minus_Q_tag) );
}
if (!Q_minus_P.empty())
{
Volume_import_modifier modifier(final_map,Q_minus_P.begin(),Q_minus_P.end());
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++=std::make_pair( new_poly,static_cast<int>(Q_minus_P_tag) );
}
if (!union_.empty())
{
Volume_import_modifier modifier(final_map,union_.begin(),union_.end(),true);
Polyhedron* new_poly=new Polyhedron();
new_poly->delegate(modifier);
*poly_output++=std::make_pair( new_poly,static_cast<int>(Join_tag) );
}
}
/**
* This updates P according to the value of features.
* Each input polyhedron is expected to bound a volume: the volume is bounded by the surface polyhedron with facet
* normals pointing outside the volume. Each facet is supposed to be counterclockwise oriented, that is its vertex
* sequence (induced by halfedges) is seen counterclockwise from the side of the facet pointed by its normal. If one or
* both polyhedra are not closed, the algorithm will end up correctly if each intersection polyline separates each surface
* in two components. In that case for each triangle of each surface path boundary, the interior of the volume is considered
* to be on the side opposite of that pointed by it normals (but the orientation must be consistent on each patch).
* the surface the volume bounded by an open surface is considered to be an infinite volume above
* or below the surface (the side not pointed by normal vectors).
* @tparam Polyline_output_iterator must be an output iterator of std::vector<Kernel::Point_3>.
* @param P is the first input triangulated polyhedron. Note that a reference is taken and P will be updated to contain the 1D intersection between the two surfaces P and Q.
* @param Q is the first input triangulated polyhedron. Note that a reference is taken and Q will be updated to contain the 1D intersection between the two surfaces P and Q.
* @param polyline_output is an output iterator that collects intersection polylines between P and Q.
* @param features is either Join_tag, Intersection_tag, P_minus_Q_tag or Q_minus_P_tag
*/
template <class Polyline_output_iterator>
void operator()( Polyhedron& P, Polyhedron& Q,
Polyline_output_iterator polyline_output,
Boolean_operation_tag features) const
{
typedef CGAL::Node_visitor_refine_polyhedra<Polyhedron> Split_visitor;
Split_visitor visitor;
CGAL::Intersection_of_Polyhedra_3<Polyhedron,
Kernel,
Split_visitor> polyline_intersections(visitor);
polyline_intersections(P, Q, polyline_output);
typedef typename Split_visitor::Combinatorial_map_3 Combinatorial_map_3;
typedef typename Split_visitor::Volume_info Volume_info;
typedef typename Combinatorial_map_3::Dart_const_handle Dart_const_handle;
const typename Split_visitor::Combinatorial_map_3& final_map=visitor.combinatorial_map();
typename Combinatorial_map_3::template One_dart_per_cell_const_range<3> cell_range=final_map.template one_dart_per_cell<3>();
std::list<Dart_const_handle> darts;
for (typename Combinatorial_map_3::template One_dart_per_cell_const_range<3>::const_iterator
it = cell_range.begin(), it_end= cell_range.end();
it!= it_end;
++it )
{
const Volume_info& info=it->template attribute<3>()->info();
std::size_t inside_size=info.inside.size();
std::size_t outside_size=info.outside.size();
if ( inside_size + outside_size != 2){
std::cerr << "Error: One volume cannot be represented using a polyhedron. Aborted.\n";
break;
}
switch (outside_size)
{
case 2:
if ( features==Join_tag ) darts.push_back(it);
break;
case 0:
if ( features==Intersection_tag ) darts.push_back(it);
break;
default:
if ( *info.inside.begin() == &P )
{ if (features == P_minus_Q_tag) darts.push_back(it); }
else
{ if (features == Q_minus_P_tag) darts.push_back(it); }
}
}
P.clear();
if (!darts.empty())
{
Volume_import_modifier modifier=
features==Join_tag?
Volume_import_modifier(final_map,darts.begin(),darts.end(),true)
: Volume_import_modifier(final_map,darts.begin(),darts.end());
P.delegate(modifier);
}
}
/** \cond */
static std::string get_type_str(const std::string& Pname,const std::string& Qname,int i)
{
switch (i)
{
case Join_tag:
return Pname+std::string("_union_")+Qname;
case P_minus_Q_tag:
return Pname+std::string("_minus_")+Qname;
case Q_minus_P_tag:
return Qname+std::string("_minus_")+Pname;
case Intersection_tag:
return Pname+std::string("_inter_")+Qname;
case Decomposition_tag:
return std::string("Decomposition");
}
return std::string("Unknow");
}
/** \endcond */
};
}
#endif // CGAL_COREFINEMENT_OPERATIONS_H

View File

@ -0,0 +1,110 @@
// 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.
//
// $UR$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_COMBINATORIAL_MAP_FOR_COREFINEMENT_H
#define CGAL_INTERNAL_COMBINATORIAL_MAP_FOR_COREFINEMENT_H
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Combinatorial_map_constructors.h>
#include <CGAL/Cell_attribute.h>
#include <set>
namespace CGAL{
namespace internal_IOP{
template <class Polyhedron>
struct Volume_info{
std::set<Polyhedron*> outside;
std::set<Polyhedron*> inside;
bool is_empty;
Volume_info():is_empty(false){}
};
struct Volume_on_merge
{
template <class Attribute>
void operator() (Attribute& a1,const Attribute& a2) const
{
CGAL_assertion(!a1.info().is_empty && !a2.info().is_empty);
std::copy(a2.info().outside.begin(),a2.info().outside.end(),std::inserter(a1.info().outside,a1.info().outside.begin()));
std::copy(a2.info().inside.begin(),a2.info().inside.end(),std::inserter(a1.info().inside,a1.info().inside.begin()));
}
};
#ifndef NDEBUG
struct Point_on_merge
{
template <class Attribute>
void operator() (Attribute& a1,const Attribute& a2) const
{
CGAL_assertion(a1.point()==a2.point() );
}
};
#endif
template < class Refs, class T, class Point_,
class Functor_on_merge_=CGAL::Null_functor,
class Functor_on_split_=CGAL::Null_functor >
class My_cell_attribute_with_point :
public CGAL::Cell_attribute_without_info<Refs, T, Functor_on_merge_, Functor_on_split_>
{
Point_ mpoint;
public:
typedef Point_ Point;
typedef Functor_on_merge_ Functor_on_merge;
typedef Functor_on_split_ Functor_on_split;
My_cell_attribute_with_point(){}
My_cell_attribute_with_point(const Point& apoint) : mpoint(apoint) {}
Point& point() { return mpoint; }
const Point& point() const { return mpoint; }
};
template <typename Traits_,class Polyhedron>
class Item_with_points_and_volume_info
{
public:
public:
static const unsigned int dimension = 3;
static const unsigned int NB_MARKS = 32;
template<class Refs>
struct Dart_wrapper
{
typedef CGAL::Dart<3, Refs > Dart;
typedef Traits_ Traits;
typedef typename Traits::FT FT;
typedef typename Traits::Point_3 Point;
typedef typename Traits::Vector_3 Vector;
#ifndef NDEBUG
typedef My_cell_attribute_with_point< Refs,CGAL::Tag_true,Point,Point_on_merge> Vertex_attribute;
#else
typedef My_cell_attribute_with_point< Refs,CGAL::Tag_true,Point> Vertex_attribute;
#endif
typedef CGAL::Cell_attribute< Refs,Volume_info<Polyhedron>,CGAL::Tag_true,Volume_on_merge > Volume_attribute;
typedef CGAL::cpp0x::tuple< Vertex_attribute,
void,
void,
Volume_attribute> Attributes;
};
};
} } //namespace CGAL::internal_IOP
#endif //CGAL_INTERNAL_COMBINATORIAL_MAP_FOR_COREFINEMENT_H

View File

@ -0,0 +1,57 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_POLYHEDRON_CONSTNESS_TYPES_H
#define CGAL_INTERNAL_POLYHEDRON_CONSTNESS_TYPES_H
namespace CGAL {
namespace internal_IOP{
template <class Polyhedron,class T>
struct Polyhedron_types;
template <class Polyhedron>
struct Polyhedron_types<Polyhedron,Tag_false>{
typedef Polyhedron& Polyhedron_ref;
typedef typename Polyhedron::Halfedge_handle Halfedge_handle;
typedef typename Polyhedron::Halfedge_iterator Halfedge_iterator;
typedef typename Polyhedron::Facet_iterator Facet_iterator;
typedef typename Polyhedron::Facet_handle Facet_handle;
typedef typename Polyhedron::Vertex_handle Vertex_handle;
typedef typename Polyhedron::Vertex Vertex;
typedef typename Polyhedron::Halfedge Halfedge;
typedef typename Polyhedron::Facet Facet;
};
template <class Polyhedron>
struct Polyhedron_types<Polyhedron,Tag_true>{
typedef const Polyhedron& Polyhedron_ref;
typedef typename Polyhedron::Halfedge_const_handle Halfedge_handle;
typedef typename Polyhedron::Halfedge_const_iterator Halfedge_iterator;
typedef typename Polyhedron::Facet_const_iterator Facet_iterator;
typedef typename Polyhedron::Facet_const_handle Facet_handle;
typedef typename Polyhedron::Vertex_const_handle Vertex_handle;
typedef const typename Polyhedron::Vertex Vertex;
typedef const typename Polyhedron::Halfedge Halfedge;
typedef const typename Polyhedron::Facet Facet;
};
} } //namespace CGAL::internal_IOP
#endif //CGAL_INTERNAL_POLYHEDRON_CONSTNESS_TYPES_H

View File

@ -0,0 +1,200 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H
#define CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Union_find.h>
#include <CGAL/tuple.h>
namespace CGAL {
namespace internal{
template <class Polyhedron>
struct Compare_handle_ptr{
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle;
bool operator()(Facet_const_handle f1,Facet_const_handle f2) const {
return &(*f1) < &(*f2);
}
bool operator()(Vertex_const_handle v1,Vertex_const_handle v2) const {
return &(*v1) < &(*v2);
}
};
struct Dummy_true{
template <class T>
bool operator()(T) const {return true;}
};
template <class Polyhedron,class HDS=typename Polyhedron::HalfedgeDS>
class Build_polyhedron_subset : public ::CGAL::Modifier_base<HDS> {
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle;
typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle;
typedef typename HDS::Vertex::Point Point;
std::list<Vertex_const_handle> points;
std::list< std::vector<unsigned int> > facets;
template <class Facet_iterator>
typename Polyhedron::Halfedge_const_handle get_facet_halfedge(Facet_iterator facet_it) const
{
return (*facet_it)->halfedge();
}
typename Polyhedron::Halfedge_const_handle get_facet_halfedge(typename Polyhedron::Facet_const_handle facet) const
{
return facet->halfedge();
}
public:
template <class Facets_const_iterator>
Build_polyhedron_subset(const Polyhedron&,Facets_const_iterator begin,Facets_const_iterator end)
{
typedef std::map<Vertex_const_handle,unsigned int,Compare_handle_ptr<Polyhedron> > Vertices;
Vertices vertices;
unsigned int index=0;
//get vertices and get face description relatively to the restricted set of vertices
for (Facets_const_iterator it=begin;it!=end;++it)
{
Halfedge_const_handle start=get_facet_halfedge(it);
Halfedge_const_handle curr=start;
facets.push_back(std::vector<unsigned int>());
std::vector<unsigned int>& indices = facets.back();
do{
bool is_new_vertex;
typename Vertices::iterator it_vertex;
::CGAL::cpp0x::tie(it_vertex,is_new_vertex)=vertices.insert(std::make_pair(curr->vertex(),index));
if (is_new_vertex) {
++index;
points.push_back(curr->vertex());
}
indices.push_back(it_vertex->second);
curr=curr->next();
}while(curr!=start);
}
}
void operator()( HDS& hds) {
::CGAL::Polyhedron_incremental_builder_3<HDS> B( hds, true);
B.begin_surface( points.size(), facets.size() );
for (typename std::list<Vertex_const_handle>::iterator it=points.begin();it!=points.end();++it)
B.add_vertex((*it)->point());
for (typename std::list< std::vector<unsigned int> >::iterator
it=facets.begin();it!=facets.end();++it)
{
B.begin_facet();
for (std::vector<unsigned int>::iterator it_i=it->begin();it_i!=it->end();++it_i)
B.add_vertex_to_facet(*it_i);
B.end_facet();
}
B.end_surface();
}
};
template <class Polyhedron,class Adjacency_criterium,class Face_to_UF_handle_map,class Result>
void extract_connected_components(
const Polyhedron& P,
const Adjacency_criterium& adjacent,
CGAL::Union_find<typename Polyhedron::Facet_const_handle>& uf,
Face_to_UF_handle_map& map_f2h,
Result& result
)
{
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle;
typedef ::CGAL::Union_find<Facet_const_handle> UF;
typedef typename UF::handle UF_handle;
typedef typename UF::iterator UF_iterator;
CGAL_precondition(P.is_pure_triangle());
//init union-find: each facet is in its own set
for (typename Polyhedron::Facet_const_iterator it=P.facets_begin();it!=P.facets_end();++it){
map_f2h.insert(std::make_pair(it,uf.make_set(it)));
}
//merge 2 facets if they share a common edge
for (typename Polyhedron::Facet_const_iterator it=P.facets_begin();it!=P.facets_end();++it){
Facet_const_handle facet=it;
UF_handle current=map_f2h.find(it)->second;
Halfedge_const_handle neighbors[3];
neighbors[0]=facet->halfedge()->opposite();
neighbors[1]=facet->halfedge()->next()->opposite();
neighbors[2]=facet->halfedge()->next()->next()->opposite();
for (int i=0;i!=3;++i){
if ( neighbors[i]->is_border_edge() ) continue;
UF_handle neigh=map_f2h.find(neighbors[i]->facet())->second;
if ( adjacent(neighbors[i]) && !uf.same_set(current,neigh) ){
uf.unify_sets(current,neigh);
}
}
}
//recover merged sets
for (UF_iterator it=uf.begin();it!=uf.end();++it){
UF_handle master=uf.find(it);
result[*master].push_back(*it);
}
}
template <class Polyhedron,class Adjacency_criterium,class Output_iterator>
void extract_connected_components(const Polyhedron& P,const Adjacency_criterium& adjacent,Output_iterator out)
{
typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
typedef ::CGAL::Union_find<Facet_const_handle> UF;
typedef typename UF::handle UF_handle;
typedef typename UF::iterator UF_iterator;
typedef std::map<Facet_const_handle,std::list<Facet_const_handle>,Compare_handle_ptr<Polyhedron> > Result;
typedef std::map<Facet_const_handle,UF_handle,Compare_handle_ptr<Polyhedron> > Facet_to_handle_map;
UF uf;
Facet_to_handle_map map_f2h;
Result result;
extract_connected_components(P,adjacent,uf,map_f2h,result);
for (typename Result::iterator it=result.begin();it!=result.end();++it)
{
typedef std::list<Facet_const_handle> Facets;
const Facets& facets=it->second;
Polyhedron new_poly;
Build_polyhedron_subset<Polyhedron> modifier(new_poly,facets.begin(),facets.end());
new_poly.delegate(modifier);
*out++=new_poly;
}
}
template <class Polyhedron,class Output_iterator>
void extract_connected_components(const Polyhedron& P,Output_iterator out)
{
extract_connected_components(P,Dummy_true(),out);
}
} } //namespace CGAL::internal
#endif //CGAL_INTERNAL_POLYHEDRON_SUBSET_EXTRACTION_H

View File

@ -0,0 +1,327 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_INTERSECTION_COPLANAR_TRIANGLES_3_H
#define CGAL_INTERNAL_INTERSECTION_COPLANAR_TRIANGLES_3_H
#include <CGAL/internal/corefinement/intersection_triangle_segment_3.h> //for Intersection_type
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Cartesian_converter.h>
#include <bitset>
//TODO rename this file when doing proper integration
namespace CGAL{
namespace internal_IOP{
//intersection point of two coplanar triangles that keeps track of
//the location of that point onto the triangles.
template <class IK,class Halfedge_handle>
struct Intersection_point_with_info
{
typedef CGAL::Exact_predicates_exact_constructions_kernel Exact_kernel;
typedef IK Input_kernel;
typedef CGAL::Cartesian_converter<Input_kernel,Exact_kernel> Converter;
Intersection_type type_1,type_2; //intersection type for 1st and 2nd facets
Halfedge_handle info_1,info_2; //halfedge providing primitive indicated by type_1 and type_2
typename Exact_kernel::Point_3 point; //the geometric embedding of the intersection
//constructor from a vertex of first triangle initialized inside the second triangle
Intersection_point_with_info(Halfedge_handle info1,Halfedge_handle info2):
type_1(VERTEX),type_2(FACET),info_1(info1),info_2(info2)
{
Converter converter;
point=converter(info_1->vertex()->point());
}
//constructor for intersection of edges. prev and curr are two points on an edge of the first facet (preserving the
//orientation of the facet). This edge is intersected by info2 from the second facet.
//
//The rational is the following: we first check whether curr and prev are on the same edge. I so we create
//an intersection point between two edges. Otherwise, the point is a vertex of the second facet included into
//the first facet.
//
//(V,F) : point initialy constructed
//(V,E) : (V,F) updated by get_orientation_and_update_info_2 (i.e lies on one edge)
//(V,V) : (V,E) updated by get_orientation_and_update_info_2 (i.e lies on two edges)
//(E,E) : created in the following function when prev and curr lie on the same edge
//(E,V) : (E,E) updated by get_orientation_and_update_info_2 (always done as lies on two edges)
//(E,F) : impossible
//(F,V) : detected when curr and prev and not on the same edge
//(F,E) : impossible
//(F,F) : impossible
//
Intersection_point_with_info(Intersection_point_with_info prev,Intersection_point_with_info curr,
Halfedge_handle info1,Halfedge_handle info2):
type_2(EDGE),info_2(info2)
{
#ifdef CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
std::cout << "prev: "; prev.print_debug();
std::cout << "curr: "; curr.print_debug(); std::cout << std::endl;
#endif //CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
Converter converter;
if (prev.type_1==VERTEX && prev.info_1->next() == curr.info_1){
CGAL_assertion(curr.type_1!=FACET);
type_1=EDGE;
info_1=curr.info_1;
}
else{
if(curr.type_1==VERTEX && prev.info_1 == curr.info_1){
CGAL_assertion(prev.type_1!=FACET);
type_1=EDGE;
info_1=curr.info_1;
}
else{
if (curr.type_1==EDGE && prev.type_1==EDGE && curr.info_1==prev.info_1){
type_1=EDGE;
info_1=curr.info_1;
}
else{
//curr and prev are not on the same edge of the first facet.
//The intersection point to be computed is a VERTEX of the second facet
type_1=FACET;
info_1=info1;
type_2=VERTEX;
//this is used to select the correct endpoint of the edge of the second facet
typename Exact_kernel::Collinear_3 is_collinear = Exact_kernel().collinear_3_object();
if ( !is_collinear(prev.point,curr.point,converter(info_2->vertex()->point()) ) ){
info_2=info_2->next()->next();
CGAL_assertion( is_collinear(prev.point,curr.point,converter(info_2->vertex()->point()) ) );
}
point = converter( info_2->vertex()->point() );
return;
}
}
}
//handle degenerate case when two edges overlap
//at least one of the two vertex has already been found as a vertex of a facet. Here we set it for the second point
if(prev.type_2!=FACET && curr.type_2!=FACET && (prev.type_1==VERTEX || prev.type_2==VERTEX) && (curr.type_1==VERTEX || curr.type_2==VERTEX)){
typename Exact_kernel::Collinear_3 is_collinear = Exact_kernel().collinear_3_object();
if ( is_collinear(prev.point,curr.point,converter(info_2->opposite()->vertex()->point()) ) ){
info_2=info_2->next()->next();
type_2=VERTEX;
point = converter( info_2->vertex()->point() );
return;
}
if ( is_collinear(prev.point,curr.point,converter(info_2->vertex()->point()) ) ){
type_2=VERTEX;
point = converter( info_2->vertex()->point() );
return;
}
}
//handle regular intersection of two edges
typename Exact_kernel::Construct_line_3 line_3=Exact_kernel().construct_line_3_object();
typename Exact_kernel::Line_3 l1=
line_3(converter(info_2->vertex()->point()),converter(info_2->opposite()->vertex()->point()));
typename Exact_kernel::Line_3 l2=line_3(prev.point,curr.point);
CGAL::Object res=Exact_kernel().intersect_3_object()(l1,l2);
const typename Exact_kernel::Point_3* ptptr=CGAL::object_cast<typename Exact_kernel::Point_3>(&res);
CGAL_assertion(ptptr!=NULL);
point=*ptptr;
}
void print_debug() const{
std::cout << " (";
if (type_1==VERTEX) std::cout << "V";
if (type_1==EDGE) std::cout << "E";
if (type_1==FACET) std::cout << "F";
if (type_1==EMPTY) std::cout << "?";
std::cout << "-" << &(*info_1);
std::cout << ";";
if (type_2==VERTEX) std::cout << "V";
if (type_2==EDGE) std::cout << "E";
if (type_2==FACET) std::cout << "F";
if (type_2==EMPTY) std::cout << "?";
std::cout << ")" << "[" << CGAL::to_double(point.x()) << "," << CGAL::to_double(point.y()) << "," << CGAL::to_double(point.z()) << "]";
}
int debug_unique_type_int() const{
int res=0;
switch (type_1){
case VERTEX: res+=1; break;
case EDGE: res+=3; break;
case FACET: res+=7; break;
default: break;
}
switch (type_2){
case VERTEX: res+=1; break;
case EDGE: res+=3; break;
case FACET: res+=7; break;
default: break;
}
return res;
}
bool is_valid(Intersection_type type,Halfedge_handle info){
bool valid=true;
Converter converter;
switch (type){
case VERTEX: valid&= converter(info->vertex()->point())==point; break;
case EDGE:{
typename Exact_kernel::Segment_3 seg=
Exact_kernel().construct_segment_3_object()( converter(info->vertex()->point()),
converter(info->opposite()->vertex()->point()) );
valid&= Exact_kernel().has_on_3_object()(seg,point);
}
break;
case FACET:{
typename Exact_kernel::Coplanar_orientation_3 orient=Exact_kernel().coplanar_orientation_3_object();
typename Exact_kernel::Point_3 p=converter(info->vertex()->point());
typename Exact_kernel::Point_3 q=converter(info->next()->vertex()->point());
typename Exact_kernel::Point_3 r=converter(info->opposite()->vertex()->point());
valid &= orient(p,q,r,point)==POSITIVE;
valid &= orient(q,r,p,point)==POSITIVE;
valid &= orient(r,p,q,point)==POSITIVE;
}
break;
default: valid=false;
}
return valid;
}
bool is_valid(){
return is_valid(type_1,info_1) && is_valid(type_2,info_2);
}
};
template<class Halfedge_handle,class Inter_pt>
CGAL::Orientation get_orientation_and_update_info_2(Halfedge_handle h,Inter_pt& p)
{
typename Inter_pt::Exact_kernel::Coplanar_orientation_3 orient=
typename Inter_pt::Exact_kernel().coplanar_orientation_3_object();
typename Inter_pt::Converter converter;
CGAL::Orientation res = orient(converter(h->opposite()->vertex()->point()),
converter(h->vertex()->point()),
converter(h->next()->vertex()->point()),
p.point);
if ( (p.type_1==VERTEX || p.type_1==EDGE) && res==COLLINEAR){
if (p.type_2==FACET){ //detect a case (VERTEX,EDGE)
p.type_2=EDGE;
p.info_2=h;
}
else{
//detect a case (VERTEX,VERTEX) or (EDGE,VERTEX)
CGAL_assertion(p.type_2==EDGE);
p.type_2=VERTEX;
if (p.info_2->next()!=h){
CGAL_assertion(h->next()==p.info_2);
p.info_2=h;
}
}
}
return res;
}
template <class Facet_handle,class Inter_pt>
void intersection_coplanar_facets_cutoff(Facet_handle f,std::list<Inter_pt>& inter_pts,Facet_handle other)
{
#ifdef CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
std::cout << "cutoff: " << f->opposite()->vertex()->point() << " " << f->vertex()->point() << std::endl;
#endif //CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
if ( inter_pts.empty() ) return;
typedef typename std::list<Inter_pt>::iterator Iterator;
std::map<Inter_pt*,Orientation> orientations;
for (Iterator it=inter_pts.begin();it!=inter_pts.end();++it){
#ifdef CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
it->print_debug();
#endif //CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
orientations[ &(*it) ]=get_orientation_and_update_info_2(f,*it);
}
#ifdef CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
std::cout << std::endl;
#endif //CGAL_DEBUG_COPLANAR_TRIANGLE_INTERSECTION
int pt_added=0;
Inter_pt* prev = &(*boost::prior(inter_pts.end()));
bool inter_pts_size_g_2 = inter_pts.size() > 2;
Iterator stop = inter_pts_size_g_2 ? inter_pts.end() : boost::prior(inter_pts.end());
for (Iterator it=inter_pts.begin();it!=stop;++it)
{
Inter_pt* curr=&(*it);
if (!inter_pts_size_g_2) std::swap(prev,curr);
Orientation or_prev=orientations[prev],or_curr=orientations[curr];
if ( (or_prev==POSITIVE && or_curr==NEGATIVE) || (or_prev==NEGATIVE && or_curr==POSITIVE) )
{
Iterator it_curr = inter_pts_size_g_2 ? it:boost::next(it);
prev=&(* inter_pts.insert( it_curr,Inter_pt(*prev,*curr,other,f) ) );
orientations[prev]=COLLINEAR;
++pt_added;
}
prev=&(*it);
}
CGAL_kernel_assertion(pt_added<3);
Iterator it=inter_pts.begin();
std::size_t nb_interpt=inter_pts.size();
//this boolean allows to reverse order of intersection points in case there were 3 remaining intersection points
//and the point in the middle was removed. In that case the order must be reversed to preserve the orientations
//of the last edge:
// A---X---B --> AB to be consistent with the other cases this should be BA!
// X---B---A --> BA
// B---A---X --> BA
//
bool should_revert_list=false;
while(it!=inter_pts.end())
{
if (orientations[&(*it)]==NEGATIVE){
inter_pts.erase(it++);
if (--nb_interpt == 2 && it!=inter_pts.end() && boost::next(it)==inter_pts.end()) should_revert_list=true;
}
else
++it;
}
if (should_revert_list && nb_interpt==2) inter_pts.reverse();
}
template <class Input_kernel,class Halfedge_handle>
void
intersection_coplanar_facets(
Halfedge_handle f1,
Halfedge_handle f2,
std::list<Intersection_point_with_info<Input_kernel,Halfedge_handle> >& output )
{
typedef Intersection_point_with_info<Input_kernel,Halfedge_handle> Inter_pt;
output.push_back( Inter_pt(f1,f2) );
output.push_back( Inter_pt(f1->next(),f2) );
output.push_back( Inter_pt(f1->next()->next(),f2) );
//intersect f2 with the three half planes which intersection defines f1
intersection_coplanar_facets_cutoff(f2,output,f1);
intersection_coplanar_facets_cutoff(f2->next(),output,f1);
intersection_coplanar_facets_cutoff(f2->next()->next(),output,f1);
}
} } //namespace CGAL::internal_IOP
#endif //CGAL_INTERNAL_INTERSECTION_COPLANAR_TRIANGLES_3_H

View File

@ -0,0 +1,166 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_H
#define CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_H
//TODO rename this file when doing proper integration
#include <CGAL/internal/corefinement/Polyhedron_constness_types.h>
#include <CGAL/internal/Intersections_3/Triangle_3_Segment_3_intersection.h>
namespace CGAL{
namespace internal_IOP{
enum Intersection_type {FACET,EDGE,VERTEX,EMPTY,COPLNR};
//define shortcut for intersection result types
template <class Polyhedron,class Is_const>
struct Intersection_types{
typedef typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle Intersection_info;
typedef cpp0x::tuple<Intersection_type,Intersection_info,bool,bool> Intersection_result;
};
template<class Polyhedron,class Kernel,class Is_const>
typename Intersection_types<Polyhedron,Is_const>::Intersection_result
find_intersection(const typename Kernel::Point_3& p, const typename Kernel::Point_3& q,
const typename Kernel::Point_3& a, const typename Kernel::Point_3& b, const typename Kernel::Point_3& c,
typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle /*hh*/,
typename Polyhedron_types<Polyhedron,Is_const>::Facet_handle fh,
bool is_vertex_coplanar=false,bool is_vertex_opposite_coplanar=false)
{
typedef typename Intersection_types<Polyhedron,Is_const>::Intersection_info Intersection_info;
typedef typename Intersection_types<Polyhedron,Is_const>::Intersection_result Intersection_result;
Orientation ab=orientation(p,q,a,b);
Orientation bc=orientation(p,q,b,c);
Orientation ca=orientation(p,q,c,a);
if ( ab==POSITIVE || bc==POSITIVE || ca==POSITIVE )
return Intersection_result(EMPTY,Intersection_info(),false,false);
int nb_coplanar=(ab==COPLANAR?1:0) + (bc==COPLANAR?1:0) + (ca==COPLANAR?1:0);
if ( nb_coplanar==0 )
return cpp0x::make_tuple(FACET,Intersection_info(fh->halfedge()),is_vertex_coplanar,is_vertex_opposite_coplanar);
if (nb_coplanar==1){
if (ab==COPLANAR)
return cpp0x::make_tuple(EDGE,Intersection_info(fh->halfedge()->next()),is_vertex_coplanar,is_vertex_opposite_coplanar);
if (bc==COPLANAR)
return cpp0x::make_tuple(EDGE,Intersection_info(fh->halfedge()->next()->next()),is_vertex_coplanar,is_vertex_opposite_coplanar);
CGAL_assertion(ca==COPLANAR);
return cpp0x::make_tuple(EDGE,Intersection_info(fh->halfedge()),is_vertex_coplanar,is_vertex_opposite_coplanar);
}
CGAL_assertion(nb_coplanar==2);
if (ab!=COPLANAR)
return cpp0x::make_tuple(VERTEX,Intersection_info(fh->halfedge()->next()->next()),is_vertex_coplanar,is_vertex_opposite_coplanar);
if (bc!=COPLANAR)
return cpp0x::make_tuple(VERTEX,Intersection_info(fh->halfedge()),is_vertex_coplanar,is_vertex_opposite_coplanar);
CGAL_assertion(ca!=COPLANAR);
return cpp0x::make_tuple(VERTEX,Intersection_info(fh->halfedge()->next()),is_vertex_coplanar,is_vertex_opposite_coplanar);
}
template<class Polyhedron,class Kernel,class Is_const>
typename Intersection_types<Polyhedron,Is_const>::Intersection_result
do_intersect(typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle hh,
typename Polyhedron_types<Polyhedron,Is_const>::Facet_handle fh)
{
typedef typename Intersection_types<Polyhedron,Is_const>::Intersection_info Intersection_info;
typedef typename Intersection_types<Polyhedron,Is_const>::Intersection_result Intersection_result;
const typename Kernel::Point_3 & a = fh->halfedge()->vertex()->point();
const typename Kernel::Point_3 & b = fh->halfedge()->next()->vertex()->point();
const typename Kernel::Point_3 & c = fh->halfedge()->next()->next()->vertex()->point();
const typename Kernel::Point_3 & p = hh->vertex()->point();
const typename Kernel::Point_3 & q = hh->opposite()->vertex()->point();
const Orientation abcp = orientation(a,b,c,p);
const Orientation abcq = orientation(a,b,c,q);
switch ( abcp ) {
case POSITIVE:
switch ( abcq ) {
case POSITIVE:
// the segment lies in the positive open halfspaces defined by the
// triangle's supporting plane
return Intersection_result(EMPTY,Intersection_info(),false,false);
case NEGATIVE:
// p sees the triangle in counterclockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(p,q,a,b,c,hh,fh);
case COPLANAR:
// q belongs to the triangle's supporting plane
// p sees the triangle in counterclockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(p,q,a,b,c,hh,fh,false,true);
default: // should not happen.
CGAL_assertion(false);
return Intersection_result(EMPTY,Intersection_info(),false,false);
}
case NEGATIVE:
switch ( abcq ) {
case POSITIVE:
// q sees the triangle in counterclockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(q,p,a,b,c,hh,fh);
case NEGATIVE:
// the segment lies in the negative open halfspaces defined by the
// triangle's supporting plane
return Intersection_result(EMPTY,Intersection_info(),false,false);
case COPLANAR:
// q belongs to the triangle's supporting plane
// p sees the triangle in clockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(q,p,a,b,c,hh,fh,false,true);
default: // should not happen.
CGAL_assertion(false);
return Intersection_result(EMPTY,Intersection_info(),false,false);
}
case COPLANAR: // p belongs to the triangle's supporting plane
switch ( abcq ) {
case POSITIVE:
// q sees the triangle in counterclockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(q,p,a,b,c,hh,fh,true,false);
case NEGATIVE:
// q sees the triangle in clockwise order
return find_intersection<Polyhedron,Kernel,Is_const>(p,q,a,b,c,hh,fh,true,false);
case COPLANAR:
// the segment is coplanar with the triangle's supporting plane
// we test whether the segment intersects the triangle in the common
// supporting plane
if ( ::CGAL::internal::do_intersect_coplanar(a,b,c,p,q,Kernel()) )
return Intersection_result(COPLNR,Intersection_info(),true,true);
return Intersection_result(EMPTY,Intersection_info(),true,true);
default: // should not happen.
CGAL_assertion(false);
return Intersection_result(EMPTY,Intersection_info(),false,false);
}
default: // should not happen.
CGAL_assertion(false);
return Intersection_result(EMPTY,Intersection_info(),false,false);
}
}
}} //namespace CGAL::internal_IOP
#endif //CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_H

View File

@ -0,0 +1,395 @@
// Copyright (c) 2011 GeometryFactory (France).
// 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.
//
// $URL$
// $Id$
//
//
// Author(s) : Sebastien Loriot
#ifndef CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_COPLANAR_H
#define CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_COPLANAR_H
namespace CGAL{
namespace internal_IOP{
//enum Intersection_type {FACET,EDGE,VERTEX,EMPTY,COPLNR};
template<class Polyhedron,class Is_const>
struct Intersection_point_coplanar{
typedef typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle Halfedge_handle;
Intersection_type type;
Halfedge_handle info;
Halfedge_handle segment_vertex;
Intersection_point_coplanar(){};
Intersection_point_coplanar(Intersection_type type_,
Halfedge_handle info_,
Halfedge_handle segment_vertex_
) :type(type_),info(info_),segment_vertex(segment_vertex_){}
};
//test q vs segment bc
template<class Inter_pt_coplanar,class Halfedge_handle>
void point_vs_segment(Inter_pt_coplanar& pt,
Halfedge_handle bc, Halfedge_handle ab,
const Orientation& pqc, const Orientation& pqb)
{
if (pqb==COLLINEAR){
pt.type=VERTEX;
pt.info=ab;
}
else{
if (pqc==COLLINEAR){
pt.type=VERTEX;
pt.info=bc;
}
else{
pt.type=EDGE;
pt.info=bc;
}
}
}
/*
// c
// / \
// ___/___\____ with q-------p
// / \
// a_______b
//supporting line of segment pq intersects ac and bc
*/
template<class Inter_pt_coplanar,class Point_3,class Halfedge_handle>
std::pair<Inter_pt_coplanar,Inter_pt_coplanar>
decision_tree(const Point_3* a,const Point_3* b,const Point_3* c,
const Point_3* p,const Point_3* q,
const Orientation& pqa,const Orientation& pqb,const Orientation& pqc,
Halfedge_handle pq,
Halfedge_handle ca,Halfedge_handle ab,Halfedge_handle bc)
{
CGAL_precondition(pqa!=NEGATIVE);
CGAL_precondition(pqb!=NEGATIVE);
CGAL_precondition(pqc!=POSITIVE);
Inter_pt_coplanar pt1(EMPTY,NULL,NULL),pt2(EMPTY,NULL,NULL);
//the segment supporting line intersects ac and bc
const Orientation bcq = coplanar_orientation(*b,*c,*q);
switch(bcq){
case NEGATIVE: //segment does not intersect the triangle
return std::make_pair(pt1,pt2);
case COLLINEAR: //q \in [bc]
point_vs_segment(pt1,bc,ab,pqc,pqb);
pt1.segment_vertex=pq;
return std::make_pair(pt1,pt2);
default:
break;
}
//===> q is to the left of bc
const Orientation cap = coplanar_orientation(*c,*a,*p);
switch(cap){
case NEGATIVE: //segment does not intersect the triangle
return false;
case COLLINEAR: //p \in [ca]
point_vs_segment(pt1,ca,bc,pqa,pqc);
pt1.segment_vertex=pq->opposite();
return std::make_pair(pt1,pt2);
default:
break;
}
//===> p is to the right of ac
const Orientation cqa = coplanar_orientation(*c,*q,*a);
const Orientation cbp = coplanar_orientation(*c,*b,*p);
if (pqc==COLLINEAR && cqa==POSITIVE && cbp==POSITIVE){
//special case when c is inside the segment pq
pt1.type=VERTEX;
pt1.info=bc;
return std::make_pair(pt1,pt2);
}
//where is located q?
switch (cqa){
case POSITIVE: //q is outside the triangle
point_vs_segment(pt1,ca,bc,pqa,pqc);
break;
case NEGATIVE: //q is inside the triangle
pt1.type=FACET;
pt1.info=pq;
break;
case COLLINEAR: //q \in [ca]
point_vs_segment(pt1,ca,bc,pqa,pqc);
pt1.segment_vertex=pq;
break;
}
//where is located p?
switch (cbp){
case POSITIVE: //p is outside the triangle
point_vs_segment(pt2,bc,ab,pqc,pqb);
break;
case NEGATIVE: //p is inside the triangle
pt2.type=FACET;
pt2.info=pq->opposite();
break;
case COLLINEAR: //p \in [bc]
point_vs_segment(pt2,bc,ab,pqc,pqb);
pt2.segment_vertex=pq->opposite();
break;
}
return std::make_pair(pt1,pt2);
}
/*
// c
// / \
// / \
// / \
// ____a_______b______ with q-------p
//supporting lines of segments pq and ab are the same.
*/
template<class Inter_pt_coplanar,class Point_3,class Halfedge_handle>
std::pair<Inter_pt_coplanar,Inter_pt_coplanar>
collinear_decision_tree(const Point_3* a,const Point_3* b,const Point_3* c,
const Point_3* p,const Point_3* q,
const Orientation& pqa,const Orientation& pqb,const Orientation& pqc,
Halfedge_handle pq,
Halfedge_handle ca,Halfedge_handle ab,Halfedge_handle bc)
{
CGAL_precondition(pqa==COLLINEAR);
CGAL_precondition(pqb==COLLINEAR);
CGAL_precondition(pqc==NEGATIVE);
Inter_pt_coplanar pt1(EMPTY,NULL,NULL),pt2(EMPTY,NULL,NULL);
//the segment supporting line intersects ac and bc
const Orientation bcq = coplanar_orientation(*b,*c,*q);
switch(bcq){
case NEGATIVE: //segment does not intersect the triangle
return std::make_pair(pt1,pt2);
case COLLINEAR: // q = b
pt1.type=VERTEX;
pt1.info=ab;
pt1.segment_vertex=pq;
return std::make_pair(pt1,pt2);
default:
break;
}
//===> q is to the left of b
const Orientation cap = coplanar_orientation(*c,*a,*p);
switch(cap){
case NEGATIVE: //segment does not intersect the triangle
return false;
case COLLINEAR: //p = a
pt1.type=VERTEX;
pt1.info=ca;
pt1.segment_vertex=pq->opposite();
return std::make_pair(pt1,pt2);
default:
break;
}
//===> p is to the right of a
const Orientation cqa = coplanar_orientation(*c,*q,*a);
const Orientation cbp = coplanar_orientation(*c,*b,*p);
//where is located q?
switch (cqa){
case POSITIVE: //q is to the left of a
pt1.type=VERTEX;
pt1.info=ca;
break;
case NEGATIVE: //q is to the right of a
pt1.type=EDGE;
pt1.info=ab;
pt1.segment_vertex=pq;
break;
case COLLINEAR: //q = a
pt1.type=VERTEX;
pt1.info=ca;
pt1.segment_vertex=pq;
break;
}
//where is located p?
switch (cbp){
case POSITIVE: //p is to the right of b
{
pt2.type=VERTEX;
pt2.info=ab;
}
break;
case NEGATIVE: //p is to the left of b
{
pt2.type=EDGE;
pt2.info=ab;
pt2.segment_vertex=pq->opposite();
}
break;
case COLLINEAR: //p = b
pt2.type=VERTEX;
pt2.info=ab;
pt2.segment_vertex=pq->opposite();
break;
}
return std::make_pair(pt1,pt2);
}
//std::pair<Intersection_point_coplanar<Polyhedron,Is_const>,Intersection_point_coplanar<Polyhedron,Is_const> >
template<class Polyhedron,class Kernel,class Is_const>
std::pair<Intersection_point_coplanar<Polyhedron,Is_const>,Intersection_point_coplanar<Polyhedron,Is_const> >
do_intersect_coplanar(typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle pq,
typename Polyhedron_types<Polyhedron,Is_const>::Face_handle fh)
{
typedef Intersection_point_coplanar<Polyhedron,Is_const> Inter_pt_coplanar;
typedef std::pair<Inter_pt_coplanar,Inter_pt_coplanar> Return_type;
typedef typename Polyhedron_types<Polyhedron,Is_const>::Halfedge_handle Halfedge_handle;
const typename Kernel::Point_3 & A = fh->halfedge()->vertex()->point();
const typename Kernel::Point_3 & B = fh->halfedge()->next()->vertex()->point();
const typename Kernel::Point_3 & C = fh->halfedge()->next()->next()->vertex()->point();
const typename Kernel::Point_3 & P = pq->vertex()->point();
const typename Kernel::Point_3 & Q = pq->opposite()->vertex()->point();
const typename Kernel::Point_3 * a = &A;
const typename Kernel::Point_3 * b = &B;
const typename Kernel::Point_3 * c = &C;
const typename Kernel::Point_3* p = &P;
const typename Kernel::Point_3* q = &Q;
Halfedge_handle ca=fh->halfedge();
Halfedge_handle ab=fh->halfedge()->next();
Halfedge_handle bc=fh->halfedge()->next()->next();
// Determine the orientation of the triangle in the common plane
if (coplanar_orientation(A,B,C) != POSITIVE){
// The triangle is not counterclockwise oriented swap two vertices.
b = &C;
c = &B;
std::swap(bc,ab);
}
// Test whether the segment's supporting line intersects the
// triangle in the common plane
Orientation pqa = coplanar_orientation(*p,*q,*a);
//ensure pqa >= 0
if (pqa == NEGATIVE){
std::swap(p,q);
pqa=POSITIVE;
pq=pq->opposite();
}
const Orientation pqb = coplanar_orientation(*p,*q,*b);
const Orientation pqc = coplanar_orientation(*p,*q,*c);
//Handle first case pq collinear with a triangle edge
if (pqa == COLLINEAR){
if (pqb == COLLINEAR){
//ab and pq are on the same line
if (pqc == NEGATIVE)
return collinear_decision_tree<Inter_pt_coplanar>
(a,b,c,p,q,pqa,pqb,pqc,pq,ca,ab,bc);
else
return collinear_decision_tree<Inter_pt_coplanar>
(a,b,c,q,p,pqa,pqb,NEGATIVE,pq->opposite(),ca,ab,bc);
}
if (pqc == COLLINEAR){
//ac and pq are on the same line
if (pqb == NEGATIVE)
return collinear_decision_tree<Inter_pt_coplanar>
(c,a,b,p,q,pqc,pqa,pqb,pq,bc,ca,ab);
else
return collinear_decision_tree<Inter_pt_coplanar>
(c,a,b,q,p,pqc,pqa,NEGATIVE,pq->opposite(),bc,ca,ab);
}
}
else
if(pqb ==COLLINEAR && pqc == COLLINEAR){
//bc and pq are on the same line
return collinear_decision_tree<Inter_pt_coplanar>
(b,c,a,q,p,pqb,pqc,NEGATIVE,pq->opposite(),ab,bc,ca);
}
CGAL_assertion(pqa!=NEGATIVE);
switch ( pqa ) {
case POSITIVE:
switch ( pqb ) {
case POSITIVE:
if (pqc == POSITIVE)
return std::make_pair(Inter_pt_coplanar(EMPTY,NULL,NULL),Inter_pt_coplanar(EMPTY,NULL,NULL));
return decision_tree<Inter_pt_coplanar>(a,b,c,p,q,pqa,pqb,pqc,pq,ca,ab,bc);
case COLLINEAR:
case NEGATIVE:
if (pqc == POSITIVE) // b is isolated on the negative side
return decision_tree<Inter_pt_coplanar>(c,a,b,p,q,pqc,pqa,pqb,pq,bc,ca,ab);
return decision_tree<Inter_pt_coplanar>
(b,c,a,q,p,POSITIVE,opposite(pqc),NEGATIVE,pq->opposite(),ab,bc,ca);
default:// should not happen.
CGAL_assertion(false);
return std::make_pair(Inter_pt_coplanar(EMPTY,NULL,NULL),Inter_pt_coplanar(EMPTY,NULL,NULL));
}
case COLLINEAR:
switch ( pqb ) {
case POSITIVE:
if (pqc == POSITIVE) // a is isolated on the negative side
return decision_tree<Inter_pt_coplanar>(b,c,a,p,q,pqb,pqc,pqa,pq,ab,bc,ca);
return decision_tree<Inter_pt_coplanar>(a,b,c,p,q,pqa,pqb,pqc,pq,ca,ab,bc);
case NEGATIVE:
if (pqc == NEGATIVE) // a is isolated on the positive side
return decision_tree<Inter_pt_coplanar>
(b,c,a,q,p,POSITIVE,POSITIVE,pqa,pq->opposite(),ab,bc,ca);
return decision_tree<Inter_pt_coplanar>(c,a,b,p,q,pqc,pqa,pqb,pq,bc,ca,ab);
default:// should not happen.
CGAL_assertion(false);
return std::make_pair(Inter_pt_coplanar(EMPTY,NULL,NULL),Inter_pt_coplanar(EMPTY,NULL,NULL));
}
default:// should not happen.
CGAL_assertion(false);
return std::make_pair(Inter_pt_coplanar(EMPTY,NULL,NULL),Inter_pt_coplanar(EMPTY,NULL,NULL));
}
}
}}//namespace CGAL::internal_IOP
#endif //CGAL_INTERNAL_INTERSECTION_TRIANGLE_SEGMENT_3_COPLANAR_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff