mirror of https://github.com/CGAL/cgal
add include files for the demo
This commit is contained in:
parent
b72b9a69fd
commit
e2e155fdb4
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue