diff --git a/BGL/doc/BGL/BGL.txt b/BGL/doc/BGL/BGL.txt index 6a319650062..23c63b9f37d 100644 --- a/BGL/doc/BGL/BGL.txt +++ b/BGL/doc/BGL/BGL.txt @@ -254,15 +254,9 @@ The main function illustrates the access to the `id()` field. \section BGLTriangulations Triangulations as Models of the Boost Graph Concept Triangulations have vertices and faces, allowing for a direct translation -as a graph. An edge is defined as a pair of a face handle and the -index of the edge. -Particular care has to be taken with the infinite vertex and its incident -edges. One can either use a -boost::filtered_graph -in order to make the infinite edges -invisible, or one can have a property map that returns an infinite length -for these edges. -A complete list can be found in the documentation of \link BGLT2GT boost::graph_traits \endlink. +as a graph. A halfedge is defined as a pair of a face handle and the +index of the edge. A complete list can be found in the documentation +of \link BGLT2GT boost::graph_traits \endlink. A classical example for an algorithm that is a combination of computational geometry and graph theory is the Euclidean Minimum @@ -291,7 +285,7 @@ use the property map returned by the call `get(boost::vertex_index,ft)`. This property map assumes that the vertex has a member function `id()` that returns a reference to an int. Therefore \cgal offers a class `Triangulation_vertex_base_with_id_2`. -It is in the users responsibility to set the indices properly. +It is in the user's responsibility to set the indices properly. The example further illustrates that the graph traits also works for the Delaunay triangulation. diff --git a/BGL/doc/BGL/CGAL/Triangulation_face_base_with_id_2.h b/BGL/doc/BGL/CGAL/Triangulation_face_base_with_id_2.h new file mode 100644 index 00000000000..83e14e58af7 --- /dev/null +++ b/BGL/doc/BGL/CGAL/Triangulation_face_base_with_id_2.h @@ -0,0 +1,45 @@ +namespace CGAL { + +/*! +\ingroup PkgBGLHelper + +The class `Triangulation_face_base_with_id_2` is a model of the +concept `TriangulationFaceBase_2`, the base face of a +2D-triangulation. It provides an integer field that can be used to +index faces for \sc{Bgl} algorithms. + +Note that the user is in charge of setting indices correctly before +running a graph algorithm. + +\tparam TriangulationTraits_2 is the geometric traits class +and must be a model of `TriangulationTraits_2`. + +\tparam TriangulationFaceBase_2 must be a face base class from which +`Triangulation_face_base_with_id_2` derives. It has the default +value `Triangulation_face_base_2`. + +\cgalModels `TriangulationFaceBase_2` + +\sa `CGAL::Triangulation_face_base_2` +*/ +template< typename TriangulationTraits_2, typename TriangulationFaceBase_2 > +class Triangulation_face_base_with_id_2 : public TriangulationFaceBase_2 { +public: + +/// \name Access Functions +/// @{ + +/*! +Returns the index. +*/ +int id() const; + +/*! +Returns a reference to the index stored in the face. +*/ +int& id(); + +/// @} + +}; /* end Triangulation_face_base_with_id_2 */ +} /* end namespace CGAL */ diff --git a/BGL/doc/BGL/Doxyfile.in b/BGL/doc/BGL/Doxyfile.in index 9681886835a..c676a95fc13 100644 --- a/BGL/doc/BGL/Doxyfile.in +++ b/BGL/doc/BGL/Doxyfile.in @@ -4,6 +4,7 @@ PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - CGAL and the Boost Graph Library" INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/Euler_operations.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/iterator.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/helpers.h \ + ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/generators.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/selection.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/split_graph_into_polylines.h \ ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/boost/graph/copy_face_graph.h \ diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index ae7ea66baa1..287b2662399 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -546,7 +546,12 @@ Methods to read and write graphs. \cgalPkgPicture{emst-detail.png} \cgalPkgSummaryBegin \cgalPkgAuthors{Andreas Fabri, Fernando Cacciola, Philipp Moeller, and Ron Wein} -\cgalPkgDesc{This package provides a framework for interfacing \cgal data structures with the algorithms of the Boost Graph Library, or \sc{BGL} for short. It allows to run graph algorithms directly on \cgal data structures which are model of the \sc{BGL} graph concepts, for example the shortest path algorithm on a Delaunay triangulation in order to compute the Euclidean minimum spanning tree. Furthermore, it introduces several new graph concepts describing halfedge data structures.} +\cgalPkgDesc{This package provides a framework for interfacing \cgal data structures + with the algorithms of the Boost Graph Library, or \sc{BGL} for short. + It allows to run graph algorithms directly on \cgal data structures which are model + of the \sc{BGL} graph concepts, for example the shortest path algorithm + on a Delaunay triangulation in order to compute the Euclidean minimum spanning tree. + Furthermore, it introduces several new graph concepts describing halfedge data structures.} \cgalPkgManuals{Chapter_CGAL_and_the_Boost_Graph_Library,PkgBGLRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin @@ -593,6 +598,7 @@ user might encounter. \cgalCRPSection{Helper Classes} - `CGAL::Triangulation_vertex_base_with_id_2` +- `CGAL::Triangulation_face_base_with_id_2` - `CGAL::Arr_vertex_index_map` - `CGAL::Arr_face_index_map` - `CGAL::HalfedgeDS_vertex_max_base_with_id` diff --git a/BGL/doc/BGL/graph_traits.txt b/BGL/doc/BGL/graph_traits.txt index 1413197ecc6..4ea10583ee7 100644 --- a/BGL/doc/BGL/graph_traits.txt +++ b/BGL/doc/BGL/graph_traits.txt @@ -150,30 +150,29 @@ and `CGAL::Triangulation_hierarchy_2` so that they are model of the graph concepts `BidirectionalGraph`, `VertexAndEdgeListGraph`, and `FaceListGraph`. -The mapping between vertices and edges of the triangulation and the +Only finite simplices exist when viewed through the scope of these graph traits classes. +The infinite vertex, halfedges, edges, and faces will thus not appear when looping around a border +vertex, or walking through the faces container. + +The mapping between vertices, edges, and faces of the triangulation and the graph is rather straightforward, but there are some subtleties. The value type of the \sc{Bgl} iterators is the vertex or edge descriptor, whereas in \cgal all iterators and circulators are also handles and hence have as value type Vertex or Edge. -The graph traits class for triangulations does not distinguish between -finite and infinite vertices and edges. As the edge weight computed -with the default property map of \sc{Bgl} algorithms (obtained with -`get(t, boost::edge_weight)`) is the length of the edge, -the edge weight is not well defined for infinite edges. For algorithms -that make use of the edge weight, the user must therefore -define a `boost::filtered_graph` or pass a property map to the -algorithm that returns "infinity" for infinite edges. - | Member | Value | Description | | :----------------------- | :----: | :---------- | -| `vertex_descriptor` | `Triangulation::Vertex_handle` | Identify vertices in the graph. | -| `edge_descriptor` | `unspecified_type` | Identify edges in the graph. It is constructible from and convertible to `Triangulation::Edge`. It is not a simple typedef, but a proper class, because in an undirected graph the edges `(u,v)` and `(v,u)` must be equal. This is not the case for the Edge type of the triangulation. | +| `vertex_descriptor` | `unspecified_type` | Identify vertices in the graph. | +| `halfedge_descriptor` | `unspecified_type` | Identify halfedges in the graph. It is constructible from and convertible to `Triangulation::Edge`. It is not a simple typedef, but a proper class, because there is no representation for halfedges in the 2D triangulation data structure. | +| `edge_descriptor` | `unspecified_type` | Identify edges in the graph. It is constructible from and convertible to `Triangulation::Edge`. It is not a simple typedef, but a proper class, because in an undirected graph the edges `(u,v)` and `(v,u)` must be equal. This is not the case for the Edge type of the triangulation. | +| `face_descriptor` | `unspecified_type` | Identify faces in the graph. | | `adjacency_iterator` | `unspecified_type` | An iterator to traverse through the vertices adjacent to a vertex. Its value type is `vertex_descriptor`. | | `out_edge_iterator` | `unspecified_type` | An iterator to traverse through the outgoing edges incident to a vertex. Its value type is `edge_descriptor`. | | `in_edge_iterator` | `unspecified_type` | An iterator to traverse through the incoming edges incident to a vertex. Its value type is `edge_descriptor`. | -| `vertex_iterator` | `unspecified_type` | An iterator to traverse through the vertices of the graph. Its value type is `vertex_descriptor`. | -| `edge_iterator` | `unspecified_type` | An iterator to traverse through the edges of the graph. Its value type is `edge_descriptor`. | +| `vertex_iterator` | `unspecified_type` | An iterator to traverse through the vertices of the graph. Its value type is `vertex_descriptor`. | +| `halfedge_iterator` | `unspecified_type` | An iterator to traverse through the halfedges of the graph. Its value type is `halfedge_descriptor`. | +| `edge_iterator` | `unspecified_type` | An iterator to traverse through the edges of the graph. Its value type is `edge_descriptor`. | +| `face_iterator` | `unspecified_type` | An iterator to traverse through the faces of the graph. Its value type is `face_descriptor`. | | `directed_category` | `boost::undirected_tag` | This graph is not directed. | | `edge_parallel_category` | `boost::disallow_parallel_edge_tag` | This graph does not support multiedges. | | `traversal_category` | Inherits from `boost::bidirectional_graph_tag`, `boost::adjacency_graph_tag`, `boost::vertex_list_graph_tag`, and `boost::edge_list_graph_tag` | The ways in which the vertices in the graph can be traversed.. | diff --git a/BGL/examples/BGL_triangulation_2/dijkstra.cpp b/BGL/examples/BGL_triangulation_2/dijkstra.cpp index 82e0393bbf8..3a1b061eb9e 100644 --- a/BGL/examples/BGL_triangulation_2/dijkstra.cpp +++ b/BGL/examples/BGL_triangulation_2/dijkstra.cpp @@ -1,103 +1,70 @@ #include -#include -#include +#include #include -#include + #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_2 Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; -typedef CGAL::Triangulation_2 Triangulation; +typedef CGAL::Triangulation_2 Triangulation; -// As we want to run Dijskra's shortest path algorithm we only -// consider finite vertices and edges. +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; -template -struct Is_finite { +typedef std::map VertexIndexMap; +typedef boost::associative_property_map VertexIdPropertyMap; - const T* t_; - - Is_finite() - : t_(NULL) - {} - - Is_finite(const T& t) - : t_(&t) - { } - - template - bool operator()(const VertexOrEdge& voe) const { - return ! t_->is_infinite(voe); - } -}; - -typedef Is_finite Filter; -typedef boost::filtered_graph Finite_triangulation; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; - -typedef std::map VertexIndexMap; -VertexIndexMap vertex_id_map; - -typedef boost::associative_property_map VertexIdPropertyMap; -VertexIdPropertyMap vertex_index_pmap(vertex_id_map); - -int -main(int argc,char* argv[]) +int main(int argc,char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/points.xy"; std::ifstream input(filename); - Triangulation t; - Filter is_finite(t); - Finite_triangulation ft(t, is_finite, is_finite); + Triangulation tr; Point p ; - while(input >> p){ - t.insert(p); - } + while(input >> p) + tr.insert(p); vertex_iterator vit, ve; + // Associate indices to the vertices + VertexIndexMap vertex_id_map; + VertexIdPropertyMap vertex_index_pmap(vertex_id_map); int index = 0; - // boost::tie assigns the first and second element of the std::pair - // returned by boost::vertices to the variables vit and ve - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; - vertex_id_map[vd]= index++; - } + + for(vertex_descriptor vd : vertices(tr)) + vertex_id_map[vd] = index++; // Dijkstra's shortest path needs property maps for the predecessor and distance // We first declare a vector - std::vector predecessor(boost::num_vertices(ft)); - // and then turn it into a property map - boost::iterator_property_map::iterator, - VertexIdPropertyMap> - predecessor_pmap(predecessor.begin(), vertex_index_pmap); + std::vector predecessor(num_vertices(tr)); - std::vector distance(boost::num_vertices(ft)); - boost::iterator_property_map::iterator, - VertexIdPropertyMap> + // and then turn it into a property map + boost::iterator_property_map::iterator, VertexIdPropertyMap> + predecessor_pmap(predecessor.begin(), vertex_index_pmap); + + std::vector distance(num_vertices(tr)); + boost::iterator_property_map::iterator, VertexIdPropertyMap> distance_pmap(distance.begin(), vertex_index_pmap); // start at an arbitrary vertex - vertex_descriptor source = *boost::vertices(ft).first; + vertex_descriptor source = *vertices(tr).first; std::cout << "\nStart dijkstra_shortest_paths at " << source->point() <<"\n"; - boost::dijkstra_shortest_paths(ft, source, - distance_map(distance_pmap) - .predecessor_map(predecessor_pmap) - .vertex_index_map(vertex_index_pmap)); + boost::dijkstra_shortest_paths(tr, source, + distance_map(distance_pmap) + .predecessor_map(predecessor_pmap) + .vertex_index_map(vertex_index_pmap)); - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; + for(vertex_descriptor vd : vertices(tr)) + { std::cout << vd->point() << " [" << vertex_id_map[vd] << "] "; - std::cout << " has distance = " << boost::get(distance_pmap,vd) - << " and predecessor "; - vd = boost::get(predecessor_pmap,vd); + std::cout << " has distance = " << boost::get(distance_pmap,vd) + << " and predecessor "; + vd = boost::get(predecessor_pmap,vd); std::cout << vd->point() << " [" << vertex_id_map[vd] << "]\n "; } - return 0; + return EXIT_SUCCESS; } diff --git a/BGL/examples/BGL_triangulation_2/dijkstra_with_internal_properties.cpp b/BGL/examples/BGL_triangulation_2/dijkstra_with_internal_properties.cpp index 9b26686d725..b1bc089d216 100644 --- a/BGL/examples/BGL_triangulation_2/dijkstra_with_internal_properties.cpp +++ b/BGL/examples/BGL_triangulation_2/dijkstra_with_internal_properties.cpp @@ -1,94 +1,66 @@ #include + #include #include -#include +#include #include -#include + #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_2 Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; -typedef CGAL::Triangulation_vertex_base_with_id_2 Tvb; -typedef CGAL::Triangulation_face_base_2 Tfb; -typedef CGAL::Triangulation_data_structure_2 Tds; -typedef CGAL::Delaunay_triangulation_2 Triangulation; +typedef CGAL::Triangulation_vertex_base_with_id_2 Tvb; +typedef CGAL::Triangulation_face_base_2 Tfb; +typedef CGAL::Triangulation_data_structure_2 Tds; +typedef CGAL::Delaunay_triangulation_2 Triangulation; -// consider finite vertices and edges. +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; -template -struct Is_finite { +typedef boost::property_map::type VertexIdPropertyMap; - const T* t_; - - Is_finite() - : t_(NULL) - {} - - Is_finite(const T& t) - : t_(&t) - { } - - template - bool operator()(const VertexOrEdge& voe) const { - return ! t_->is_infinite(voe); - } -}; - -typedef Is_finite Filter; -typedef boost::filtered_graph Finite_triangulation; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; - - -int -main(int argc,char* argv[]) +int main(int argc,char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/points.xy"; std::ifstream input(filename); - Triangulation t; - Filter is_finite(t); - Finite_triangulation ft(t, is_finite, is_finite); + Triangulation tr; - Point p ; - while(input >> p){ - t.insert(p); - } + Point p; + while(input >> p) + tr.insert(p); - vertex_iterator vit, ve; // associate indices to the vertices int index = 0; - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; + for(vertex_descriptor vd : vertices(tr)) vd->id()= index++; - } - typedef boost::property_map::type VertexIdPropertyMap; - VertexIdPropertyMap vertex_index_pmap = get(boost::vertex_index, ft); + VertexIdPropertyMap vertex_index_pmap = get(boost::vertex_index, tr); // Dijkstra's shortest path needs property maps for the predecessor and distance - std::vector predecessor(boost::num_vertices(ft)); + std::vector predecessor(num_vertices(tr)); boost::iterator_property_map::iterator, VertexIdPropertyMap> predecessor_pmap(predecessor.begin(), vertex_index_pmap); - std::vector distance(boost::num_vertices(ft)); + std::vector distance(num_vertices(tr)); boost::iterator_property_map::iterator, VertexIdPropertyMap> distance_pmap(distance.begin(), vertex_index_pmap); - vertex_descriptor source = *boost::vertices(ft).first; + vertex_descriptor source = *vertices(tr).first; std::cout << "\nStart dijkstra_shortest_paths at " << source->point() << std::endl; - boost::dijkstra_shortest_paths(ft, source , - distance_map(distance_pmap) - .predecessor_map(predecessor_pmap)); + boost::dijkstra_shortest_paths(tr, source, distance_map(distance_pmap) + .predecessor_map(predecessor_pmap)); - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; + for(vertex_descriptor vd : vertices(tr)) + { std::cout << vd->point() << " [" << vd->id() << "] "; std::cout << " has distance = " << get(distance_pmap,vd) << " and predecessor "; + vd = get(predecessor_pmap,vd); std::cout << vd->point() << " [" << vd->id() << "]\n"; } - return 0; + + return EXIT_SUCCESS; } diff --git a/BGL/examples/BGL_triangulation_2/emst.cpp b/BGL/examples/BGL_triangulation_2/emst.cpp index ca8282d3195..4de38c2adef 100644 --- a/BGL/examples/BGL_triangulation_2/emst.cpp +++ b/BGL/examples/BGL_triangulation_2/emst.cpp @@ -1,98 +1,65 @@ #include + #include #include #include -#include + #include +#include +#include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_2 Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; -typedef CGAL::Delaunay_triangulation_2 Triangulation; +typedef CGAL::Delaunay_triangulation_2 Triangulation; -// As we only consider finite vertices and edges -// we need the following filter - -template -struct Is_finite { - - const T* t_; - - Is_finite() - : t_(NULL) - {} - - Is_finite(const T& t) - : t_(&t) - { } - - template - bool operator()(const VertexOrEdge& voe) const { - return ! t_->is_infinite(voe); - } -}; - -typedef Is_finite Filter; -typedef boost::filtered_graph Finite_triangulation; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; -typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef boost::graph_traits::edge_descriptor edge_descriptor; // The BGL makes use of indices associated to the vertices // We use a std::map to store the index -typedef std::map VertexIndexMap; -VertexIndexMap vertex_id_map; +typedef std::map VertexIndexMap; // A std::map is not a property map, because it is not lightweight -typedef boost::associative_property_map VertexIdPropertyMap; -VertexIdPropertyMap vertex_index_pmap(vertex_id_map); +typedef boost::associative_property_map VertexIdPropertyMap; -int -main(int argc,char* argv[]) +int main(int argc,char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/points.xy"; std::ifstream input(filename); - Triangulation t; - Filter is_finite(t); - Finite_triangulation ft(t, is_finite, is_finite); + Triangulation tr; - Point p ; - while(input >> p){ - t.insert(p); - } + Point p; + while(input >> p) + tr.insert(p); - vertex_iterator vit, ve; // Associate indices to the vertices + VertexIndexMap vertex_id_map; + VertexIdPropertyMap vertex_index_pmap(vertex_id_map); int index = 0; - // boost::tie assigns the first and second element of the std::pair - // returned by boost::vertices to the variables vit and ve - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; - vertex_id_map[vd]= index++; - } + for(vertex_descriptor vd : vertices(tr)) + vertex_id_map[vd] = index++; // We use the default edge weight which is the squared length of the edge // This property map is defined in graph_traits_Triangulation_2.h // In the function call you can see a named parameter: vertex_index_map - std::list mst; - boost::kruskal_minimum_spanning_tree(ft, - std::back_inserter(mst), - vertex_index_map(vertex_index_pmap)); + std::list mst; + boost::kruskal_minimum_spanning_tree(tr, std::back_inserter(mst), + vertex_index_map(vertex_index_pmap)); + std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; + for(edge_descriptor ed : mst) + { + vertex_descriptor svd = source(ed, tr); + vertex_descriptor tvd = target(ed, tr); + Triangulation::Vertex_handle sv = svd; + Triangulation::Vertex_handle tv = tvd; + std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; + } - std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; - - for(std::list::iterator it = mst.begin(); it != mst.end(); ++it){ - edge_descriptor ed = *it; - vertex_descriptor svd = source(ed,t); - vertex_descriptor tvd = target(ed,t); - Triangulation::Vertex_handle sv = svd; - Triangulation::Vertex_handle tv = tvd; - std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; - } - - return 0; + return EXIT_SUCCESS; } diff --git a/BGL/examples/BGL_triangulation_2/emst_cdt_plus_hierarchy.cpp b/BGL/examples/BGL_triangulation_2/emst_cdt_plus_hierarchy.cpp index acac3a76a68..9db9e5ba347 100644 --- a/BGL/examples/BGL_triangulation_2/emst_cdt_plus_hierarchy.cpp +++ b/BGL/examples/BGL_triangulation_2/emst_cdt_plus_hierarchy.cpp @@ -1,4 +1,5 @@ #include + #include #include #include @@ -9,104 +10,71 @@ #include #include -#include + #include +#include +#include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::Point_2 Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_2 Point; -typedef CGAL::Triangulation_vertex_base_2 Vbb; -typedef CGAL::Triangulation_hierarchy_vertex_base_2 Vb; -typedef CGAL::Constrained_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 TDS; -typedef CGAL::Exact_predicates_tag Itag; -typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; -typedef CGAL::Triangulation_hierarchy_2 CDTH; -typedef CGAL::Constrained_triangulation_plus_2 Triangulation; +typedef CGAL::Triangulation_vertex_base_2 Vbb; +typedef CGAL::Triangulation_hierarchy_vertex_base_2 Vb; +typedef CGAL::Constrained_triangulation_face_base_2 Fb; +typedef CGAL::Triangulation_data_structure_2 TDS; +typedef CGAL::Exact_predicates_tag Itag; +typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; +typedef CGAL::Triangulation_hierarchy_2 CDTH; +typedef CGAL::Constrained_triangulation_plus_2 Triangulation; - -// As we only consider finite vertices and edges -// we need the following filter - -template -struct Is_finite { - - const T* t_; - - Is_finite() - : t_(NULL) - {} - - Is_finite(const T& t) - : t_(&t) - { } - - template - bool operator()(const VertexOrEdge& voe) const { - return ! t_->is_infinite(voe); - } -}; - -typedef Is_finite Filter; -typedef boost::filtered_graph Finite_triangulation; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; -typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef boost::graph_traits::edge_descriptor edge_descriptor; // The BGL makes use of indices associated to the vertices // We use a std::map to store the index -typedef std::map VertexIndexMap; -VertexIndexMap vertex_id_map; +typedef std::map VertexIndexMap; // A std::map is not a property map, because it is not lightweight -typedef boost::associative_property_map VertexIdPropertyMap; -VertexIdPropertyMap vertex_index_pmap(vertex_id_map); +typedef boost::associative_property_map VertexIdPropertyMap; -int -main(int argc,char* argv[]) +int main(int argc,char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/points.xy"; std::ifstream input(filename); - Triangulation t; - Filter is_finite(t); - Finite_triangulation ft(t, is_finite, is_finite); + Triangulation tr; - Point p ; - while(input >> p){ - t.insert(p); - } + Point p; + while(input >> p) + tr.insert(p); - vertex_iterator vit, ve; // Associate indices to the vertices + VertexIndexMap vertex_id_map; + VertexIdPropertyMap vertex_index_pmap(vertex_id_map); int index = 0; - // boost::tie assigns the first and second element of the std::pair - // returned by boost::vertices to the variables vit and ve - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; - vertex_id_map[vd]= index++; - } + for(vertex_descriptor vd : vertices(tr)) + vertex_id_map[vd] = index++; // We use the default edge weight which is the squared length of the edge // This property map is defined in graph_traits_Triangulation_2.h // In the function call you can see a named parameter: vertex_index_map - std::list mst; - boost::kruskal_minimum_spanning_tree(ft, - std::back_inserter(mst), - vertex_index_map(vertex_index_pmap)); + std::list mst; + boost::kruskal_minimum_spanning_tree(tr, + std::back_inserter(mst), + vertex_index_map(vertex_index_pmap)); - std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; + std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; + for(edge_descriptor ed : mst) + { + vertex_descriptor svd = source(ed, tr); + vertex_descriptor tvd = target(ed, tr); + Triangulation::Vertex_handle sv = svd; + Triangulation::Vertex_handle tv = tvd; + std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; + } - for(std::list::iterator it = mst.begin(); it != mst.end(); ++it){ - edge_descriptor ed = *it; - vertex_descriptor svd = source(ed,t); - vertex_descriptor tvd = target(ed,t); - Triangulation::Vertex_handle sv = svd; - Triangulation::Vertex_handle tv = tvd; - std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; - } - - return 0; + return EXIT_SUCCESS; } diff --git a/BGL/examples/BGL_triangulation_2/emst_regular.cpp b/BGL/examples/BGL_triangulation_2/emst_regular.cpp index 7b8983d6365..40f9af43377 100644 --- a/BGL/examples/BGL_triangulation_2/emst_regular.cpp +++ b/BGL/examples/BGL_triangulation_2/emst_regular.cpp @@ -1,38 +1,24 @@ #include -#include #include #include - #include #include -#include #include +#include +#include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef K::FT FT; -typedef K::Weighted_point_2 Weighted_point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; +typedef K::Weighted_point_2 Weighted_point; -typedef CGAL::Regular_triangulation_2 Triangulation; +typedef CGAL::Regular_triangulation_2 Triangulation; -// As we only consider finite vertices and edges -// we need the following filter - -template -struct Is_finite { - - const T* t_; - - Is_finite() : t_(NULL) { } - Is_finite(const T& t) : t_(&t) { } - - template - bool operator()(const VertexOrEdge& voe) const { - return ! t_->is_infinite(voe); - } -}; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef boost::graph_traits::edge_descriptor edge_descriptor; template struct Compute_edge_weight @@ -42,7 +28,7 @@ struct Compute_edge_weight Compute_edge_weight(const T& t) : t_(t) { } typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; FT operator()(const edge_descriptor ed) const { vertex_descriptor svd = source(ed, t_); @@ -53,69 +39,54 @@ struct Compute_edge_weight } }; -typedef Is_finite Filter; -typedef boost::filtered_graph Finite_triangulation; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; -typedef boost::graph_traits::edge_descriptor edge_descriptor; - // The BGL makes use of indices associated to the vertices // We use a std::map to store the index typedef std::map VertexIndexMap; -VertexIndexMap vertex_id_map; // A std::map is not a property map, because it is not lightweight typedef boost::associative_property_map VertexIdPropertyMap; -VertexIdPropertyMap vertex_index_pmap(vertex_id_map); -int -main(int argc,char* argv[]) +int main(int argc,char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/weighted_points.xyw"; std::ifstream input(filename); - Triangulation t; - Filter is_finite(t); - Finite_triangulation ft(t, is_finite, is_finite); + Triangulation tr; - Weighted_point wp ; - while(input >> wp){ - t.insert(wp); - } + Weighted_point wp; + while(input >> wp) + tr.insert(wp); // Note that with the input "data/weighted_points.xyw", there is one hidden vertex - std::cout << "number of hidden vertices: " << t.number_of_hidden_vertices() << std::endl; + std::cout << "number of hidden vertices: " << tr.number_of_hidden_vertices() << std::endl; - vertex_iterator vit, ve; // Associate indices to the vertices + VertexIndexMap vertex_id_map; + VertexIdPropertyMap vertex_index_pmap(vertex_id_map); int index = 0; - // boost::tie assigns the first and second element of the std::pair - // returned by boost::vertices to the variables vit and ve - for(boost::tie(vit,ve)=boost::vertices(ft); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; + + for(vertex_descriptor vd : vertices(tr)) vertex_id_map[vd]= index++; - } // We use a custom edge length property map that computes the power distance // between the extremities of an edge of the regular triangulation typedef Compute_edge_weight Edge_weight_functor; // In the function call you can see a named parameter: vertex_index_map - std::list mst; - boost::kruskal_minimum_spanning_tree( - ft, std::back_inserter(mst), - vertex_index_map(vertex_index_pmap). - weight_map(CGAL::internal::boost_::make_function_property_map< - edge_descriptor, FT, Edge_weight_functor>(Edge_weight_functor(t)))); + std::list mst; + boost::kruskal_minimum_spanning_tree(tr, std::back_inserter(mst), + vertex_index_map(vertex_index_pmap) + .weight_map(CGAL::internal::boost_::make_function_property_map< + edge_descriptor, FT, Edge_weight_functor>(Edge_weight_functor(tr)))); - std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; - for(std::list::iterator it = mst.begin(); it != mst.end(); ++it){ - edge_descriptor ed = *it; - vertex_descriptor svd = source(ed,t); - vertex_descriptor tvd = target(ed,t); - Triangulation::Vertex_handle sv = svd; - Triangulation::Vertex_handle tv = tvd; - std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; - } + std::cout << "The edges of the Euclidean mimimum spanning tree:" << std::endl; + for(edge_descriptor ed : mst) + { + vertex_descriptor svd = source(ed, tr); + vertex_descriptor tvd = target(ed, tr); + Triangulation::Vertex_handle sv = svd; + Triangulation::Vertex_handle tv = tvd; + std::cout << "[ " << sv->point() << " | " << tv->point() << " ] " << std::endl; + } - return 0; + return EXIT_SUCCESS; } diff --git a/BGL/examples/BGL_triangulation_2/face_graph.cpp b/BGL/examples/BGL_triangulation_2/face_graph.cpp index efc5535a6a3..aa31b224721 100644 --- a/BGL/examples/BGL_triangulation_2/face_graph.cpp +++ b/BGL/examples/BGL_triangulation_2/face_graph.cpp @@ -1,4 +1,5 @@ #include + #include #include #include @@ -6,110 +7,81 @@ #include +typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic; +typedef CGAL::Projection_traits_xy_3 K; +typedef K::Point_2 Point; -typedef CGAL::Exact_predicates_inexact_constructions_kernel Epic; -typedef CGAL::Projection_traits_xy_3 K; -typedef K::Point_2 Point; +typedef CGAL::Triangulation_2 Triangulation; -typedef CGAL::Triangulation_2 Triangulation; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; +typedef boost::graph_traits::halfedge_iterator halfedge_iterator; +typedef boost::graph_traits::edge_iterator edge_iterator; +typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::graph_traits::face_descriptor face_descriptor; +typedef boost::graph_traits::face_iterator face_iterator; +typedef std::map VertexIndexMap; +typedef boost::associative_property_map VertexIdPropertyMap; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; -typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; -typedef boost::graph_traits::halfedge_iterator halfedge_iterator; -typedef boost::graph_traits::face_descriptor face_descriptor; -typedef boost::graph_traits::vertex_iterator vertex_iterator; -typedef boost::graph_traits::face_iterator face_iterator; -typedef boost::graph_traits::edge_iterator edge_iterator; -typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::property_map::type Ppmap; -typedef std::map VertexIndexMap; -VertexIndexMap vertex_id_map; - -typedef boost::associative_property_map VertexIdPropertyMap; -VertexIdPropertyMap vertex_index_pmap(vertex_id_map); - -typedef std::map HalfedgeIndexMap; -HalfedgeIndexMap halfedge_id_map; - -typedef boost::associative_property_map HalfedgeIdPropertyMap; -HalfedgeIdPropertyMap halfedge_index_pmap(halfedge_id_map); - -int -main(int,char*[]) +int main(int /*argc*/, char** /*argc*/) { - Triangulation t; + Triangulation tr; - t.insert(Point(0.1,0,1)); - t.insert(Point(1,0,1)); - t.insert(Point(0.2,0.2, 2)); - t.insert(Point(0,1,2)); - t.insert(Point(0,2,3)); + tr.insert(Point(0.1,0,1)); + tr.insert(Point(1,0,1)); + tr.insert(Point(0.2,0.2, 2)); + tr.insert(Point(0,1,2)); + tr.insert(Point(0,2,3)); - vertex_iterator vit, ve; // Associate indices to the vertices + VertexIndexMap vertex_id_map; + VertexIdPropertyMap vertex_index_pmap(vertex_id_map); int index = 0; - // boost::tie assigns the first and second element of the std::pair - // returned by boost::vertices to the variables vit and ve - for(boost::tie(vit,ve) = vertices(t); vit!=ve; ++vit ){ - vertex_descriptor vd = *vit; - if(! t.is_infinite(vd)){ - vertex_id_map[vd]= index++; - } - } + for(vertex_descriptor vd : vertices(tr)) + vertex_id_map[vd] = index++; std::cerr << index << " vertices" << std::endl; - index = 0; - face_iterator fit,fe; - for(boost::tie(fit,fe) = faces(t); fit!= fe; ++fit){ - face_descriptor fd = *fit; - halfedge_descriptor hd = halfedge(fd,t); - halfedge_descriptor n = next(hd,t); - - halfedge_descriptor nn = next(n,t); - if(next(nn,t) != hd){ - std::cerr << "the face is not a triangle" << std::endl; - } - - ++index; - } - - std::cerr << index << " faces" << std::endl; - index = 0; - edge_iterator eit,ee; - for(boost::tie(eit,ee) = edges(t); eit!= ee; ++eit){ - edge_descriptor ed = *eit; - vertex_descriptor vd = source(ed,t); - CGAL_USE(vd); - ++index; - } - - std::cerr << index << " edges" << std::endl; index = 0; - - halfedge_iterator hit,he; - for(boost::tie(hit,he) = halfedges(t); hit!= he; ++hit){ - halfedge_descriptor hd = *hit; - vertex_descriptor vd = source(hd,t); + for(halfedge_descriptor hd : halfedges(tr)) + { + vertex_descriptor vd = source(hd, tr); CGAL_USE(vd); ++index; } std::cerr << index << " halfedges" << std::endl; - std::cerr << num_vertices(t) << " " << num_edges(t) << " " << num_halfedges(t) << " " << num_faces(t) << std::endl; - - typedef boost::property_map::type Ppmap; - Ppmap ppmap = get(boost::vertex_point, t); - - - for(vertex_descriptor vd : vertices_around_target(*vertices(t).first, t)){ - std::cout << ppmap[vd] << std::endl; + index = 0; + for(edge_descriptor ed : edges(tr)) + { + vertex_descriptor vd = source(ed, tr); + CGAL_USE(vd); + ++index; } + std::cerr << index << " edges" << std::endl; + index = 0; + for(face_descriptor fd : faces(tr)) + { + halfedge_descriptor hd = halfedge(fd, tr); + CGAL_USE(hd); + ++index; + } + std::cerr << index << " faces" << std::endl; - ppmap[*(++vertices(t).first)] = Point(78,1,2); - std::cout << " changed point of vertex " << ppmap[*(++vertices(t).first)] << std::endl; + std::cerr << num_vertices(tr) << " " << num_halfedges(tr) << " " << num_edges(tr) << " " << num_faces(tr) << std::endl; - return 0; + std::cout << "vertices incident to the first vertex:" << std::endl; + Ppmap ppmap = get(boost::vertex_point, tr); + for(vertex_descriptor vd : vertices_around_target(*vertices(tr).first, tr)) + std::cout << ppmap[vd] << std::endl; + + ppmap[*(++vertices(tr).first)] = Point(78, 1, 2); + std::cout << "changed point of vertex " << ppmap[*(++vertices(tr).first)] << std::endl; + + return EXIT_SUCCESS; } diff --git a/BGL/include/CGAL/boost/graph/generators.h b/BGL/include/CGAL/boost/graph/generators.h new file mode 100644 index 00000000000..5189bd7297d --- /dev/null +++ b/BGL/include/CGAL/boost/graph/generators.h @@ -0,0 +1,829 @@ +// Copyright (c) 2014, 2017 GeometryFactory (France). All rights reserved. +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Maxime Gimeno, +// Mael Rouxel-Labbé + +#ifndef CGAL_BOOST_GRAPH_GENERATORS_H +#define CGAL_BOOST_GRAPH_GENERATORS_H + +#include +#include + +#include +#include + +namespace CGAL { +namespace Euler { + +// Some forward declaration to break the helpers.h > generators.h > Euler_operations.h cycle +template< typename Graph> +void fill_hole(typename boost::graph_traits::halfedge_descriptor h, + Graph& g); + +template +typename boost::graph_traits::face_descriptor add_face(const VertexRange& vr, + Graph& g); + +} // namespace Euler + +namespace internal { + +template +void swap_vertices(typename boost::graph_traits::vertex_descriptor& p, + typename boost::graph_traits::vertex_descriptor& q, + FaceGraph& g); + +template +typename std::iterator_traits::value_type +random_entity_in_range(InputIterator first, InputIterator beyond, + CGAL::Random& rnd = get_default_random()) +{ + typedef typename std::iterator_traits::difference_type size_type; + + size_type zero = 0, ne = std::distance(first, beyond); + std::advance(first, rnd.uniform_int(zero, ne - 1)); + + return *first; +} + +template +typename std::iterator_traits::value_type +random_entity_in_range(const CGAL::Iterator_range& range, + CGAL::Random& rnd = get_default_random()) +{ + return random_entity_in_range(range.begin(), range.end(), rnd); +} + +// \brief returns a random non-null vertex incident to the face `fd` of the polygon mesh `g`. +// \tparam Graph a model of `HalfedgeGraph` +template +typename boost::graph_traits::vertex_descriptor +random_vertex_in_face(typename boost::graph_traits::face_descriptor fd, + const Graph& g, + CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(vertices_around_face(halfedge(fd, g), g), rnd); +} + +// \brief returns a random non-null halfedge incident to the face `fd` of the polygon mesh `g`. +// \tparam Graph a model of `HalfedgeGraph` +template +typename boost::graph_traits::halfedge_descriptor +random_halfedge_in_face(typename boost::graph_traits::face_descriptor fd, + const Graph& g, + CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(halfedges_around_face(halfedge(fd, g), g), rnd); +} + +// \brief returns a random non-null vertex of the polygon mesh `g`. +// \tparam Graph a model of `VertexListGraph` +template +typename boost::graph_traits::vertex_descriptor +random_vertex_in_mesh(const Graph& g, CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(vertices(g), rnd); +} + +// \brief returns a random non-null halfedge of the polygon mesh `g`. +// \tparam Graph a model of `HalfedgeListGraph` +template +typename boost::graph_traits::halfedge_descriptor +random_halfedge_in_mesh(const Graph& g, CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(halfedges(g), rnd); +} + +// \brief returns a random non-null edge of the polygon mesh `g`. +// \tparam Graph a model of `EdgeListGraph` +template +typename boost::graph_traits::edge_descriptor +random_edge_in_mesh(const Graph& g, CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(edges(g), rnd); +} + +// \brief returns a random non-null face of the polygon mesh `g`. +// \tparam Graph a model of `FaceListGraph` +template +typename boost::graph_traits::face_descriptor +random_face_in_mesh(const Graph& g, CGAL::Random& rnd = get_default_random()) +{ + return internal::random_entity_in_range(faces(g), rnd); +} + +} // namespace internal + +/** + * \ingroup PkgBGLHelperFct + * + * \brief Creates an isolated triangle + * with its vertices initialized to `p0`, `p1` and `p2`, and adds it to the graph `g`. + * + * \returns the non-border halfedge that has the target vertex associated with `p0`. + **/ +template +typename boost::graph_traits::halfedge_descriptor +make_triangle(const P& p0, const P& p1, const P& p2, Graph& g) +{ + typedef typename boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::halfedge_descriptor halfedge_descriptor; + + typedef typename Traits::face_descriptor face_descriptor; + typedef typename boost::property_map::type Point_property_map; + Point_property_map ppmap = get(CGAL::vertex_point, g); + vertex_descriptor v0, v1, v2; + v0 = add_vertex(g); + v1 = add_vertex(g); + v2 = add_vertex(g); + + ppmap[v0] = p0; + ppmap[v1] = p1; + ppmap[v2] = p2; + halfedge_descriptor h0 = halfedge(add_edge(g), g); + halfedge_descriptor h1 = halfedge(add_edge(g), g); + halfedge_descriptor h2 = halfedge(add_edge(g), g); + set_next(h0, h1, g); + set_next(h1, h2, g); + set_next(h2, h0, g); + set_target(h0, v1, g); + set_target(h1, v2, g); + set_target(h2, v0, g); + set_halfedge(v1, h0, g); + set_halfedge(v2, h1, g); + set_halfedge(v0, h2, g); + face_descriptor f = add_face(g); + set_face(h0, f, g); + set_face(h1, f, g); + set_face(h2, f, g); + set_halfedge(f, h0, g); + h0 = opposite(h0, g); + h1 = opposite(h1, g); + h2 = opposite(h2, g); + set_next(h0, h2, g); + set_next(h2, h1, g); + set_next(h1, h0, g); + set_target(h0, v0, g); + set_target(h1, v1, g); + set_target(h2, v2, g); + set_face(h0, boost::graph_traits::null_face(), g); + set_face(h1, boost::graph_traits::null_face(), g); + set_face(h2, boost::graph_traits::null_face(), g); + + return opposite(h2, g); +} + +namespace internal { + +template +typename boost::graph_traits::halfedge_descriptor +make_quad(typename boost::graph_traits::vertex_descriptor v0, + typename boost::graph_traits::vertex_descriptor v1, + typename boost::graph_traits::vertex_descriptor v2, + typename boost::graph_traits::vertex_descriptor v3, + Graph& g) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + halfedge_descriptor h0 = halfedge(add_edge(g), g); + halfedge_descriptor h1 = halfedge(add_edge(g), g); + halfedge_descriptor h2 = halfedge(add_edge(g), g); + halfedge_descriptor h3 = halfedge(add_edge(g), g); + set_next(h0, h1, g); + set_next(h1, h2, g); + set_next(h2, h3, g); + set_next(h3, h0, g); + set_target(h0, v1, g); + set_target(h1, v2, g); + set_target(h2, v3, g); + set_target(h3, v0, g); + set_halfedge(v1, h0, g); + set_halfedge(v2, h1, g); + set_halfedge(v3, h2, g); + set_halfedge(v0, h3, g); + face_descriptor f = add_face(g); + set_face(h0, f, g); + set_face(h1, f, g); + set_face(h2, f, g); + set_face(h3, f, g); + set_halfedge(f, h0, g); + h0 = opposite(h0, g); + h1 = opposite(h1, g); + h2 = opposite(h2, g); + h3 = opposite(h3, g); + set_next(h0, h3, g); + set_next(h3, h2, g); + set_next(h2, h1, g); + set_next(h1, h0, g); + set_target(h0, v0, g); + set_target(h1, v1, g); + set_target(h2, v2, g); + set_target(h3, v3, g); + set_face(h0, boost::graph_traits::null_face(), g); + set_face(h1, boost::graph_traits::null_face(), g); + set_face(h2, boost::graph_traits::null_face(), g); + set_face(h3, boost::graph_traits::null_face(), g); + return opposite(h3, g); +} + +// default Functor for make_grid +template +struct Default_grid_maker + : public CGAL::Creator_uniform_3 +{ + Point operator()(const Size_type& i, const Size_type& j) const { + return CGAL::Creator_uniform_3::operator ()(i,j,0); + } +}; + +} // namespace internal + +/** + * \ingroup PkgBGLHelperFct + * + * \brief Creates an isolated quad with + * its vertices initialized to `p0`, `p1`, `p2`, and `p3`, and adds it to the graph `g`. + * + * \returns the non-border halfedge that has the target vertex associated with `p0`. + **/ +template +typename boost::graph_traits::halfedge_descriptor +make_quad(const P& p0, const P& p1, const P& p2, const P& p3, Graph& g) +{ + typedef typename boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type Point_property_map; + + Point_property_map ppmap = get(CGAL::vertex_point, g); + + vertex_descriptor v0, v1, v2, v3; + v0 = add_vertex(g); + v1 = add_vertex(g); + v2 = add_vertex(g); + v3 = add_vertex(g); + ppmap[v0] = p0; + ppmap[v1] = p1; + ppmap[v2] = p2; + ppmap[v3] = p3; + + return internal::make_quad(v0, v1, v2, v3, g); +} + +/** + * \ingroup PkgBGLHelperFct + * \brief Creates an isolated hexahedron + * with its vertices initialized to `p0`, `p1`, ...\ , and `p7`, and adds it to the graph `g`. + * \image html hexahedron.png + * \image latex hexahedron.png + * \returns the halfedge that has the target vertex associated with `p0`, in the face with the vertices with the points `p0`, `p1`, `p2`, and `p3`. + **/ +template +typename boost::graph_traits::halfedge_descriptor +make_hexahedron(const P& p0, const P& p1, const P& p2, const P& p3, + const P& p4, const P& p5, const P& p6, const P& p7, Graph& g) +{ + typedef typename boost::graph_traits Traits; + typedef typename Traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::vertex_descriptor vertex_descriptor; + + typedef typename boost::property_map::type Point_property_map; + Point_property_map ppmap = get(CGAL::vertex_point, g); + + vertex_descriptor v0, v1, v2, v3, v4, v5, v6, v7; + v0 = add_vertex(g); + v1 = add_vertex(g); + v2 = add_vertex(g); + v3 = add_vertex(g); + v4 = add_vertex(g); + v5 = add_vertex(g); + v6 = add_vertex(g); + v7 = add_vertex(g); + ppmap[v0] = p0; + ppmap[v1] = p1; + ppmap[v2] = p2; + ppmap[v3] = p3; + ppmap[v4] = p4; + ppmap[v5] = p5; + ppmap[v6] = p6; + ppmap[v7] = p7; + + halfedge_descriptor ht = internal::make_quad(v4, v5, v6, v7, g); + halfedge_descriptor hb = prev(internal::make_quad(v0, v3, v2, v1, g), g); + for(int i=0; i <4; ++i) + { + halfedge_descriptor h = halfedge(add_edge(g), g); + set_target(h,target(hb, g), g); + set_next(h, opposite(hb, g), g); + set_next(opposite(prev(ht, g), g), h, g); + h = opposite(h, g); + set_target(h, source(prev(ht, g), g), g); + set_next(h, opposite(next(next(ht, g), g), g), g); + set_next(opposite(next(hb, g), g), h, g); + hb = next(hb, g); + ht = prev(ht, g); + } + for(int i=0; i <4; ++i) + { + Euler::fill_hole(opposite(hb, g), g); + hb = next(hb, g); + } + + return next(next(hb, g), g); +} + +/** + * \ingroup PkgBGLHelperFct + * \brief Creates an isolated tetrahedron + * with its vertices initialized to `p0`, `p1`, `p2`, and `p3`, and adds it to the graph `g`. + * \image html tetrahedron.png + * \image latex tetrahedron.png + * \returns the halfedge that has the target vertex associated with `p0`, in the face with the vertices with the points `p0`, `p1`, and `p2`. + **/ +template +typename boost::graph_traits::halfedge_descriptor +make_tetrahedron(const P& p0, const P& p1, const P& p2, const P& p3, Graph& g) +{ + typedef typename boost::graph_traits Traits; + typedef typename Traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::face_descriptor face_descriptor; + + typedef typename boost::property_map::type Point_property_map; + Point_property_map ppmap = get(CGAL::vertex_point, g); + + vertex_descriptor v0, v1, v2, v3; + v0 = add_vertex(g); + v2 = add_vertex(g); // this and the next line are switched to keep points in order + v1 = add_vertex(g); + v3 = add_vertex(g); + + ppmap[v0] = p0; + ppmap[v1] = p2;// this and the next line are switched to reorient the surface + ppmap[v2] = p1; + ppmap[v3] = p3; + halfedge_descriptor h0 = halfedge(add_edge(g), g); + halfedge_descriptor h1 = halfedge(add_edge(g), g); + halfedge_descriptor h2 = halfedge(add_edge(g), g); + set_next(h0, h1, g); + set_next(h1, h2, g); + set_next(h2, h0, g); + set_target(h0, v1, g); + set_target(h1, v2, g); + set_target(h2, v0, g); + set_halfedge(v1, h0, g); + set_halfedge(v2, h1, g); + set_halfedge(v0, h2, g); + face_descriptor f = add_face(g); + set_face(h0, f, g); + set_face(h1, f, g); + set_face(h2, f, g); + set_halfedge(f, h0, g); + h0 = opposite(h0, g); + h1 = opposite(h1, g); + h2 = opposite(h2, g); + set_next(h0, h2, g); + set_next(h2, h1, g); + set_next(h1, h0, g); + set_target(h0, v0, g); + set_target(h1, v1, g); + set_target(h2, v2, g); + halfedge_descriptor h3 = halfedge(add_edge(g), g); + halfedge_descriptor h4 = halfedge(add_edge(g), g); + halfedge_descriptor h5 = halfedge(add_edge(g), g); + set_target(h3, v3, g); + set_target(h4, v3, g); + set_target(h5, v3, g); + set_halfedge(v3, h3, g); + + set_next(h0, h3, g); + set_next(h1, h4, g); + set_next(h2, h5, g); + + set_next(h3, opposite(h4, g), g); + set_next(h4, opposite(h5, g), g); + set_next(h5, opposite(h3, g), g); + set_next(opposite(h4, g), h0, g); + set_next(opposite(h5, g), h1, g); + set_next(opposite(h3, g), h2, g); + + set_target(opposite(h3, g), v0, g); + set_target(opposite(h4, g), v1, g); + set_target(opposite(h5, g), v2, g); + + f = add_face(g); + set_halfedge(f, h0, g); + set_face(h0, f, g); + set_face(h3, f, g); + set_face(opposite(h4, g), f, g); + f = add_face(g); + set_halfedge(f, h1, g); + set_face(h1, f, g); + set_face(h4, f, g); + set_face(opposite(h5, g), f, g); + f = add_face(g); + set_halfedge(f, h2, g); + set_face(h2, f, g); + set_face(h5, f, g); + set_face(opposite(h3, g), f, g); + + return opposite(h2, g); +} + +/** + * \ingroup PkgBGLHelperFct + * + * \brief Creates a triangulated regular prism, outward oriented, + * having `nb_vertices` vertices in each of its bases and adds it to the graph `g`. + * If `center` is (0, 0, 0), then the first point of the prism is (`radius`, `height`, 0) + * + * \param nb_vertices the number of vertices per base. It must be greater than or equal to 3. + * \param g the graph in which the regular prism will be created. + * \param base_center the center of the circle in which the lower base is inscribed. + * \param height the distance between the two bases. + * \param radius the radius of the circles in which the bases are inscribed. + * \param is_closed determines if the bases must be created or not. If `is_closed` is `true`, `center` is a vertex. + * + * \returns the halfedge that has the target vertex associated with the first point in the first face. + */ +template +typename boost::graph_traits::halfedge_descriptor +make_regular_prism(typename boost::graph_traits::vertices_size_type nb_vertices, + Graph& g, + const P& base_center = P(0,0,0), + typename CGAL::Kernel_traits

::Kernel::FT height = 1.0, + typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0, + bool is_closed = true) +{ + CGAL_assertion(nb_vertices >= 3); + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename CGAL::Kernel_traits

::Kernel::FT FT; + + typedef typename boost::property_map::type Point_property_map; + Point_property_map vpmap = get(CGAL::vertex_point, g); + + const FT to_rad = CGAL_PI / 180.0; + const FT precision = 360.0 / nb_vertices; + const FT diameter = 2 * radius; + + std::vector vertices; + vertices.resize(nb_vertices*2); + for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i < nb_vertices; ++i) + { + put(vpmap, vertices[i], + P(0.5*diameter * cos(i*precision*to_rad) + base_center.x(), + height+base_center.y(), + -0.5*diameter * sin(i*precision*to_rad) + base_center.z())); + + put(vpmap, + vertices[i+nb_vertices], + P(0.5*diameter * cos(i*precision*to_rad) + base_center.x(), + base_center.y(), + -0.5*diameter * sin(i*precision*to_rad) + base_center.z())); + } + + //fill faces + std::vector face; + face.resize(3); + for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i +typename boost::graph_traits::halfedge_descriptor +make_pyramid(typename boost::graph_traits::vertices_size_type nb_vertices, + Graph& g, + const P& base_center = P(0,0,0), + typename CGAL::Kernel_traits

::Kernel::FT height = 1.0, + typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0, + bool is_closed = true) +{ + CGAL_assertion(nb_vertices >= 3); + + typedef typename boost::property_map::type Point_property_map; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename CGAL::Kernel_traits

::Kernel::FT FT; + + const FT to_rad = CGAL_PI / 180.0; + const FT precision = 360.0/nb_vertices; + const FT diameter = 2*radius; + + Point_property_map vpmap = get(CGAL::vertex_point, g); + + std::vector vertices; + vertices.resize(nb_vertices); + for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i face; + face.resize(3); + for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i +typename boost::graph_traits::halfedge_descriptor +make_icosahedron(Graph& g, + const P& center = P(0,0,0), + typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0) +{ + typedef typename boost::property_map::type Point_property_map; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Point_property_map vpmap = get(CGAL::vertex_point, g); + + // create the initial icosahedron + std::vector v_vertices; + v_vertices.resize(12); + for(int i=0; i<12; ++i) + v_vertices[i] = add_vertex(g); + + typename CGAL::Kernel_traits

::Kernel::FT t = radius * (1.0 + CGAL::approximate_sqrt(5.0)) / 2.0; + + put(vpmap, v_vertices[0], P(-radius + center.x(), t + center.y(), 0.0 + center.z())); + put(vpmap, v_vertices[1], P( radius + center.x(), t + center.y(), 0.0 + center.z())); + put(vpmap, v_vertices[2], P(-radius + center.x(), -t + center.y(), 0.0 + center.z())); + put(vpmap, v_vertices[3], P( radius + center.x(), -t + center.y(), 0.0 + center.z())); + + put(vpmap, v_vertices[4], P( 0.0 + center.x(), -radius + center.y(), t + center.z())); + put(vpmap, v_vertices[5], P( 0.0 + center.x(), radius + center.y(), t + center.z())); + put(vpmap, v_vertices[6], P( 0.0 + center.x(), -radius + center.y(), -t + center.z())); + put(vpmap, v_vertices[7], P( 0.0 + center.x(), radius + center.y(), -t + center.z())); + + put(vpmap, v_vertices[8], P( t + center.x(), 0.0 + center.y(), -radius + center.z())); + put(vpmap, v_vertices[9], P( t + center.x(), 0.0 + center.y(), radius + center.z())); + put(vpmap, v_vertices[10], P(-t + center.x(), 0.0 + center.y(), -radius + center.z())); + put(vpmap, v_vertices[11], P(-t + center.x(), 0.0 + center.y(), radius + center.z())); + + std::vector face; + face.resize(3); + face[1] = v_vertices[0]; face[0] = v_vertices[5]; face[2] = v_vertices[11]; + Euler::add_face(face, g); + face[1] = v_vertices[0]; face[0] = v_vertices[1]; face[2] = v_vertices[5]; + Euler::add_face(face, g); + face[1] = v_vertices[0]; face[0] = v_vertices[7]; face[2] = v_vertices[1]; + Euler::add_face(face, g); + face[1] = v_vertices[0]; face[0] = v_vertices[10]; face[2] = v_vertices[7]; + Euler::add_face(face, g); + face[1] = v_vertices[0]; face[0] = v_vertices[11]; face[2] = v_vertices[10]; + Euler::add_face(face, g); + + face[1] = v_vertices[1]; face[0] = v_vertices[9]; face[2] = v_vertices[5]; + Euler::add_face(face, g); + face[1] = v_vertices[5]; face[0] = v_vertices[4]; face[2] = v_vertices[11]; + Euler::add_face(face, g); + face[1] = v_vertices[11]; face[0] = v_vertices[2]; face[2] = v_vertices[10]; + Euler::add_face(face, g); + face[1] = v_vertices[10]; face[0] = v_vertices[6]; face[2] = v_vertices[7]; + Euler::add_face(face, g); + face[1] = v_vertices[7]; face[0] = v_vertices[8]; face[2] = v_vertices[1]; + Euler::add_face(face, g); + + face[1] = v_vertices[3]; face[0] = v_vertices[4]; face[2] = v_vertices[9]; + Euler::add_face(face, g); + face[1] = v_vertices[3]; face[0] = v_vertices[2]; face[2] = v_vertices[4]; + Euler::add_face(face, g); + face[1] = v_vertices[3]; face[0] = v_vertices[6]; face[2] = v_vertices[2]; + Euler::add_face(face, g); + face[1] = v_vertices[3]; face[0] = v_vertices[8]; face[2] = v_vertices[6]; + Euler::add_face(face, g); + face[1] = v_vertices[3]; face[0] = v_vertices[9]; face[2] = v_vertices[8]; + Euler::add_face(face, g); + + face[1] = v_vertices[4]; face[0] = v_vertices[5]; face[2] = v_vertices[9]; + Euler::add_face(face, g); + face[1] = v_vertices[2]; face[0] = v_vertices[11]; face[2] = v_vertices[4]; + Euler::add_face(face, g); + face[1] = v_vertices[6]; face[0] = v_vertices[10]; face[2] = v_vertices[2]; + Euler::add_face(face, g); + face[1] = v_vertices[8]; face[0] = v_vertices[7]; face[2] = v_vertices[6]; + Euler::add_face(face, g); + face[1] = v_vertices[9]; face[0] = v_vertices[1]; face[2] = v_vertices[8]; + Euler::add_face(face, g); + + return halfedge(v_vertices[1], v_vertices[0], g).first; +} + +/*! + * \ingroup PkgBGLHelperFct + * + * \brief Creates a row major ordered grid with `i` cells along the width and `j` cells + * along the height and adds it to the graph `g`. + * An internal property map for `CGAL::vertex_point_t` must be available in `Graph`. + * + * \param i the number of cells along the width. + * \param j the number of cells along the height. + * \param g the graph in which the grid will be created. + * \param calculator the functor that will assign coordinates to the grid vertices. + * \param triangulated decides if a cell is composed of one quad or two triangles. + * If `triangulated` is `true`, the diagonal of each cell is oriented from (0,0) to (1,1) + * in the cell coordinates. + * + *\tparam CoordinateFunctor a function object providing `Point_3 operator()(size_type I, size_type J)` with `Point_3` being + * the value_type of the internal property_map for `CGAL::vertex_point_t`. + * and outputs a `boost::property_traits::%type>::%value_type`. + * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`]. + *

%Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] + * + * \returns the non-border non-diagonal halfedge that has the target vertex associated with the first point of the grid (default is (0,0,0) ). + */ +template +typename boost::graph_traits::halfedge_descriptor +make_grid(typename boost::graph_traits::vertices_size_type i, + typename boost::graph_traits::vertices_size_type j, + Graph& g, + const CoordinateFunctor& calculator, + bool triangulated = false) +{ + typedef typename boost::property_map::type Point_property_map; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typename boost::graph_traits::vertices_size_type w(i+1), h(j+1); + Point_property_map vpmap = get(CGAL::vertex_point, g); + //create the vertices + std::vector v_vertices; + v_vertices.resize(static_cast(w*h)); + for(std::size_t k = 0; k < v_vertices.size(); ++k) + v_vertices[k] = add_vertex(g); + //assign the coordinates + for(typename boost::graph_traits::vertices_size_type a=0; a::vertices_size_type b=0; b face; + if(triangulated) + face.resize(3); + else + face.resize(4); + + for(typename boost::graph_traits::vertices_size_type a = 0; a::vertices_size_type b = 0; b +typename boost::graph_traits::halfedge_descriptor +make_grid(typename boost::graph_traits::vertices_size_type w, + typename boost::graph_traits::vertices_size_type h, + Graph& g, + bool triangulated = false) +{ + typedef typename boost::graph_traits::vertices_size_type Size_type; + typedef typename boost::property_traits::type>::value_type Point; + + return make_grid(w, h, g, internal::Default_grid_maker(), triangulated); +} + +} // namespace CGAL + +// Here at the bottom because helpers.h must include generators (for backward compatibility reasons), +// and Euler_operations.h needs helpers.h +#include + +#endif // CGAL_BOOST_GRAPH_GENERATORS_H diff --git a/BGL/include/CGAL/boost/graph/helpers.h b/BGL/include/CGAL/boost/graph/helpers.h index 065c37448a3..f66dc6a6d00 100644 --- a/BGL/include/CGAL/boost/graph/helpers.h +++ b/BGL/include/CGAL/boost/graph/helpers.h @@ -21,29 +21,16 @@ #ifndef CGAL_BOOST_GRAPH_HELPERS_H #define CGAL_BOOST_GRAPH_HELPERS_H - -#include #include #include #include #include -#include #include +#include namespace CGAL { - namespace Euler { - - template< typename Graph> - void fill_hole(typename boost::graph_traits::halfedge_descriptor h, - Graph& g); - - template - typename boost::graph_traits::face_descriptor add_face(const VertexRange& vr, - Graph& g); - }//Euler - /*! \ingroup PkgBGLHelperFct returns `true` if the halfedge `hd` is on a border. @@ -730,674 +717,6 @@ bool is_hexahedron( typename boost::graph_traits::halfedge_descriptor return true; } - - -/** - * \ingroup PkgBGLHelperFct - * \brief Creates an isolated triangle - * with its vertices initialized to `p0`, `p1` and `p2`, and adds it to the graph `g`. - * \returns the non-border halfedge that has the target vertex associated with `p0`. - **/ -template -typename boost::graph_traits::halfedge_descriptor -make_triangle(const P& p0, const P& p1, const P& p2, Graph& g) -{ - typedef typename boost::graph_traits Traits; - typedef typename Traits::halfedge_descriptor halfedge_descriptor; - typedef typename Traits::vertex_descriptor vertex_descriptor; - typedef typename Traits::face_descriptor face_descriptor; - typedef typename boost::property_map::type Point_property_map; - Point_property_map ppmap = get(CGAL::vertex_point, g); - vertex_descriptor v0, v1, v2; - v0 = add_vertex(g); - v1 = add_vertex(g); - v2 = add_vertex(g); - - ppmap[v0] = p0; - ppmap[v1] = p1; - ppmap[v2] = p2; - halfedge_descriptor h0 = halfedge(add_edge(g),g); - halfedge_descriptor h1 = halfedge(add_edge(g),g); - halfedge_descriptor h2 = halfedge(add_edge(g),g); - set_next(h0, h1, g); - set_next(h1, h2, g); - set_next(h2, h0, g); - set_target(h0, v1, g); - set_target(h1, v2, g); - set_target(h2, v0, g); - set_halfedge(v1, h0, g); - set_halfedge(v2, h1, g); - set_halfedge(v0, h2, g); - face_descriptor f = add_face(g); - set_face(h0,f,g); - set_face(h1,f,g); - set_face(h2,f,g); - set_halfedge(f,h0,g); - h0 = opposite(h0,g); - h1 = opposite(h1,g); - h2 = opposite(h2,g); - set_next(h0, h2, g); - set_next(h2, h1, g); - set_next(h1, h0, g); - set_target(h0, v0, g); - set_target(h1, v1, g); - set_target(h2, v2, g); - set_face(h0, boost::graph_traits::null_face(),g); - set_face(h1, boost::graph_traits::null_face(),g); - set_face(h2, boost::graph_traits::null_face(),g); - return opposite(h2,g); -} - -namespace internal { - -template -typename boost::graph_traits::halfedge_descriptor -make_quad(typename boost::graph_traits::vertex_descriptor v0, - typename boost::graph_traits::vertex_descriptor v1, - typename boost::graph_traits::vertex_descriptor v2, - typename boost::graph_traits::vertex_descriptor v3, Graph& g) -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - halfedge_descriptor h0 = halfedge(add_edge(g),g); - halfedge_descriptor h1 = halfedge(add_edge(g),g); - halfedge_descriptor h2 = halfedge(add_edge(g),g); - halfedge_descriptor h3 = halfedge(add_edge(g),g); - set_next(h0, h1, g); - set_next(h1, h2, g); - set_next(h2, h3, g); - set_next(h3, h0, g); - set_target(h0, v1, g); - set_target(h1, v2, g); - set_target(h2, v3, g); - set_target(h3, v0, g); - set_halfedge(v1, h0, g); - set_halfedge(v2, h1, g); - set_halfedge(v3, h2, g); - set_halfedge(v0, h3, g); - face_descriptor f = add_face(g); - set_face(h0,f,g); - set_face(h1,f,g); - set_face(h2,f,g); - set_face(h3,f,g); - set_halfedge(f,h0,g); - h0 = opposite(h0,g); - h1 = opposite(h1,g); - h2 = opposite(h2,g); - h3 = opposite(h3,g); - set_next(h0, h3, g); - set_next(h3, h2, g); - set_next(h2, h1, g); - set_next(h1, h0, g); - set_target(h0, v0, g); - set_target(h1, v1, g); - set_target(h2, v2, g); - set_target(h3, v3, g); - set_face(h0, boost::graph_traits::null_face(),g); - set_face(h1, boost::graph_traits::null_face(),g); - set_face(h2, boost::graph_traits::null_face(),g); - set_face(h3, boost::graph_traits::null_face(),g); - return opposite(h3,g); -} - -//default Functor for make_grid -template -struct Default_grid_maker - : public CGAL::Creator_uniform_3 -{ - Point operator()(const Size_type& i, const Size_type& j)const - { - return CGAL::Creator_uniform_3::operator ()(i,j,0); - } -}; -} // namespace internal - -/** - * \ingroup PkgBGLHelperFct - * \brief Creates an isolated quad with - * its vertices initialized to `p0`, `p1`, `p2`, and `p3`, and adds it to the graph `g`. - * \returns the non-border halfedge that has the target vertex associated with `p0`. - **/ -template -typename boost::graph_traits::halfedge_descriptor -make_quad(const P& p0, const P& p1, const P& p2, const P& p3, Graph& g) -{ - typedef typename boost::graph_traits Traits; - typedef typename Traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::type Point_property_map; - Point_property_map ppmap = get(CGAL::vertex_point, g); - vertex_descriptor v0, v1, v2, v3; - v0 = add_vertex(g); - v1 = add_vertex(g); - v2 = add_vertex(g); - v3 = add_vertex(g); - - ppmap[v0] = p0; - ppmap[v1] = p1; - ppmap[v2] = p2; - ppmap[v3] = p3; - return internal::make_quad(v0, v1, v2, v3, g); -} - -/** - * \ingroup PkgBGLHelperFct - * \brief Creates an isolated hexahedron - * with its vertices initialized to `p0`, `p1`, ...\ , and `p7`, and adds it to the graph `g`. - * \image html hexahedron.png - * \image latex hexahedron.png - * \returns the halfedge that has the target vertex associated with `p0`, in the face with the vertices with the points `p0`, `p1`, `p2`, and `p3`. - **/ -template -typename boost::graph_traits::halfedge_descriptor -make_hexahedron(const P& p0, const P& p1, const P& p2, const P& p3, - const P& p4, const P& p5, const P& p6, const P& p7, Graph& g) -{ - typedef typename boost::graph_traits Traits; - typedef typename Traits::halfedge_descriptor halfedge_descriptor; - typedef typename Traits::vertex_descriptor vertex_descriptor; - - typedef typename boost::property_map::type Point_property_map; - Point_property_map ppmap = get(CGAL::vertex_point, g); - vertex_descriptor v0, v1, v2, v3, v4, v5, v6, v7; - v0 = add_vertex(g); - v1 = add_vertex(g); - v2 = add_vertex(g); - v3 = add_vertex(g); - v4 = add_vertex(g); - v5 = add_vertex(g); - v6 = add_vertex(g); - v7 = add_vertex(g); - ppmap[v0] = p0; - ppmap[v1] = p1; - ppmap[v2] = p2; - ppmap[v3] = p3; - ppmap[v4] = p4; - ppmap[v5] = p5; - ppmap[v6] = p6; - ppmap[v7] = p7; - - halfedge_descriptor ht = internal::make_quad(v4, v5, v6, v7, g); - halfedge_descriptor hb = prev(internal::make_quad(v0, v3, v2, v1, g),g); - for(int i=0; i <4; i++){ - halfedge_descriptor h = halfedge(add_edge(g),g); - set_target(h,target(hb,g),g); - set_next(h,opposite(hb,g),g); - set_next(opposite(prev(ht,g),g),h,g); - h = opposite(h,g); - set_target(h,source(prev(ht,g),g),g); - set_next(h,opposite(next(next(ht,g),g),g),g); - set_next(opposite(next(hb,g),g),h,g); - hb = next(hb,g); - ht = prev(ht,g); - } - for(int i=0; i <4; i++){ - Euler::fill_hole(opposite(hb,g),g); - hb = next(hb,g); - } - return next(next(hb,g),g); -} -/** - * \ingroup PkgBGLHelperFct - * \brief Creates an isolated tetrahedron - * with its vertices initialized to `p0`, `p1`, `p2`, and `p3`, and adds it to the graph `g`. - * \image html tetrahedron.png - * \image latex tetrahedron.png - * \returns the halfedge that has the target vertex associated with `p0`, in the face with the vertices with the points `p0`, `p1`, and `p2`. - **/ -template -typename boost::graph_traits::halfedge_descriptor -make_tetrahedron(const P& p0, const P& p1, const P& p2, const P& p3, Graph& g) -{ - typedef typename boost::graph_traits Traits; - typedef typename Traits::halfedge_descriptor halfedge_descriptor; - typedef typename Traits::vertex_descriptor vertex_descriptor; - typedef typename Traits::face_descriptor face_descriptor; - typedef typename boost::property_map::type Point_property_map; - - Point_property_map ppmap = get(CGAL::vertex_point, g); - vertex_descriptor v0, v1, v2, v3; - v0 = add_vertex(g); - v2 = add_vertex(g); // this and the next line are switched to keep points in order - v1 = add_vertex(g); - v3 = add_vertex(g); - - ppmap[v0] = p0; - ppmap[v1] = p2;// this and the next line are switched to reorient the surface - ppmap[v2] = p1; - ppmap[v3] = p3; - halfedge_descriptor h0 = halfedge(add_edge(g),g); - halfedge_descriptor h1 = halfedge(add_edge(g),g); - halfedge_descriptor h2 = halfedge(add_edge(g),g); - set_next(h0, h1, g); - set_next(h1, h2, g); - set_next(h2, h0, g); - set_target(h0, v1, g); - set_target(h1, v2, g); - set_target(h2, v0, g); - set_halfedge(v1, h0, g); - set_halfedge(v2, h1, g); - set_halfedge(v0, h2, g); - face_descriptor f = add_face(g); - set_face(h0,f,g); - set_face(h1,f,g); - set_face(h2,f,g); - set_halfedge(f,h0,g); - h0 = opposite(h0,g); - h1 = opposite(h1,g); - h2 = opposite(h2,g); - set_next(h0, h2, g); - set_next(h2, h1, g); - set_next(h1, h0, g); - set_target(h0, v0, g); - set_target(h1, v1, g); - set_target(h2, v2, g); - halfedge_descriptor h3 = halfedge(add_edge(g),g); - halfedge_descriptor h4 = halfedge(add_edge(g),g); - halfedge_descriptor h5 = halfedge(add_edge(g),g); - set_target(h3, v3, g); - set_target(h4, v3, g); - set_target(h5, v3, g); - set_halfedge(v3, h3, g); - - set_next(h0, h3, g); - set_next(h1, h4, g); - set_next(h2, h5, g); - - set_next(h3, opposite(h4,g), g); - set_next(h4, opposite(h5,g), g); - set_next(h5, opposite(h3,g), g); - set_next(opposite(h4,g), h0, g); - set_next(opposite(h5,g), h1, g); - set_next(opposite(h3,g), h2, g); - - set_target(opposite(h3,g), v0, g); - set_target(opposite(h4,g), v1, g); - set_target(opposite(h5,g), v2, g); - - f = add_face(g); - set_halfedge(f,h0,g); - set_face(h0, f, g); - set_face(h3, f, g); - set_face(opposite(h4,g), f, g); - f = add_face(g); - set_halfedge(f,h1,g); - set_face(h1, f, g); - set_face(h4, f, g); - set_face(opposite(h5,g), f, g); - f = add_face(g); - set_halfedge(f,h2,g); - set_face(h2, f, g); - set_face(h5, f, g); - set_face(opposite(h3,g), f, g); - - return opposite(h2,g); -} - -/** - * \ingroup PkgBGLHelperFct - * \brief Creates a triangulated regular prism, outward oriented, - * having `nb_vertices` vertices in each of its bases and adds it to the graph `g`. - * If `center` is (0, 0, 0), then the first point of the prism is (`radius`, `height`, 0) - * \param nb_vertices the number of vertices per base. It must be greater than or equal to 3. - * \param g the graph in which the regular prism will be created. - * \param base_center the center of the circle in which the lower base is inscribed. - * \param height the distance between the two bases. - * \param radius the radius of the circles in which the bases are inscribed. - * \param is_closed determines if the bases must be created or not. If `is_closed` is `true`, `center` is a vertex. - * \returns the halfedge that has the target vertex associated with the first point in the first face. - */ -template -typename boost::graph_traits::halfedge_descriptor -make_regular_prism( - typename boost::graph_traits::vertices_size_type nb_vertices, - Graph& g, - const P& base_center = P(0,0,0), - typename CGAL::Kernel_traits

::Kernel::FT height = 1.0, - typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0, - bool is_closed = true) -{ - CGAL_assertion(nb_vertices >= 3); - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::Kernel_traits

::Kernel::FT FT; - - const FT to_rad = CGAL_PI / 180.0; - const FT precision = 360.0/nb_vertices; - const FT diameter = 2*radius; - Point_property_map vpmap = get(CGAL::vertex_point, g); - std::vector vertices; - vertices.resize(nb_vertices*2); - for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i < nb_vertices; ++i) - { - put(vpmap, - vertices[i], - P(0.5*diameter*cos(i*precision*to_rad)+base_center.x(), - height+base_center.y(), - -0.5*diameter*sin(i*precision*to_rad) + base_center.z())); - - put(vpmap, - vertices[i+nb_vertices], - P(0.5*diameter*cos(i*precision*to_rad)+base_center.x(), - base_center.y(), - -0.5*diameter*sin(i*precision*to_rad)+base_center.z())); - } - std::vector face; - face.resize(3); - //fill faces - for(typename boost::graph_traits::vertices_size_type i=0; i::vertices_size_type i=0; i -typename boost::graph_traits::halfedge_descriptor -make_pyramid( - typename boost::graph_traits::vertices_size_type nb_vertices, - Graph& g, - const P& base_center = P(0,0,0), - typename CGAL::Kernel_traits

::Kernel::FT height = 1.0, - typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0, - bool is_closed = true) -{ - CGAL_assertion(nb_vertices >= 3); - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::Kernel_traits

::Kernel::FT FT; - const FT to_rad = CGAL_PI / 180.0; - const FT precision = 360.0/nb_vertices; - const FT diameter = 2*radius; - Point_property_map vpmap = get(CGAL::vertex_point, g); - std::vector vertices; - vertices.resize(nb_vertices); - for(typename boost::graph_traits::vertices_size_type i=0; - i::vertices_size_type i=0; - i < nb_vertices; ++i) - { - - put(vpmap, - vertices[i], - P(0.5*diameter*cos(i*precision*to_rad)+base_center.x(), - base_center.y(), - -0.5*diameter*sin(i*precision*to_rad)+base_center.z())); - } - std::vector face; - face.resize(3); - //fill faces - for(typename boost::graph_traits::vertices_size_type i=0; - i::vertices_size_type i=0; - i -typename boost::graph_traits::halfedge_descriptor -make_icosahedron( - Graph& g, - const P& center = P(0,0,0), - typename CGAL::Kernel_traits

::Kernel::FT radius = 1.0) -{ - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Point_property_map vpmap = get(CGAL::vertex_point, g); - // create the initial icosahedron - std::vector v_vertices; - v_vertices.resize(12); - for(int i=0; i<12; ++i) - v_vertices[i] = add_vertex(g); - typename CGAL::Kernel_traits

::Kernel::FT t = - (radius + radius*CGAL::approximate_sqrt(5.0)) / 2.0; - - put(vpmap, v_vertices[0],P(-radius + center.x(), t + center.y(), 0.0 + center.z())); - put(vpmap, v_vertices[1],P( radius + center.x(), t + center.y(), 0.0 + center.z())); - put(vpmap, v_vertices[2],P(-radius + center.x(), -t + center.y(), 0.0 + center.z())); - put(vpmap, v_vertices[3],P( radius + center.x(), -t + center.y(), 0.0 + center.z())); - - put(vpmap, v_vertices[4],P( 0.0 + center.x(), -radius + center.y(), t + center.z())); - put(vpmap, v_vertices[5],P( 0.0 + center.x(), radius + center.y(), t + center.z())); - put(vpmap, v_vertices[6],P( 0.0 + center.x(), -radius + center.y(), -t + center.z())); - put(vpmap, v_vertices[7],P( 0.0 + center.x(), radius + center.y(), -t + center.z())); - - put(vpmap, v_vertices[8],P( t + center.x(), 0.0 + center.y(), -radius + center.z())); - put(vpmap, v_vertices[9],P( t + center.x(), 0.0 + center.y(), radius + center.z())); - put(vpmap, v_vertices[10],P(-t + center.x(), 0.0 + center.y(), -radius + center.z())); - put(vpmap, v_vertices[11],P(-t + center.x(), 0.0 + center.y(), radius + center.z())); - - std::vector face; - face.resize(3); - face[1] = v_vertices[0]; face[0] = v_vertices[5]; face[2] = v_vertices[11]; - Euler::add_face(face, g); - face[1] = v_vertices[0]; face[0] = v_vertices[1]; face[2] = v_vertices[5]; - Euler::add_face(face, g); - face[1] = v_vertices[0]; face[0] = v_vertices[7]; face[2] = v_vertices[1]; - Euler::add_face(face, g); - face[1] = v_vertices[0]; face[0] = v_vertices[10]; face[2] = v_vertices[7]; - Euler::add_face(face, g); - face[1] = v_vertices[0]; face[0] = v_vertices[11]; face[2] = v_vertices[10]; - Euler::add_face(face, g); - - face[1] = v_vertices[1] ; face[0] = v_vertices[9] ; face[2] = v_vertices[5]; - Euler::add_face(face, g); - face[1] = v_vertices[5] ; face[0] = v_vertices[4]; face[2] = v_vertices[11]; - Euler::add_face(face, g); - face[1] = v_vertices[11]; face[0] = v_vertices[2]; face[2] = v_vertices[10]; - Euler::add_face(face, g); - face[1] = v_vertices[10]; face[0] = v_vertices[6] ; face[2] = v_vertices[7]; - Euler::add_face(face, g); - face[1] = v_vertices[7] ; face[0] = v_vertices[8] ; face[2] = v_vertices[1]; - Euler::add_face(face, g); - - face[1] = v_vertices[3] ; face[0] = v_vertices[4] ; face[2] = v_vertices[9]; - Euler::add_face(face, g); - face[1] = v_vertices[3] ; face[0] = v_vertices[2] ; face[2] = v_vertices[4]; - Euler::add_face(face, g); - face[1] = v_vertices[3] ; face[0] = v_vertices[6] ; face[2] = v_vertices[2]; - Euler::add_face(face, g); - face[1] = v_vertices[3] ; face[0] = v_vertices[8] ; face[2] = v_vertices[6]; - Euler::add_face(face, g); - face[1] = v_vertices[3] ; face[0] = v_vertices[9] ; face[2] = v_vertices[8]; - Euler::add_face(face, g); - - face[1] = v_vertices[4] ; face[0] = v_vertices[5] ; face[2] = v_vertices[9] ; - Euler::add_face(face, g); - face[1] = v_vertices[2] ; face[0] = v_vertices[11] ; face[2] = v_vertices[4]; - Euler::add_face(face, g); - face[1] = v_vertices[6] ; face[0] = v_vertices[10] ; face[2] = v_vertices[2]; - Euler::add_face(face, g); - face[1] = v_vertices[8] ; face[0] = v_vertices[7] ; face[2] = v_vertices[6] ; - Euler::add_face(face, g); - face[1] = v_vertices[9] ; face[0] = v_vertices[1] ; face[2] = v_vertices[8] ; - Euler::add_face(face, g); - - return halfedge(v_vertices[1], v_vertices[0], g).first; -} - - -/*! - * \ingroup PkgBGLHelperFct - * - * \brief Creates a row major ordered grid with `i` cells along the width and `j` cells - * along the height and adds it to the graph `g`. - * An internal property map for `CGAL::vertex_point_t` must be available in `Graph`. - * - * \param i the number of cells along the width. - * \param j the number of cells along the height. - * \param g the graph in which the grid will be created. - * \param calculator the functor that will assign coordinates to the grid vertices. - * \param triangulated decides if a cell is composed of one quad or two triangles. - * If `triangulated` is `true`, the diagonal of each cell is oriented from (0,0) to (1,1) - * in the cell coordinates. - *\tparam CoordinateFunctor a function object providing `Point_3 operator()(size_type I, size_type J)` with `Point_3` being - * the value_type of the internal property_map for `CGAL::vertex_point_t`. - * and outputs a `boost::property_traits::%type>::%value_type`. - * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`]. - *

%Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] - * \returns the non-border non-diagonal halfedge that has the target vertex associated with the first point of the grid (default is (0,0,0) ). - */ -template -typename boost::graph_traits::halfedge_descriptor -make_grid(typename boost::graph_traits::vertices_size_type i, - typename boost::graph_traits::vertices_size_type j, - Graph& g, - const CoordinateFunctor& calculator, - bool triangulated = false) -{ - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typename boost::graph_traits::vertices_size_type w(i+1), h(j+1); - Point_property_map vpmap = get(CGAL::vertex_point, g); - //create the vertices - std::vector v_vertices; - v_vertices.resize(static_cast(w*h)); - for(std::size_t k = 0; k < v_vertices.size(); ++k) - v_vertices[k] = add_vertex(g); - //assign the coordinates - for(typename boost::graph_traits::vertices_size_type a = 0; a::vertices_size_type b=0; b face; - if(triangulated) - face.resize(3); - else - face.resize(4); - for(typename boost::graph_traits::vertices_size_type a = 0; a::vertices_size_type b = 0; b -typename boost::graph_traits::halfedge_descriptor -make_grid(typename boost::graph_traits::vertices_size_type w, - typename boost::graph_traits::vertices_size_type h, - Graph& g, - bool triangulated = false) -{ - typedef typename boost::graph_traits::vertices_size_type Size_type; - typedef typename boost::property_traits::type>::value_type Point; - return make_grid(w, h, g, internal::Default_grid_maker(), triangulated); -} - namespace internal { template @@ -1556,10 +875,86 @@ bool is_empty(const FaceGraph& g) return boost::empty(vertices(g)); } +/// \ingroup PkgBGLHelperFct +/// +/// \brief returns the number of calls to `next()` one has to apply to the halfedge `hd` +/// for `source(hd, mesh) == vd` to be true, starting from `hd = halfedge(fd, tm)`. +/// +/// \tparam Graph a model of `FaceGraph` +/// +/// \param vd a vertex of `g` whose index is sought +/// \param fd a face of `g` in which the index of `vd` is sought +/// \param g a mesh of type `Graph` +/// +/// \pre `vd` is a vertex of `fd`. +template +int vertex_index_in_face(const typename boost::graph_traits::vertex_descriptor vd, + const typename boost::graph_traits::face_descriptor fd, + const Graph& g) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + halfedge_descriptor start = halfedge(fd, g); + halfedge_descriptor current = start; + int counter = 0; + + do + { + if(source(current, g) == vd) + break; + + ++counter; + current = next(current, g); + } + while(current != start); + + if(counter != 0 && current == start) + { + CGAL_assertion_msg(false, "Could not find vertex in face"); + return -1; + } + + return counter; +} + +/// \ingroup PkgBGLHelperFct +/// +/// \brief returns the number of calls to `next(hd, tm)` one has to apply to `hd` for `hd == he` +/// to be true, starting from `hd = halfedge(face(he, tm), tm)`. +/// +/// \tparam Graph a model of `FaceGraph`. +/// +/// \param he a halfedge of `g` whose index in `face(he, tm)` is sought +/// \param g an object of type `Graph` +/// +template +int halfedge_index_in_face(typename boost::graph_traits::halfedge_descriptor he, + const Graph& g) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + CGAL_precondition(he != boost::graph_traits::null_halfedge()); + CGAL_precondition(!is_border(he, g)); + + face_descriptor f = face(he, g); + halfedge_descriptor start = halfedge(f, g); + halfedge_descriptor current = start; + int count = 0; + + while(current != he) + { + current = next(current, g); + ++count; + } + + return count; +} + } // namespace CGAL -// Include "Euler_operations.h" at the end, because its implementation -// requires this header. -#include +// Here at the bottom because helpers.h must include generators (for backward compatibility reasons), +// and Euler_operations.h needs helpers.h +#include #endif // CGAL_BOOST_GRAPH_HELPERS_H diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 3273de59c53..da7517a15de 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -83,6 +83,7 @@ CGAL_add_named_parameter(output_iterator_t, output_iterator, output_iterator) CGAL_add_named_parameter(erase_all_duplicates_t, erase_all_duplicates, erase_all_duplicates) CGAL_add_named_parameter(require_same_orientation_t, require_same_orientation, require_same_orientation) CGAL_add_named_parameter(face_size_map_t, face_size_map, face_size_map) +CGAL_add_named_parameter(snapping_tolerance_t, snapping_tolerance, snapping_tolerance) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost) diff --git a/BGL/package_info/BGL/dependencies b/BGL/package_info/BGL/dependencies index 4a55ee6163f..ebc36eadd85 100644 --- a/BGL/package_info/BGL/dependencies +++ b/BGL/package_info/BGL/dependencies @@ -18,5 +18,6 @@ Modular_arithmetic Number_types Profiling_tools Property_map +Random_numbers STL_Extension Stream_support diff --git a/BGL/test/BGL/graph_concept_Triangulation_2.cpp b/BGL/test/BGL/graph_concept_Triangulation_2.cpp index a62819f5c0c..951e4beb2bc 100644 --- a/BGL/test/BGL/graph_concept_Triangulation_2.cpp +++ b/BGL/test/BGL/graph_concept_Triangulation_2.cpp @@ -1,4 +1,5 @@ #include + #include #include #include @@ -40,6 +41,8 @@ void concept_check_triangulation() boost::function_requires< CGAL::HalfedgeListGraphConcept >(); boost::function_requires< CGAL::FaceGraphConcept >(); boost::function_requires< CGAL::FaceListGraphConcept >(); + + // Triangulations are not mutable graphs // boost::function_requires< CGAL::MutableHalfedgeGraphConcept >(); // boost::function_requires< CGAL::MutableFaceGraphConcept >(); @@ -59,6 +62,6 @@ int main() concept_check_triangulation(); concept_check_triangulation(); concept_check_triangulation(); - + return 0; } diff --git a/BGL/test/BGL/test_Has_member_id.cpp b/BGL/test/BGL/test_Has_member_id.cpp index e04d040c86d..6ff478d04c2 100644 --- a/BGL/test/BGL/test_Has_member_id.cpp +++ b/BGL/test/BGL/test_Has_member_id.cpp @@ -2,9 +2,13 @@ #include #include + #include #include +#include +#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Polyhedron_3 Polyhedron; typedef CGAL::Polyhedron_3 Polyhedron_with_ids; @@ -32,5 +36,9 @@ int main() CGAL_static_assertion( (Has_member_id::Face>::value)); + CGAL_static_assertion(!Has_member_id >::value); + CGAL_static_assertion(Has_member_id >::value); + CGAL_static_assertion(Has_member_id >::value); + return 0; } diff --git a/BGL/test/BGL/test_Prefix.h b/BGL/test/BGL/test_Prefix.h index 8aacfd12f99..e5343a10659 100644 --- a/BGL/test/BGL/test_Prefix.h +++ b/BGL/test/BGL/test_Prefix.h @@ -1,8 +1,6 @@ #ifndef CGAL_TEST_PREFIX_H #define CGAL_TEST_PREFIX_H -#define CGAL_USE_SURFACE_MESH - #include #include @@ -12,14 +10,34 @@ #include #include + #include #include #include -#ifdef CGAL_USE_SURFACE_MESH #include #include -#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -37,10 +55,7 @@ typedef CGAL::Linear_cell_complex_traits<3, Kernel> MyTraits; typedef CGAL::Linear_cell_complex_for_bgl_combinatorial_map_helper <2, 3, MyTraits>::type LCC; - -#ifdef CGAL_USE_SURFACE_MESH typedef CGAL::Surface_mesh SM; -#endif #if defined(CGAL_USE_OPENMESH) @@ -55,6 +70,31 @@ typedef CGAL::Surface_mesh SM; typedef OpenMesh::PolyMesh_ArrayKernelT OMesh; #endif +typedef CGAL::Triangulation_vertex_base_with_id_2 Vbb; +typedef CGAL::Triangulation_face_base_with_id_2 Fbb; + +typedef CGAL::Triangulation_2 > Triangulation_2; +typedef CGAL::Delaunay_triangulation_2 > Delaunay_triangulation_2; + +typedef CGAL::Regular_triangulation_vertex_base_2 RVb; +typedef CGAL::Regular_triangulation_face_base_2 RFb; +typedef CGAL::Regular_triangulation_2 > Regular_triangulation_2; + +typedef CGAL::Constrained_triangulation_face_base_2 CDFb; +typedef CGAL::Triangulation_hierarchy_vertex_base_2 CDVb; +typedef CGAL::Constrained_triangulation_2 > Constrained_triangulation_2; +typedef CGAL::Constrained_Delaunay_triangulation_2 > Constrained_Delaunay_triangulation_2; + +typedef CGAL::Constrained_triangulation_plus_2< + Constrained_Delaunay_triangulation_2> CDT_P2; + +typedef CGAL::Triangulation_hierarchy_2 Triangulation_hierarchy_2; + #include // helper to easily define all graph_traits members @@ -137,21 +177,46 @@ std::vector t_data() return vs; } -std::vector poly_data() -{ return t_data(); } - -#if defined(CGAL_USE_SURFACE_MESH) -std::vector sm_data() -{ return t_data(); } -#endif +std::vector poly_data() { return t_data(); } +std::vector sm_data() { return t_data(); } +std::vector lcc_data() { return t_data(); } #if defined(CGAL_USE_OPENMESH) -std::vector omesh_data() -{ return t_data(); } +std::vector omesh_data() { return t_data(); } #endif -std::vector lcc_data() -{ return t_data(); } +template +Tr build_dummy_triangulation() +{ + typedef typename Tr::Point Point; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + Tr t; + t.insert(Point(0.1,0)); + t.insert(Point(1,0)); + t.insert(Point(0.2,0.2)); + t.insert(Point(0,1)); + t.insert(Point(0,2)); + + int id = 0; + for(vertex_descriptor vd : vertices(t)) + vd->id() = id++; + + id = 0; + for(face_descriptor fd : faces(t)) + fd->id() = id++; + + return t; +} + +Triangulation_2 t2_data() { return build_dummy_triangulation(); } +Delaunay_triangulation_2 dt2_data() { return build_dummy_triangulation(); } +Regular_triangulation_2 rt2_data() { return build_dummy_triangulation(); } +Constrained_triangulation_2 ct2_data() { return build_dummy_triangulation(); } +Constrained_Delaunay_triangulation_2 cdt2_data() { return build_dummy_triangulation(); } +CDT_P2 cdtp2_data() { return build_dummy_triangulation(); } +Triangulation_hierarchy_2 t2h_data() { return build_dummy_triangulation(); } template struct Surface_fixture_1 { diff --git a/BGL/test/BGL/test_Properties.cpp b/BGL/test/BGL/test_Properties.cpp index 07975c24940..3ffd9d1720e 100644 --- a/BGL/test/BGL/test_Properties.cpp +++ b/BGL/test/BGL/test_Properties.cpp @@ -1,5 +1,5 @@ - #include "test_Prefix.h" + #include template< typename G, @@ -31,7 +31,6 @@ void index_uniqueness(const G&, void index_uniqueness_poly(const Polyhedron& g) { - std::cerr << "testing Polyhedron\n"; index_uniqueness(g, edges(g) , get(boost::edge_index, g)); index_uniqueness(g, vertices(g), get(boost::vertex_index, g)); index_uniqueness(g, faces(g), get(boost::face_index, g)); @@ -45,28 +44,23 @@ void index_uniqueness_poly(const Polyhedron& g) void index_uniqueness_lcc(const LCC& g) { - std::cerr << "testing Linear_cell_complex\n"; index_uniqueness(g, edges(g) , get(boost::edge_index, g)); index_uniqueness(g, vertices(g), get(boost::vertex_index, g)); index_uniqueness(g, faces(g), get(boost::face_index, g)); index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g)); } -#if defined(CGAL_USE_SURFACE_MESH) void index_uniqueness_sm(const SM& g) { - std::cerr << "testing Surface_mesh\n"; index_uniqueness(g, edges(g) , get(boost::edge_index, g)); index_uniqueness(g, vertices(g), get(boost::vertex_index, g)); index_uniqueness(g, faces(g), get(boost::face_index, g)); index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g)); } -#endif #if defined(CGAL_USE_OPENMESH) void index_uniqueness_omesh(const OMesh& g) { - std::cerr << "testing OpenMesh\n"; index_uniqueness(g, edges(g) , get(boost::edge_index, g)); index_uniqueness(g, vertices(g), get(boost::vertex_index, g)); index_uniqueness(g, faces(g), get(boost::face_index, g)); @@ -74,35 +68,48 @@ void index_uniqueness_omesh(const OMesh& g) } #endif -int -main() +template +void index_uniqueness_tr(const Triangulation& g) { + index_uniqueness(g, edges(g) , get(boost::edge_index, g)); + index_uniqueness(g, vertices(g), get(boost::vertex_index, g)); + index_uniqueness(g, faces(g), get(boost::face_index, g)); + index_uniqueness(g, halfedges(g), get(boost::halfedge_index, g)); +} + +int main() +{ + std::cout << "testing Polyhedron\n"; std::vector polys = poly_data(); - - for(Polyhedron p : polys){ + for(Polyhedron p : polys) index_uniqueness_poly(p); - } + std::cout << "testing Linear_cell_complex\n"; std::vector lccs = lcc_data(); - for(LCC p : lccs){ + for(LCC p : lccs) index_uniqueness_lcc(p); - } -#if defined(CGAL_USE_SURFACE_MESH) + std::cout << "testing Surface_mesh\n"; std::vector sms = sm_data(); - - for(SM p : sms){ + for(SM p : sms) index_uniqueness_sm(p); - } -#endif #if defined(CGAL_USE_OPENMESH) + std::cout << "testing OpenMesh\n"; std::vector omeshs = omesh_data(); - for(OMesh p : omeshs){ + for(OMesh p : omeshs) index_uniqueness_omesh(p); - } #endif + std::cout << "testing Triangulations\n"; + index_uniqueness_tr(t2_data()); + index_uniqueness_tr(dt2_data()); + index_uniqueness_tr(rt2_data()); + index_uniqueness_tr(ct2_data()); + index_uniqueness_tr(cdt2_data()); + index_uniqueness_tr(cdtp2_data()); + index_uniqueness_tr(t2h_data()); + std::cerr << "done\n"; return 0; } diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index e797e2b3398..dead4cbdb85 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -88,6 +88,7 @@ void test(const NamedParameters& np) assert(get_param(np, CGAL::internal_np::require_same_orientation).v == 49); assert(get_param(np, CGAL::internal_np::use_bool_op_to_clip_surface).v == 50); assert(get_param(np, CGAL::internal_np::face_size_map).v == 52); + assert(get_param(np, CGAL::internal_np::snapping_tolerance).v == 57); // Named parameters that we use in the package 'Surface Mesh Simplification' assert(get_param(np, CGAL::internal_np::get_cost_policy).v == 34); @@ -169,6 +170,7 @@ void test(const NamedParameters& np) check_same_type<49>(get_param(np, CGAL::internal_np::require_same_orientation)); check_same_type<50>(get_param(np, CGAL::internal_np::use_bool_op_to_clip_surface)); check_same_type<52>(get_param(np, CGAL::internal_np::face_size_map)); + check_same_type<57>(get_param(np, CGAL::internal_np::snapping_tolerance)); // Named parameters that we use in the package 'Surface Mesh Simplification' check_same_type<34>(get_param(np, CGAL::internal_np::get_cost_policy)); @@ -254,6 +256,7 @@ int main() .erase_all_duplicates(A<48>(48)) .require_same_orientation(A<49>(49)) .face_size_map(A<52>(52)) + .snapping_tolerance(A<57>(57)) ); return EXIT_SUCCESS; diff --git a/BGL/test/BGL/test_graph_traits.cpp b/BGL/test/BGL/test_graph_traits.cpp index 102b04ff3ba..58144b4e366 100644 --- a/BGL/test/BGL/test_graph_traits.cpp +++ b/BGL/test/BGL/test_graph_traits.cpp @@ -1,11 +1,11 @@ - - #include "test_Prefix.h" -#include -#include + #include -typedef boost::unordered_set id_map; +#include +#include + +typedef boost::unordered_set id_map; template void test_isolated_vertex() @@ -58,6 +58,29 @@ void test_halfedge_around_face_iterator(const Graph& g) } } +template +void test_halfedge_iterators(const G& g) +{ + typedef boost::graph_traits< G > Traits; + typedef typename Traits::halfedge_iterator halfedge_iterator; + typedef typename Traits::halfedges_size_type halfedges_size_type; + + // do we iterate as many as that? + halfedge_iterator hb, he; + boost::tie(hb, he) = halfedges(g); + assert(boost::numeric_cast(std::distance(hb, he)) == num_halfedges(g)); + + id_map ids; + unsigned int count = 0; + for(boost::tie(hb, he) = halfedges(g); hb != he; ++hb) { + std::pair r = ids.insert(get(boost::halfedge_index, g, *hb)); + // unique? + assert(r.second); + ++count; + } + assert(count == num_halfedges(g)); +} + template void test_edge_iterators(const G& g) { @@ -86,7 +109,7 @@ void test_edge_iterators(const G& g) } template -void test_vertex_iterators(G& g) +void test_vertex_iterators(const G& g) { typedef boost::graph_traits< G > Traits; typedef typename Traits::vertex_iterator vertex_iterator; @@ -203,6 +226,41 @@ void test_in_out_edges(const G& g) } } +template +void test_adjacent_vertices(const G& g) +{ + typedef boost::graph_traits< G > Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::in_edge_iterator in_edge_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::adjacency_iterator adjacency_iterator; + typedef std::pair ret; + + vertex_descriptor v = *(vertices(g).begin()); + + adjacency_iterator vb, ve; + boost::tie(vb, ve) = adjacent_vertices(v, g); + + in_edge_iterator ieb, iee; + boost::tie(ieb, iee) = in_edges(v, g); + + out_edge_iterator oeb, oee; + boost::tie(oeb, oee) = out_edges(v, g); + + assert(std::distance(vb, ve) == std::distance(ieb, iee)); + assert(std::distance(vb, ve) == std::distance(oeb, oee)); + + for(; vb != ve; ++vb) + { + vertex_descriptor s = *vb; + assert(s != v); + assert(s != Traits::null_vertex()); + ret found = edge(s, v, g); + assert(found.second); + } +} + // check that every edge can be found through edge(u, v, g) template void test_edge_find(const G& g) @@ -256,39 +314,56 @@ void test_read(const G& g) assert(CGAL::is_valid_polygon_mesh(g)); } - template -void -test(const std::vector& graphs) +void test_const_graph(const Graph& g) { - for(const Graph& p : graphs){ - test_edge_iterators(p); - test_read(p); - test_vertex_iterators(p); - test_out_edges(p); - test_in_edges(p); - test_in_out_edges(p); - test_edge_find(p); - test_faces(p); - test_halfedge_around_vertex_iterator(p); - test_halfedge_around_face_iterator(p); - } - test_isolated_vertex(); + test_vertex_iterators(g); + test_halfedge_iterators(g); + test_edge_iterators(g); + test_read(g); + test_out_edges(g); + test_in_edges(g); + test_in_out_edges(g); +// test_adjacent_vertices(g); + test_edge_find(g); + test_faces(g); + test_halfedge_around_vertex_iterator(g); + test_halfedge_around_face_iterator(g); } -int -main() +template +void test_graph_range(const std::vector& graphs) { - test(poly_data()); + for(const Graph& g : graphs) + { + test_const_graph(g); + test_isolated_vertex(); + } +} - test(lcc_data()); +int main() +{ + std::cout << "Test polyhedron data..." << std::endl; + test_graph_range(poly_data()); -#if defined(CGAL_USE_SURFACE_MESH) - test(sm_data()); -#endif + std::cout << "Test LCC data..." << std::endl; + test_graph_range(lcc_data()); + + std::cout << "Test Surface_mesh data..." << std::endl; + test_graph_range(sm_data()); + + std::cout << "Test T2 data..." << std::endl; + test_const_graph(t2_data()); + test_const_graph(dt2_data()); + test_const_graph(rt2_data()); + test_const_graph(ct2_data()); + test_const_graph(cdt2_data()); + test_const_graph(cdtp2_data()); + test_const_graph(t2h_data()); #if defined(CGAL_USE_OPENMESH) - test(omesh_data()); + std::cout << "Test OpenMesh data..." << std::endl; + test_graph_range(omesh_data()); #endif std::cerr << "done" << std::endl; diff --git a/BGL/test/BGL/test_helpers.cpp b/BGL/test/BGL/test_helpers.cpp index 3ba16eb4d6e..2464a60150a 100644 --- a/BGL/test/BGL/test_helpers.cpp +++ b/BGL/test/BGL/test_helpers.cpp @@ -1,40 +1,31 @@ -#include -#include +#include #include #include -#include + +#include #include #include -typedef CGAL::Simple_cartesian K; -typedef K::Point_3 Point_3; +#include +#include +typedef CGAL::Simple_cartesian K; +typedef K::Point_3 Point_3; template -void -test(const char *fname, bool triangle, bool quad, bool tetrahedron, bool hexahedron) +void test_validity() { - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - std::cerr << "test(" << fname << ")"<< std::endl; - Mesh m; - std::ifstream in(fname); - in >> m; - halfedge_descriptor hd = *halfedges(m).first; - assert(CGAL::is_isolated_triangle(hd, m) == triangle); - assert(CGAL::is_isolated_quad(hd, m) == quad); - assert(CGAL::is_tetrahedron(hd, m) == tetrahedron); - assert(CGAL::is_hexahedron(hd, m) == hexahedron); - } + std::cerr << "test validity" << std::endl; -template -void -test_validity(Mesh& mesh) -{ typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::property_map::type VPMap; + + Mesh mesh; VPMap vpmap = get(CGAL::vertex_point, mesh); + vertex_descriptor vertices[4]; edge_descriptor edges[4]; vertices[0] = add_vertex(mesh); @@ -100,11 +91,32 @@ test_validity(Mesh& mesh) } -int main() +template +void test(const char *fname, bool triangle, bool quad, bool tetrahedron, bool hexahedron) { - typedef CGAL::Surface_mesh Mesh; - Mesh mesh; - test_validity(mesh); + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + std::cerr << "test(" << fname << ")"<< std::endl; + + Mesh m; + std::ifstream in(fname); + in >> m; + + halfedge_descriptor hd = *halfedges(m).first; + assert(CGAL::is_isolated_triangle(hd, m) == triangle); + assert(CGAL::is_isolated_quad(hd, m) == quad); + assert(CGAL::is_tetrahedron(hd, m) == tetrahedron); + assert(CGAL::is_hexahedron(hd, m) == hexahedron); +} + +template +void test_generators() +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + // triangle quad tetra hexa test("data/triangle.off", true, false, false, false ); test("data/quad.off", false, true, false, false ); @@ -112,20 +124,21 @@ int main() test("data/cube.off", false, false, false, false ); test("data/cube-quads.off", false, false, false, true ); - typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; - Point_3 a(0,0,0), b(1,0,0), c(1,1,0), d(0,1,0); Point_3 aa(0,0,1), bb(1,0,1), cc(1,1,1), dd(0,1,1); + Mesh m; halfedge_descriptor hd; hd = CGAL::make_triangle(a,b,c,m); assert(CGAL::is_isolated_triangle(hd,m)); assert(CGAL::is_valid_polygon_mesh(m)); + m.clear(); hd = CGAL::make_quad(a,b,c,d,m); assert(CGAL::is_isolated_quad(hd,m)); assert(CGAL::is_valid_polygon_mesh(m)); assert(CGAL::is_quad_mesh(m)); + m.clear(); hd = CGAL::make_tetrahedron(a,b,c,d,m); assert(CGAL::is_tetrahedron(hd,m)); @@ -136,26 +149,86 @@ int main() assert(CGAL::is_hexahedron(hd,m)); assert(CGAL::is_quad_mesh(m)); assert(CGAL::is_valid_polygon_mesh(m)); + m.clear(); CGAL::make_icosahedron(m); assert(num_faces(m) == 20); assert(CGAL::is_triangle_mesh(m)); assert(CGAL::is_valid_polygon_mesh(m)); + m.clear(); hd = CGAL::make_pyramid(3, m); assert(num_faces(m) == 6); assert(CGAL::is_triangle_mesh(m)); assert(CGAL::is_valid_polygon_mesh(m)); + m.clear(); hd = CGAL::make_regular_prism(4, m); assert(num_faces(m) == 16); assert(CGAL::is_triangle_mesh(m)); assert(CGAL::is_valid_polygon_mesh(m)); + m.clear(); CGAL::make_grid(3,3,m); assert(num_faces(m) == 9); assert(CGAL::is_quad_mesh(m)); assert(CGAL::is_valid_polygon_mesh(m)); - std::cerr << "done" << std::endl; - return 0; + + // ----------------------------------------------------------------------------------------------- + + std::cerr << "test random element generators" << std::endl; + + vertex_descriptor v; + halfedge_descriptor h; + edge_descriptor e; + face_descriptor f; + + CGAL::Random rnd; + + // --------------------------------------------------------------------------- + v = CGAL::internal::random_vertex_in_mesh(m, rnd); + assert(v != boost::graph_traits::null_vertex()); + + h = CGAL::internal::random_halfedge_in_mesh(m, rnd); + assert(h != boost::graph_traits::null_halfedge()); + + e = CGAL::internal::random_edge_in_mesh(m, rnd); + + f = CGAL::internal::random_face_in_mesh(m, rnd); + assert(f != boost::graph_traits::null_face()); + + // --------------------------------------------------------------------------- + h = CGAL::internal::random_halfedge_in_face(f, m, rnd); + assert(h != boost::graph_traits::null_halfedge()); + assert(face(h, m) == f); + + v = CGAL::internal::random_vertex_in_face(f, m, rnd); + assert(v != boost::graph_traits::null_vertex()); + + // could use vertices_around_face, but it's the point is not to + bool has_vertex = false; + halfedge_descriptor done = h; + do + { + if(target(h, m) == v) + { + has_vertex = true; + break; + } + + h = next(h, m); + } + while(h != done); + assert(has_vertex); +} + +int main() +{ + typedef CGAL::Surface_mesh Mesh; + + test_validity(); + test_generators(); + + std::cerr << "done" << std::endl; + return EXIT_SUCCESS; } diff --git a/Convex_decomposition_3/package_info/Convex_decomposition_3/dependencies b/Convex_decomposition_3/package_info/Convex_decomposition_3/dependencies index 607af68f95f..67573918303 100644 --- a/Convex_decomposition_3/package_info/Convex_decomposition_3/dependencies +++ b/Convex_decomposition_3/package_info/Convex_decomposition_3/dependencies @@ -28,6 +28,7 @@ Polyhedron Polyhedron_IO Profiling_tools Property_map +Random_numbers STL_Extension Spatial_sorting Stream_support diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index 87de0bf0782..ffd68c8819d 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -55,6 +55,7 @@ #include #include #include +#include #include #include diff --git a/Heat_method_3/package_info/Heat_method_3/dependencies b/Heat_method_3/package_info/Heat_method_3/dependencies index 31c24f8489e..90510db1ab2 100644 --- a/Heat_method_3/package_info/Heat_method_3/dependencies +++ b/Heat_method_3/package_info/Heat_method_3/dependencies @@ -14,6 +14,7 @@ Number_types Polygon_mesh_processing Profiling_tools Property_map +Random_numbers STL_Extension Solver_interface Stream_support diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 539996c0312..ce3590e59ab 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -24,7 +24,16 @@ Release date: September 2019 for all vertices, which enables to use C++11 for-loops. - **Breaking change**: The constructor and the `insert()` function of `CGAL::Triangulation_3` which takes a range of points as argument no longer performs a `spatial_sort()` of the points. -- Add constructor and `insert()` function to `CGAL::Triangulation_3` that takes a range of points with info. + - Added constructor and `insert()` function to `CGAL::Triangulation_3` that takes a range of points with info. + - **breaking change** The graph traits enabling CGAL's 2D triangulations to be used as a parameter + for any graph-based algorithm of CGAL (or boost) have been improved to fully model the `FaceGraph` concept. + In addition, only the finite simplicies (those not incident to the infinite vertex) of the 2D triangulations + are now visibile through this scope. The complete triangulation can still be accessed as a graph, + by using the graph traits of the underlying triangulation data structure (usually, + `CGAL::Triangulation_data_structure_2`). + - Introduced a new face base class, `Triangulation_face_base_with_id_2` which enables storing + user-defined integer IDs in the face of any 2D triangulation, a precondition to use some + BGL algorithms. ### Surface Mesh - New functions to read and write using the PLY format, @@ -42,6 +51,11 @@ Release date: September 2019 Parameters. ### Polygon Mesh Processing + - Introduced a wide range of new functions related to location of queries on a triangle mesh, + such as `CGAL::Polygon_mesh_processing::locate(Point, Mesh)`, . The location of a point on a triangle mesh + is expressed as the pair of a face and the barycentric coordinates of the point in this face, + enabling robust manipulation of locations (for example, intersections of two 3D segments living + within the same face). - Added the function `CGAL::Polygon_mesh_processing::centroid()`, which computes the centroid of a closed triangle mesh. - Added the functions `CGAL::Polygon_mesh_processing::stitch_boundary_cycle()` and diff --git a/Installation/include/CGAL/license/Polygon_mesh_processing/locate.h b/Installation/include/CGAL/license/Polygon_mesh_processing/locate.h new file mode 100644 index 00000000000..ada8db271c7 --- /dev/null +++ b/Installation/include/CGAL/license/Polygon_mesh_processing/locate.h @@ -0,0 +1,63 @@ +// Copyright (c) 2019 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + +#ifndef CGAL_LICENSE_POLYGON_MESH_PROCESSING_LOCATE_H +#define CGAL_LICENSE_POLYGON_MESH_PROCESSING_LOCATE_H + +#include +#include + +#ifdef CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE + +# if CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the Polygon Mesh Processing - Locate package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ + of the Polygon Mesh Processing - Locate package. \ + You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL Polygon Mesh Processing - Locate package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL Polygon Mesh Processing - Locate package under the terms of \ + the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_POLYGON_MESH_PROCESSING_LOCATE_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_CHECK_POLYGON_MESH_PROCESSING_LOCATE_H diff --git a/Interpolation/examples/Interpolation/nn_coordinates_2.cpp b/Interpolation/examples/Interpolation/nn_coordinates_2.cpp index 2570c69a3ff..6d84acdd82e 100644 --- a/Interpolation/examples/Interpolation/nn_coordinates_2.cpp +++ b/Interpolation/examples/Interpolation/nn_coordinates_2.cpp @@ -8,7 +8,6 @@ #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::FT Coord_type; typedef K::Point_2 Point; @@ -21,12 +20,20 @@ int main() { Delaunay_triangulation dt; - for(int y=0; y<3; ++y) - for(int x=0; x<3; ++x) - dt.insert(K::Point_2(x, y)); +// for(int y=0; y<3; ++y) +// for(int x=0; x<3; ++x) +// dt.insert(K::Point_2(x, y)); + + dt.insert(K::Point_2(50.18, -61.82)); + dt.insert(K::Point_2(50.18, -61.80)); + + dt.insert(K::Point_2(10, -61)); + dt.insert(K::Point_2(70, -61)); + dt.insert(K::Point_2(50, -30)); + dt.insert(K::Point_2(50, -90)); // coordinates computation - K::Point_2 p(1.2, 0.7); // query point + K::Point_2 p(50.18, -61.82); // query point Point_coordinate_vector coords; CGAL::Triple, K::FT, bool> result = @@ -42,9 +49,10 @@ int main() std::cout << "Coordinate computation successful." << std::endl; std::cout << "Normalization factor: " << norm << std::endl; + std::cout << "Coordinates for point: (" << p << ") are the following: " << std::endl; for(std::size_t i=0; i` provides the required functionality. It expects two template -parameters: A model of the concept `DelaunayTriangulationTraits_2` +parameters: a model of the concept `DelaunayTriangulationTraits_2` and a model of the concept `Periodic_2Offset_2`. Since the concept `TriangulationTraits_2` refines the concept `DelaunayTriangulationTraits_2`, the class diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt index ef6dbe7bd91..8452a3bf4e3 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/NamedParameters.txt @@ -390,6 +390,17 @@ if orientation should matter when determining whether two faces are duplicates. Default: `false` \cgalNPEnd +\cgalNPBegin{snapping_tolerance} \anchor PMP_snapping_tolerance +Parameter used in the function `locate_in_face()` to to snap barycentric coordinates. Depending on the geometric traits used, +the computation of the barycentric coordinates might be an inexact construction, thus leading +to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +still ensuring that the total sum of the coordinates is `1`. +\n +Type: `Kernel::FT` \n +Default: `0` +\cgalNPEnd + \cgalNPBegin{face_size_map} \anchor PMP_face_size_map Parameter used in the functions `keep_large_connected_components()` and `keep_largest_connected_components()` to pass a property map that gives the size of a face when diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index 3193cbf966b..3f2520b62ad 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -54,6 +54,10 @@ /// Functions to detect sharp edges and surface patches of polygon meshes. /// \ingroup PkgPolygonMeshProcessingRef +/// \defgroup PMP_locate_grp Location Functions +/// Functions to locate points on a mesh, and manipulate such locations. +/// \ingroup PkgPolygonMeshProcessingRef + /// \defgroup PMP_predicates_grp Intersection Detection Functions /// Functions to detect intersections. /// Note that those functions will be exact as long as the underlying do-intersect predicates used are exact. @@ -121,6 +125,12 @@ and provides a list of the parameters that are used in this package. - `CGAL::Polygon_mesh_processing::is_needle_triangle_face()` - `CGAL::Polygon_mesh_processing::is_cap_triangle_face()` +\cgalCRPSection{Location Functions} +- \link PMP_locate_grp Point Location \endlink +- \link PMP_locate_grp Location Predicates \endlink +- \link PMP_locate_grp Nearest Face Location Queries \endlink +- \link PMP_locate_grp Random Location Generation \endlink + \cgalCRPSection{Orientation Functions} - `CGAL::Polygon_mesh_processing::orient_polygon_soup()` - `CGAL::Polygon_mesh_processing::orient()` diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 48521ec2ec2..0ab5c270cf9 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -463,6 +463,24 @@ This package offers a toolkit of functions to detect such undesirable elements. - `CGAL::Polygon_mesh_processing::is_cap_triangle_face()` - `CGAL::Polygon_mesh_processing::is_needle_triangle_face()` +\subsection PMPLocationFunctions Surface Location Functions + +To ease the manipulation of points on a surface, \cgal offers a multitude of functions based upon +a different representation of a point on a polygon mesh: the point is represented as a pair of +a face of the polygon mesh and a triplet of barycentric coordinates. This definition enables +a robust handling of polylines between points living in the same face: for example, two 3D segments +created by four points within the same face that should intersect might not actually intersect due to +inexact computations. However, manipulating these same points through their barycentric coordinates +can instead be done, and intersections computed in the barycentric space will not suffer +from the same issues. Furthermore, this definition is only dependent on the intrinsic dimension +of the surface (i.e. 2) and not on the ambient dimension within which the surface is embedded. + +The functions of the group \ref PMP_locate_grp offer the following functionalities: +location computations (`CGAL::Polygon_mesh_processing::locate()`, and similar) given a point, +finding the nearest point on a mesh given a point or a ray +(`CGAL::Polygon_mesh_processing::locate_with_AABB_tree()`, and similar), and location-based predicates +(for example, `CGAL::Polygon_mesh_processing::is_on_face_border()`). + **************************************** \section PMPOrientation Orientation diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h new file mode 100644 index 00000000000..c1620434bb1 --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -0,0 +1,1924 @@ +// Copyright (c) 2014, 2017, 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé, +// Stephen Kiazyk +// +#ifndef CGAL_POLYGON_MESH_PROCESSING_LOCATE_H +#define CGAL_POLYGON_MESH_PROCESSING_LOCATE_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// Everywhere in this file: +// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +// between the coordinates in `bc` and the vertices of the face `f` is the following: +// - `w0` corresponds to `source(halfedge(f, tm), tm)` +// - `w1` corresponds to `target(halfedge(f, tm), tm)` +// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` + +namespace CGAL { + +namespace Polygon_mesh_processing { + +namespace internal { + +// The Ray must have the same ambient dimension as the property map's value type (aka, the point type) + +template ::value> +struct Ray_type_selector +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Ray_2 type; +}; + +template +struct Ray_type_selector +{ + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::Ray_3 type; +}; + +} // end namespace internal + +/// \ingroup PMP_locate_grp +/// +/// \brief Helper class whose sole purpose is to make it easier to access some useful types. +/// +/// \tparam TriangleMesh a model of `FaceListGraph` +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +template +class Location_traits +{ +public: + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef boost::variant descriptor_variant; + +#ifdef DOXYGEN_RUNNING + /// This is the type of the vertex point property map, either the one passed through the named parameters + /// or the default, internal one of the mesh. + typedef unspecified_type VPM; + + /// The traits class, either passed as a named parameter or deduced from the Point type + /// of the vertex property map (the point type must then be compatible with `CGAL::Kernel_traits`) + typedef unspecified_type Geom_traits; +#else + typedef typename GetVertexPointMap::const_type VPM; + typedef typename GetGeomTraits::type Geom_traits; +#endif + + typedef typename boost::property_traits::value_type Point; + typedef typename Geom_traits::FT FT; + +#ifdef DOXYGEN_RUNNING + /// Either Geom_traits::Ray_2 or Geom_traits::Ray_3, depending on the ambient dimension of the mesh + typedef unspecified_type Ray; +#else + typedef typename internal::Ray_type_selector::type Ray; +#endif + + typedef std::array Barycentric_coordinates; + + /// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) + /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance + /// between the coordinates in `bc` and the vertices of the face `f` is the following: + /// - `w0` corresponds to `source(halfedge(f, tm), tm)` + /// - `w1` corresponds to `target(halfedge(f, tm), tm)` + /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` + typedef std::pair Face_location; +}; + +// forward declarations +template +bool is_in_face(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm); + +template +typename Location_traits::descriptor_variant +get_descriptor_from_location(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm); + +template +typename Location_traits::Face_location +locate_in_face(typename boost::graph_traits::halfedge_descriptor he, + typename Location_traits::FT t, + const TriangleMesh& tm); +// end of forward declarations + +namespace internal { + +template +OutputIterator +incident_faces(const typename Location_traits::Face_location& location, + const TriangleMesh& tm, + OutputIterator out) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef boost::variant descriptor_variant; + + descriptor_variant dv = get_descriptor_from_location(location, tm); + + if(const vertex_descriptor* vd_ptr = boost::get(&dv)) + { + const vertex_descriptor vd = *vd_ptr; + for(face_descriptor fd : faces_around_target(halfedge(vd, tm), tm)) + *out++ = fd; + } + else if(const halfedge_descriptor* hd_ptr = boost::get(&dv)) + { + const halfedge_descriptor hd = *hd_ptr; + *out++ = face(hd, tm); + *out++ = face(opposite(hd, tm), tm); + } + else + { + const face_descriptor fd = boost::get(dv); + *out++ = fd; + } + + return out; +} + +// Snapping coordinates for robustness +template +bool +snap_coordinates_to_border(typename Location_traits::Barycentric_coordinates& coords, + const typename Location_traits::FT tolerance = + std::numeric_limits::FT>::epsilon()) +{ + typedef typename Location_traits::FT FT; + +#ifdef CGAL_PMP_LOCATE_DEBUG + std::cout << "Pre-snapping: " << coords[0] << " " << coords[1] << " " << coords[2] << std::endl; + std::cout << "Sum: " << coords[0] + coords[1] + coords[2] << std::endl; + std::cout << "tolerance: " << tolerance << std::endl; +#endif + + // To still keep a sum roughly equals to 1, keep in memory the small changes + FT residue = 0.; + bool snapped = false; + + for(int i=0; i<3; ++i) + { + if(CGAL::abs(coords[i]) <= tolerance) + { + snapped = true; + residue += coords[i]; + coords[i] = 0.; + } + else if(CGAL::abs(1 - coords[i]) <= tolerance) + { + snapped = true; + residue -= 1. - coords[i]; + coords[i] = 1.; + } + } + + // Dump the residue into one of the barycentric values that is neither 0 nor 1 + for(int i=0; i<3; ++i) + { + if(coords[i] != 0. && coords[i] != 1.) + { + coords[i] += residue; + break; + } + } + +#ifdef CGAL_PMP_LOCATE_DEBUG + std::cout << "Post-snapping: " << coords[0] << " " + << coords[1] << " " + << coords[2] << std::endl; + std::cout << "Sum: " << coords[0] + coords[1] + coords[2] << std::endl; +#endif + + return snapped; +} + +template +bool +snap_location_to_border(typename Location_traits::Face_location& loc, + const typename Location_traits::FT tolerance = + std::numeric_limits::FT>::epsilon()) +{ + return snap_coordinates_to_border(loc.second, tolerance); +} + +template +struct Barycentric_coordinate_calculator // 2D version +{ + std::array + operator()(const P& ip, const P& iq, const P& ir, const P& iquery, const K& k) const + { + typedef typename K::FT FT; + typedef typename K::Vector_2 Vector_2; + + typename K::Construct_point_2 cp2 = k.construct_point_2_object(); + typename K::Construct_vector_2 cv2 = k.construct_vector_2_object(); + typename K::Compute_scalar_product_2 csp2 = k.compute_scalar_product_2_object(); + + const typename K::Point_2& p = cp2(ip); + const typename K::Point_2& q = cp2(iq); + const typename K::Point_2& r = cp2(ir); + const typename K::Point_2& query = cp2(iquery); + + Vector_2 v0 = cv2(p, q); + Vector_2 v1 = cv2(p, r); + Vector_2 v2 = cv2(p, query); + + FT d00 = csp2(v0, v0); + FT d01 = csp2(v0, v1); + FT d11 = csp2(v1, v1); + FT d20 = csp2(v2, v0); + FT d21 = csp2(v2, v1); + + FT denom = d00 * d11 - d01 * d01; + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. + + FT v = (d11 * d20 - d01 * d21) / denom; + FT w = (d00 * d21 - d01 * d20) / denom; + + return CGAL::make_array(FT(FT(1) - v - w), v, w); + } +}; + +template +struct Barycentric_coordinate_calculator +{ + std::array + operator()(const P& ip, const P& iq, const P& ir, const P& iquery, const K& k) const + { + typedef typename K::FT FT; + typedef typename K::Vector_3 Vector_3; + + typename K::Construct_point_3 cp3 = k.construct_point_3_object(); + typename K::Construct_vector_3 cv3 = k.construct_vector_3_object(); + typename K::Compute_scalar_product_3 csp3 = k.compute_scalar_product_3_object(); + + const typename K::Point_3& p = cp3(ip); + const typename K::Point_3& q = cp3(iq); + const typename K::Point_3& r = cp3(ir); + const typename K::Point_3& query = cp3(iquery); + + Vector_3 v0 = cv3(p, q); + Vector_3 v1 = cv3(p, r); + Vector_3 v2 = cv3(p, query); + + FT d00 = csp3(v0, v0); + FT d01 = csp3(v0, v1); + FT d11 = csp3(v1, v1); + FT d20 = csp3(v2, v0); + FT d21 = csp3(v2, v1); + + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. + FT denom_inv = 1. / (d00 * d11 - d01 * d01); + + FT v = (d11 * d20 - d01 * d21) * denom_inv; + FT w = (d00 * d21 - d01 * d20) * denom_inv; + + return CGAL::make_array(FT(FT(1) - v - w), v, w); + } +}; + +template +struct Barycentric_point_constructor // 2D version +{ + typedef typename K::FT FT; + + P operator()(const P& p, const FT wp, const P& q, const FT wq, const P& r, const FT wr, + const K& /*k*/) const + { + FT sum = wp + wq + wr; + CGAL_assertion(sum != 0); + + // In theory, this should be compute_x_2(compute_point_2(...)) and construct_P() at the end... + FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; + FT y = (wp * p.y() + wq * q.y() + wr * r.y()) / sum; + + return P(x, y); + } +}; + +template +struct Barycentric_point_constructor // 3D version +{ + typedef typename K::FT FT; + + P operator()(const P& p, const FT wp, const P& q, const FT wq, const P& r, const FT wr, + const K& /*k*/) const + { + FT sum = wp + wq + wr; + CGAL_assertion(sum != 0); + FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; + FT y = (wp * p.y() + wq * q.y() + wr * r.y()) / sum; + FT z = (wp * p.z() + wq * q.z() + wr * r.z()) / sum; + + return P(x, y, z); + } +}; + +} // namespace internal + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a set of three points and a query point, computes the barycentric +/// coordinates of the query point with respect to the first three points. +/// +/// \tparam Point the type of a geometric 2D or 3D point +/// \tparam K the type of a geometric traits. Must be a model of `Kernel`. +/// +/// \param p,q,r three points with respect to whom the barycentric coordinates of `query` will be computed +/// \param query the query point whose barycentric coordinates will be computed +/// \param k an instance of the geometric traits +/// +/// \pre `p`, `q`, and `r` are not collinear. +/// \pre It must be possible to extract a kernel type model of `Kernel`, using `CGAL::Kernel_traits

` +/// (this is the case for all standard %CGAL point types and classes inheriting such point types). +/// \pre `query` lies on the plane defined by `p`, `q`, and `r`. +/// +template +std::array +barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Point& query, + const K& k) +{ + internal::Barycentric_coordinate_calculator calculator; + return calculator(p, q, r, query, k); +} + +template +std::array::type::FT, 3> +barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Point& query) +{ + typedef typename CGAL::Kernel_traits::type Kernel; + + return barycentric_coordinates(p, q, r, query, Kernel()); +} + +/// \name Random Location Generation +/// @{ + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns a random point over the halfedge `hd`, as a location. +/// +/// \details The random point is chosen on the halfedge, meaning that all +/// its barycentric coordinates are positive. It is constructed by uniformly generating +/// a value `t` between `0` and `1` and setting the barycentric coordinates to `t`, `1-t`, +/// and `0` for respetively the source and target of `hd`, and the third vertex. +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param hd a halfedge of `tm` +/// \param tm a triangulated surface mesh +/// \param rnd optional random number generator +/// +template +typename Location_traits::Face_location +random_location_on_halfedge(typename boost::graph_traits::halfedge_descriptor hd, + const TriangleMesh& tm, + CGAL::Random& rnd = get_default_random()) +{ + typedef typename Location_traits::FT FT; + + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + + FT t(rnd.uniform_real(0., 1.)); + return locate_in_face(hd, t, tm); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns a random point over the face `fd`, as a location. +/// +/// \details The random point is on the face, meaning that all its barycentric coordinates +/// are positive. It is constructed by uniformly picking a value `u` between `0` and `1`, +/// a value `v` between `1-u`, and setting the barycentric coordinates to `u`, `v`, and +/// `1-u-v` for respectively the source and target of `halfedge(fd, tm)`, and the third point. +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param fd a face of `tm` +/// \param tm a triangulated surface mesh +/// \param rnd optional random number generator +/// +template +typename Location_traits::Face_location +random_location_on_face(typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm, + CGAL::Random& rnd = get_default_random()) +{ + typedef typename Location_traits::FT FT; + + CGAL_USE(tm); + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + CGAL_precondition(fd != boost::graph_traits::null_face()); + + // calling 'rnd.uniform real' with double in case FT comes from an EPECK kernel (which doesn't seem to work too well) + FT u(rnd.uniform_real(0., 1.)); + FT v(rnd.uniform_real(0., CGAL::to_double(FT(1) - u))); + + return std::make_pair(fd, CGAL::make_array(u, v, FT(FT(1) - u - v))); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns a random point over the mesh `tm`. +/// +/// \details The returned location is obtained by choosing a random face of the mesh and +/// a random point on that face. The barycentric coordinates of the point in the face +/// are thus all positive. Note that all faces have the same probability to be chosen. +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param tm a triangulated surface mesh +/// \param rnd optional random number generator +/// +/// \sa `random_location_on_face()` +/// +template +typename Location_traits::Face_location +random_location_on_mesh(const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + + face_descriptor fd = CGAL::internal::random_face_in_mesh(tm, rnd); + return random_location_on_face(fd, tm, rnd); +} + +/// @} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns a descriptor to the simplex +/// of smallest dimension on which the point corresponding to the location lies. +/// +/// \details In other words: +/// - if the point lies on a vertex, this function returns a `boost::graph_traits::%vertex_descriptor` `v`; +/// - if the point lies on a halfedge, this function returns a `boost::graph_traits::%halfedge_descriptor` `hd` +/// (note that in that case, `loc.first == face(hd, tm)` holds). +/// - otherwise, this function returns a `boost::graph_traits::%face_descriptor` +/// `fd` (equal to `loc.first`). +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre the location corresponds to a point that is within a face of `tm`. +/// \pre `loc` describes the barycentric coordinates of a point that lives on the face (boundary included), +/// meaning the barycentric coordinates are all positive. +/// +template +typename Location_traits::descriptor_variant +get_descriptor_from_location(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename Location_traits::Barycentric_coordinates Barycentric_coordinates; + + const face_descriptor fd = loc.first; + const Barycentric_coordinates& bar = loc.second; + + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + CGAL_precondition(fd != boost::graph_traits::null_face()); + CGAL_precondition(is_in_face(loc, tm)); + + // the first barycentric coordinate corresponds to source(halfedge(fd, tm), tm) + halfedge_descriptor hd = prev(halfedge(fd, tm), tm); + + // check if the point is a vertex + for(int i=0; i<3; ++i) + { + if(bar[i] == 1) // coordinate at target(hd, tm) + return target(hd, tm); + hd = next(hd, tm); + } + CGAL_assertion(hd == prev(halfedge(fd, tm), tm)); + + // check if the point is on an edge + for(int i=0; i<3; ++i) + { + if(bar[i] == 0) // coordinate at target(hd, tm) + return prev(hd, tm); + hd = next(hd, tm); + } + + return fd; +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns the geometric position described +/// by these coordinates, as a point. +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param loc the location to transform into a point +/// \param tm a triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +typename Location_traits::Point +construct_point(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + + typedef typename GetGeomTraits::type Geom_traits; + + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + + VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + Geom_traits gt = choose_param(get_param(np, internal_np::geom_traits), Geom_traits()); + + halfedge_descriptor hd = halfedge(loc.first, tm); + const Point& p0 = get(vpm, source(hd, tm)); + const Point& p1 = get(vpm, target(hd, tm)); + const Point& p2 = get(vpm, target(next(hd, tm), tm)); + + internal::Barycentric_point_constructor bp_constructor; + return bp_constructor(p0, loc.second[0], p1, loc.second[1], p2, loc.second[2], gt); +} + +template +typename property_map_value::type +construct_point(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm) +{ + return construct_point(loc, tm, parameters::all_default()); +} + +/// \name Location Predicates +/// @{ + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns whether the location is +/// on the vertex `vd` or not. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param vd a vertex of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +bool +is_on_vertex(const typename Location_traits::Face_location& loc, + const typename boost::graph_traits::vertex_descriptor vd, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename Location_traits::descriptor_variant descriptor_variant; + + if(!is_in_face(loc, tm)) + return false; + + descriptor_variant dv = get_descriptor_from_location(loc, tm); + + if(const vertex_descriptor* vd_ptr = boost::get(&dv)) + return (vd == *vd_ptr); + + return false; +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns whether the location is +/// on the halfedge `hd` or not. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param hd a halfedge of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +bool +is_on_halfedge(const typename Location_traits::Face_location& loc, + const typename boost::graph_traits::halfedge_descriptor hd, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Location_traits::descriptor_variant descriptor_variant; + + if(!is_in_face(loc, tm)) + return false; + + descriptor_variant dv = get_descriptor_from_location(loc, tm); + + if(const vertex_descriptor* vd_ptr = boost::get(&dv)) + return (*vd_ptr == source(hd, tm) || *vd_ptr == target(hd, tm)); + else if(const halfedge_descriptor* hd_ptr = boost::get(&dv)) + return (*hd_ptr == hd); + + return false; +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a set of barycentric coordinates, returns whether those barycentric +/// coordinates correspond to a point within the face (boundary included), +/// that is, if all the barycentric coordinates are positive. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param bar an array of barycentric coordinates +/// \param tm a triangulated surface mesh +/// +template +bool +is_in_face(const typename Location_traits::Barycentric_coordinates& bar, + const TriangleMesh& tm) +{ + CGAL_USE(tm); + CGAL_precondition(CGAL::is_triangle_mesh(tm)); + + for(int i=0; i<3; ++i) + { + // "|| bar[i] > 1." is not needed because if everything is positive and the sum is '1', + // then each coefficient is below '1'. + if(bar[i] < 0.) + return false; + } + + return true; +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns whether the location is +/// in the face (boundary included) or not. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +bool +is_in_face(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm) +{ + return is_in_face(loc.second, tm); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns whether the location is on the boundary +/// of the face or not. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +bool +is_on_face_border(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm) +{ + typedef typename Location_traits::Face_location Face_location; + typedef typename Face_location::second_type Barycentric_coordinates; + + if(!is_in_face(loc, tm)) + return false; + + const Barycentric_coordinates& bar = loc.second; + + for(int i=0; i<3; ++i) + if(bar[i] == 0.) + return true; + + return false; +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, returns whether the location is +/// on the border of the mesh or not. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc a location with `loc.first` a face of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// +template +bool +is_on_mesh_border(const typename Location_traits::Face_location& loc, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename Location_traits::Face_location Face_location; + typedef typename Face_location::second_type Barycentric_coordinates; + + const face_descriptor fd = loc.first; + const Barycentric_coordinates& bar = loc.second; + + if(!is_in_face(bar, tm)) + return false; + + // the first barycentric coordinate corresponds to source(halfedge(fd, tm), tm) + halfedge_descriptor hd = prev(halfedge(fd, tm), tm); + + // check if the point is a vertex + for(int i=0; i<3; ++i) + { + if(bar[i] == 1.) // coordinate at target(hd, tm) + return bool(CGAL::is_border(target(hd, tm), tm)); + hd = next(hd, tm); + } + CGAL_assertion(hd == prev(halfedge(fd, tm), tm)); + + // check if the point is on an edge + for(int i=0; i<3; ++i) + { + if(bar[i] == 0.) // coordinate at target(hd, tm) + return CGAL::is_border(edge(prev(hd, tm), tm), tm); + hd = next(hd, tm); + } + + // point is strictly within the face, so it's not on the border + return false; +} + +/// @} + +/// \name Point Location +/// @{ + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns the location of the given vertex `vd` as a location, +/// that is an ordered pair specifying a face incident to `vd` +/// and the barycentric coordinates of the vertex `vd` in that face. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param vd a vertex of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `vd` is not an isolated vertex +/// +template +typename Location_traits::Face_location +locate_in_face(typename boost::graph_traits::vertex_descriptor vd, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename Location_traits::FT FT; + typedef typename Location_traits::Face_location Face_location; + + halfedge_descriptor he = halfedge(vd, tm); + + // Find a real face in case 'he' is a border halfedge + for(halfedge_descriptor hd : halfedges_around_target(he, tm)) + { + if(!is_border(hd, tm)) + { + he = hd; + break; + } + } + + CGAL_postcondition(!CGAL::is_border(he, tm)); // must find a 'real' face incident to 'vd' + + face_descriptor fd = face(he, tm); + + CGAL_assertion(target(he, tm) == vd); + CGAL_assertion(fd != boost::graph_traits::null_face()); + + // isolated vertex + if(fd == boost::graph_traits::null_face()) + return Face_location(); + + FT coords[3] = { FT(0), FT(0), FT(0) }; + he = next(he, tm); // so that source(he, tm) == vd and it's simpler to handle 'index_in_face' + std::size_t halfedge_local_index = halfedge_index_in_face(he, tm); + coords[halfedge_local_index] = FT(1); + + return std::make_pair(fd, CGAL::make_array(coords[0], coords[1], coords[2])); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns the location of a given vertex as a location in `fd`, +/// that is an ordered pair composed of `fd` and of the barycentric coordinates +/// of the vertex in `fd`. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param vd a vertex of `tm` and a vertex of the face `fd` +/// \param fd a face of `tm` +/// \param tm a triangulated surface mesh +/// +/// \pre `fd` is not the null face +/// +template +typename Location_traits::Face_location +locate_in_face(const typename boost::graph_traits::vertex_descriptor vd, + const typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm) +{ + typedef typename Location_traits::FT FT; + + CGAL_precondition(fd != boost::graph_traits::null_face()); + + FT coords[3] = { FT(0), FT(0), FT(0) }; + std::size_t vertex_local_index = vertex_index_in_face(vd, fd, tm); + coords[vertex_local_index] = FT(1); + + return std::make_pair(fd, CGAL::make_array(coords[0], coords[1], coords[2])); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a point described by a halfedge `he` and a scalar `t` +/// as `p = (1 - t) * source(he, tm) + t * target(he, tm)`, +/// returns this location along the given edge as a location, that is +/// an ordered pair specifying a face containing the location and the +/// barycentric coordinates of that location in that face. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param he a halfedge of `tm` +/// \param t the parametric distance of the desired point along `he` +/// \param tm a triangulated surface mesh +/// +template +typename Location_traits::Face_location +locate_in_face(const typename boost::graph_traits::halfedge_descriptor he, + const typename Location_traits::FT t, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename Location_traits::FT FT; + + face_descriptor fd = face(he, tm); + std::size_t edge_local_index = halfedge_index_in_face(he, tm); + + const FT one_minus_t(FT(1) - t); + FT coords[3] = { FT(0), FT(0), FT(0) }; + coords[edge_local_index] = one_minus_t; + coords[(edge_local_index + 1) % 3] = t; + + return std::make_pair(fd, CGAL::make_array(coords[0], coords[1], coords[2])); +} + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a point `query` and a face `fd` of a triangulated surface mesh, +/// returns this location as a location, that is +/// an ordered pair composed of `fd` and of the barycentric coordinates of +/// `query` with respect to the vertices of `fd`. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param query a point +/// \param fd a face of `tm` +/// \param tm a triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalParamBegin{snapping_tolerance} +/// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, +/// the computation of the barycentric coordinates might be an inexact construction, thus leading +/// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +/// of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +/// still ensuring that the total sum of the coordinates is `1`. By default, the tolerance is `0`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +/// \pre `fd` is not the null face +/// +template +typename Location_traits::Face_location +locate_in_face(const typename Location_traits::Point& query, + const typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename Location_traits::FT FT; + + // VertexPointMap + typedef typename GetGeomTraits::type Geom_traits; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + + VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + Geom_traits gt = choose_param(get_param(np, internal_np::geom_traits), Geom_traits()); + + FT snap_tolerance = choose_param(get_param(np, internal_np::snapping_tolerance), 0); + + CGAL_precondition(fd != boost::graph_traits::null_face()); + + vertex_descriptor vd0 = source(halfedge(fd, tm), tm); + vertex_descriptor vd1 = target(halfedge(fd, tm), tm); + vertex_descriptor vd2 = target(next(halfedge(fd, tm), tm), tm); + + const Point& p0 = get(vpm, vd0); + const Point& p1 = get(vpm, vd1); + const Point& p2 = get(vpm, vd2); + + std::array coords = barycentric_coordinates(p0, p1, p2, query, gt); + + if(snap_tolerance != FT(0) && !is_in_face(coords, tm)) + { + std::cerr << "Warning: point " << query << " is not in the input face" << std::endl; + std::cerr << "Coordinates: " << coords[0] << " " << coords[1] << " " << coords[2] << std::endl; + + // Try to to snap the coordinates, hoping the problem is just a -1e-17ish epsilon + // pushing the coordinates over the edge + internal::snap_coordinates_to_border(coords, snap_tolerance); + } + + return std::make_pair(fd, coords); +} + +#ifndef DOXYGEN_RUNNING // because this is in the middle of a @{ @} doxygen group +template +typename Location_traits::Face_location +locate_in_face(const typename property_map_value::type& query, + const typename boost::graph_traits::face_descriptor f, + const TriangleMesh& tm) +{ + return locate_in_face(query, f, tm, parameters::all_default()); +} +#endif + +/// \ingroup PMP_locate_grp +/// +/// \brief Given a location, that is an ordered pair composed of a +/// `boost::graph_traits::%face_descriptor` and an array +/// of barycentric coordinates, and a second face adjacent to the first, +/// return the location of the point in the second face. +/// +/// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +/// +/// \tparam TriangleMesh a model of `FaceGraph` +/// +/// \param loc the first location, with `loc.first` being a face of `tm` +/// \param fd the second face, adjacent to `loc.first` +/// \param tm the triangle mesh to which `he` belongs +/// +/// \pre `loc` corresponds to a point that lies on a face incident to both `loc.first` and `fd`. +/// +template +typename Location_traits::Face_location +locate_in_adjacent_face(const typename Location_traits::Face_location& loc, + const typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef boost::variant descriptor_variant; + + typedef typename Location_traits::Face_location Face_location; + typedef typename Location_traits::FT FT; + + if(loc.first == fd) + return loc; + + Face_location loc_in_fd = std::make_pair(fd, CGAL::make_array(FT(0), FT(0), FT(0))); + descriptor_variant dv = get_descriptor_from_location(loc, tm); + + if(const vertex_descriptor* vd_ptr = boost::get(&dv)) + { + int index_of_vd = vertex_index_in_face(*vd_ptr, fd, tm); + loc_in_fd.second[index_of_vd] = 1.; + // Note that the barycentric coordinates were initialized to 0, + // so the second and third coordinates are already set up properly. + } + else if(const halfedge_descriptor* hd_ptr = boost::get(&dv)) + { + // Note that, here, we know that we are _not_ on a vertex + const halfedge_descriptor hd = *hd_ptr; + const halfedge_descriptor opp_hd = opposite(hd, tm); + CGAL_assertion(face(hd, tm) == loc.first); + CGAL_assertion(face(opp_hd, tm) == fd); + CGAL_assertion(loc.first != boost::graph_traits::null_face()); + CGAL_assertion(fd != boost::graph_traits::null_face()); + + const int index_of_hd = halfedge_index_in_face(hd, tm); + const int index_of_opp_hd = halfedge_index_in_face(opp_hd, tm); + + // - Coordinates will be non-null at indices `index_of_hd` + // and `index_of_hd + 1` in loc.first. + // - Coordinates will be non-null at indices `index_of_opp_hd` + // and `index_of_opp_hd + 1` in f. + // - The halfedges `hd` and `opp_hd` have opposite directions. + loc_in_fd.second[index_of_opp_hd] = loc.second[(index_of_hd + 1)%3]; + loc_in_fd.second[(index_of_opp_hd + 1)%3] = loc.second[index_of_hd]; + // note that the barycentric coordinates were initialized at 0, + // so the third coordinate is already set up properly + } + else + { + CGAL_assertion_code(const face_descriptor fd2 = boost::get(dv);) + CGAL_assertion(fd2 != boost::graph_traits::null_face()); + CGAL_assertion(fd2 != fd); + + // Calling this function for a location that is (strictly) in a face but + // asking for the location in a nearby face is meaningless + CGAL_assertion(false); + } + + CGAL_postcondition(loc_in_fd.first == fd); + return loc_in_fd; +} + +// not documenting the next two functions as they are too technical +#ifndef DOXYGEN_RUNNING + +// Finding a common face to a location and a point +// - the first location must be known +// - the second must be a point in a face incident to get_descriptor_from_location(known_location) +// note: not returning the query location to emphasis that the known location can change too. +template +bool +locate_in_common_face(typename Location_traits::Face_location& known_location, + const typename Location_traits::Point& query, + typename Location_traits::Face_location& query_location, + const TriangleMesh& tm, + const typename Location_traits::FT tolerance = + std::numeric_limits::FT>::epsilon()) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef boost::variant descriptor_variant; + descriptor_variant dv = get_descriptor_from_location(known_location, tm); + + bool is_query_location_in_face = false; + + if(const vertex_descriptor* vd_ptr = boost::get(&dv)) + { + const vertex_descriptor vd = *vd_ptr; + halfedge_descriptor hd = halfedge(vd, tm); + + for(face_descriptor fd : faces_around_target(hd, tm)) + { + if(fd == boost::graph_traits::null_face()) + continue; + + // check if 'query' can be found in that face + query_location = locate_in_face(query, fd, tm); + internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + + is_query_location_in_face = is_in_face(query_location, tm); + + if(is_query_location_in_face) + break; + } + } + else if(const halfedge_descriptor* hd_ptr = boost::get(&dv)) + { + const halfedge_descriptor hd = *hd_ptr; + face_descriptor fd = face(hd, tm); + + if(fd != boost::graph_traits::null_face()) + { + query_location = locate_in_face(query, fd, tm); + internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + is_query_location_in_face = is_in_face(query_location, tm); + } + + if(!is_query_location_in_face) + { + fd = face(opposite(hd, tm), tm); + query_location = locate_in_face(query, fd, tm); + is_query_location_in_face = is_in_face(query_location, tm); + } + } + else + { + const face_descriptor fd = boost::get(dv); + + CGAL_precondition(fd != boost::graph_traits::null_face()); + + query_location = locate_in_face(query, fd, tm); + internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + is_query_location_in_face = is_in_face(query_location, tm); + } + + // if this is not the same face as for 'known_query', change 'known_location' + if(is_query_location_in_face && query_location.first != known_location.first) + known_location = locate_in_adjacent_face(known_location, query_location.first, tm); + + return is_query_location_in_face; +} + +// Finding a common face to two locations +// - both locations must be known but can change +template +bool +locate_in_common_face(typename Location_traits::Face_location& first_location, + typename Location_traits::Face_location& second_location, + const TriangleMesh& tm) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + // Check that we actually have something to do + if(first_location.first == second_location.first) + return true; + + bool is_first_location_on_border = is_on_face_border(first_location, tm); + bool is_second_location_on_border = is_on_face_border(second_location, tm); + + // We have already checked that they have different faces, if neither are on + // a border, then it's hopeless + if(!is_first_location_on_border && !is_second_location_on_border) + return false; + + // Find a common face in the sets of incident faces of each location + std::set first_incident_faces; + std::set second_incident_faces; + + internal::incident_faces(first_location, tm, std::inserter(first_incident_faces, first_incident_faces.begin())); + internal::incident_faces(second_location, tm, std::inserter(second_incident_faces, second_incident_faces.begin())); + + typename std::set::const_iterator fit = first_incident_faces.begin(); + typename std::set::const_iterator fend = first_incident_faces.end(); + typename std::set::const_iterator sit = second_incident_faces.begin(); + typename std::set::const_iterator send = second_incident_faces.end(); + + while(fit!=fend && sit!=send) + { + if(*fit == boost::graph_traits::null_face()) + ++fit; + if(*sit == boost::graph_traits::null_face()) + ++sit; + + if(*fit == *sit) + break; + else if(*fit < *sit) + ++fit; + else + ++sit; + } + + if(fit == fend || sit == send) // no common face... + return false; + + CGAL_assertion(*fit == *sit); + face_descriptor common_fd = *fit; + CGAL_assertion(common_fd != boost::graph_traits::null_face()); + + if(first_location.first != common_fd) + first_location = locate_in_adjacent_face(first_location, common_fd, tm); + + if(second_location.first != common_fd) + second_location = locate_in_adjacent_face(second_location, common_fd, tm); + + CGAL_postcondition(first_location.first == second_location.first); + return true; +} +#endif // DOXYGEN_RUNNING + +/// @} + +namespace internal { + +template::value> +struct Point_to_Point_3 // 2D case +{ + typedef typename Location_traits::Geom_traits::Point_3 Point_3; + + Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), 0); } +}; + +template +struct Point_to_Point_3::Geom_traits::Point_3, + 3> // 3D case with nothing to do +{ + typedef typename Location_traits::Geom_traits::Point_3 Point_3; + + const Point_3& operator()(const Point_3& p) const { return p; } +}; + +template +struct Point_to_Point_3 // Generic 3D case +{ + typedef typename Location_traits::Geom_traits::Point_3 Point_3; + + Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), p.z()); } +}; + +template +struct Ray_to_Ray_3 // 2D case +{ + typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename Geom_traits::Ray_2 Ray_2; + typedef typename Geom_traits::Ray_3 Ray_3; + typedef Point_to_Point_3 P2_to_P3; + + Ray_3 operator()(const Ray_2& r) const + { + P2_to_P3 to_p3; + return Ray_3(to_p3(r.source()), to_p3(r.second_point())); + } + + const Ray_3& operator()(const Ray_3& r) const { return r; } +}; + +// Readable property map that converts the output of a given vertex point map to a 3D point +template::const_type> +struct Point_to_Point_3_VPM +{ +private: + typedef VertexPointMap VPM; + typedef Point_to_Point_3_VPM Self; + +public: + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_traits::value_type Point; + typedef Point_to_Point_3 P_to_P3; + + typedef typename CGAL::Kernel_traits::Kernel K; + typedef typename K::Point_3 Point_3; + + // required typedefs + typedef typename boost::property_traits::key_type key_type; + typedef Point_3 value_type; + typedef value_type reference; + typedef boost::readable_property_map_tag category; + + // Constructors + Point_to_Point_3_VPM() : conv_(), vpm_() { } // required for compilation by AABBtraits + Point_to_Point_3_VPM(const VertexPointMap vpm) : conv_(), vpm_(vpm) { } + Point_to_Point_3_VPM(const TriangleMesh& mesh) + : conv_(), vpm_(get_const_property_map(boost::vertex_point, mesh)) + { } + + // Access + const P_to_P3& converter() const { return conv_; } + const VertexPointMap& vpm() const { return vpm_; } + + // get function for property map + inline friend reference get(const Self& pmap, key_type v) { + return pmap.converter()(get(pmap.vpm(), v)); + } + +private: + // Can't be const nor references due to AABB_traits, so make sure to use property maps! + P_to_P3 conv_; + VertexPointMap vpm_; +}; + +// Two different functions, because the AABB's traits' VPM must match the passed VPM (that is, +// the original VPM wrapped with P_to_P3_VPM if the VPM's value_type was not Point_3) +template +void build_AABB_tree(const TriangleMesh& tm, + AABB_tree& outTree, + const VPM& wrapped_vpm, + typename std::enable_if< + std::is_same< + typename AABBTraits::Point_3, typename boost::property_traits::value_type + >::value>::type* = 0) +{ + typename boost::graph_traits::face_iterator ffirst, fbeyond; + boost::tie(ffirst, fbeyond) = faces(tm); + outTree.rebuild(ffirst, fbeyond, tm, wrapped_vpm); + outTree.build(); +} + +template +void build_AABB_tree(const TriangleMesh& tm, + AABB_tree& outTree, + const VPM& vpm, + typename std::enable_if< + !std::is_same< + typename AABBTraits::Point_3, typename boost::property_traits::value_type + >::value>::type* = 0) +{ + typedef internal::Point_to_Point_3_VPM Wrapped_VPM; + const Wrapped_VPM wrapped_vpm(vpm); + + return internal::build_AABB_tree(tm, outTree, wrapped_vpm); +} + +} // namespace internal + +/// \name Nearest Face Location Queries +/// The following functions can be used to find the closest point on a triangle mesh, given either +/// a point or a ray. This closest point is computed using a `CGAL::AABB_tree`. Users intending +/// to call location functions on more than a single point (or ray) should first compute an AABB +/// tree to store it (otherwise, it will be recomputed every time). Note that since the AABB tree +/// class is a 3D structure, it might be required to wrap your point property map to convert your +/// point type to the 3D point type (i.e., your kernel's `%Point_3`) if you are working +/// with a 2D triangle structure. +/// +/// @{ + +/// \ingroup PMP_locate_grp +/// +/// \brief creates an AABB tree suitable for use with `locate_with_AABB_tree()`. +/// +/// \details This function should first be called by users who intend to locate multiple points: +/// in this case, it is better to first build an AABB tree, and use the function +/// `locate_with_AABB_tree()` that takes as parameter an AABB tree, instead of calling `locate()` +/// multiple times, which will build a new AABB tree on every call. +/// +/// \tparam TriangleMesh a model of `FaceListGraph` +/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param tm a triangulated surface mesh +/// \param outTree output parameter that stores the computed `AABB_tree` +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +void build_AABB_tree(const TriangleMesh& tm, + AABB_tree< + CGAL::AABB_traits< + typename Location_traits::Geom_traits, + CGAL::AABB_face_graph_triangle_primitive + > >& outTree, + const NamedParameters& np) +{ + typedef typename GetVertexPointMap::const_type VertexPointMap; + + const VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + + return internal::build_AABB_tree(tm, outTree, vpm); +} + +#ifndef DOXYGEN_RUNNING +template +void build_AABB_tree(const TriangleMesh& tm, + AABB_tree& outTree) +{ + return build_AABB_tree(tm, outTree, parameters::all_default()); +} +#endif + +/// \ingroup PMP_locate_grp +/// +/// \brief returns the face location nearest to the given point, as a location. +/// +/// Note that it is possible for the triangle mesh to have ambiant dimension `2` (e.g. the mesh +/// is a 2D triangulation, or a CGAL::Surface_mesh >), as long as an appropriate +/// vertex point property map is passed in the AABB tree, which will convert from 2D to 3D. +/// +/// \tparam TriangleMesh a model of `FaceListGraph` +/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param p the point to locate on the input triangulated surface mesh +/// \param tree an AABB tree containing the triangular faces of the input surface mesh to perform the point location with +/// \param tm a triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalParamBegin{snapping_tolerance} +/// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, +/// the computation of the barycentric coordinates might be an inexact construction, thus leading +/// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +/// of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +/// still ensuring that the total sum of the coordinates is `1`. By default, the tolerance is `0`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +typename Location_traits::Face_location +locate_with_AABB_tree(const typename Location_traits::Point& p, + const AABB_tree< + CGAL::AABB_traits< + typename Location_traits::Geom_traits, + CGAL::AABB_face_graph_triangle_primitive + > >& tree, + const TriangleMesh& tm, + const NamedParameters& np) +{ + typedef typename Location_traits::Point Point; + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename boost::property_traits::value_type Point_3; + CGAL_static_assertion((std::is_same::value)); + + typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; + + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + + const Point_3& p3 = P_to_P3()(p); + typename AABB_tree::Point_and_primitive_id result = tree.closest_point_and_primitive(p3); + + // The VPM might return a point of any dimension, but the AABB tree necessarily returns + // a Point_3. So, wrap the VPM (again) to give a Point_3. Even if it's already wrapped, we're just + // forwarding a const& anyway. + const VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + const WrappedVPM wrapped_vpm(vpm); + + return locate_in_face(result.first, result.second, tm, CGAL::parameters::vertex_point_map(wrapped_vpm)); +} + +#ifndef DOXYGEN_RUNNING +template +typename Location_traits::Face_location +locate_with_AABB_tree(const typename Location_traits::Point& p, + const AABB_tree& tree, + const TriangleMesh& tm) +{ + return locate_with_AABB_tree(p, tree, tm, parameters::all_default()); +} +#endif + +/// \ingroup PMP_locate_grp +/// +/// \brief returns the nearest face location to the given point. +/// +/// \details Note that this function will build an AABB tree on each call. If you need +/// to call this function more than once, first use `build_AABB_tree()` to create a +/// an AABB tree that you can store and use the function `locate_with_AABB_tree()`. +/// +/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param p the point to locate on the input triangulated surface mesh +/// \param tm a triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalParamBegin{snapping_tolerance} +/// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, +/// the computation of the barycentric coordinates might be an inexact construction, thus leading +/// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +/// of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +/// still ensuring that the total sum of the coordinates is `1`. By default, the tolerance is `0`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +typename Location_traits::Face_location +locate(const typename Location_traits::Point& p, + const TriangleMesh& tm, + const NamedParameters& np) +{ + // Wrap the input VPM with a one converting to 3D (costs nothing if the input VPM + // already has value type Kernel::Point_3) + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef typename Location_traits::Point Intrinsic_point; + + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits< + typename Location_traits::Geom_traits, + AABB_face_graph_primitive> AABB_face_graph_traits; + + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename AABB_face_graph_traits::Point_3 Point_3; + + CGAL_static_assertion((std::is_same::value)); + + const VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + const WrappedVPM wrapped_vpm(vpm); + + AABB_tree tree; + build_AABB_tree(tm, tree, parameters::vertex_point_map(wrapped_vpm)); + + const Point_3& p3 = P_to_P3()(p); + return locate_with_AABB_tree(p3, tree, tm, parameters::vertex_point_map(wrapped_vpm)); +} + +#ifndef DOXYGEN_RUNNING +template +typename Location_traits::Face_location +locate(const typename property_map_value::type& p, + const TriangleMesh& tm) +{ + return locate(p, tm, parameters::all_default()); +} +#endif + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns the face location along `ray` nearest to its source point. +/// +/// If the ray does not intersect the mesh, a default constructed location is returned. +/// +/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param ray a ray to intersect with the input triangulated surface mesh +/// \param tree an AABB tree containing the triangular faces of the input surface mesh to perform the point location with +/// \param tm a triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalParamBegin{snapping_tolerance} +/// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, +/// the computation of the barycentric coordinates might be an inexact construction, thus leading +/// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +/// of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +/// still ensuring that the total sum of the coordinates is `1`. By default, the tolerance is `0`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +typename Location_traits::Face_location +locate_with_AABB_tree(const typename Location_traits::Ray& ray, + const AABB_tree< + CGAL::AABB_traits< + typename Location_traits::Geom_traits, + CGAL::AABB_face_graph_triangle_primitive + > >& tree, + const TriangleMesh& tm, + const NamedParameters& np) +{ + typedef typename Location_traits::Geom_traits Geom_traits; + + typedef typename Geom_traits::FT FT; + typedef typename Geom_traits::Point_3 Point_3; + typedef typename Geom_traits::Ray_3 Ray_3; + + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef internal::Ray_to_Ray_3 R_to_R3; + + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; + typedef AABB_tree AABB_face_graph_tree; + typedef typename AABB_face_graph_tree::template Intersection_and_primitive_id::Type Intersection_type; + typedef boost::optional Ray_intersection; + + // First, transform the ray into a 3D ray if needed + Ray_3 ray_3 = R_to_R3()(ray); + + std::vector intersections; + tree.all_intersections(ray_3, std::back_inserter(intersections)); + + bool found = false; + FT nearest_distance = 0; + Point_3 nearest_point = CGAL::ORIGIN; + face_descriptor nearest_face; + + for(std::size_t i = 0; i < intersections.size(); ++i) + { + if(intersections[i]) + { + Point_3* intersection_point = boost::get(&(intersections[i]->first)); + + if(intersection_point) + { + FT distance = CGAL::squared_distance(*intersection_point, ray_3.source()); + + if(!found || distance < nearest_distance) + { + found = true; + nearest_point = *intersection_point; + nearest_distance = distance; + nearest_face = intersections[i]->second; + } + } + } + } + + if(found) + { + // wrap the VPM to make sure it is producing 3D points + const VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + WrappedVPM wrapped_vpm(vpm); + + return locate_in_face(nearest_point, nearest_face, tm, CGAL::parameters::vertex_point_map(wrapped_vpm)); + } + else + return std::make_pair(boost::graph_traits::null_face(), + CGAL::make_array(FT(0), FT(0), FT(0))); +} + +#ifndef DOXYGEN_RUNNING +template +typename Location_traits::Face_location +locate_with_AABB_tree(const typename Location_traits::Ray& ray, + const AABB_tree& tree, + const TriangleMesh& tm) +{ + return locate_with_AABB_tree(ray, tree, tm, parameters::all_default()); +} +#endif + +/// \ingroup PMP_locate_grp +/// +/// \brief Returns the face location along `ray` nearest to its source point. +/// +/// If the ray does not intersect the mesh, a default constructed location is returned. +/// +/// \details Note that this function will build an AABB tree on each call. If you need +/// to call this function more than once, use `build_AABB_tree()` to cache a +/// copy of the `AABB_tree`, and use the overloads of this function +/// that accept a reference to an AABB tree as input. +/// +/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// +/// \param ray a ray to intersect with the input triangulated surface mesh +/// \param tm the input triangulated surface mesh +/// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `tm`. +/// If this parameter is omitted, an internal property map for +/// `boost::vertex_point_t` must be available in `TriangleMesh`. +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel`. +/// \cgalParamEnd +/// \cgalParamBegin{snapping_tolerance} +/// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, +/// the computation of the barycentric coordinates might be an inexact construction, thus leading +/// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle +/// of an edge). The coordinates will be snapped towards `0` and `1` if the difference is smaller than the tolerance value, while +/// still ensuring that the total sum of the coordinates is `1`. By default, the tolerance is `0`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +typename Location_traits::Face_location +locate(const typename Location_traits::Ray& ray, + const TriangleMesh& tm, + const NamedParameters& np) +{ + typedef typename GetVertexPointMap::const_type VertexPointMap; + + // Wrap the input VPM with a one converting to 3D (costs nothing if the input VPM + // already has value type Geom_traits::Point_3) + typedef internal::Point_to_Point_3_VPM VPM; + + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits::Geom_traits, + AABB_face_graph_primitive> AABB_face_graph_traits; + + const VertexPointMap vpm = boost::choose_param(boost::get_param(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, tm)); + const VPM wrapped_vpm(vpm); + + AABB_tree tree; + build_AABB_tree(tm, tree, parameters::vertex_point_map(wrapped_vpm)); + + return locate_with_AABB_tree(ray, tree, tm, np); +} + +#ifndef DOXYGEN_RUNNING +template +typename Location_traits::Face_location +locate(const typename internal::Ray_type_selector< + typename Location_traits::Point>::type& ray, + const TriangleMesh& tm) +{ + return locate(ray, tm, parameters::all_default()); +} +#endif + +/// @} + +} // namespace Polygon_mesh_processing +} // namespace CGAL + +#endif // CGAL_POLYGON_MESH_PROCESSING_LOCATE_H diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 6242058639f..16d8bce9ff2 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -88,6 +88,7 @@ endif() create_single_source_cgal_program("test_repair_polygon_soup.cpp") create_single_source_cgal_program("test_shape_predicates.cpp") create_single_source_cgal_program("test_pmp_collision_detection.cpp") + create_single_source_cgal_program("test_pmp_locate.cpp") create_single_source_cgal_program("test_pmp_snapping.cpp") create_single_source_cgal_program("test_pmp_non_conforming_snapping.cpp") create_single_source_cgal_program("remove_degeneracies_test.cpp") diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/blobby_2D.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/blobby_2D.off new file mode 100644 index 00000000000..24774d3cb35 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/blobby_2D.off @@ -0,0 +1,522 @@ +OFF +195 325 0 +-0.24592500000000000 0.02013070000000000 +-0.23906300000000000 0.00917146000000000 +-0.22414600000000001 0.02627040000000000 +-0.21665699999999999 0.09137350000000000 +-0.20436900000000000 0.13125800000000001 +-0.22717399999999999 0.11141900000000000 +-0.23814700000000000 -0.00559741000000000 +-0.22804700000000000 -0.00611597000000000 +-0.23734700000000000 0.00223480000000000 +-0.17373700000000000 0.10742100000000000 +-0.18601799999999999 0.12388100000000001 +-0.28231400000000001 0.05716840000000000 +-0.26321000000000000 0.03789740000000000 +-0.24498400000000001 0.05559020000000000 +-0.20538999999999999 0.04444000000000000 +-0.20414800000000000 0.02031610000000000 +-0.25870100000000001 0.08402350000000000 +-0.26684400000000003 0.10788800000000000 +-0.22636600000000001 0.00430057000000000 +-0.18667000000000000 0.14006900000000000 +-0.16358800000000001 0.13642799999999999 +-0.20508599999999999 0.14620600000000000 +-0.26247900000000002 0.01860690000000000 +-0.24475300000000000 0.00128651000000000 +-0.17287900000000000 0.07846690000000001 +-0.14485700000000001 0.12063500000000001 +-0.13344700000000001 0.15071200000000001 +-0.25083600000000000 0.00914945000000000 +-0.18010599999999999 0.03686900000000000 +-0.18816300000000000 0.02293980000000000 +-0.20318600000000001 -0.03005060000000000 +-0.17436699999999999 -0.01695920000000000 +-0.20029500000000000 -0.00554548000000000 +-0.21379000000000001 -0.01019390000000000 +-0.22625999999999999 -0.01602680000000000 +-0.18674800000000000 -0.00071344700000000 +-0.03932460000000000 -0.02666830000000000 +-0.03925560000000000 -0.05397620000000000 +-0.01404300000000000 -0.05156900000000000 +-0.01281140000000000 -0.03297440000000000 +0.00025716100000000 -0.04038760000000000 +-0.00235339000000000 -0.06635020000000000 +0.00514285000000000 -0.02623370000000000 +-0.05370540000000000 -0.10002100000000000 +-0.06064010000000000 -0.07184490000000000 +-0.10332300000000000 -0.09791700000000000 +-0.09767480000000001 -0.06580080000000001 +-0.02287800000000000 -0.12280500000000000 +-0.01834440000000000 -0.10006500000000000 +-0.03703030000000000 -0.10977800000000000 +-0.22790700000000000 -0.03429780000000000 +-0.24421999999999999 -0.02160990000000000 +-0.21956100000000001 -0.00229464000000000 +-0.01882920000000000 -0.07918520000000000 +-0.19679700000000000 0.00930870000000000 +-0.17767800000000000 0.01133440000000000 +-0.15034600000000001 -0.03228640000000000 +-0.09626770000000000 -0.03217010000000000 +-0.12686400000000000 -0.01489330000000000 +-0.03686590000000000 -0.08920240000000000 +-0.04727000000000000 -0.12435800000000000 +-0.07423990000000000 -0.11637599999999999 +-0.28881000000000001 0.08273820000000000 +-0.19542799999999999 -0.05568390000000000 +-0.25102000000000002 -0.03770290000000000 +-0.25682800000000000 -0.01989910000000000 +-0.01044890000000000 -0.11426799999999999 +-0.15682900000000000 -0.07004180000000000 +-0.15470700000000001 0.02812290000000000 +-0.06659100000000000 -0.04315070000000000 +-0.06487910000000000 -0.14555499999999999 +-0.14442099999999999 -0.11574900000000000 +-0.15122400000000000 -0.15927800000000000 +-0.11173900000000000 -0.14992600000000000 +-0.03111620000000000 -0.14380999999999999 +-0.16651299999999999 -0.17455000000000001 +-0.13802300000000001 -0.17901800000000001 +-0.26305400000000001 -0.03008160000000000 +-0.21636000000000000 -0.14896999999999999 +-0.21421299999999999 -0.11310099999999999 +-0.24318400000000001 -0.14052799999999999 +-0.18837999999999999 -0.17875099999999999 +-0.18471000000000001 -0.14161699999999999 +-0.15202099999999999 0.00089938800000000 +-0.27395000000000003 -0.04066720000000000 +-0.18671699999999999 -0.09123320000000000 +-0.22246400000000000 -0.07536089999999999 +-0.09578760000000000 -0.13067799999999999 +-0.23696500000000001 0.12865599999999999 +-0.25777400000000000 -0.05791230000000000 +-0.28615400000000002 0.03984230000000000 +-0.00327775000000000 -0.00841017000000000 +-0.25280999999999998 -0.00309231000000000 +0.00121365000000000 -0.08619950000000000 +-0.17146900000000001 -0.00241387000000000 +-0.15892999999999999 -0.01343940000000000 +-0.21124000000000001 0.00524665000000000 +-0.06533350000000000 -0.01421250000000000 +-0.21189600000000000 -0.00271869000000000 +-0.25108000000000003 -0.09202000000000000 +-0.31369799999999998 0.03807740000000000 +-0.27149099999999998 -0.11406700000000000 +-0.28459699999999999 -0.07320550000000001 +-0.07589390000000000 -0.18407699999999999 +-0.06261100000000000 -0.17513000000000001 +-0.07609330000000000 -0.16314200000000001 +0.00016327700000000 -0.10355200000000001 +-0.02872410000000000 -0.00156414000000000 +-0.01435380000000000 0.00308408000000000 +-0.12731200000000001 0.01677310000000000 +-0.13466700000000001 0.00094315400000000 +0.00202303000000000 0.07827919999999999 +0.02841240000000000 0.08494169999999999 +0.01594670000000000 0.10307900000000000 +-0.00962830000000000 0.14879200000000001 +-0.01673320000000000 0.11896400000000000 +0.00534235000000000 0.12164000000000000 +-0.03012780000000000 0.10138900000000001 +-0.02854770000000000 0.07080069999999999 +-0.00592029000000000 0.10068500000000000 +-0.31689800000000001 0.06285480000000000 +-0.00926267000000000 0.01742490000000000 +-0.02594480000000000 0.01520790000000000 +0.03956540000000000 0.06584290000000000 +-0.00259196000000000 0.05460730000000000 +-0.04968400000000000 0.01822080000000000 +-0.07789880000000000 0.02296420000000000 +-0.06690250000000000 0.00647931000000000 +-0.04768020000000000 -0.14828000000000000 +0.02457530000000000 0.15474499999999999 +0.11276600000000001 0.09952060000000000 +0.07082629999999999 0.08771039999999999 +0.09508170000000001 0.07003930000000000 +0.08551670000000000 0.03420360000000000 +0.06843790000000000 0.05875820000000000 +0.04888310000000000 0.02946740000000000 +0.05944330000000000 0.01189650000000000 +0.08005260000000000 0.01455180000000000 +0.15004899999999999 0.10953400000000001 +0.15212899999999999 0.07574839999999999 +-0.03531200000000000 0.17809400000000000 +-0.05507500000000000 0.15928200000000001 +-0.02680130000000000 0.15953400000000001 +0.04326160000000000 0.16105800000000001 +0.05561930000000000 0.14540500000000001 +0.06160470000000000 0.16266600000000001 +0.12242400000000001 0.13998200000000000 +0.09908670000000000 0.13400400000000001 +-0.00513261000000000 0.16801199999999999 +0.02864610000000000 0.17255899999999999 +0.02302540000000000 0.18896600000000000 +0.05399200000000000 0.12448900000000000 +0.03694350000000000 0.13911499999999999 +0.03778010000000000 0.10418200000000000 +0.01162540000000000 0.03488840000000000 +-0.05307370000000000 0.13435200000000000 +-0.06687100000000000 0.11254300000000000 +-0.10134500000000000 0.00172185000000000 +0.07658940000000000 0.14677899999999999 +0.07598090000000000 0.12629000000000001 +0.01506890000000000 0.00949618000000000 +-0.08534820000000000 0.08532910000000000 +-0.02799170000000000 0.13784500000000000 +0.12397300000000000 0.07188710000000000 +0.00496704000000000 0.01990390000000000 +-0.07667960000000000 0.13824400000000001 +-0.09684780000000000 0.11329300000000000 +0.07175130000000000 -0.00410704000000000 +0.02393600000000000 -0.01454820000000000 +0.04050310000000000 0.00510915000000000 +-0.02270260000000000 0.04054320000000000 +-0.00573450000000000 0.03748440000000000 +-0.09173530000000001 0.04960090000000000 +-0.05740990000000000 -0.16077300000000000 +-0.11552800000000001 0.07408670000000001 +0.11186599999999999 0.04843290000000000 +-0.12656600000000001 0.10163000000000000 +-0.15584899999999999 0.05703930000000000 +-0.11467300000000000 -0.17524799999999999 +0.00996937000000000 -0.01298980000000000 +0.00042625600000000 0.00615835000000000 +-0.09476610000000001 -0.17258599999999999 +-0.10563200000000000 0.15925500000000001 +-0.11695800000000001 0.13199100000000000 +-0.12928400000000001 0.04635750000000000 +0.04950970000000000 0.17627999999999999 +0.03775450000000000 0.18965699999999999 +-0.05625970000000000 0.04608740000000000 +-0.05938180000000000 0.18434700000000001 +-0.07765430000000000 0.16547300000000001 +0.05390970000000000 -0.00800927000000000 +0.09879780000000001 0.00829006000000000 +-0.01792850000000000 0.19112499999999999 +0.00412912000000000 0.19402800000000001 +-0.28409000000000001 0.02300040000000000 +3 0 1 2 +3 3 4 5 +3 6 7 8 +3 9 10 3 +3 10 4 3 +3 11 12 13 +3 14 2 15 +3 16 5 17 +3 13 12 0 +3 18 1 8 +3 19 10 20 +3 19 21 4 +3 22 0 12 +3 16 3 5 +3 7 18 8 +3 1 18 2 +3 13 14 3 +3 23 8 1 +3 9 24 25 +3 25 26 20 +3 20 9 25 +3 3 24 9 +3 0 22 27 +3 16 13 3 +3 28 14 29 +3 4 10 19 +3 0 27 1 +3 14 24 3 +3 30 31 32 +3 30 33 34 +3 35 32 31 +3 36 37 38 +3 36 38 39 +3 40 39 38 +3 38 41 40 +3 39 40 42 +3 43 44 45 +3 45 44 46 +3 47 48 49 +3 50 34 51 +3 23 1 27 +3 7 33 52 +3 38 37 53 +3 29 54 55 +3 56 57 58 +3 59 48 53 +3 60 43 61 +3 62 11 16 +3 55 28 29 +3 63 56 31 +3 64 51 65 +3 66 48 47 +3 46 67 45 +3 55 68 28 +3 49 59 43 +3 37 69 44 +3 70 60 61 +3 71 72 73 +3 47 60 74 +3 37 44 59 +3 50 63 30 +3 43 45 61 +3 37 36 69 +3 72 75 76 +3 64 65 77 +3 78 79 80 +3 78 81 82 +3 68 55 83 +3 77 84 64 +3 6 51 34 +3 79 85 86 +3 30 34 50 +3 56 63 67 +3 70 61 87 +3 88 17 5 +3 84 89 64 +3 86 63 50 +3 90 12 11 +3 33 7 34 +3 45 67 71 +3 42 91 39 +3 92 51 6 +3 41 53 93 +3 86 64 89 +3 94 31 95 +3 83 94 95 +3 2 18 96 +3 69 97 57 +3 61 45 87 +3 52 98 96 +3 99 79 86 +3 54 96 32 +3 49 48 59 +3 38 53 41 +3 50 64 86 +3 11 100 90 +3 82 71 85 +3 82 72 71 +3 35 54 32 +3 78 82 79 +3 36 97 69 +3 80 99 101 +3 98 32 96 +3 52 18 7 +3 98 33 32 +3 102 101 99 +3 103 104 105 +3 106 48 66 +3 107 91 108 +3 109 83 110 +3 111 112 113 +3 34 7 6 +3 114 115 116 +3 59 44 43 +3 117 118 119 +3 29 15 54 +3 119 118 111 +3 62 120 11 +3 108 121 122 +3 123 111 124 +3 125 126 127 +3 102 89 84 +3 74 60 128 +3 116 129 114 +3 50 51 64 +3 130 131 132 +3 35 31 94 +3 133 134 135 +3 133 136 137 +3 83 95 58 +3 138 130 139 +3 115 117 119 +3 86 85 63 +3 17 62 16 +3 46 57 56 +3 107 122 125 +3 140 141 142 +3 79 99 80 +3 143 144 145 +3 130 146 147 +3 45 71 87 +3 148 149 150 +3 107 127 97 +3 151 152 153 +3 123 124 154 +3 117 155 156 +3 118 124 111 +3 56 67 46 +3 48 93 53 +3 71 73 87 +3 107 36 39 +3 110 58 157 +3 92 65 51 +3 60 49 43 +3 158 144 159 +3 160 135 154 +3 161 117 156 +3 117 115 162 +3 130 132 163 +3 29 14 15 +3 96 18 52 +3 47 49 60 +3 160 154 164 +3 156 165 166 +3 129 149 148 +3 52 33 98 +3 167 137 136 +3 143 152 144 +3 46 69 57 +3 160 168 169 +3 124 170 171 +3 136 135 169 +3 155 141 165 +3 125 122 170 +3 30 32 33 +3 131 153 112 +3 172 109 157 +3 134 123 135 +3 105 104 173 +3 166 174 161 +3 142 162 114 +3 2 96 15 +3 155 117 162 +3 59 53 37 +3 153 116 113 +3 107 39 91 +3 23 6 8 +3 139 130 163 +3 133 135 136 +3 163 132 175 +3 20 10 9 +3 176 24 177 +3 72 178 73 +3 127 126 157 +3 179 180 91 +3 178 181 73 +3 116 152 129 +3 182 26 183 +3 68 83 109 +3 89 102 99 +3 142 114 148 +3 118 117 161 +3 109 184 68 +3 149 185 186 +3 187 118 161 +3 134 131 123 +3 180 108 91 +3 126 125 187 +3 138 146 130 +3 86 89 99 +3 157 109 110 +3 184 109 172 +3 141 188 189 +3 157 126 172 +3 83 55 94 +3 83 58 110 +3 172 161 174 +3 180 179 160 +3 82 75 72 +3 93 48 106 +3 14 13 2 +3 132 133 175 +3 97 157 57 +3 183 26 25 +3 2 13 0 +3 120 100 11 +3 172 174 184 +3 144 151 159 +3 165 189 182 +3 164 121 180 +3 179 168 160 +3 16 11 13 +3 190 167 136 +3 131 112 123 +3 166 161 156 +3 149 129 143 +3 151 153 131 +3 170 187 125 +3 82 81 75 +3 143 145 185 +3 153 152 116 +3 148 140 142 +3 151 144 152 +3 95 31 56 +3 97 36 107 +3 5 4 88 +3 73 181 105 +3 149 143 185 +3 165 141 189 +3 112 111 123 +3 177 174 176 +3 187 170 118 +3 174 166 176 +3 114 129 148 +3 147 158 159 +3 85 67 63 +3 28 24 14 +3 158 145 144 +3 159 151 131 +3 187 161 172 +3 70 173 128 +3 55 35 94 +3 25 176 183 +3 105 173 70 +3 154 171 164 +3 24 176 25 +3 142 141 155 +3 55 54 35 +3 191 133 137 +3 130 159 131 +3 162 142 155 +3 180 160 164 +3 170 122 121 +3 147 159 130 +3 140 148 192 +3 68 177 28 +3 21 88 4 +3 162 115 114 +3 169 190 136 +3 87 73 105 +3 148 150 193 +3 179 91 42 +3 175 133 191 +3 87 105 70 +3 170 121 171 +3 116 115 119 +3 63 31 30 +3 148 193 192 +3 149 186 150 +3 141 140 188 +3 160 169 135 +3 118 170 124 +3 68 184 177 +3 129 152 143 +3 132 131 134 +3 15 96 54 +3 107 125 127 +3 113 116 119 +3 132 134 133 +3 128 60 70 +3 56 58 95 +3 111 113 119 +3 105 181 103 +3 164 171 121 +3 155 165 156 +3 85 71 67 +3 177 184 174 +3 154 124 171 +3 72 76 178 +3 135 123 154 +3 194 22 12 +3 113 112 153 +3 79 82 85 +3 57 157 58 +3 122 107 108 +3 121 108 180 +3 165 182 183 +3 177 24 28 +3 166 183 176 +3 127 157 97 +3 44 69 46 +3 90 194 12 +3 168 190 169 +3 165 183 166 +3 172 126 187 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/stair.xy b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/stair.xy new file mode 100644 index 00000000000..3d6f2434d85 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/stair.xy @@ -0,0 +1,160 @@ +0.00605396 0.00360027 +0.0117095 0.00496933 +0.00292489 -0.0056444 +0.018654 -0.00345866 +0.0208731 -0.00712699 +0.0349622 0.00520127 +0.0226514 0.00273598 +0.0443469 0.00641652 +0.0320264 -0.00785089 +0.0536853 -0.00492172 +0.0477706 0.00445479 +0.0639807 0.00509629 +0.0673864 -0.000544755 +0.068878 0.00636891 +0.0786834 -0.00880306 +0.0838299 0.00977294 +0.087326 -0.0021897 +0.079062 0.000772423 +0.0984893 0.00905454 +0.0994487 -0.00770074 +0.100736 0.00717826 +0.0994229 0.00250389 +0.100252 0.0167278 +0.0960604 0.00802011 +0.103545 0.0289233 +0.108446 0.0183656 +0.106763 0.0262313 +0.106452 0.0420934 +0.0997256 0.0427598 +0.107064 0.0403298 +0.0928101 0.0560955 +0.10136 0.0583232 +0.104819 0.0562105 +0.0902899 0.0706163 +0.10994 0.0770702 +0.0923621 0.0704878 +0.0919434 0.0865538 +0.0963674 0.0842679 +0.103725 0.0803259 +0.102273 0.101166 +0.100319 0.0952791 +0.108403 0.0942299 +0.113529 0.0981625 +0.108027 0.103066 +0.126272 0.0950435 +0.133506 0.0939314 +0.124776 0.107205 +0.131076 0.107853 +0.136759 0.109119 +0.15444 0.102357 +0.143707 0.104111 +0.160272 0.0974776 +0.165379 0.103348 +0.173751 0.0916309 +0.174657 0.0937715 +0.167267 0.0980068 +0.170889 0.0905988 +0.185414 0.102092 +0.189813 0.10002 +0.199397 0.0909473 +0.198222 0.107717 +0.198974 0.099872 +0.201479 0.108827 +0.205074 0.107075 +0.202 0.124977 +0.191185 0.121976 +0.206848 0.134009 +0.196679 0.137767 +0.19255 0.148035 +0.190151 0.143856 +0.195263 0.155428 +0.20595 0.148822 +0.204421 0.152387 +0.191967 0.169495 +0.197981 0.169699 +0.191872 0.176798 +0.207398 0.170317 +0.194859 0.178978 +0.190444 0.183389 +0.196073 0.192833 +0.200019 0.190352 +0.205824 0.198579 +0.217043 0.198723 +0.210708 0.208976 +0.225591 0.209213 +0.224774 0.208331 +0.228376 0.201784 +0.233852 0.192014 +0.230703 0.196273 +0.241172 0.192107 +0.241027 0.203219 +0.257393 0.199803 +0.266244 0.190504 +0.263176 0.1902 +0.279822 0.191442 +0.267419 0.200092 +0.270919 0.209937 +0.294279 0.199399 +0.292596 0.208336 +0.302111 0.206854 +0.297261 0.193606 +0.302447 0.195568 +0.307461 0.217454 +0.302133 0.219113 +0.300152 0.216012 +0.296763 0.223723 +0.302571 0.234727 +0.298522 0.237272 +0.307834 0.234066 +0.296568 0.250613 +0.298385 0.251664 +0.29308 0.261943 +0.295426 0.266549 +0.293096 0.259791 +0.292439 0.271056 +0.291263 0.275271 +0.300944 0.286063 +0.308624 0.284206 +0.306603 0.285177 +0.302574 0.289769 +0.303807 0.303483 +0.308102 0.301263 +0.316854 0.306492 +0.313448 0.299638 +0.325862 0.304911 +0.328301 0.305416 +0.335535 0.300855 +0.327652 0.299601 +0.334895 0.301131 +0.339451 0.303238 +0.356128 0.293215 +0.359167 0.306227 +0.350648 0.309557 +0.359385 0.291005 +0.360515 0.305818 +0.377582 0.301763 +0.373333 0.308693 +0.375172 0.299768 +0.398744 0.298911 +0.390985 0.295462 +0.39465 0.305079 +0.397266 0.302934 +0.391293 0.303944 +0.401355 0.307406 +0.391301 0.312749 +0.401141 0.331346 +0.403843 0.339273 +0.397447 0.32984 +0.401007 0.345187 +0.401435 0.350856 +0.404534 0.358367 +0.40019 0.350997 +0.401021 0.359769 +0.398586 0.362409 +0.403735 0.370503 +0.400571 0.381428 +0.409145 0.374727 +0.402981 0.379619 +0.406312 0.38398 +0.405032 0.387826 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp new file mode 100644 index 00000000000..fda2e0924a5 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp @@ -0,0 +1,826 @@ +#include +#include +#include + +// Graphs +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace PMP = CGAL::Polygon_mesh_processing; + +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; +typedef CGAL::Simple_cartesian::Type> Exact_kernel; + +template +typename CGAL::Kernel_traits::type::Ray_2 +random_2D_ray(const AABB_tree& aabb_tree, CGAL::Random& rnd) +{ + typedef typename AABB_tree::AABB_traits::Point_3 Point_3; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_2 Point_2; + typedef typename Kernel::Ray_2 Ray_2; + + const CGAL::Bbox_3& bbox = aabb_tree.bbox(); + + FT px = (bbox.xmin() == bbox.xmax()) ? bbox.xmin() : rnd.get_double(bbox.xmin(), bbox.xmax()); + FT py = (bbox.ymin() == bbox.ymax()) ? bbox.ymin() : rnd.get_double(bbox.ymin(), bbox.ymax()); + + FT qx = (bbox.xmin() == bbox.xmax()) ? bbox.xmin() : rnd.get_double(bbox.xmin(), bbox.xmax()); + FT qy = (bbox.ymin() == bbox.ymax()) ? bbox.ymin() : rnd.get_double(bbox.ymin(), bbox.ymax()); + + return Ray_2(Point_2(px, py), Point_2(qx, qy)); +} + +template +typename CGAL::Kernel_traits::type::Ray_3 +random_3D_ray(const AABB_tree& aabb_tree, CGAL::Random& rnd) +{ + typedef typename AABB_tree::AABB_traits::Point_3 Point_3; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + typedef typename Kernel::Ray_3 Ray_3; + + const CGAL::Bbox_3& bbox = aabb_tree.bbox(); + + FT px = (bbox.xmin() == bbox.xmax()) ? bbox.xmin() : rnd.get_double(bbox.xmin(), bbox.xmax()); + FT py = (bbox.ymin() == bbox.ymax()) ? bbox.ymin() : rnd.get_double(bbox.ymin(), bbox.ymax()); + FT pz = (bbox.zmin() == bbox.zmax()) ? bbox.zmin() : rnd.get_double(bbox.zmin(), bbox.zmax()); + + FT qx = (bbox.xmin() == bbox.xmax()) ? bbox.xmin() : rnd.get_double(bbox.xmin(), bbox.xmax()); + FT qy = (bbox.ymin() == bbox.ymax()) ? bbox.ymin() : rnd.get_double(bbox.ymin(), bbox.ymax()); + FT qz = (bbox.zmin() == bbox.zmax()) ? bbox.zmin() : rnd.get_double(bbox.zmin(), bbox.zmax()); + + return Ray_3(Point_3(px, py, pz), Point_3(qx, qy, qz)); +} + +template +bool is_equal(const FT& a, const FT& b) +{ + if(std::is_floating_point::value) + return (CGAL::abs(a - b) <= 1e-7); // numeric_limits' epsilon is too restrictive... + else + return (a == b); +} + +template +void test_snappers(const G& g) +{ + std::cout << " test snappers..." << std::endl; + + typedef typename PMP::Location_traits::FT FT; + + typename PMP::Location_traits::Barycentric_coordinates coords = CGAL::make_array(FT(1e-6), FT(0.9999999999999999999), FT(1e-7)); + typename PMP::Location_traits::Face_location loc = std::make_pair(*(faces(g).first), coords); + + // --------------------------------------------------------------------------- + PMP::internal::snap_coordinates_to_border(coords); // uses numeric_limits' epsilon() + assert(coords[0] == FT(1e-6) && coords[1] == FT(1) && coords[2] == FT(1e-7)); + + PMP::internal::snap_coordinates_to_border(coords, 1e-5); + assert(coords[0] == FT(0) && coords[1] == FT(1) && coords[2] == FT(0)); + + // --------------------------------------------------------------------------- + PMP::internal::snap_location_to_border(loc); // uses numeric_limits' epsilon() + assert(!PMP::is_on_face_border(loc, g)); + + PMP::internal::snap_location_to_border(loc, 1e-7); + assert(PMP::is_on_face_border(loc, g)); +} + + +template +struct Point_to_bare_point +{ + typedef typename K::Point_2 type; +}; + +template +struct Point_to_bare_point +{ + typedef typename K::Point_3 type; +}; + +template +void test_constructions(const G& g, CGAL::Random& rnd) +{ + std::cout << " test constructions..." << std::endl; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename PMP::Location_traits::descriptor_variant descriptor_variant; + + typedef typename boost::property_map_value::type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + typedef typename Point_to_bare_point::type Bare_point; + + typedef typename PMP::Location_traits::Barycentric_coordinates Barycentric_coordinates; + typedef typename PMP::Location_traits::Face_location Face_location; + + typedef typename boost::property_map::const_type VPM; + VPM vpm = CGAL::get_const_property_map(boost::vertex_point, g); + + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + halfedge_descriptor h = halfedge(f, g); + vertex_descriptor v = source(h, g); + + Point p = get(vpm, v); + Point q = get(vpm, target(h, g)); + Point r = get(vpm, target(next(h, g), g)); + + Bare_point bp(p); + Bare_point bq(q); + Bare_point br(r); + + Barycentric_coordinates bar; + Face_location loc; + loc.first = f; + + // --------------------------------------------------------------------------- + bar = PMP::barycentric_coordinates(p, q, r, p, Kernel()); + assert(is_equal(bar[0], FT(1)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(0))); + bar = PMP::barycentric_coordinates(p, q, r, q, Kernel()); + assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(1)) && is_equal(bar[2], FT(0))); + bar = PMP::barycentric_coordinates(p, q, r, r, Kernel()); + assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(1))); + + Point mp = Point(CGAL::midpoint(bp, bq)); + bar = PMP::barycentric_coordinates(p, q, r, mp); + assert(is_equal(bar[0], FT(0.5)) && is_equal(bar[1], FT(0.5)) && is_equal(bar[2], FT(0))); + + int n = 100; + while(n --> 0) // :) + { + const FT a = rnd.get_double(-1., 1.); + const FT b = rnd.get_double(-1., 1.); + const FT c = 1. - a - b; + + Bare_point barycentric_pt = CGAL::barycenter(bp, a, bq, b, br, c); + bar = PMP::barycentric_coordinates(p, q, r, Point(barycentric_pt)); + assert(is_equal(bar[0], a) && is_equal(bar[1], b) && is_equal(bar[2], c)); + + loc.second = bar; + const FT sq_dist = CGAL::squared_distance(barycentric_pt, Bare_point(PMP::construct_point(loc, g))); + assert(is_equal(sq_dist, FT(0))); + } + + // --------------------------------------------------------------------------- + loc = std::make_pair(f, CGAL::make_array(FT(0.3), FT(0.4), FT(0.3))); + descriptor_variant dv = PMP::get_descriptor_from_location(loc, g); + const face_descriptor* fd = boost::get(&dv); + assert(fd); + + loc = std::make_pair(f, CGAL::make_array(FT(0.5), FT(0.5), FT(0))); + dv = PMP::get_descriptor_from_location(loc, g); + const halfedge_descriptor* hd = boost::get(&dv); + assert(hd); + + loc = std::make_pair(f, CGAL::make_array(FT(1), FT(0), FT(0))); + assert(PMP::is_on_vertex(loc, source(halfedge(f, g), g), g)); + dv = PMP::get_descriptor_from_location(loc, g); + if(const vertex_descriptor* v = boost::get(&dv)) { } else { assert(false); } + + // --------------------------------------------------------------------------- + + Point s = PMP::construct_point(loc, g, CGAL::parameters::all_default()); + s = PMP::construct_point(loc, g); + assert(s == get(vpm, source(halfedge(f, g), g))); +} + +template +void test_random_entities(const G& g, CGAL::Random& rnd) +{ + std::cout << " test random entities..." << std::endl; + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + typedef typename boost::property_map_value::type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + // --------------------------------------------------------------------------- + Face_location loc; + + halfedge_descriptor h = CGAL::internal::random_halfedge_in_mesh(g, rnd); + if(is_border(h, g)) + h = opposite(h, g); + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + + int nn = 100; + while(nn --> 0) // the infamous 'go to zero' operator + { + loc = PMP::random_location_on_mesh(g, rnd); + assert(loc.first != boost::graph_traits::null_face()); + assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && + loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && + loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); + + loc = PMP::random_location_on_face(f, g, rnd); + assert(loc.first == f); + assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && + loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && + loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); + + loc = PMP::random_location_on_halfedge(h, g, rnd); + assert(loc.first == face(h, g)); + assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && + loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && + loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); + int h_id = CGAL::halfedge_index_in_face(h, g); + assert(loc.second[(h_id+2)%3] == FT(0)); + } +} + +template +void test_helpers(const G& g, CGAL::Random& rnd) +{ + std::cout << " test helpers..." << std::endl; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + halfedge_descriptor h = halfedge(f, g); + vertex_descriptor v = source(h, g); + + // --------------------------------------------------------------------------- + // Local index + int pos = CGAL::vertex_index_in_face(v, f, g); + assert(pos == 0); + pos = CGAL::vertex_index_in_face(target(h, g), f, g); + assert(pos == 1); + pos = CGAL::vertex_index_in_face(target(next(h, g), g), f, g); + assert(pos == 2); + + pos = CGAL::halfedge_index_in_face(h, g); + assert(pos == 0); + pos = CGAL::halfedge_index_in_face(next(h, g), g); + assert(pos == 1); + pos = CGAL::halfedge_index_in_face(prev(h, g), g); + assert(pos == 2); + + // --------------------------------------------------------------------------- + // Incident faces + Face_location loc = PMP::random_location_on_face(f, g, rnd); + std::set s; + PMP::internal::incident_faces(loc, g, std::inserter(s, s.begin())); + assert(PMP::is_on_face_border(loc, g) || s.size() == 1); + + loc = PMP::random_location_on_halfedge(h, g, rnd); + std::vector vec; + PMP::internal::incident_faces(loc, g, std::back_inserter(vec)); + assert(PMP::is_on_vertex(loc, source(h, g), g) || PMP::is_on_vertex(loc, target(h, g), g) || vec.size() == 2); +} + +template +void test_predicates(const G& g, CGAL::Random& rnd) +{ + std::cout << " test predicates..." << std::endl; + + typedef typename boost::property_map_value::type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + halfedge_descriptor h = halfedge(f, g); + vertex_descriptor v = source(h, g); + + // --------------------------------------------------------------------------- + Face_location loc(f, CGAL::make_array(FT(1), FT(0), FT(0))); + assert(PMP::is_on_vertex(loc, v, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(1), FT(0))); + assert(PMP::is_on_vertex(loc, target(h, g), g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); + assert(PMP::is_on_vertex(loc, target(next(h, g), g), g)); + loc = Face_location(f, CGAL::make_array(FT(-1), FT(1), FT(1))); + assert(!PMP::is_on_vertex(loc, target(next(h, g), g), g)); + + // --------------------------------------------------------------------------- + loc = Face_location(f, CGAL::make_array(FT(0.5), FT(0.5), FT(0))); + assert(PMP::is_on_halfedge(loc, h, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(0.5), FT(0.5))); + assert(PMP::is_on_halfedge(loc, next(h, g), g)); + loc = Face_location(f, CGAL::make_array(FT(-0.5), FT(1.5), FT(0))); + assert(!PMP::is_on_halfedge(loc, h, g)); + loc = Face_location(f, CGAL::make_array(FT(0.1), FT(-0.6), FT(1.5))); + assert(!PMP::is_on_halfedge(loc, h, g)); + + // --------------------------------------------------------------------------- + loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); + assert(PMP::is_in_face(loc, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); + assert(PMP::is_in_face(loc, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(2), FT(-1))); + assert(!PMP::is_in_face(loc, g)); + + // --------------------------------------------------------------------------- + loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); + assert(!PMP::is_on_face_border(loc, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(0.6), FT(0.4))); + assert(PMP::is_on_face_border(loc, g)); + loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); + assert(PMP::is_on_face_border(loc, g)); + loc = Face_location(f, CGAL::make_array(FT(-0.2), FT(0), FT(1.2))); + assert(!PMP::is_on_face_border(loc, g)); + + // --------------------------------------------------------------------------- + int max = 1000, counter = 0; + typename boost::graph_traits::halfedge_iterator hit, hend; + boost::tie(hit, hend) = halfedges(g); + for(; hit!=hend; ++hit) + { + const halfedge_descriptor h = *hit; + if(face(h, g) == boost::graph_traits::null_face()) + continue; + + const int id_of_h = CGAL::halfedge_index_in_face(h, g); + const face_descriptor f = face(h, g); + loc.first = f; + + loc.second[id_of_h] = FT(1); + loc.second[(id_of_h+1)%3] = FT(0); + loc.second[(id_of_h+2)%3] = FT(0); + boost::optional opt_hd = CGAL::is_border(source(h, g), g); + assert(PMP::is_on_mesh_border(loc, g) == (opt_hd != boost::none)); + + loc.second[id_of_h] = FT(0.5); + loc.second[(id_of_h+1)%3] = FT(0.5); + assert(PMP::is_on_mesh_border(loc, g) == CGAL::is_border(edge(h, g), g)); + + // Even if the point does lie on the border of the mesh, 'false' is returned because + // another face descriptor should be used. + loc.second[id_of_h] = -0.5; + loc.second[(id_of_h+1)%3] = 1.5; + assert(!PMP::is_on_mesh_border(loc, g)); + + if(++counter > max) + break; + } +} + +template +void test_locate_in_face(const G& g, CGAL::Random& rnd) +{ + std::cout << " test locate_in_face()..." << std::endl; + + typedef typename boost::property_map_value::type Point; + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + typedef typename boost::property_map::const_type VertexPointMap; + VertexPointMap vpm = CGAL::get_const_property_map(boost::vertex_point, g); + + const face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + const halfedge_descriptor h = halfedge(f, g); + const vertex_descriptor v = target(h, g); + + Face_location loc; + typename PMP::Location_traits::FT a = 0.1; + Point p = get(vpm, v); + + loc = PMP::locate_in_face(v, g); + assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); + + loc = PMP::locate_in_face(v, f, g); + assert(loc.first == f); + assert(is_equal(loc.second[0], FT(0)) && is_equal(loc.second[1], FT(1)) && is_equal(loc.second[2], FT(0))); + + loc = PMP::locate_in_face(h, a, g); + const int h_id = CGAL::halfedge_index_in_face(h, g); + assert(loc.first == f && is_equal(loc.second[(h_id+2)%3], FT(0))); + + loc = PMP::locate_in_face(p, f, g, CGAL::parameters::all_default()); + int v_id = CGAL::vertex_index_in_face(v, f, g); + assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); + + loc = PMP::locate_in_face(p, f, g); + v_id = CGAL::vertex_index_in_face(v, f, g); + assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); + + // --------------------------------------------------------------------------- + loc.second[0] = FT(0.2); + loc.second[1] = FT(0.8); + loc.second[2] = FT(0); + + halfedge_descriptor neigh_hd = opposite(halfedge(f, g), g); + face_descriptor neigh_f = face(neigh_hd, g); + + // Want to check good correspondence seen from one side and the other. If unfortunately + // we have selected a border face, can't do anything! + if(neigh_f != boost::graph_traits::null_face()) + { + int neigh_hd_id = CGAL::halfedge_index_in_face(neigh_hd, g); + Face_location neigh_loc; + neigh_loc.first = neigh_f; + neigh_loc.second[neigh_hd_id] = FT(0.3); + neigh_loc.second[(neigh_hd_id+1)%3] = FT(0.7); + neigh_loc.second[(neigh_hd_id+2)%3] = FT(0); + + PMP::locate_in_adjacent_face(loc, neigh_f, g); + + assert(PMP::locate_in_common_face(loc, neigh_loc, g)); + + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g)); + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, 1e-7)); + } +} + +template +struct Locate_with_AABB_tree_Tester // 2D case +{ + template + void operator()(const G& g, CGAL::Random& rnd) const + { + std::cout << " test locate_with_AABB_tree (2D)..." << std::endl; + + typedef typename boost::property_map_value::type Point; + + typedef typename boost::property_map::const_type VertexPointMap; + + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + typedef typename Kernel::Ray_2 Ray_2; + typedef typename Kernel::Ray_3 Ray_3; + typedef typename Kernel::Point_3 Point_3; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + halfedge_descriptor h = halfedge(f, g); + vertex_descriptor v = target(h, g); + + // --------------------------------------------------------------------------- + typedef typename boost::property_traits::value_type Intrinsic_point; + typedef PMP::internal::Point_to_Point_3 Intrinsic_point_to_Point_3; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + CGAL_static_assertion((std::is_same::value)); + + Intrinsic_point_to_Point_3 to_p3; + + CGAL::AABB_tree tree_a; + VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); + typename boost::property_traits::value_type p_a = get(vpm_a, v); + const Point_3& p3_a = to_p3(p_a); + + CGAL::AABB_tree tree_b; + WrappedVertexPointMap vpm_b(g); + // --------------------------------------------------------------------------- + + PMP::build_AABB_tree(g, tree_a); + assert(tree_a.size() == num_faces(g)); + + PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); + assert(tree_b.size() == num_faces(g)); + + Face_location loc = PMP::locate_with_AABB_tree(p_a, tree_a, g); + + // sanitize otherwise some test platforms fail + PMP::internal::snap_location_to_border(loc, 1e-7); + + assert(PMP::is_on_vertex(loc, v, g)); // might fail du to precision issues... + assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); + assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + + loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); + assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + + // --------------------------------------------------------------------------- + loc = PMP::locate(p_a, g); + assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + assert(PMP::is_in_face(loc, g)); + + loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + assert(PMP::is_in_face(loc, g)); + + loc = PMP::locate(CGAL::ORIGIN, g, CGAL::parameters::vertex_point_map(vpm_b)); + assert(PMP::is_in_face(loc, g)); + + // --------------------------------------------------------------------------- + Ray_2 r2 = random_2D_ray >(tree_a, rnd); + loc = PMP::locate_with_AABB_tree(r2, tree_a, g); + if(loc.first != boost::graph_traits::null_face()) + assert(PMP::is_in_face(loc, g)); + + Ray_3 r3 = random_3D_ray >(tree_b, rnd); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + } +}; + +template +struct My_3D_Point +{ + typedef typename K::FT FT; + + typedef K R; + typedef CGAL::Dimension_tag<3> Ambient_dimension; + typedef CGAL::Dimension_tag<0> Feature_dimension; + + My_3D_Point() { } + My_3D_Point(const CGAL::Origin& /*o*/) : cx(0), cy(0), cz(0) { } + My_3D_Point(const FT x, const FT y, const FT z) : cx(x), cy(y), cz(z) { } + + FT x() const { return cx; } + FT y() const { return cy; } + FT z() const { return cz; } + +private: + FT cx, cy, cz; +}; + +template <> +struct Locate_with_AABB_tree_Tester<3> // 3D +{ + template + void operator()(const G& g, CGAL::Random& rnd) const + { + std::cout << " test locate_with_AABB_tree (3D)..." << std::endl; + + typedef typename boost::property_map_value::type Point; + + typedef typename CGAL::Kernel_traits::type Kernel; + typedef typename Kernel::FT FT; + typedef typename Kernel::Ray_3 Ray_3; + typedef typename Kernel::Point_3 Point_3; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename PMP::Location_traits::Face_location Face_location; + + face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); + halfedge_descriptor h = halfedge(f, g); + vertex_descriptor v = target(h, g); + + // --------------------------------------------------------------------------- + typedef typename PMP::Location_traits::VPM VertexPointMap; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + CGAL_static_assertion((std::is_same::value)); + + CGAL::AABB_tree tree_a; + VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); + typename boost::property_traits::value_type p3_a = get(vpm_a, v); + + // below tests the case where the value type of the VPM is not Kernel::Point_3 + typedef My_3D_Point Intrinsic_point; + typedef std::map Custom_map; + typedef boost::associative_property_map Custom_VPM; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive_with_WVPM; + typedef CGAL::AABB_traits AABB_face_graph_traits_with_WVPM; + + CGAL::AABB_tree tree_b; + Custom_map custom_map; + for(vertex_descriptor vd : vertices(g)) + { + const Point_3& p = get(vpm_a, vd); + custom_map[vd] = Intrinsic_point(p.x(), p.y(), p.z()); + } + + Custom_VPM custom_vpm(custom_map); + WrappedVertexPointMap vpm_b(custom_vpm); + // --------------------------------------------------------------------------- + + PMP::build_AABB_tree(g, tree_a); + assert(tree_a.size() == num_faces(g)); + + PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); + assert(tree_b.size() == num_faces(g)); + + Face_location loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g); + assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); + assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); + assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); + + loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); + assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); + + // --------------------------------------------------------------------------- + loc = PMP::locate(p3_a, g); + assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); + assert(PMP::is_in_face(loc, g)); + + loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + assert(PMP::is_in_face(loc, g)); + + // doesn't necessarily have to wrap with a P_to_P3 here, it'll do it internally + loc = PMP::locate(CGAL::ORIGIN, g, CGAL::parameters::vertex_point_map(custom_vpm)); + assert(PMP::is_in_face(loc, g)); + + // --------------------------------------------------------------------------- + Ray_3 r3 = random_3D_ray >(tree_b, rnd); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + } +}; + + +template +void test_locate(const G& g, CGAL::Random& rnd) +{ + assert(num_vertices(g) != 0 && num_faces(g) != 0); + + test_snappers(g); + test_constructions(g, rnd); + test_random_entities(g, rnd); + test_helpers(g, rnd); + test_predicates(g, rnd); + test_locate_in_face(g, rnd); + + // This test has slight syntax changes between 2D and 3D (e.g. testing ray_2 in 3D makes no sense) + Locate_with_AABB_tree_Tester< + CGAL::Ambient_dimension::Point>::value>()(g, rnd); +} + +template +void test_2D_triangulation(const char* fname, CGAL::Random& rnd) +{ + typedef CGAL::Regular_triangulation_2 RT; + + std::cout << "Testing Regular_triangulation_2 " << fname; + + std::ifstream in(fname); + assert(in.good()); + + RT tr; + double x, y; + while(in >> x >> y) + tr.insert(typename RT::Point(x, y)); + + std::ofstream out("triangulation.off"); + out << "OFF\n"; + out << tr.number_of_vertices() << " " << std::distance(tr.finite_faces_begin(), tr.finite_faces_end()) << " 0\n"; + + std::size_t counter = 0; + std::map ids; + for(const auto& v : CGAL::make_range(tr.finite_vertices_begin(), tr.finite_vertices_end())) + { + out << v.point().point() << " 0\n"; + if(ids.insert(std::make_pair(v.point().point(), counter)).second) + ++counter; + } + + for(const auto& fd : CGAL::make_range(tr.finite_faces_begin(), tr.finite_faces_end())) + { + out << "3 " << ids[fd.vertex(0)->point().point()] << " " << ids[fd.vertex(1)->point().point()] << " " << ids[fd.vertex(2)->point().point()] << "\n"; + } + + out.close(); + + std::cout << " (" << tr.number_of_vertices() << " vertices)..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + test_locate(tr, rnd); +} + +template +void test_2D_surface_mesh(const char* fname, CGAL::Random& rnd) +{ + typedef typename K::Point_2 Point; + typedef CGAL::Surface_mesh Mesh; + + std::cout << "Testing Surface_mesh " << fname << "..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + std::ifstream input(fname); + assert(input.good()); + + Mesh tm; + if(!input || !(input >> tm)) + { + std::cerr << "Error: cannot read file."; + return; + } + + test_locate(tm, rnd); +} + +template +void test_3D_surface_mesh(const char* fname, CGAL::Random& rnd) +{ + typedef typename K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + std::cout << "Testing Surface_mesh " << fname << "..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + std::ifstream input(fname); + Mesh tm; + if(!input || !(input >> tm)) + { + std::cerr << "Error: cannot read file."; + return; + } + + test_locate(tm, rnd); +} + +template +void test_polyhedron(const char* fname, CGAL::Random& rnd) +{ + typedef CGAL::Polyhedron_3 Polyhedron; + + std::cout << "Testing Polyhedron_3 " << fname << "..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + std::ifstream input(fname); + Polyhedron poly; + if(!input || !(input >> poly)) + { + std::cerr << "Error: cannot read file."; + return; + } + + test_locate(poly, rnd); +} + +template +void test(CGAL::Random& rnd) +{ + test_2D_triangulation("data/stair.xy", rnd); + test_2D_surface_mesh("data/blobby_2D.off", rnd); + test_3D_surface_mesh("data/mech-holes-shark.off", rnd); + test_polyhedron("data-coref/elephant_split_2.off", rnd); +} + +int main() +{ + std::cout.precision(17); + std::cout << std::fixed; + +// CGAL::Random rnd(1557332474); // if needed to debug with a fixed seed + CGAL::Random rnd(CGAL::get_default_random()); + + std::cout << "The seed is " << rnd.get_seed() << std::endl; + + test(rnd); + test(rnd); + + return EXIT_SUCCESS; +} diff --git a/Ridges_3/package_info/Ridges_3/dependencies b/Ridges_3/package_info/Ridges_3/dependencies index f4b40909932..3d5486b85be 100644 --- a/Ridges_3/package_info/Ridges_3/dependencies +++ b/Ridges_3/package_info/Ridges_3/dependencies @@ -9,6 +9,7 @@ Number_types Principal_component_analysis_LGPL Profiling_tools Property_map +Random_numbers Ridges_3 STL_Extension Stream_support diff --git a/Subdivision_method_3/package_info/Subdivision_method_3/dependencies b/Subdivision_method_3/package_info/Subdivision_method_3/dependencies index 95d535dc571..b42b51ec6d8 100644 --- a/Subdivision_method_3/package_info/Subdivision_method_3/dependencies +++ b/Subdivision_method_3/package_info/Subdivision_method_3/dependencies @@ -9,6 +9,7 @@ Modular_arithmetic Number_types Profiling_tools Property_map +Random_numbers STL_Extension Stream_support Subdivision_method_3 diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 8985f14dc6d..17822714110 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -257,8 +258,9 @@ namespace CGAL { // increment. SM_Edge_index operator++(int) { SM_Edge_index tmp(*this); halfedge_ = SM_Halfedge_index((size_type)halfedge_ + 2); return tmp; } + SM_Edge_index operator+=(std::ptrdiff_t n) { halfedge_ = SM_Halfedge_index(size_type(std::ptrdiff_t(halfedge_) + 2*n)); return *this; } - // prints the index and a short identification string to an ostream. + // prints the index and a short identification string to an ostream. friend std::ostream& operator<<(std::ostream& os, SM_Edge_index const& e) { return (os << 'e' << (size_type)e << " on " << e.halfedge()); @@ -2088,6 +2090,24 @@ private: //------------------------------------------------------- private data return sm; } + /// \cond SKIP_IN_MANUAL + template ::value> + struct Output_point_23 + { + template + Stream& operator()(Stream& os, const Point& p) const { os << p.x() << " " << p.y() << " " << p.z(); return os; } + }; + + template + struct Output_point_23 // 2D Point specialization + { + template + Stream& operator()(Stream& os, const Point& p) const { os << p.x() << " " << p.y(); return os; } + }; + + /// \endcond + /// \relates Surface_mesh /// Inserts the surface mesh in an output stream in Ascii OFF format. @@ -2121,10 +2141,12 @@ private: //------------------------------------------------------- private data get_const_property_map(CGAL::vertex_point, sm)); reindex.resize(sm.num_vertices()); int n = 0; + + Output_point_23

op; for(Vertex_index v : sm.vertices()){ - P p = get(vpm, v); - os << p.x() << " " << p.y() << " " << p.z(); + op(os, get(vpm, v)); + if(has_vcolors) { CGAL::Color color = vcolors[v]; @@ -2360,6 +2382,30 @@ private: //------------------------------------------------------- private data return in; } + template ::value> + struct Read_point_23 + { + template + Point operator()(Stream& is) const + { + double x, y, z; + is >> iformat(x) >> iformat(y) >> iformat(z); + return Point(x, y, z); + } + }; + + template + struct Read_point_23 // 2D specialization + { + template + Point operator()(Stream& is) const + { + double x, y; + is >> iformat(x) >> iformat(y); + return Point(x, y); + } + }; /// @endcond @@ -2418,22 +2464,19 @@ private: //------------------------------------------------------- private data } char ci; + Read_point_23

point_reader; for(int i=0; i < n; i++){ is >> sm_skip_comments; - double x, y, z; - is >> iformat(x) >> iformat(y) >> iformat(z); - + Vertex_index vi = sm.add_vertex(); - put(vpm, vi, P(x, y, z)); - - + put(vpm, vi, point_reader(is)); + vertexmap[i] = vi; if(v_has_normals){ is >> v; vnormal[vi] = v; } - if(i == 0 && ((off == "COFF") || (off == "CNOFF"))){ std::string col; std::getline(is, col); diff --git a/Surface_mesh/package_info/Surface_mesh/dependencies b/Surface_mesh/package_info/Surface_mesh/dependencies index 474db4e6713..bb41a0ba625 100644 --- a/Surface_mesh/package_info/Surface_mesh/dependencies +++ b/Surface_mesh/package_info/Surface_mesh/dependencies @@ -13,6 +13,7 @@ Modular_arithmetic Number_types Profiling_tools Property_map +Random_numbers STL_Extension Stream_support Surface_mesh diff --git a/Surface_mesh_approximation/package_info/Surface_mesh_approximation/dependencies b/Surface_mesh_approximation/package_info/Surface_mesh_approximation/dependencies index aaf95de7e9d..b1ab146c636 100644 --- a/Surface_mesh_approximation/package_info/Surface_mesh_approximation/dependencies +++ b/Surface_mesh_approximation/package_info/Surface_mesh_approximation/dependencies @@ -14,6 +14,7 @@ Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools Property_map +Random_numbers STL_Extension Solver_interface Stream_support diff --git a/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies b/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies index 5263ccfb5b7..974b4a8f5f5 100644 --- a/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies +++ b/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies @@ -14,6 +14,7 @@ Number_types Polygon_mesh_processing Profiling_tools Property_map +Random_numbers STL_Extension Solver_interface Stream_support diff --git a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies index 9dbfd435104..b5bfe486174 100644 --- a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies +++ b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies @@ -17,6 +17,7 @@ Polygon Polygon_mesh_processing Profiling_tools Property_map +Random_numbers STL_Extension Solver_interface Spatial_sorting diff --git a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies index 1124ba800da..a903992f736 100644 --- a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies +++ b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies @@ -13,6 +13,7 @@ Modular_arithmetic Number_types Profiling_tools Property_map +Random_numbers STL_Extension Spatial_searching Stream_support diff --git a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies index 7c2cadf30fd..a6626ec4390 100644 --- a/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies +++ b/Surface_mesh_simplification/package_info/Surface_mesh_simplification/dependencies @@ -11,6 +11,7 @@ Modular_arithmetic Number_types Profiling_tools Property_map +Random_numbers STL_Extension Stream_support Surface_mesh_simplification diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 06aaf45b9e5..a4b8c75e49a 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -61,8 +61,7 @@ class Triangulation_data_structure_2 typedef typename Vb::template Rebind_TDS::Other Vertex_base; typedef typename Fb::template Rebind_TDS::Other Face_base; - friend class Triangulation_ds_edge_iterator_2; - friend class Triangulation_ds_edge_iterator_2; + friend class Triangulation_ds_edge_iterator_2; friend class Triangulation_ds_face_circulator_2; friend class Triangulation_ds_edge_circulator_2; friend class Triangulation_ds_vertex_circulator_2; @@ -90,9 +89,7 @@ public: typedef typename Face_range::iterator Face_iterator; typedef typename Vertex_range::iterator Vertex_iterator; - typedef Triangulation_ds_edge_iterator_2 Edge_iterator; - typedef Triangulation_ds_edge_iterator_2 Halfedge_iterator; typedef Triangulation_ds_face_circulator_2 Face_circulator; typedef Triangulation_ds_vertex_circulator_2 Vertex_circulator; @@ -104,8 +101,7 @@ public: typedef Vertex_iterator Vertex_handle; typedef Face_iterator Face_handle; - - typedef std::pair Edge; + typedef std::pair Edge; typedef std::list List_edges; @@ -203,15 +199,7 @@ public: Edges edges() const { return Edges(edges_begin(),edges_end()); } - - Halfedge_iterator halfedges_begin() const { - return Halfedge_iterator(this); - } - Halfedge_iterator halfedges_end() const { - return Halfedge_iterator(this,1); - } - Face_circulator incident_faces(Vertex_handle v, Face_handle f = Face_handle()) const{ return Face_circulator(v,f); diff --git a/TDS_2/include/CGAL/Triangulation_ds_iterators_2.h b/TDS_2/include/CGAL/Triangulation_ds_iterators_2.h index 610e72c254f..303f7d8afa8 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_iterators_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_iterators_2.h @@ -31,8 +31,7 @@ namespace CGAL { - // with Once set to false, the Edge is reported twice, seen from the two adjacentfaces - template +template class Triangulation_ds_edge_iterator_2 { public: @@ -47,7 +46,7 @@ public: typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; - typedef Triangulation_ds_edge_iterator_2 Edge_iterator; + typedef Triangulation_ds_edge_iterator_2 Edge_iterator; private: const Tds* _tds; @@ -71,15 +70,14 @@ public: private: void increment(); void decrement(); - bool associated_edge(CGAL::Tag_true); - bool associated_edge(CGAL::Tag_false); + bool associated_edge(); }; // Edge iterator implementation -template -Triangulation_ds_edge_iterator_2 :: +template +Triangulation_ds_edge_iterator_2:: Triangulation_ds_edge_iterator_2(const Tds * tds) : _tds(tds) { @@ -90,12 +88,12 @@ Triangulation_ds_edge_iterator_2(const Tds * tds) } pos = _tds->faces().begin(); if (_tds->dimension() == 1) edge.second = 2; - while ( pos != _tds->faces().end() - && !associated_edge(Boolean_tag()) ) increment(); + while ( pos != _tds->faces().end() && !associated_edge()) + increment(); } -template -Triangulation_ds_edge_iterator_2 :: +template +Triangulation_ds_edge_iterator_2:: Triangulation_ds_edge_iterator_2(const Tds * tds, int ) : _tds(tds) { @@ -105,19 +103,19 @@ Triangulation_ds_edge_iterator_2(const Tds * tds, int ) } -template +template inline bool -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2:: operator==(const Edge_iterator& fi) const { return _tds == fi._tds && pos == fi.pos && edge.second == fi.edge.second; } -template +template inline void -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2:: increment() { CGAL_triangulation_precondition(_tds->dimension() >= 1); @@ -127,10 +125,10 @@ increment() return; } -template +template inline void -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2:: decrement() { CGAL_triangulation_precondition(_tds->dimension() >= 1); @@ -140,57 +138,48 @@ decrement() return; } -template +template inline bool -Triangulation_ds_edge_iterator_2 :: -associated_edge(Tag_true) +Triangulation_ds_edge_iterator_2:: +associated_edge() { if (_tds->dimension() == 1) {return true;} return Face_handle(pos) < pos->neighbor(edge.second); } -template +template inline -bool -Triangulation_ds_edge_iterator_2 :: -associated_edge(Tag_false) -{ - return true; -} - -template -inline -Triangulation_ds_edge_iterator_2& -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2& +Triangulation_ds_edge_iterator_2:: operator++() { //CGAL_triangulation_precondition(pos != Iterator_base() && // pos != _tds->faces().end()); do increment(); - while( pos != _tds->faces().end() && !associated_edge(Boolean_tag())); + while( pos != _tds->faces().end() && !associated_edge()); return *this; } -template +template inline -Triangulation_ds_edge_iterator_2& -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2& +Triangulation_ds_edge_iterator_2:: operator--() { // CGAL_triangulation_precondition(pos != Iterator_base() // && *this != Edge_iterator(_tds)); do decrement(); - while ( !associated_edge(Boolean_tag()) && *this != Edge_iterator(_tds) ); + while ( !associated_edge() && *this != Edge_iterator(_tds) ); return *this; } -template +template inline -Triangulation_ds_edge_iterator_2 -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2 +Triangulation_ds_edge_iterator_2:: operator++(int) { Edge_iterator tmp(*this); @@ -198,10 +187,10 @@ operator++(int) return tmp; } -template +template inline -Triangulation_ds_edge_iterator_2 -Triangulation_ds_edge_iterator_2 :: +Triangulation_ds_edge_iterator_2 +Triangulation_ds_edge_iterator_2:: operator--(int) { Edge_iterator tmp(*this); @@ -209,20 +198,20 @@ operator--(int) return tmp; } -template +template inline -typename Triangulation_ds_edge_iterator_2::Edge* -Triangulation_ds_edge_iterator_2 :: +typename Triangulation_ds_edge_iterator_2::Edge* +Triangulation_ds_edge_iterator_2:: operator->() const { edge.first = pos; return &edge; } -template +template inline -typename Triangulation_ds_edge_iterator_2::Edge& -Triangulation_ds_edge_iterator_2 :: +typename Triangulation_ds_edge_iterator_2::Edge& +Triangulation_ds_edge_iterator_2:: operator*() const { edge.first = pos; diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Triangulation_hierarchy_2.h index 74deac2f6ee..ff141b114e0 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Triangulation_hierarchy_2.h @@ -32,7 +32,8 @@ when it is built for Delaunay triangulations. However it can be used as well for other triangulations. -\tparam Tr may be any of the \cgal triangulation classes. +\tparam Tr may be any of the \cgal triangulation classes. The vertex of the triangulation must + be a model of the concept `TriangulationHierarchyVertexBase_2`. \cgalHeading{Types} diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index c8822421986..fce494586f8 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -130,7 +130,6 @@ public: typedef typename Tds::Face_iterator All_faces_iterator; typedef typename Tds::Edge_iterator All_edges_iterator; - typedef typename Tds::Halfedge_iterator All_halfedges_iterator; typedef typename Tds::Vertex_iterator All_vertices_iterator; class Perturbation_order @@ -491,8 +490,6 @@ public: All_edges_iterator all_edges_end() const; All_edges all_edges() const; - All_halfedges_iterator all_halfedges_begin() const; - All_halfedges_iterator all_halfedges_end() const; //for compatibility with previous versions Face_iterator faces_begin() const {return finite_faces_begin();} @@ -3348,22 +3345,6 @@ all_edges() const return _tds.edges(); } -template -typename Triangulation_2::All_halfedges_iterator -Triangulation_2:: -all_halfedges_begin() const -{ - return _tds.halfedges_begin(); -} - -template -typename Triangulation_2::All_halfedges_iterator -Triangulation_2:: -all_halfedges_end() const -{ - return _tds.halfedges_end(); -} - template inline typename Triangulation_2::Face_circulator diff --git a/Triangulation_2/include/CGAL/Triangulation_face_base_with_id_2.h b/Triangulation_2/include/CGAL/Triangulation_face_base_with_id_2.h new file mode 100644 index 00000000000..39d96c49113 --- /dev/null +++ b/Triangulation_2/include/CGAL/Triangulation_face_base_with_id_2.h @@ -0,0 +1,63 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_TRIANGULATION_FACE_BASE_WITH_ID_2_H +#define CGAL_TRIANGULATION_FACE_BASE_WITH_ID_2_H + +#include + +namespace CGAL { + +template < typename GT, + typename Fb = Triangulation_face_base_2 > +class Triangulation_face_base_with_id_2 + : public Fb +{ +public: + typedef typename Fb::Vertex_handle Vertex_handle; + typedef typename Fb::Face_handle Face_handle; + + template < typename TDS2 > + struct Rebind_TDS { + typedef typename Fb::template Rebind_TDS::Other Fb2; + typedef Triangulation_face_base_with_id_2 Other; + }; + + Triangulation_face_base_with_id_2() : Fb() { } + + Triangulation_face_base_with_id_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2) + : Fb(v0, v1, v2) + { } + + Triangulation_face_base_with_id_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, + Face_handle n0, Face_handle n1, Face_handle n2) + : Fb(v0, v1, v2, n0, n1, n2) + { } + + int& id() { return _id; } + int id() const { return _id; } + +private: + int _id; +}; + +} //namespace CGAL + +#endif // CGAL_TRIANGULATION_FACE_BASE_WITH_ID_2_H diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index aa536a5e11c..157f91bbf0c 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -56,11 +56,11 @@ const int Triangulation_hierarchy_2__minsize = 20; const int Triangulation_hierarchy_2__maxlevel = 5; // maximal number of points is 30^5 = 24 millions ! -template < class Tr_> +template class Triangulation_hierarchy_2 : public Tr_ { - public: +public: typedef Tr_ Tr_Base; typedef typename Tr_Base::Geom_traits Geom_traits; typedef typename Tr_Base::size_type size_type; @@ -273,8 +273,8 @@ private: -template -Triangulation_hierarchy_2:: +template +Triangulation_hierarchy_2:: Triangulation_hierarchy_2(const Geom_traits& traits) : Tr_Base(traits) { @@ -285,9 +285,9 @@ Triangulation_hierarchy_2(const Geom_traits& traits) // copy constructor duplicates vertices and faces -template -Triangulation_hierarchy_2:: -Triangulation_hierarchy_2(const Triangulation_hierarchy_2 &tr) +template +Triangulation_hierarchy_2:: +Triangulation_hierarchy_2(const Triangulation_hierarchy_2 &tr) : Tr_Base() { // create an empty triangulation to be able to delete it ! @@ -299,20 +299,20 @@ Triangulation_hierarchy_2(const Triangulation_hierarchy_2 &tr) //Assignement -template -Triangulation_hierarchy_2 & -Triangulation_hierarchy_2:: -operator=(const Triangulation_hierarchy_2 &tr) +template +Triangulation_hierarchy_2 & +Triangulation_hierarchy_2:: +operator=(const Triangulation_hierarchy_2 &tr) { copy_triangulation(tr); return *this; } -template +template void -Triangulation_hierarchy_2:: -copy_triangulation(const Triangulation_hierarchy_2 &tr) +Triangulation_hierarchy_2:: +copy_triangulation(const Triangulation_hierarchy_2 &tr) { { for(int i=0;i &tr) } } -/* template */ +/* template */ /* void */ -/* Triangulation_hierarchy_2:: */ +/* Triangulation_hierarchy_2:: */ /* add_hidden_vertices_into_map(Tag_false, */ /* std::map& V) { */ /* return; */ /* } */ -/* template */ +/* template */ /* void */ -/* Triangulation_hierarchy_2:: */ +/* Triangulation_hierarchy_2:: */ /* add_hidden_vertices_into_map(Tag_true, */ /* std::map& V) */ /* { */ @@ -371,10 +371,10 @@ copy_triangulation(const Triangulation_hierarchy_2 &tr) /* } */ -template +template void -Triangulation_hierarchy_2:: -swap(Triangulation_hierarchy_2 &tr) +Triangulation_hierarchy_2:: +swap(Triangulation_hierarchy_2 &tr) { Tr_Base* temp; Tr_Base::swap(tr); @@ -385,8 +385,8 @@ swap(Triangulation_hierarchy_2 &tr) } } -template -Triangulation_hierarchy_2:: +template +Triangulation_hierarchy_2:: ~Triangulation_hierarchy_2() { clear(); @@ -395,9 +395,9 @@ Triangulation_hierarchy_2:: } } -template +template void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: clear() { for(int i=0;i +template bool -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: is_valid(bool verbose, int level) const { bool result = true; @@ -440,9 +440,9 @@ is_valid(bool verbose, int level) const } -template -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: insert(const Point &p, Face_handle loc) { int vertex_level = random_level(); @@ -466,9 +466,9 @@ insert(const Point &p, Face_handle loc) return first; } -template -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: insert(const Point& p, Locate_type lt, Face_handle loc, @@ -499,18 +499,18 @@ insert(const Point& p, return first; } -template +template inline -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: push_back(const Point &p) { return insert(p); } -template +template void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: remove(Vertex_handle v ) { Vertex_handle u=v->up(); @@ -523,10 +523,10 @@ remove(Vertex_handle v ) } } -template +template template void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: remove_and_give_new_faces(Vertex_handle v, OutputItFaces fit) { Vertex_handle u=v->up(); @@ -541,33 +541,33 @@ remove_and_give_new_faces(Vertex_handle v, OutputItFaces fit) } -template +template inline void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: remove_degree_3(Vertex_handle v ) { remove(v); } -template +template inline void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: remove_first(Vertex_handle v ) { remove(v); } -template +template inline void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: remove_second(Vertex_handle v ) { remove(v); } -template -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: move_if_no_collision(Vertex_handle v, const Point &p) { Vertex_handle u=v->up(), norm = v; int l = 0 ; @@ -581,9 +581,9 @@ move_if_no_collision(Vertex_handle v, const Point &p) { return norm; } -template -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: move(Vertex_handle v, const Point &p) { CGAL_triangulation_precondition(!is_infinite(v)); Vertex_handle w = move_if_no_collision(v,p); @@ -594,10 +594,10 @@ move(Vertex_handle v, const Point &p) { return v; } -template +template template -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: move_if_no_collision_and_give_new_faces(Vertex_handle v, const Point &p, OutputItFaces oif) { @@ -619,11 +619,11 @@ move_if_no_collision_and_give_new_faces(Vertex_handle v, const Point &p, return norm; } -template < class Tr > +template template < class OutputItFaces > inline -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2::insert_and_give_new_faces(const Point &p, +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2::insert_and_give_new_faces(const Point &p, OutputItFaces oif, Face_handle loc) { @@ -648,12 +648,12 @@ Triangulation_hierarchy_2::insert_and_give_new_faces(const Point &p, } return first; } - -template < class Tr > + +template template < class OutputItFaces > inline -typename Triangulation_hierarchy_2::Vertex_handle -Triangulation_hierarchy_2:: +typename Triangulation_hierarchy_2::Vertex_handle +Triangulation_hierarchy_2:: insert_and_give_new_faces(const Point &p, Locate_type lt, Face_handle loc, @@ -685,9 +685,9 @@ insert_and_give_new_faces(const Point &p, return first; } -template -typename Triangulation_hierarchy_2::Face_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Face_handle +Triangulation_hierarchy_2:: locate(const Point& p, Locate_type& lt, int& li, Face_handle loc) const { Face_handle positions[Triangulation_hierarchy_2__maxlevel]; @@ -695,9 +695,9 @@ locate(const Point& p, Locate_type& lt, int& li, Face_handle loc) const return positions[0]; } -template -typename Triangulation_hierarchy_2::Face_handle -Triangulation_hierarchy_2:: +template +typename Triangulation_hierarchy_2::Face_handle +Triangulation_hierarchy_2:: locate(const Point& p, Face_handle loc ) const { Locate_type lt; @@ -705,9 +705,9 @@ locate(const Point& p, Face_handle loc ) const return locate(p, lt, li, loc); } -template +template void -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: locate_in_all(const Point& p, Locate_type& lt, int& li, @@ -769,9 +769,9 @@ locate_in_all(const Point& p, pos[0]=hierarchy[0]->locate(p,lt,li,loc == Face_handle() ? position : loc); // at level 0 } -template +template int -Triangulation_hierarchy_2:: +Triangulation_hierarchy_2:: random_level() { boost::geometric_distribution<> proba(1.0/Triangulation_hierarchy_2__ratio); diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_Delaunay_triangulation_2.h index 9c9180d3135..da2bd0c34f6 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_Delaunay_triangulation_2.h @@ -21,185 +21,17 @@ #ifndef CGAL_GRAPH_TRAITS_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H #define CGAL_GRAPH_TRAITS_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to -// treat a CGAL Constrained_triangulation_2 object as a boost graph "as is". No -// wrapper is needed for the Constrained_triangulation_2 object. +// treat a CGAL Delaunay_triangulation_2 object as a boost graph "as is". No +// wrapper is needed for the Constrained_Delaunay_triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS, typename Itag +#define CGAL_2D_TRIANGULATION CGAL::Constrained_Delaunay_triangulation_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES GT, TDS, Itag - -namespace boost { - - template - struct graph_traits< CGAL::Constrained_Delaunay_triangulation_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef CGAL::Constrained_Delaunay_triangulation_2 Constrained_Delaunay_triangulation; - - typedef typename CGAL::Constrained_Delaunay_triangulation_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Constrained_Delaunay_triangulation_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Constrained_Delaunay_triangulation_2::Edge> edge_descriptor; - typedef typename CGAL::Constrained_Delaunay_triangulation_2::All_edges_iterator edge_iterator; - - typedef CGAL::detail::T2_halfedge_descriptor halfedge_descriptor; - typedef typename Constrained_Delaunay_triangulation::All_halfedges_iterator halfedge_iterator; - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename Constrained_Delaunay_triangulation::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - - - template - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::edge_descriptor e, - const CGAL::Constrained_Delaunay_triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::edge_descriptor e, - const CGAL::Constrained_Delaunay_triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::vertex_descriptor u, - const CGAL::Constrained_Delaunay_triangulation_2& g) - { - typename CGAL::Constrained_Delaunay_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::vertex_descriptor u, - const CGAL::Constrained_Delaunay_triangulation_2& g) - { - typename CGAL::Constrained_Delaunay_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_Delaunay_triangulation_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - - - template - inline CT2_vertex_id_map - get(boost::vertex_index_t, const CGAL::Constrained_Delaunay_triangulation_2& ) { - CT2_vertex_id_map m; - return m; - } - - template - inline CT2_vertex_point_map - get(boost::vertex_point_t, const CGAL::Constrained_Delaunay_triangulation_2& ) { - CT2_vertex_point_map m; - return m; - } - template - inline CT2_edge_id_map - get(boost::edge_index_t, const CGAL::Constrained_Delaunay_triangulation_2& ) { - CT2_edge_id_map m; - return m; - } - - template - inline CT2_edge_weight_map - get(boost::edge_weight_t, const CGAL::Constrained_Delaunay_triangulation_2& g) { - CT2_edge_weight_map m(g); - return m; - } - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::CT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyehdron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::CT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_2.h index f235ef1e975..9939ac33457 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_2.h @@ -21,309 +21,17 @@ #ifndef CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_2_H #define CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to -// treat a CGAL Constrained_triangulation_2 object as a boost graph "as is". No +// treat a CGAL Delaunay_triangulation_2 object as a boost graph "as is". No // wrapper is needed for the Constrained_triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS, typename Itag +#define CGAL_2D_TRIANGULATION CGAL::Constrained_triangulation_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES GT, TDS, Itag - -namespace boost { - - template - struct graph_traits< CGAL::Constrained_triangulation_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef CGAL::Constrained_triangulation_2 Constrained_triangulation; - - typedef typename CGAL::Constrained_triangulation_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Constrained_triangulation_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Constrained_triangulation_2::Edge> edge_descriptor; - typedef typename CGAL::Constrained_triangulation_2::All_edges_iterator edge_iterator; - - typedef CGAL::detail::T2_halfedge_descriptor halfedge_descriptor; - - typedef typename Constrained_triangulation::All_halfedges_iterator halfedge_iterator; - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename Constrained_triangulation::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - - - template - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::edge_descriptor e, - const CGAL::Constrained_triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::edge_descriptor e, - const CGAL::Constrained_triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::vertex_descriptor u, - const CGAL::Constrained_triangulation_2& g) - { - typename CGAL::Constrained_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_triangulation_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::vertex_descriptor u, - const CGAL::Constrained_triangulation_2& g) - { - typename CGAL::Constrained_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_triangulation_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - - - // property maps - template - class CT2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Constrained_triangulation_2::Vertex_handle key_type; - - CT2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class CT2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename CGAL::Constrained_triangulation_2::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Constrained_triangulation_2::Vertex_handle key_type; - - friend reference get(CT2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(CT2_vertex_point_map, key_type vh, reference v) - { - vh->point()=v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - template - class CT2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Constrained_triangulation_2::Edge key_type; - - CT2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - template - class CT2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Constrained_triangulation_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename Gt::FT value_type; - typedef value_type reference; - typedef typename CGAL::Constrained_triangulation_2::Edge key_type; - - CT2_edge_weight_map(const CGAL::Constrained_triangulation_2& tr_) - : tr(tr_) - { } - - typename Gt::FT operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - - template - inline CT2_vertex_id_map - get(boost::vertex_index_t, const CGAL::Constrained_triangulation_2& ) { - CT2_vertex_id_map m; - return m; - } - - template - inline CT2_vertex_point_map - get(boost::vertex_point_t, const CGAL::Constrained_triangulation_2& ) { - CT2_vertex_point_map m; - return m; - } - - template - inline CT2_edge_id_map - get(boost::edge_index_t, const CGAL::Constrained_triangulation_2& ) { - CT2_edge_id_map m; - return m; - } - - template - inline CT2_edge_weight_map - get(boost::edge_weight_t, const CGAL::Constrained_triangulation_2& g) { - CT2_edge_weight_map m(g); - return m; - } - - template - struct CT2_property_map { }; - - template <> - struct CT2_property_map { - template - struct bind_ { - typedef CT2_vertex_id_map type; - typedef CT2_vertex_id_map const_type; - }; - }; - - template <> - struct CT2_property_map { - template - struct bind_ { - typedef CT2_vertex_point_map type; - typedef CT2_vertex_point_map const_type; - }; - }; - - - - template <> - struct CT2_property_map { - template - struct bind_ { - typedef CT2_edge_id_map type; - typedef CT2_edge_id_map const_type; - }; - }; - - - template <> - struct CT2_property_map { - template - struct bind_ { - typedef CT2_edge_weight_map type; - typedef CT2_edge_weight_map const_type; - }; - }; - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::CT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyehdron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::CT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h index 5d35c80e748..1bed68fbf9c 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h @@ -21,304 +21,17 @@ #ifndef CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_PLUS_2_H #define CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_PLUS_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to -// treat a CGAL Constrained_triangulation_plus_2 object as a boost graph "as is". No +// treat a CGAL Delaunay_triangulation_2 object as a boost graph "as is". No // wrapper is needed for the Constrained_triangulation_plus_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename Tr +#define CGAL_2D_TRIANGULATION CGAL::Constrained_triangulation_plus_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES Tr - -namespace boost { - - template - struct graph_traits< CGAL::Constrained_triangulation_plus_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits::edge_iterator edge_iterator; - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - typedef typename boost::graph_traits::halfedge_iterator halfedge_iterator; - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename boost::graph_traits::out_edge_iterator out_edge_iterator; - typedef typename boost::graph_traits::in_edge_iterator in_edge_iterator; - typedef typename boost::graph_traits::Incident_vertices_iterator Incident_vertices_iterator; - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename boost::graph_traits::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - - - template - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::edge_descriptor e, - const CGAL::Constrained_triangulation_plus_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::edge_descriptor e, - const CGAL::Constrained_triangulation_plus_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::vertex_descriptor u, - const CGAL::Constrained_triangulation_plus_2& g) - { - typename CGAL::Constrained_triangulation_plus_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::vertex_descriptor u, - const CGAL::Constrained_triangulation_plus_2& g) - { - typename CGAL::Constrained_triangulation_plus_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Constrained_triangulation_plus_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - - - // property maps - template - class CTP2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Constrained_triangulation_plus_2::Vertex_handle key_type; - - CTP2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class CTP2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename CGAL::Constrained_triangulation_plus_2::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Constrained_triangulation_plus_2::Vertex_handle key_type; - - friend reference get(CTP2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(CTP2_vertex_point_map, key_type vh, reference v) - { - vh->point()=v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - template - class CTP2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Constrained_triangulation_plus_2::Edge key_type; - - CTP2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - template - class CTP2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Constrained_triangulation_plus_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename Tr::Geom_traits::FT value_type; - typedef value_type reference; - typedef typename CGAL::Constrained_triangulation_plus_2::Edge key_type; - - CTP2_edge_weight_map(const CGAL::Constrained_triangulation_plus_2& tr_) - : tr(tr_) - { } - - typename Tr::Geom_traits::FT operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - - template - inline CTP2_vertex_id_map - get(boost::vertex_index_t, const CGAL::Constrained_triangulation_plus_2& ) { - CTP2_vertex_id_map m; - return m; - } - - template - inline CTP2_vertex_point_map - get(boost::vertex_point_t, const CGAL::Constrained_triangulation_plus_2& ) { - CTP2_vertex_point_map m; - return m; - } - - template - inline CTP2_edge_id_map - get(boost::edge_index_t, const CGAL::Constrained_triangulation_plus_2& ) { - CTP2_edge_id_map m; - return m; - } - - template - inline CTP2_edge_weight_map - get(boost::edge_weight_t, const CGAL::Constrained_triangulation_plus_2& g) { - CTP2_edge_weight_map m(g); - return m; - } - - template - struct CTP2_property_map { }; - - template <> - struct CTP2_property_map { - template - struct bind_ { - typedef CTP2_vertex_id_map type; - typedef CTP2_vertex_id_map const_type; - }; - }; - - template <> - struct CTP2_property_map { - template - struct bind_ { - typedef CTP2_vertex_point_map type; - typedef CTP2_vertex_point_map const_type; - }; - }; - - - - template <> - struct CTP2_property_map { - template - struct bind_ { - typedef CTP2_edge_id_map type; - typedef CTP2_edge_id_map const_type; - }; - }; - - - template <> - struct CTP2_property_map { - template - struct bind_ { - typedef CTP2_edge_weight_map type; - typedef CTP2_edge_weight_map const_type; - }; - }; - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::CTP2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyhedron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::CTP2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_CONSTRAINED_TRIANGULATION_PLUS_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Delaunay_triangulation_2.h index 4ce347b7e6f..2d8f16c6990 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Delaunay_triangulation_2.h @@ -14,163 +14,24 @@ // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ -// +// // // Author(s) : Andreas Fabri, Fernando Cacciola #ifndef CGAL_GRAPH_TRAITS_DELAUNAY_TRIANGULATION_2_H #define CGAL_GRAPH_TRAITS_DELAUNAY_TRIANGULATION_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to // treat a CGAL Delaunay_triangulation_2 object as a boost graph "as is". No // wrapper is needed for the Delaunay_triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Delaunay_triangulation_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES GT, TDS - -namespace boost { - - template - struct graph_traits< CGAL::Delaunay_triangulation_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef CGAL::Delaunay_triangulation_2 Delaunay_triangulation; - - typedef typename CGAL::Delaunay_triangulation_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Triangulation_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Delaunay_triangulation_2::Edge> edge_descriptor; - typedef typename CGAL::Delaunay_triangulation_2::All_edges_iterator edge_iterator; - - typedef CGAL::detail::T2_halfedge_descriptor halfedge_descriptor; - - typedef typename Delaunay_triangulation::All_halfedges_iterator halfedge_iterator; - - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename Delaunay_triangulation::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type halfedges_size_type; - typedef size_type edges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - - - template - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::edge_descriptor e, - const CGAL::Delaunay_triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::edge_descriptor e, - const CGAL::Delaunay_triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::vertex_descriptor u, - const CGAL::Delaunay_triangulation_2& g) - { - typename CGAL::Delaunay_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Delaunay_triangulation_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::vertex_descriptor u, - const CGAL::Delaunay_triangulation_2& g) - { - typename CGAL::Delaunay_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Delaunay_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Delaunay_triangulation_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::T2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyhedron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::T2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_DELAUNAY_TRIANGULATION_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Regular_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Regular_triangulation_2.h index 6c5fc6c41c6..821a2af153f 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Regular_triangulation_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Regular_triangulation_2.h @@ -14,307 +14,24 @@ // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ -// +// // // Author(s) : Andreas Fabri, Fernando Cacciola #ifndef CGAL_GRAPH_TRAITS_REGULAR_TRIANGULATION_2_H #define CGAL_GRAPH_TRAITS_REGULAR_TRIANGULATION_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to // treat a CGAL Regular_triangulation_2 object as a boost graph "as is". No // wrapper is needed for the Regular_triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Regular_triangulation_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES GT, TDS - -namespace boost { - - template - struct graph_traits< CGAL::Regular_triangulation_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef CGAL::Regular_triangulation_2 Regular_triangulation; - - typedef typename CGAL::Regular_triangulation_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Triangulation_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Regular_triangulation_2::Edge> edge_descriptor; - typedef typename CGAL::Regular_triangulation_2::All_edges_iterator edge_iterator; - - typedef CGAL::detail::T2_halfedge_descriptor halfedge_descriptor; - - typedef typename Regular_triangulation::All_halfedges_iterator halfedge_iterator; - - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename Regular_triangulation::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - template - inline Iterator_range >::vertex_iterator> - vertices(const Regular_triangulation_2& g) - { - typedef typename boost::graph_traits< Regular_triangulation_2 >::vertex_iterator - Iter; - return make_range( Iter(g.all_vertices_begin()), Iter(g.all_vertices_end()) ); - } - - - template - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Regular_triangulation_2 >::edge_descriptor e, - const CGAL::Regular_triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Regular_triangulation_2 >::edge_descriptor e, - const CGAL::Regular_triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::vertex_descriptor u, - const CGAL::Regular_triangulation_2& g) - { - typename CGAL::Regular_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Regular_triangulation_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::vertex_descriptor u, - const CGAL::Regular_triangulation_2& g) - { - typename CGAL::Regular_triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Regular_triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Regular_triangulation_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - - - - // property maps - template - class RT2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Regular_triangulation_2::Vertex_handle key_type; - - RT2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class RT2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename Tds::Vertex::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Regular_triangulation_2::Vertex_handle key_type; - - friend reference get(RT2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(RT2_vertex_point_map, key_type vh, reference v) - { - vh->point()=v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - - template - class RT2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Regular_triangulation_2::Edge key_type; - - RT2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - - template - class RT2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Regular_triangulation_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename Gt::FT value_type; - typedef value_type reference; - typedef typename CGAL::Regular_triangulation_2::Edge key_type; - - RT2_edge_weight_map(const CGAL::Regular_triangulation_2& tr_) - : tr(tr_) - { } - - value_type operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - template - inline RT2_edge_weight_map - get(boost::edge_weight_t, const CGAL::Regular_triangulation_2& g) { - RT2_edge_weight_map m(g); - return m; - } - - template - struct RT2_property_map { }; - - template <> - struct RT2_property_map { - template - struct bind_ { - typedef RT2_vertex_id_map type; - typedef RT2_vertex_id_map const_type; - }; - }; - - - - template <> - struct RT2_property_map { - template - struct bind_ { - typedef RT2_vertex_point_map type; - typedef RT2_vertex_point_map const_type; - }; - }; - - - template <> - struct RT2_property_map { - template - struct bind_ { - typedef RT2_edge_id_map type; - typedef RT2_edge_id_map const_type; - }; - }; - - - template <> - struct RT2_property_map { - template - struct bind_ { - typedef RT2_edge_weight_map type; - typedef RT2_edge_weight_map const_type; - }; - }; - - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::RT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyhedron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::RT2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_REGULAR_TRIANGULATION_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_2.h index 0a901850a6d..8889bbf55e0 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_2.h @@ -21,676 +21,17 @@ #ifndef CGAL_GRAPH_TRAITS_TRIANGULATION_2_H #define CGAL_GRAPH_TRAITS_TRIANGULATION_2_H -#include - -// include this to avoid a VC15 warning -#include -#include -#include -#include -#include -#include - -#include #include -#include -#include +#include // The functions and classes in this file allows the user to // treat a CGAL Triangulation_2 object as a boost graph "as is". No // wrapper is needed for the Triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Triangulation_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES GT, TDS -namespace CGAL { - - namespace detail { - - template - struct T2_halfedge_descriptor - { - typedef typename Tr::Face_handle face_descriptor; - face_descriptor first; - int second; - operator std::pair() { return std::make_pair(first,second); } - - T2_halfedge_descriptor() - : first(), second(0) - {} - - T2_halfedge_descriptor(const typename Tr::Edge& e) - : first(e.first), second(e.second) - {} - - T2_halfedge_descriptor(face_descriptor fd, int i) - : first(fd), second(i) - {} - - friend std::size_t hash_value(const T2_halfedge_descriptor& h) - { - return hash_value(h.first); - } - - bool operator==(const T2_halfedge_descriptor& other) const - { - return (first == other.first) && (second == other.second); - } - - bool operator!=(const T2_halfedge_descriptor& other) const - { - return (first != other.first) || (second != other.second); - } - - bool operator<(const T2_halfedge_descriptor& other) const - { - if(first < other.first) return true; - if(first > other.first) return false; - return second < other.second; - } - }; - - - } // namespace detail -} // namespace CGAL - -namespace boost { - - template - struct graph_traits< CGAL::Triangulation_2 > { - - struct T2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef CGAL::Triangulation_2 Triangulation; - - typedef typename CGAL::Triangulation_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Triangulation_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Triangulation_2::Edge> edge_descriptor; - typedef typename CGAL::Triangulation_2::All_edges_iterator edge_iterator; - - - typedef CGAL::detail::T2_halfedge_descriptor halfedge_descriptor; - - typedef typename Triangulation::All_halfedges_iterator halfedge_iterator; - - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef T2_graph_traversal_category traversal_category; - typedef typename Triangulation::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - - -namespace CGAL { - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - next(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first, g.ccw(e.second)); - } - - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - prev(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first, g.cw(e.second)); - } - - - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - opposite(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2& g) - { - - return g.mirror_edge(e); - } - - template - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< Triangulation_2 >::edge_descriptor e, - const Triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< Triangulation_2 >::edge_descriptor e, - const Triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor - source(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor - target(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_2 >::face_descriptor - face(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2&) - { - return e.first; - } - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_2 >::face_descriptor f, - const Triangulation_2&) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(f,0); - } - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_2 >::vertex_descriptor v, - const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits< Triangulation_2 >::face_descriptor face_descriptor; - face_descriptor fd = v->face(); - int i = fd->index(v); - return halfedge_descriptor(fd,g.ccw(i)); - } - - template - typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_2 >::edge_descriptor e, - const Triangulation_2&) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first,e.second); - } - - template - typename boost::graph_traits< Triangulation_2 >::edge_descriptor - edge(typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor e, - const Triangulation_2&) - { - typedef typename boost::graph_traits< Triangulation_2 >::edge_descriptor edge_descriptor; - return edge_descriptor(e.first,e.second); - } - - template - std::pair >::edge_descriptor, - bool> - edge(typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor v, - const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::edge_descriptor edge_descriptor; - - typename Triangulation_2::Edge_circulator c = g.incident_edges(u), done(c); - if (c != 0) { - do { - // find the index of the other vertex of *c - int indv = 3 - c->first->index(u) - c->second; - if(c->first->vertex(indv) == v) - return std::make_pair(edge_descriptor(c->first, c->second), true); - } while (++c != done); - } - - return std::make_pair(edge_descriptor(), false); - } - - template - std::pair >::halfedge_descriptor, - bool> - halfedge(typename boost::graph_traits >::vertex_descriptor u, - typename boost::graph_traits >::vertex_descriptor v, - const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits< Triangulation_2 >::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits< Triangulation_2 >::face_descriptor face_descriptor; - - std::pair eb = edge(u, v, g); - - if(!eb.second) - return std::make_pair(halfedge_descriptor(), false); - - const edge_descriptor& e = eb.first; - - if(e.first->vertex(g.ccw(e.first->index(u))) == v) - { - return std::make_pair(halfedge_descriptor(e.first, e.second), true); - } - else - { - face_descriptor nf = e.first->neighbor(e.second); - int idx = nf->index(e.first); - return std::make_pair(halfedge_descriptor(nf, idx), true); - } - } - - template - inline Iterator_range >::vertex_iterator> - vertices(const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::vertex_iterator - Iter; - return make_range( Iter(g.all_vertices_begin()), Iter(g.all_vertices_end()) ); - } - - - template - inline Iterator_range >::edge_iterator> - edges(const Triangulation_2& g) - { - return make_range(g.all_edges_begin(), g.all_edges_end()); - } - - template - inline Iterator_range >::halfedge_iterator > - halfedges(const Triangulation_2& g) - { - return make_range(g.all_halfedges_begin(), g.all_halfedges_end()); - } - - template - inline Iterator_range >::face_iterator > - faces(const Triangulation_2& g) - { - typedef typename boost::graph_traits< Triangulation_2 >::face_iterator - Iter; - return make_range( Iter(g.all_faces_begin()), Iter(g.all_faces_end()) ); - } - - template - typename boost::graph_traits< Triangulation_2 >::degree_size_type - out_degree( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename boost::graph_traits< Triangulation_2 >::degree_size_type deg = 0; - typename Triangulation_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - template - inline Iterator_range >::out_edge_iterator > - out_edges( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename Triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< Triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_2 > - ::out_edge_iterator Iter; - - return make_range( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline Iterator_range >::in_edge_iterator > - in_edges( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename Triangulation_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< Triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_2 > - ::in_edge_iterator Iter; - return make_range( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline Iterator_range >::adjacency_iterator> - adjacent_vertices( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename Triangulation_2::Vertex_circulator vc = out_edge_iterator(u,u.face()); - typename boost::graph_traits< Triangulation_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_2 > - ::adjacency_iterator Iter; - return make_range( Iter(vc), Iter(vc,out_deg) ); - } - - template - typename boost::graph_traits< Triangulation_2 >::vertices_size_type - num_vertices(const Triangulation_2& g) - { - return g.tds().number_of_vertices(); - } - - template - typename boost::graph_traits< Triangulation_2 >::edges_size_type - num_edges(const Triangulation_2& g) - { - - return g.tds().number_of_vertices() + g.tds().number_of_faces() - 2; - } - - template - typename boost::graph_traits< Triangulation_2 >::halfedges_size_type - num_halfedges(const Triangulation_2& g) - { - return num_edges(g) * 2; - } - - template - typename boost::graph_traits< Triangulation_2 >::faces_size_type - num_faces(const Triangulation_2& g) - { - return g.tds().number_of_faces(); - } - - template - typename boost::graph_traits< Triangulation_2 >::degree_size_type - in_degree( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename boost::graph_traits< Triangulation_2 >::degree_size_type deg = 0; - typename Triangulation_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - template - typename boost::graph_traits< Triangulation_2 >::degree_size_type - degree( - typename boost::graph_traits< Triangulation_2 >::vertex_descriptor u, - const Triangulation_2& g) - { - typename boost::graph_traits< Triangulation_2 >::degree_size_type deg = 0; - typename Triangulation_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - - // property maps - template - class T2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_2::Vertex_handle key_type; - - T2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class T2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename Tds::Vertex::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Triangulation_2::Vertex_handle key_type; - - friend reference get(T2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(T2_vertex_point_map, key_type vh, reference v) - { - vh->point() = v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - - template - class T2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_2::Edge key_type; - - T2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - template - class T2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Triangulation_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename Gt::FT value_type; - typedef value_type reference; - typedef typename CGAL::Triangulation_2::Edge key_type; - - T2_edge_weight_map(const CGAL::Triangulation_2& tr_) - : tr(tr_) - { } - - value_type operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - - template - inline T2_vertex_id_map - get(boost::vertex_index_t, const Triangulation_2&) { - T2_vertex_id_map m; - return m; - } - - template - inline T2_vertex_point_map - get(boost::vertex_point_t, const Triangulation_2&) { - T2_vertex_point_map m; - return m; - } - - template - inline T2_edge_id_map - get(boost::edge_index_t, const Triangulation_2&) { - T2_edge_id_map m; - return m; - } - - template - inline T2_edge_weight_map - get(boost::edge_weight_t, const Triangulation_2& g) { - T2_edge_weight_map m(g); - return m; - } - - template - struct T2_property_map { }; - - template <> - struct T2_property_map { - template - struct bind_ { - typedef T2_vertex_id_map type; - typedef T2_vertex_id_map const_type; - }; - }; - - template <> - struct T2_property_map { - template - struct bind_ { - typedef T2_vertex_point_map type; - typedef T2_vertex_point_map const_type; - }; - }; - - template <> - struct T2_property_map { - template - struct bind_ { - typedef T2_edge_id_map type; - typedef T2_edge_id_map const_type; - }; - }; - - template <> - struct T2_property_map { - template - struct bind_ { - typedef T2_edge_weight_map type; - typedef T2_edge_weight_map const_type; - }; - }; - -} // namespace CGAL - -namespace boost { - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::T2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyehdron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::T2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - -} // namespace boost - - -namespace CGAL { - - template - inline - typename boost::property_traits< - typename boost::property_map,PropertyTag>::const_type>::value_type - get(PropertyTag p, const Triangulation_2& g, const Key& key) { - return get(get(p, g), key); - } - - template - inline void - put(PropertyTag p, Triangulation_2& g, - const Key& key, const Value& value) - { - typedef typename boost::property_map, PropertyTag>::type Map; - Map pmap = get(p, g); - put(pmap, key, value); - } - -} // namespace CGAL - -namespace boost { - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - - -namespace std { - - -#if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4099) // For VC10 it is class hash -#endif - -#ifndef CGAL_CFG_NO_STD_HASH - - template < class Tr> - struct hash > { - std::size_t operator()(const CGAL::detail::T2_halfedge_descriptor& e) const - { - return hash_value(e); - } - }; - -#endif // CGAL_CFG_NO_STD_HASH - -#if defined(BOOST_MSVC) -# pragma warning(pop) -#endif - -} // namespace std - +#include #endif // CGAL_GRAPH_TRAITS_TRIANGULATION_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_data_structure_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_data_structure_2.h index 4a79b2f69ef..28de1f8cc58 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_data_structure_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_data_structure_2.h @@ -25,756 +25,324 @@ // include this to avoid a VC15 warning #include +#include +#include + +#include +#include +#include #include #include #include #include -#include -#include -#include -#include - // The functions and classes in this file allows the user to // treat a CGAL Triangulation_data_structure_2 object as a boost graph "as is". No // wrapper is needed for the Triangulation_data_structure_2 object. +namespace boost { -namespace CGAL { - - namespace detail { - -template < class T, class EdgeBase > -class Edge : public EdgeBase { - -public: - typedef typename T::Face_handle Face_handle ; - - Edge() - {} - - Edge(Face_handle fh, int i) - : EdgeBase(fh,i) - {} - - Edge(const EdgeBase& e) - : EdgeBase(e) - {} - - Edge(const Edge& e) - : EdgeBase(e) - {} - - Edge& - operator=(const Edge& e) - { - this->first = e.first; - this->second = e.second; - return *this; - } - - friend std::size_t hash_value(const Edge& e) - { - if (e.first==Face_handle()) return 0; - return hash_value(e.firstneighbor(e.second)? - e.first:e.first->neighbor(e.second)); - } - - bool operator==(const Edge& other) const - { - if((this->first == other.first)&&(this->second == other.second)) return true; - Face_handle fh = this->first->neighbor(this->second); - if(other.first != fh) return false; - int i = fh->index(this->first); - return (other.second == i); - } - - bool operator!=(Edge& other) const - { - return ! (*this == other); - } -}; - -template -class Out_edge_circulator : public Circ +template +struct graph_traits > { -private: - mutable E e; - -public: - - typedef E value_type; - typedef E* pointer; - typedef E& reference; - - Out_edge_circulator() - : Circ() - {} - - Out_edge_circulator(Circ c) - : Circ(c) - {} - - const E& operator*() const - { - E ed = static_cast(this)->operator*(); - e = E(ed.first->neighbor(ed.second), ed.first->neighbor(ed.second)->index(ed.first)); - return e; - } -}; - -template -class In_edge_circulator : public Circ -{ -private: - mutable E e; - -public: - - typedef E value_type; - typedef E* pointer; - typedef E& reference; - - In_edge_circulator() - : Circ() - {} - - In_edge_circulator(Circ c) - : Circ(c) - {} - - const E& operator*() const -{ - typename Circ::value_type ed = static_cast(this)->operator*(); - e = E(ed); - return e; - } -}; - - - template - struct TDS2_halfedge_descriptor - { - typedef typename Tr::Face_handle face_descriptor; - face_descriptor first; - int second; - operator std::pair() { return std::make_pair(first,second); } - - TDS2_halfedge_descriptor() - : first(), second(0) - {} - - TDS2_halfedge_descriptor(const typename Tr::Edge& e) - : first(e.first), second(e.second) - {} - - TDS2_halfedge_descriptor(face_descriptor fd, int i) - : first(fd), second(i) - {} - - friend std::size_t hash_value(const TDS2_halfedge_descriptor& h) - { - return hash_value(h.first); - } - - bool operator==(const TDS2_halfedge_descriptor& other) const - { - return (first == other.first) && (second == other.second); - } - - bool operator!=(const TDS2_halfedge_descriptor& other) const - { - return (first != other.first) || (second != other.second); - } - - bool operator<(const TDS2_halfedge_descriptor& other) const - { - if(first < other.first) return true; - if(first > other.first) return false; - return second < other.second; - } - }; - - - } // namespace detail -} // namespace CGAL - -namespace std{ - -// workaround a bug detected on at least g++ 4.4 where boost::next(Iterator) -// is picked as a candidate for next(h,g) -template -struct iterator_traits< CGAL::detail::TDS2_halfedge_descriptor > -{ - typedef void* iterator_category; - typedef void* difference_type; - typedef void* value_type; - typedef void* reference; -}; - -} // end of namespace std - -namespace boost { - - template - struct graph_traits< CGAL::Triangulation_data_structure_2 > { - - struct TDS2_graph_traversal_category : + struct TDS2_graph_traversal_category : public virtual bidirectional_graph_tag, public virtual adjacency_graph_tag, public virtual edge_list_graph_tag, public virtual vertex_list_graph_tag { }; - typedef CGAL::Triangulation_data_structure_2 Triangulation_data_structure; + typedef CGAL::Triangulation_data_structure_2 Triangulation_data_structure; - typedef typename CGAL::Triangulation_data_structure_2::Vertex_handle vertex_descriptor; - typedef typename CGAL::Triangulation_data_structure_2::Face_handle face_descriptor; - typedef CGAL::detail::Edge, typename CGAL::Triangulation_data_structure_2::Edge> edge_descriptor; - typedef typename CGAL::Triangulation_data_structure_2::Edge_iterator edge_iterator; + typedef typename Triangulation_data_structure::Vertex_handle vertex_descriptor; + typedef CGAL::internal::T2_halfedge_descriptor halfedge_descriptor; + typedef CGAL::internal::T2_edge_descriptor edge_descriptor; + typedef typename Triangulation_data_structure::Face_handle face_descriptor; + typedef CGAL::Prevent_deref vertex_iterator; + typedef CGAL::internal::T2_halfedge_iterator halfedge_iterator; + typedef CGAL::internal::T2_edge_iterator edge_iterator; + typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::detail::TDS2_halfedge_descriptor halfedge_descriptor; + typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; + typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; + typedef CGAL::Counting_iterator Incident_vertices_iterator; + typedef Incident_vertices_iterator adjacency_iterator; - typedef typename CGAL::Triangulation_data_structure_2::Halfedge_iterator halfedge_iterator; + typedef undirected_tag directed_category; + typedef disallow_parallel_edge_tag edge_parallel_category; + typedef TDS2_graph_traversal_category traversal_category; - typedef CGAL::Prevent_deref vertex_iterator; - typedef CGAL::Prevent_deref face_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > out_edge_iterator; - typedef CGAL::Counting_iterator, edge_descriptor > in_edge_iterator; - typedef CGAL::Counting_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; + typedef typename Triangulation_data_structure::size_type size_type; + typedef size_type vertices_size_type; + typedef size_type edges_size_type; + typedef size_type halfedges_size_type; + typedef size_type faces_size_type; + typedef size_type degree_size_type; - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef TDS2_graph_traversal_category traversal_category; - typedef typename Triangulation_data_structure::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; + // nulls + static vertex_descriptor null_vertex() { return vertex_descriptor(); } + static face_descriptor null_face() { return face_descriptor(); } + static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } +}; +template +struct graph_traits > + : public graph_traits< CGAL::Triangulation_data_structure_2 > +{ }; } // namespace boost - namespace CGAL { - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - next(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +next(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2& ) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + return halfedge_descriptor(e.first, Triangulation_data_structure_2::ccw(e.second)); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +prev(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2& ) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + return halfedge_descriptor(e.first, Triangulation_data_structure_2::cw(e.second)); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +opposite(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2& g) +{ + typedef typename Triangulation_data_structure_2::Edge Edge; + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + return halfedge_descriptor(g.mirror_edge(Edge(e.first, e.second))); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor +source(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, const Triangulation_data_structure_2& ) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first, Triangulation_data_structure_2::ccw(e.second)); - } +{ + return e.first->vertex(Triangulation_data_structure_2::ccw(e.second)); +} - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - prev(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, +template +typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor +target(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, const Triangulation_data_structure_2& ) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first, Triangulation_data_structure_2::cw(e.second)); - } +{ + return e.first->vertex(Triangulation_data_structure_2::cw(e.second)); +} - +template +typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor +source(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2& ) +{ + return e.first->vertex(Triangulation_data_structure_2::ccw(e.second)); +} - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - opposite(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, - const Triangulation_data_structure_2& g) - { - - return g.mirror_edge(e); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor - source(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, - const Triangulation_data_structure_2& ) - { - return e.first->vertex(Triangulation_data_structure_2::ccw(e.second)); - } +template +typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor +target(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2& ) +{ + return e.first->vertex(Triangulation_data_structure_2::cw(e.second)); +} - template - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor - target(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, - const Triangulation_data_structure_2& ) - { - return e.first->vertex(Triangulation_data_structure_2::cw(e.second)); - } +template +typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor +face(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2&) +{ + return e.first; +} - template - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor - source(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, - const Triangulation_data_structure_2& ) - { - return e.first->vertex(Triangulation_data_structure_2::ccw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor - target(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, - const Triangulation_data_structure_2& ) - { - return e.first->vertex(Triangulation_data_structure_2::cw(e.second)); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor - face(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor f, const Triangulation_data_structure_2&) - { - return e.first; +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + return halfedge_descriptor(f,0); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor v, + const Triangulation_data_structure_2& ) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor face_descriptor; + face_descriptor fd = v->face(); + int i = fd->index(v); + return halfedge_descriptor(fd,Triangulation_data_structure_2::ccw(i)); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor +halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, + const Triangulation_data_structure_2&) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; + return halfedge_descriptor(e.first, e.second); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor +edge(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, + const Triangulation_data_structure_2&) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor edge_descriptor; + return edge_descriptor(e.first,e.second); +} + +template +inline Iterator_range >::vertex_iterator> +vertices(const Triangulation_data_structure_2& g) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_iterator Iter; + return make_range(Iter(g.vertices_begin()), Iter(g.vertices_end())); +} + +template +inline Iterator_range >::edge_iterator> +edges(const Triangulation_data_structure_2& g) +{ + typedef typename boost::graph_traits >::edge_iterator Iter; + return make_range(Iter(g.edges_begin()), Iter(g.edges_end())); +} + +template +inline Iterator_range >::halfedge_iterator > +halfedges(const Triangulation_data_structure_2& g) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_iterator Iter; + return make_range(Iter(g.edges_begin()), Iter(g.edges_end())); +} + +template +inline Iterator_range >::face_iterator > +faces(const Triangulation_data_structure_2& g) +{ + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::face_iterator Iter; + return make_range(Iter(g.faces_begin()), Iter(g.faces_end())); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type +out_degree(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; + typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); + if ( c != 0) { + do { + ++deg; + } while (++c != done); } + return deg; +} - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor f, - const Triangulation_data_structure_2&) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(f,0); +template +inline Iterator_range >::out_edge_iterator > +out_edges(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename Triangulation_data_structure_2::Edge_circulator ec(u,u->face()); + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::out_edge_iterator Iter; + + return make_range(Iter(ec), Iter(ec,out_deg)); +} + +template +inline Iterator_range >::in_edge_iterator > +in_edges(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename Triangulation_data_structure_2::Edge_circulator ec(u,u->face()); + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::in_edge_iterator Iter; + return make_range(Iter(ec), Iter(ec,out_deg)); +} + +template +inline Iterator_range >::adjacency_iterator> +adjacent_vertices(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename Triangulation_data_structure_2::Vertex_circulator vc = out_edge_iterator(u,u.face()); + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); + typedef typename boost::graph_traits< Triangulation_data_structure_2 >::adjacency_iterator Iter; + return make_range( Iter(vc), Iter(vc,out_deg) ); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::vertices_size_type +num_vertices(const Triangulation_data_structure_2& g) +{ + return g.number_of_vertices(); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::edges_size_type +num_edges(const Triangulation_data_structure_2& g) +{ + return g.number_of_vertices() + g.number_of_faces() - 2; +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::halfedges_size_type +num_halfedges(const Triangulation_data_structure_2& g) +{ + return num_edges(g) * 2; +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::faces_size_type +num_faces(const Triangulation_data_structure_2& g) +{ + return g.number_of_faces(); +} + +template +typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type +in_degree(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; + typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); + if ( c != 0) { + do { + ++deg; + } while (++c != done); } + return deg; +} - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor v, - const Triangulation_data_structure_2& ) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::face_descriptor face_descriptor; - face_descriptor fd = v->face(); - int i = fd->index(v); - return halfedge_descriptor(fd,Triangulation_data_structure_2::ccw(i)); +template +typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type +degree(typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, + const Triangulation_data_structure_2& g) +{ + typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; + typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); + if ( c != 0) { + do { + ++deg; + } while (++c != done); } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor - halfedge(typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor e, - const Triangulation_data_structure_2&) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor halfedge_descriptor; - return halfedge_descriptor(e.first,e.second); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor - edge(typename boost::graph_traits< Triangulation_data_structure_2 >::halfedge_descriptor e, - const Triangulation_data_structure_2&) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::edge_descriptor edge_descriptor; - return edge_descriptor(e.first,e.second); - } - - - template - inline Iterator_range >::vertex_iterator> - vertices(const Triangulation_data_structure_2& g) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_iterator - Iter; - return make_range( Iter(g.vertices_begin()), Iter(g.vertices_end()) ); - } - - - template - inline Iterator_range >::edge_iterator> - edges(const Triangulation_data_structure_2& g) - { - return make_range(g.edges_begin(), g.edges_end()); - } - - template - inline Iterator_range >::halfedge_iterator > - halfedges(const Triangulation_data_structure_2& g) - { - return make_range(g.halfedges_begin(), g.halfedges_end()); - } - - template - inline Iterator_range >::face_iterator > - faces(const Triangulation_data_structure_2& g) - { - typedef typename boost::graph_traits< Triangulation_data_structure_2 >::face_iterator - Iter; - return make_range( Iter(g.faces_begin()), Iter(g.faces_end()) ); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type - out_degree( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; - typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - template - inline Iterator_range >::out_edge_iterator > - out_edges( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename Triangulation_data_structure_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_data_structure_2 > - ::out_edge_iterator Iter; - - return make_range( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline Iterator_range >::in_edge_iterator > - in_edges( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename Triangulation_data_structure_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_data_structure_2 > - ::in_edge_iterator Iter; - return make_range( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline Iterator_range >::adjacency_iterator> - adjacent_vertices( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename Triangulation_data_structure_2::Vertex_circulator vc = out_edge_iterator(u,u.face()); - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< Triangulation_data_structure_2 > - ::adjacency_iterator Iter; - return make_range( Iter(vc), Iter(vc,out_deg) ); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::vertices_size_type - num_vertices(const Triangulation_data_structure_2& g) - { - return g.number_of_vertices(); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::edges_size_type - num_edges(const Triangulation_data_structure_2& g) - { - - return g.number_of_vertices() + g.number_of_faces() - 2; - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::halfedges_size_type - num_halfedges(const Triangulation_data_structure_2& g) - { - return num_edges(g) * 2; - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::faces_size_type - num_faces(const Triangulation_data_structure_2& g) - { - return g.number_of_faces(); - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type - in_degree( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; - typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - template - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type - degree( - typename boost::graph_traits< Triangulation_data_structure_2 >::vertex_descriptor u, - const Triangulation_data_structure_2& g) - { - typename boost::graph_traits< Triangulation_data_structure_2 >::degree_size_type deg = 0; - typename Triangulation_data_structure_2::Edge_circulator c = g.incident_edges(u), done(c); - if ( c != 0) { - do { - ++deg; - } while (++c != done); - } - return deg; - } - - - // property maps - template - class TDS2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_data_structure_2::Vertex_handle key_type; - - TDS2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class TDS2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename VB::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Triangulation_data_structure_2::Vertex_handle key_type; - - friend reference get(TDS2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(TDS2_vertex_point_map, key_type vh, reference v) - { - vh->point()=v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - - template - class TDS2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_data_structure_2::Edge key_type; - - TDS2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - template - class TDS2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Triangulation_data_structure_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename VB::FT value_type; - typedef value_type reference; - typedef typename CGAL::Triangulation_data_structure_2::Edge key_type; - - TDS2_edge_weight_map(const CGAL::Triangulation_data_structure_2& tr_) - : tr(tr_) - { } - - value_type operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - - template - inline TDS2_vertex_id_map - get(boost::vertex_index_t, const Triangulation_data_structure_2&) { - TDS2_vertex_id_map m; - return m; - } - - template - inline TDS2_vertex_point_map - get(boost::vertex_point_t, const Triangulation_data_structure_2&) { - TDS2_vertex_point_map m; - return m; - } - - template - inline TDS2_edge_id_map - get(boost::edge_index_t, const Triangulation_data_structure_2&) { - TDS2_edge_id_map m; - return m; - } - - template - inline TDS2_edge_weight_map - get(boost::edge_weight_t, const Triangulation_data_structure_2& g) { - TDS2_edge_weight_map m(g); - return m; - } - - template - struct TDS2_property_map { }; - - template <> - struct TDS2_property_map { - template - struct bind_ { - typedef TDS2_vertex_id_map type; - typedef TDS2_vertex_id_map const_type; - }; - }; - - - - template <> - struct TDS2_property_map { - template - struct bind_ { - typedef TDS2_vertex_point_map type; - typedef TDS2_vertex_point_map const_type; - }; - }; - - - template <> - struct TDS2_property_map { - template - struct bind_ { - typedef TDS2_edge_id_map type; - typedef TDS2_edge_id_map const_type; - }; - }; - - - template <> - struct TDS2_property_map { - template - struct bind_ { - typedef TDS2_edge_weight_map type; - typedef TDS2_edge_weight_map const_type; - }; - }; + return deg; +} } // namespace CGAL -namespace boost { - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::TDS2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyehdron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::TDS2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - -} // namespace boost - - -namespace CGAL { - - template - inline - typename boost::property_traits< - typename boost::property_map,PropertyTag>::const_type>::value_type - get(PropertyTag p, const Triangulation_data_structure_2& g, const Key& key) { - return get(get(p, g), key); - } - - template - inline void - put(PropertyTag p, Triangulation_data_structure_2& g, - const Key& key, const Value& value) - { - typedef typename boost::property_map, PropertyTag>::type Map; - Map pmap = get(p, g); - put(pmap, key, value); - } - -} // namespace CGAL - -namespace boost { - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - - -namespace std { - - -#if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4099) // For VC10 it is class hash -#endif - -#ifndef CGAL_CFG_NO_STD_HASH - - template < class T, class EdgeBase> - struct hash > { - std::size_t operator()(const CGAL::detail::Edge& e) const - { - return hash_value(e); - } - }; - - template < class Tr> - struct hash > { - std::size_t operator()(const CGAL::detail::TDS2_halfedge_descriptor& e) const - { - return hash_value(e); - } - }; - -#endif // CGAL_CFG_NO_STD_HASH - -#if defined(BOOST_MSVC) -# pragma warning(pop) -#endif - -} // namespace std - - #endif // CGAL_GRAPH_TRAITS_TRIANGULATION_DATA_STRUCTURE_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_hierarchy_2.h index dd24d64a7ae..246a0ce5e58 100644 --- a/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/boost/graph/graph_traits_Triangulation_hierarchy_2.h @@ -21,306 +21,17 @@ #ifndef CGAL_GRAPH_TRAITS_TRIANGULATION_HIERARCHY_2_H #define CGAL_GRAPH_TRAITS_TRIANGULATION_HIERARCHY_2_H -// include this to avoid a VC15 warning -#include - -#include -#include -#include -#include -#include #include +#include // The functions and classes in this file allows the user to -// treat a CGAL Triangulation_hierarchy_2 object as a boost graph "as is". No -// wrapper is needed for the Triangulation_hierarchy_2 object. +// treat a CGAL Delaunay_triangulation_2 object as a boost graph "as is". No +// wrapper is needed for the Constrained_triangulation_2 object. +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename Tr +#define CGAL_2D_TRIANGULATION CGAL::Triangulation_hierarchy_2 +#define CGAL_2D_TRIANGULATION_TEMPLATES Tr - -namespace boost { - - template - struct graph_traits< CGAL::Triangulation_hierarchy_2 > { - - struct DT2_graph_traversal_category : - public virtual bidirectional_graph_tag, - public virtual adjacency_graph_tag, - public virtual edge_list_graph_tag, - public virtual vertex_list_graph_tag { }; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits::edge_iterator edge_iterator; - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - typedef typename boost::graph_traits::halfedge_iterator halfedge_iterator; - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; - typedef typename boost::graph_traits::face_iterator face_iterator; - typedef typename boost::graph_traits::out_edge_iterator out_edge_iterator; - typedef typename boost::graph_traits::in_edge_iterator in_edge_iterator; - typedef typename boost::graph_traits::Incident_vertices_iterator Incident_vertices_iterator; - typedef Incident_vertices_iterator adjacency_iterator; - - typedef undirected_tag directed_category; - typedef disallow_parallel_edge_tag edge_parallel_category; - typedef DT2_graph_traversal_category traversal_category; - typedef typename boost::graph_traits::size_type size_type; - typedef size_type vertices_size_type; - typedef size_type edges_size_type; - typedef size_type halfedges_size_type; - typedef size_type faces_size_type; - typedef size_type degree_size_type; - - // nulls - static vertex_descriptor null_vertex() { return vertex_descriptor(); } - static face_descriptor null_face() { return face_descriptor(); } - static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } - }; - - -} // namespace boost - -namespace CGAL { - - - - template - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::vertex_descriptor - source(typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::edge_descriptor e, - const CGAL::Triangulation_hierarchy_2& g) - { - return e.first->vertex(g.ccw(e.second)); - } - - template - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::vertex_descriptor - target(typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::edge_descriptor e, - const CGAL::Triangulation_hierarchy_2& g) - { - return e.first->vertex(g.cw(e.second)); - } - - - template - inline std::pair< - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::out_edge_iterator, - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::out_edge_iterator > - out_edges( - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::vertex_descriptor u, - const CGAL::Triangulation_hierarchy_2& g) - { - typename CGAL::Triangulation_hierarchy_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 > - ::out_edge_iterator Iter; - - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - template - inline std::pair< - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::in_edge_iterator, - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::in_edge_iterator > - in_edges( - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::vertex_descriptor u, - const CGAL::Triangulation_hierarchy_2& g) - { - typename CGAL::Triangulation_hierarchy_2::Edge_circulator ec(u,u->face()); - typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 >::degree_size_type out_deg = out_degree(u,g); - typedef typename boost::graph_traits< CGAL::Triangulation_hierarchy_2 > - ::in_edge_iterator Iter; - return std::make_pair( Iter(ec), Iter(ec,out_deg) ); - } - - - - // property maps - template - class TH2_vertex_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_hierarchy_2::Vertex_handle key_type; - - TH2_vertex_id_map() - {} - - long operator[](key_type vh) const { - return vh->id(); - } - }; - - template - class TH2_vertex_point_map - { - public: - typedef boost::lvalue_property_map_tag category; - typedef typename CGAL::Triangulation_hierarchy_2::Point value_type; - typedef value_type& reference; - typedef typename CGAL::Triangulation_hierarchy_2::Vertex_handle key_type; - - friend reference get(TH2_vertex_point_map, key_type vh) - { - return vh->point(); - } - friend void put(TH2_vertex_point_map, key_type vh, reference v) - { - vh->point()=v; - } - reference operator[](key_type vh) const { - return vh->point(); - } - }; - - template - class TH2_edge_id_map - : public boost::put_get_helper > - { - public: - typedef boost::readable_property_map_tag category; - typedef int value_type; - typedef int reference; - typedef typename CGAL::Triangulation_hierarchy_2::Edge key_type; - - TH2_edge_id_map() - {} - - long operator[](key_type e) const { - return (3 * e.first.id()) + e.second; - } - }; - - template - class TH2_edge_weight_map - : public boost::put_get_helper > - { - private: - const CGAL::Triangulation_hierarchy_2& tr; - public: - typedef boost::readable_property_map_tag category; - typedef typename Tr::Geom_traits::FT value_type; - typedef value_type reference; - typedef typename CGAL::Triangulation_hierarchy_2::Edge key_type; - - TH2_edge_weight_map(const CGAL::Triangulation_hierarchy_2& tr_) - : tr(tr_) - { } - - typename Tr::Geom_traits::FT operator[](key_type e) const { - return approximate_sqrt(tr.segment(e).squared_length()); - } - }; - - - template - inline TH2_vertex_id_map - get(boost::vertex_index_t, const CGAL::Triangulation_hierarchy_2& ) { - TH2_vertex_id_map m; - return m; - } - - template - inline TH2_vertex_point_map - get(boost::vertex_point_t, const CGAL::Triangulation_hierarchy_2& ) { - TH2_vertex_point_map m; - return m; - } - - template - inline TH2_edge_id_map - get(boost::edge_index_t, const CGAL::Triangulation_hierarchy_2& ) { - TH2_edge_id_map m; - return m; - } - - template - inline TH2_edge_weight_map - get(boost::edge_weight_t, const CGAL::Triangulation_hierarchy_2& g) { - TH2_edge_weight_map m(g); - return m; - } - - template - struct TH2_property_map { }; - - template <> - struct TH2_property_map { - template - struct bind_ { - typedef TH2_vertex_id_map type; - typedef TH2_vertex_id_map const_type; - }; - }; - - template <> - struct TH2_property_map { - template - struct bind_ { - typedef TH2_vertex_point_map type; - typedef TH2_vertex_point_map const_type; - }; - }; - - - - template <> - struct TH2_property_map { - template - struct bind_ { - typedef TH2_edge_id_map type; - typedef TH2_edge_id_map const_type; - }; - }; - - - template <> - struct TH2_property_map { - template - struct bind_ { - typedef TH2_edge_weight_map type; - typedef TH2_edge_weight_map const_type; - }; - }; - -} // namespace CGAL - -namespace boost { - - // g++ 'enumeral_type' in template unification not implemented workaround - template - struct property_map, Tag> { - typedef typename - CGAL::TH2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - // see struct property_map in Polyhedron for an explanation - template - struct property_map, Tag> { - typedef typename - CGAL::TH2_property_map::template bind_ map_gen; - typedef typename map_gen::type type; - typedef typename map_gen::const_type const_type; - }; - - - // What are those needed for ??? - template - struct edge_property_type > { - typedef void type; - }; - - template - struct vertex_property_type > { - typedef void type; - }; -} // namespace boost - +#include #endif // CGAL_GRAPH_TRAITS_TRIANGULATION_HIERARCHY_2_H diff --git a/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation.h b/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation.h new file mode 100644 index 00000000000..1684327ec32 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation.h @@ -0,0 +1,473 @@ +// Copyright (c) 2007, 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé, +// Andreas Fabri, +// Fernando Cacciola + +#ifndef CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS + #error CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS is not defined +#endif + +#ifndef CGAL_2D_TRIANGULATION + #error CGAL_2D_TRIANGULATION is not defined +#endif + +#ifndef CGAL_2D_TRIANGULATION_TEMPLATES + #error CGAL_2D_TRIANGULATION_TEMPLATES is not defined +#endif + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost { + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +struct graph_traits< CGAL_2D_TRIANGULATION > +{ + typedef CGAL_2D_TRIANGULATION Triangulation; + + struct T2_graph_traversal_category : + public virtual bidirectional_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag, + public virtual vertex_list_graph_tag + { }; + + typedef typename Triangulation::Vertex_handle vertex_descriptor; + typedef CGAL::internal::T2_halfedge_descriptor halfedge_descriptor; + typedef CGAL::internal::T2_edge_descriptor edge_descriptor; + typedef typename Triangulation::Face_handle face_descriptor; + + // We need to go from 'Finite_vertex_iterator' to 'Vertex_handle' (and even more + // in the case of RT2, since it has also a hidden filter) + typedef CGAL::internal::Dereference_to_handle_enforcer< + Triangulation, + typename Triangulation::Finite_vertices_iterator, + vertex_descriptor> vertex_iterator; + typedef CGAL::internal::Dereference_to_handle_enforcer< + Triangulation, + typename Triangulation::Finite_faces_iterator, + face_descriptor> face_iterator; + typedef CGAL::internal::T2_halfedge_iterator halfedge_iterator; + typedef CGAL::internal::T2_edge_iterator edge_iterator; + + typedef CGAL::internal::T2_vertex_circulator Vertex_circulator; + typedef CGAL::Counting_iterator adjacency_iterator; + typedef CGAL::internal::In_edge_circulator In_edge_circ; + typedef CGAL::Counting_iterator in_edge_iterator; + typedef CGAL::internal::Out_edge_circulator Out_edge_circ; + typedef CGAL::Counting_iterator out_edge_iterator; + + typedef undirected_tag directed_category; + typedef disallow_parallel_edge_tag edge_parallel_category; + typedef T2_graph_traversal_category traversal_category; + + typedef typename Triangulation::size_type size_type; + typedef size_type vertices_size_type; + typedef size_type halfedges_size_type; + typedef size_type edges_size_type; + typedef size_type faces_size_type; + typedef size_type degree_size_type; + + // nulls + static vertex_descriptor null_vertex() { return vertex_descriptor(); } + static halfedge_descriptor null_halfedge() { return halfedge_descriptor(); } + static face_descriptor null_face() { return face_descriptor(); } +}; + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +struct graph_traits + : public graph_traits< CGAL_2D_TRIANGULATION > +{ }; + +} // namespace boost + +namespace CGAL { + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor +source(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor e, + const CGAL_2D_TRIANGULATION& g) +{ + CGAL_precondition(!g.is_infinite(e)); + return e.first->vertex(g.ccw(e.second)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor +source(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + return h.first->vertex(g.ccw(h.second)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor +target(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor e, + const CGAL_2D_TRIANGULATION& g) +{ + CGAL_precondition(!g.is_infinite(e)); + return e.first->vertex(g.cw(e.second)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor +target(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + return h.first->vertex(g.cw(h.second)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +next(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor face_descriptor; + + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + + face_descriptor f = h.first; + int i = h.second; + if(!g.is_infinite(f)) + return halfedge_descriptor(f, g.ccw(i)); + + // Now, 'h' is border halfedge, move on to the adjacent infinite face + face_descriptor neigh_f = f->neighbor(g.ccw(i)); + return halfedge_descriptor(neigh_f, g.ccw(neigh_f->index(f))); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +prev(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor face_descriptor; + + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + + face_descriptor f = h.first; + int i = h.second; + if(!g.is_infinite(f)) + return halfedge_descriptor(f, g.cw(i)); + + // Now, 'h' is border halfedge, move on to the adjacent infinite face + face_descriptor neigh_f = f->neighbor(g.cw(i)); + return halfedge_descriptor(neigh_f, g.cw(neigh_f->index(f))); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +opposite(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + return halfedge_descriptor(g.mirror_edge(typename CGAL_2D_TRIANGULATION::Edge(h.first, h.second))); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor +face(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + if(g.is_infinite(h.first)) + return boost::graph_traits< CGAL_2D_TRIANGULATION >::null_face(); + else + return h.first; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +halfedge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor f, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + + CGAL_USE(g); + CGAL_precondition(!g.is_infinite(f)); + return halfedge_descriptor(f, 0); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +halfedge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor face_descriptor; + + CGAL_precondition(!g.is_infinite(v)); + + face_descriptor f = v->face(); + int i = f->index(v); + + while(g.is_infinite(f)) + { + f = f->neighbor(g.cw(i)); + i = f->index(v); + } + + return halfedge_descriptor(f, g.ccw(i)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor +halfedge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor e, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + + CGAL_USE(g); + CGAL_precondition(!g.is_infinite(e)); + return halfedge_descriptor(e.first, e.second); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor +edge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor h, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor edge_descriptor; + + CGAL_USE(g); + CGAL_precondition(!g.is_infinite(std::make_pair(h.first, h.second))); + return edge_descriptor(h.first, h.second); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +std::pair::edge_descriptor, + bool> +edge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor u, + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor edge_descriptor; + + CGAL_precondition(!g.is_infinite(u)); + CGAL_precondition(!g.is_infinite(v)); + + typename CGAL_2D_TRIANGULATION::Edge_circulator c = g.incident_edges(u), done(c); + if(c != 0) + { + do + { + if(!g.is_infinite(*c)) + { + // find the index of the other vertex of *c + int indv = 3 - c->first->index(u) - c->second; + if(c->first->vertex(indv) == v) + return std::make_pair(edge_descriptor(c->first, c->second), true); + } + } while (++c != done); + } + + return std::make_pair(edge_descriptor(), false); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +std::pair::halfedge_descriptor, + bool> +halfedge(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor u, + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_descriptor face_descriptor; + + CGAL_precondition(!g.is_infinite(u)); + CGAL_precondition(!g.is_infinite(v)); + + std::pair eb = edge(u, v, g); + + if(!eb.second) + return std::make_pair(halfedge_descriptor(), false); + + const edge_descriptor& e = eb.first; + + if(e.first->vertex(g.ccw(e.first->index(u))) == v) + { + return std::make_pair(halfedge_descriptor(e.first, e.second), true); + } + else + { + face_descriptor nf = e.first->neighbor(e.second); + int idx = nf->index(e.first); + return std::make_pair(halfedge_descriptor(nf, idx), true); + } +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::vertex_iterator> +vertices(const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_iterator Iter; + return make_range( Iter(g.finite_vertices_begin()), Iter(g.finite_vertices_end()) ); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::halfedge_iterator > +halfedges(const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedge_iterator Iter; + return make_range(Iter(g.finite_edges_begin()), Iter(g.finite_edges_end())); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::edge_iterator> +edges(const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edge_iterator Iter; + return make_range(Iter(g.finite_edges_begin()), Iter(g.finite_edges_end())); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::face_iterator > +faces(const CGAL_2D_TRIANGULATION& g) +{ + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::face_iterator Iter; + return make_range(Iter(g.finite_faces_begin()), Iter(g.finite_faces_end())); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type +degree(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type deg = 0; + typename CGAL_2D_TRIANGULATION::Edge_circulator c = g.incident_edges(v), done(c); + if(c != 0) + { + do { + if(!g.is_infinite(*c)) + ++deg; + } while (++c != done); + } + + return deg; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type +in_degree(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + return degree(v, g); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type +out_degree(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + return degree(v, g); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::in_edge_iterator > +in_edges(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef CGAL::internal::In_edge_circulator< CGAL_2D_TRIANGULATION > Circ; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::in_edge_iterator Iter; + + typename CGAL_2D_TRIANGULATION::Edge_circulator ec(v, v->face()); + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type deg = degree(v, g); + + return make_range(Iter(Circ(ec, g)), Iter(Circ(ec, g), deg)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::out_edge_iterator > +out_edges(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef CGAL::internal::Out_edge_circulator< CGAL_2D_TRIANGULATION > Circ; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::out_edge_iterator Iter; + + typename CGAL_2D_TRIANGULATION::Edge_circulator ec(v, v->face()); + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type deg = degree(v, g); + + return make_range(Iter(Circ(ec, g)), Iter(Circ(ec, g), deg)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline Iterator_range::adjacency_iterator> +adjacent_vertices(typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertex_descriptor v, + const CGAL_2D_TRIANGULATION& g) +{ + typedef CGAL::internal::T2_vertex_circulator< CGAL_2D_TRIANGULATION > Circ; + typedef typename boost::graph_traits< CGAL_2D_TRIANGULATION >::adjacency_iterator Iter; + + typename CGAL_2D_TRIANGULATION::Edge_circulator ec(v, v->face()); + typename boost::graph_traits< CGAL_2D_TRIANGULATION >::degree_size_type deg = degree(v, g); + + return make_range(Iter(Circ(ec, g)), Iter(Circ(ec, g), deg)); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::vertices_size_type +num_vertices(const CGAL_2D_TRIANGULATION& g) +{ + return g.number_of_vertices(); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::faces_size_type +num_faces(const CGAL_2D_TRIANGULATION& g) +{ + return g.number_of_faces(); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::edges_size_type +num_edges(const CGAL_2D_TRIANGULATION& g) +{ + // Euler characteristic for a triangulated topological disk is V-E+F=1 + return num_vertices(g) + num_faces(g) - 1; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +typename boost::graph_traits< CGAL_2D_TRIANGULATION >::halfedges_size_type +num_halfedges(const CGAL_2D_TRIANGULATION& g) +{ + return num_edges(g) * 2; +} + +} // namespace CGAL + +#undef CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS +#undef CGAL_2D_TRIANGULATION +#undef CGAL_2D_TRIANGULATION_TEMPLATES diff --git a/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h b/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h new file mode 100644 index 00000000000..c05ca0598f1 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/internal/graph_traits_2D_triangulation_helper.h @@ -0,0 +1,470 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#include +#include +#include + +#include +#include +#include + +#include + +#ifndef CGAL_GRAPH_TRAITS_2D_TRIANGULATION_HELPERS +#define CGAL_GRAPH_TRAITS_2D_TRIANGULATION_HELPERS + +namespace CGAL { +namespace internal { + +// A triangulation edge is a face handle + an int, and is thus actually a halfedge... +template +struct T2_halfedge_descriptor + : public Tr::Edge +{ + typedef typename Tr::Edge Base; + typedef typename Tr::Face_handle Face_handle; + + T2_halfedge_descriptor() {} + T2_halfedge_descriptor(Face_handle fh, int i) : Base(fh, i) { } + explicit T2_halfedge_descriptor(const Base& e) : Base(e) { } + T2_halfedge_descriptor(const T2_halfedge_descriptor& h) : Base(h) { } + + const Base& base() const { return static_cast(*this); } + + T2_halfedge_descriptor& operator=(const T2_halfedge_descriptor& h) + { + this->first = h.first; + this->second = h.second; + return *this; + } + + friend std::size_t hash_value(const T2_halfedge_descriptor& e) { + return hash_value(e.first); + } +}; + +// An edge is just a halfedge, but we give it a complete structure to distinguish it from Tr::Edge +template +struct T2_edge_descriptor +{ + typedef typename Tr::Face_handle Face_handle; + + T2_edge_descriptor() : first(), second(0) { } + explicit T2_edge_descriptor(const typename Tr::Edge& e) : first(e.first), second(e.second) { } + T2_edge_descriptor(Face_handle fd, int i) : first(fd), second(i) { } + + // so that we can still do stuff like tr.is_finite(edge_descriptor) without any hassle + operator std::pair() const { return std::make_pair(first, second); } + + friend std::size_t hash_value(const T2_edge_descriptor& h) + { + if(h.first == Face_handle()) + return 0; + + return hash_value(h.first < h.first->neighbor(h.second) ? h.first + : h.first->neighbor(h.second)); + } + + bool operator==(const T2_edge_descriptor& other) const + { + if((first == other.first) && (second == other.second)) + return true; + + Face_handle fh = first->neighbor(second); + if(other.first != fh) + return false; + + int i = fh->index(first); + return (other.second == i); + } + bool operator!=(T2_edge_descriptor& other) const { return ! (*this == other); } + + void get_canonical_edge_representation(Face_handle& fh, int& i) const + { + Face_handle neigh_fh = fh->neighbor(i); + Face_handle canonical_fh = (fh < neigh_fh) ? fh : neigh_fh; + + int canonical_i = (fh < neigh_fh) ? i : neigh_fh->index(fh); + + fh = canonical_fh; + i = canonical_i; + } + + bool operator<(const T2_edge_descriptor& other) const + { + if(*this == other) + return false; + + Face_handle tfh = first; + int ti = second; + get_canonical_edge_representation(tfh, ti); + + Face_handle ofh = other.first; + int oi = other.second; + get_canonical_edge_representation(ofh, oi); + + if(tfh < ofh) return true; + if(tfh > ofh) return false; + return ti < oi; + } + + Face_handle first; + int second; +}; + +// A halfedge iterator is just an edge iterator that duplicates everything twice, +// to see the edge from either side. +// Could probably be factorized with T2_edge_iterator, but it's clearer this way. +template +struct T2_halfedge_iterator +{ +private: + typedef T2_halfedge_iterator Self; + typedef EdgeIterator Edge_iterator; + typedef T2_halfedge_descriptor Descriptor; + typedef typename Tr::Face_handle Face_handle; + +public: + typedef Descriptor value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + T2_halfedge_iterator() { } + T2_halfedge_iterator(const Edge_iterator& feit) : it(feit), on_adjacent_face(false) { } + + Self& operator++() + { + // If we are on the first face, move to the opposite face. If we are already on the opposite face, + // then it's time to move on the next edge + if(on_adjacent_face) { + ++it; + on_adjacent_face = false; + } else { + on_adjacent_face = true; + } + + return *this; + } + + Self& operator--() + { + // Note that while decreasing, we start from the opposite face + if(on_adjacent_face) { + on_adjacent_face = false; + } else { + --it; + on_adjacent_face = true; + } + + return *this; + } + + Self operator++(int) { Self tmp = *this; operator++(); return tmp; } + Self operator--(int) { Self tmp = *this; operator--(); return tmp; } + + bool operator==(const Self& other) const { return it == other.it; } + bool operator!=(const Self& other) const { return !(*this == other); } + + reference operator*() const + { + if(on_adjacent_face) + { + Face_handle neigh_f = it->first->neighbor(it->second); + hd = Descriptor(neigh_f, neigh_f->index(it->first)); + return hd; + } else { + hd = Descriptor(it->first, it->second); + return hd; + } + } + +private: + Edge_iterator it; + bool on_adjacent_face; + mutable Descriptor hd; +}; + +template +struct T2_edge_iterator +{ +private: + typedef T2_edge_iterator Self; + typedef EdgeIterator Edge_iterator; + typedef T2_edge_descriptor Descriptor; + +public: + typedef Descriptor value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + T2_edge_iterator() { } + T2_edge_iterator(const Edge_iterator& feit) : it(feit) { } + + bool operator==(const Self& other) const { return it == other.it; } + bool operator!=(const Self& other) const { return !(*this == other); } + Self& operator++() { ++it; return *this; } + Self& operator--() { --it; return *this; } + Self operator++(int) { Self tmp = *this; operator++(); return tmp; } + Self operator--(int) { Self tmp = *this; operator--(); return tmp; } + + reference operator*() const + { + ed = Descriptor(*it); + return ed; + } + +private: + Edge_iterator it; + mutable Descriptor ed; +}; + +// Must distinguish TDS and triangulations circulators (later are filtered) +template +class TDS2_Out_edge_circulator + : public Circ +{ +private: + mutable E e; + +public: + typedef E value_type; + typedef E* pointer; + typedef E& reference; + + TDS2_Out_edge_circulator() : Circ() {} + TDS2_Out_edge_circulator(Circ c) : Circ(c) {} + + const E& operator*() const + { + E ed = static_cast(this)->operator*(); + e = E(ed.first->neighbor(ed.second), ed.first->neighbor(ed.second)->index(ed.first)); + return e; + } +}; + +template +class TDS2_In_edge_circulator + : public Circ +{ +private: + mutable E e; + +public: + typedef E value_type; + typedef E* pointer; + typedef E& reference; + + TDS2_In_edge_circulator() : Circ() {} + TDS2_In_edge_circulator(Circ c) : Circ(c) {} + + const E& operator*() const + { + typename Circ::value_type ed = static_cast(this)->operator*(); + e = E(ed); + return e; + } +}; + +template +struct T2_edge_circulator + : public Tr::Edge_circulator +{ +private: + typedef T2_edge_circulator Self; + typedef typename Tr::Edge Edge; + typedef typename Tr::Edge_circulator Base; + +public: + typedef T2_edge_descriptor value_type; + typedef value_type* pointer; + typedef value_type& reference; + + T2_edge_circulator() : Base() { } + T2_edge_circulator(const Base& c, const Tr& tr) : Base(c), tr(&tr), e() { } + + // Note that the inf check is on the edge in the circulator, not on 'e', which isn't built yet + Self& operator++() { + do { this->Base::operator++(); } while(tr->is_infinite(this->Base::operator*())); + return *this; + } + Self& operator--() { + do { this->Base::operator--(); } while(tr->is_infinite(this->Base::operator*())); + return *this; + } + Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } + Self operator--(int) { Self tmp(*this); --(*this); return tmp; } + +protected: + const Tr* tr; + mutable value_type e; +}; + +template +struct In_edge_circulator + : public T2_edge_circulator +{ +private: + typedef T2_edge_circulator Base; + typedef typename Tr::Edge Edge; + typedef typename Tr::Edge_circulator Edge_circulator; + +public: + typedef T2_edge_descriptor value_type; + typedef value_type* pointer; + typedef value_type& reference; + + In_edge_circulator() : Base() { } + In_edge_circulator(const Edge_circulator& c, const Tr& tr) : Base(c, tr) { } + + const value_type& operator*() const + { + this->e = value_type(this->Base::operator*()); + return this->e; + } +}; + +template +struct Out_edge_circulator + : public T2_edge_circulator +{ +private: + typedef T2_edge_circulator Base; + typedef typename Tr::Edge Edge; + typedef typename Tr::Edge_circulator Edge_circulator; + +public: + typedef T2_edge_descriptor value_type; + typedef value_type* pointer; + typedef value_type& reference; + + Out_edge_circulator() : Base() { } + Out_edge_circulator(const Edge_circulator& c, const Tr& tr) : Base(c, tr) { } + + const value_type& operator*() const + { + Edge ed(this->Base::operator*()); + this->e = value_type(ed.first->neighbor(ed.second), + ed.first->neighbor(ed.second)->index(ed.first)); + return this->e; + } +}; + +template +struct T2_vertex_circulator + : public In_edge_circulator +{ +private: + typedef In_edge_circulator Base; + typedef T2_edge_descriptor edge_descriptor; + typedef typename Tr::Edge_circulator Edge_circulator; + typedef typename Tr::Vertex_handle Vertex_handle; + +public: + typedef Vertex_handle value_type; + typedef value_type& reference; + + T2_vertex_circulator() : Base() { } + T2_vertex_circulator(const Edge_circulator& c, const Tr& tr) : Base(c, tr) { } + + const value_type& operator*() const + { + const edge_descriptor& edge = this->Base::operator*(); + v = edge.first->vertex(this->tr->ccw(edge.second)); + return v; + } + +private: + // Because we wrap the iterator with a Counting_iterator, which returns a ref in its operator*() + mutable Vertex_handle v; +}; + +template +struct Dereference_to_handle_enforcer + : public boost::iterator_adaptor< + Dereference_to_handle_enforcer, + Iterator /*base*/, + Handle /*value*/, + boost::use_default, + Handle /*reference*/ + > +{ +public: + typedef Handle value_type; + +private: + typedef Dereference_to_handle_enforcer Self; + typedef Iterator I; + typedef boost::iterator_adaptor Base; + +public: + Dereference_to_handle_enforcer() { } + explicit Dereference_to_handle_enforcer(const I& i) : Base(i) { } + +private: + friend class boost::iterator_core_access; + value_type dereference() const { return value_type(this->base()); } +}; + +} // namespace internal +} // namespace CGAL + +namespace std { + +// workaround a bug detected on at least g++ 4.4 where boost::next(Iterator) +// is picked as a candidate for next(h,g) +template +struct iterator_traits< CGAL::internal::T2_halfedge_descriptor > +{ + typedef void* iterator_category; + typedef void* difference_type; + typedef void* value_type; + typedef void* reference; +}; + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4099) // For VC10 it is class hash +#endif + +#ifndef CGAL_CFG_NO_STD_HASH + +template < class Tr> +struct hash > +{ + std::size_t operator()(const CGAL::internal::T2_halfedge_descriptor& e) const { + return hash_value(e); + } +}; + +#endif // CGAL_CFG_NO_STD_HASH + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +} // namespace std + +#endif // CGAL_GRAPH_TRAITS_2D_TRIANGULATION_HELPERS diff --git a/Triangulation_2/include/CGAL/boost/graph/internal/properties_2D_triangulation.h b/Triangulation_2/include/CGAL/boost/graph/internal/properties_2D_triangulation.h new file mode 100644 index 00000000000..1c912a22243 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/internal/properties_2D_triangulation.h @@ -0,0 +1,383 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#include +#include +#include + +#ifndef CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS + #error CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS is not defined +#endif + +#ifndef CGAL_2D_TRIANGULATION + #error CGAL_2D_TRIANGULATION is not defined +#endif + +// note only the properties below are protected by the macro, +// the rest of the file is the shared implementation of properties for all 2D triangulations +#ifndef CGAL_BOOST_GRAPH_PROPERTIES_2D_TRIANGULATION_H +#define CGAL_BOOST_GRAPH_PROPERTIES_2D_TRIANGULATION_H + +namespace CGAL { +namespace internal { + +template +struct T2_halfedge_descriptor; + +template +struct T2_edge_descriptor; + +template +class T2_vertex_point_map +{ +public: + typedef boost::lvalue_property_map_tag category; + typedef typename Tr::Point value_type; + typedef value_type& reference; + typedef typename Tr::Vertex_handle key_type; + + T2_vertex_point_map() { } + + friend reference get(T2_vertex_point_map, key_type vh) + { + return vh->point(); + } + friend void put(T2_vertex_point_map, key_type vh, const value_type& v) + { + vh->point() = v; + } + + reference operator[](key_type vh) const { return vh->point(); } +}; + +template +class T2_edge_weight_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef typename Tr::Geom_traits::FT value_type; + typedef value_type reference; + typedef CGAL::internal::T2_edge_descriptor key_type; + + T2_edge_weight_map(const Tr& tr_) : tr(tr_) { } + + value_type operator[](key_type e) const { return approximate_sqrt(tr.segment(e).squared_length()); } + +private: + const Tr& tr; +}; + +template +class T2_vertex_id_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef typename Tr::Vertex_handle key_type; + + T2_vertex_id_map(const Tr& tr) : tr(tr) { } + + value_type operator[](key_type v) const { + CGAL_precondition(!tr.is_infinite(v)); + return v->id(); + } + + const Tr& tr; +}; + +template +class T2_halfedge_id_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef CGAL::internal::T2_halfedge_descriptor key_type; + + typedef typename Tr::Face_handle Face_handle; + + T2_halfedge_id_map(const Tr& tr) : tr(tr) { } + + // Halfedge id is twice the edge id, and +0/+1 depending whether + // h.first is such that h.first < opposite(h).first --> different ids + value_type operator[](key_type h) const + { + const Face_handle f1 = h.first; + const Face_handle f2 = f1->neighbor(h.second); + CGAL_assertion(!tr.is_infinite(f1) || !tr.is_infinite(f2)); + + if(tr.is_infinite(f1)) + return 2*(3 * f2->id() + f2->index(f1)); + else if(tr.is_infinite(f2)) + return 2*(3 * f1->id() + h.second) + 1; + else if(f1->id() < f2->id()) + return 2*(3 * f1->id() + h.second); + else + return 2*(3 * f2->id() + f2->index(f1)) + 1; + } + +private: + const Tr& tr; +}; + +template +class T2_edge_id_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef CGAL::internal::T2_edge_descriptor key_type; + typedef typename Tr::Face_handle Face_handle; + + T2_edge_id_map(const Tr& tr) : tr(tr) { } + + value_type operator[](key_type e) const + { + const Face_handle f1 = e.first; + const Face_handle f2 = f1->neighbor(e.second); + CGAL_assertion(!tr.is_infinite(f1) || !tr.is_infinite(f2)); + + if(tr.is_infinite(f1)) + return 3 * f2->id() + f2->index(f1); + else if(tr.is_infinite(f2)) + return 3 * f1->id() + e.second; + else if(f1->id() < f2->id()) + return 3 * f1->id() + e.second; + else + return 3 * f2->id() + f2->index(f1); + } + +private: + const Tr& tr; +}; + +template +class T2_face_id_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef typename Tr::Face_handle key_type; + + T2_face_id_map(const Tr& tr) : tr(tr) { } + + value_type operator[](key_type f) const { + CGAL_precondition(!tr.is_infinite(f)); + return f->id(); + } + +private: + const Tr& tr; +}; + +template +struct T2_property_map { }; + +template +struct T2_property_map +{ + typedef internal::T2_vertex_point_map type; + typedef internal::T2_vertex_point_map const_type; +}; + +template +struct T2_property_map +{ + typedef internal::T2_edge_weight_map type; + typedef internal::T2_edge_weight_map const_type; +}; + +template +struct T2_property_map +{ + typedef internal::T2_vertex_id_map type; + typedef internal::T2_vertex_id_map const_type; +}; + +template +struct T2_property_map +{ + typedef internal::T2_halfedge_id_map type; + typedef internal::T2_halfedge_id_map const_type; +}; + +template +struct T2_property_map +{ + typedef internal::T2_edge_id_map type; + typedef internal::T2_edge_id_map const_type; +}; + +template +struct T2_property_map +{ + typedef internal::T2_face_id_map type; + typedef internal::T2_face_id_map const_type; +}; + +} // end namespace internal +} // CGAL + +#endif // CGAL_BOOST_GRAPH_PROPERTIES_2D_TRIANGULATION_H + +// overloads and specializations in the boost namespace +namespace boost { + +// g++ 'enumeral_type' in template unification not implemented workaround +template +struct property_map +{ + typedef typename CGAL::internal::T2_property_map map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; +}; + +// see struct property_map in Polyehdron for an explanation +template +struct property_map +{ + typedef typename CGAL::internal::T2_property_map map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; +}; + +} // end namespace boost + +namespace CGAL { + +template +struct graph_has_property + : CGAL::Tag_true{}; +template +struct graph_has_property + : CGAL::Tag_true{}; + +template +struct graph_has_property + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL_2D_TRIANGULATION::Vertex + >::value + > +{}; +template +struct graph_has_property + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL_2D_TRIANGULATION::Face + >::value + > +{}; +template +struct graph_has_property + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL_2D_TRIANGULATION::Face + >::value + > +{}; +template +struct graph_has_property + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL_2D_TRIANGULATION::Face + >::value + > +{}; + +// property maps +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_vertex_point_map< CGAL_2D_TRIANGULATION > +get(boost::vertex_point_t, const CGAL_2D_TRIANGULATION&) +{ + internal::T2_vertex_point_map< CGAL_2D_TRIANGULATION > m; + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_edge_weight_map< CGAL_2D_TRIANGULATION > +get(boost::edge_weight_t, const CGAL_2D_TRIANGULATION& g) +{ + internal::T2_edge_weight_map< CGAL_2D_TRIANGULATION > m(g); + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_vertex_id_map< CGAL_2D_TRIANGULATION > +get(boost::vertex_index_t, const CGAL_2D_TRIANGULATION& g) +{ + internal::T2_vertex_id_map< CGAL_2D_TRIANGULATION > m(g); + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_halfedge_id_map< CGAL_2D_TRIANGULATION > +get(boost::halfedge_index_t, const CGAL_2D_TRIANGULATION& g) +{ + internal::T2_halfedge_id_map< CGAL_2D_TRIANGULATION > m(g); + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_edge_id_map< CGAL_2D_TRIANGULATION > +get(boost::edge_index_t, const CGAL_2D_TRIANGULATION& g) +{ + internal::T2_edge_id_map< CGAL_2D_TRIANGULATION > m(g); + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS > +inline internal::T2_face_id_map< CGAL_2D_TRIANGULATION > +get(boost::face_index_t, const CGAL_2D_TRIANGULATION& g) +{ + internal::T2_face_id_map< CGAL_2D_TRIANGULATION > m(g); + return m; +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS, class PropertyTag, class Key> +inline +typename boost::property_traits< + typename boost::property_map< CGAL_2D_TRIANGULATION, PropertyTag>::const_type>::value_type +get(PropertyTag p, const CGAL_2D_TRIANGULATION& g, const Key& key) +{ + return get(get(p, g), key); +} + +template < CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS, class PropertyTag, class Key, class Value> +inline void +put(PropertyTag p, CGAL_2D_TRIANGULATION& g, const Key& key, const Value& value) +{ + typedef typename boost::property_map::type Map; + Map pmap = get(p, g); + put(pmap, key, value); +} + +} // namespace CGAL + +#undef CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS +#undef CGAL_2D_TRIANGULATION diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_Delaunay_triangulation_2.h new file mode 100644 index 00000000000..39bc63b86b7 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_Delaunay_triangulation_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H +#define CGAL_PROPERTIES_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS, typename Itag +#define CGAL_2D_TRIANGULATION CGAL::Constrained_Delaunay_triangulation_2 + +#include + +#endif /* CGAL_PROPERTIES_CONSTRAINED_DELAUNAY_TRIANGULATION_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_2.h new file mode 100644 index 00000000000..cf240c2bd07 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_2_H +#define CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS, typename Itag +#define CGAL_2D_TRIANGULATION CGAL::Constrained_triangulation_2 + +#include + +#endif /* CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_plus_2.h new file mode 100644 index 00000000000..a110f485ba5 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Constrained_triangulation_plus_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_PLUS_2_H +#define CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_PLUS_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename Tr +#define CGAL_2D_TRIANGULATION CGAL::Constrained_triangulation_plus_2 + +#include + +#endif /* CGAL_PROPERTIES_CONSTRAINED_TRIANGULATION_PLUS_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Delaunay_triangulation_2.h new file mode 100644 index 00000000000..f67b8e03ce6 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Delaunay_triangulation_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_DELAUNAY_TRIANGULATION_2_H +#define CGAL_PROPERTIES_DELAUNAY_TRIANGULATION_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Delaunay_triangulation_2 + +#include + +#endif /* CGAL_PROPERTIES_DELAUNAY_TRIANGULATION_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Regular_triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Regular_triangulation_2.h new file mode 100644 index 00000000000..1dd7da20f96 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Regular_triangulation_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_REGULAR_TRIANGULATION_2_H +#define CGAL_PROPERTIES_REGULAR_TRIANGULATION_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Regular_triangulation_2 + +#include + +#endif /* CGAL_PROPERTIES_REGULAR_TRIANGULATION_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_2.h new file mode 100644 index 00000000000..81f7a4c953d --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_TRIANGULATION_2_H +#define CGAL_PROPERTIES_TRIANGULATION_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename GT, typename TDS +#define CGAL_2D_TRIANGULATION CGAL::Triangulation_2 + +#include + +#endif /* CGAL_PROPERTIES_TRIANGULATION_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_data_structure_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_data_structure_2.h new file mode 100644 index 00000000000..a2cb3d1411c --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_data_structure_2.h @@ -0,0 +1,354 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_TRIANGULATION_DATA_STRUCTURE_2_H +#define CGAL_PROPERTIES_TRIANGULATION_DATA_STRUCTURE_2_H + +#include +#include +#include + +#include + +#include + +namespace CGAL { +namespace internal { + +// property maps +template +class TDS2_vertex_point_map +{ +public: + typedef boost::lvalue_property_map_tag category; + typedef typename VB::Point value_type; + typedef value_type& reference; + typedef typename CGAL::Triangulation_data_structure_2::Vertex_handle key_type; + + friend reference get(TDS2_vertex_point_map, key_type vh) { return vh->point(); } + friend void put(TDS2_vertex_point_map, key_type vh, reference v) { vh->point() = v; } + reference operator[](key_type vh) const { return vh->point(); } +}; + +template +class TDS2_edge_weight_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef typename VB::FT value_type; + typedef value_type reference; + typedef typename CGAL::Triangulation_data_structure_2::Edge key_type; + + TDS2_edge_weight_map(const CGAL::Triangulation_data_structure_2& tds_) : tds(tds_) { } + + value_type operator[](key_type e) const { return approximate_sqrt(tds.segment(e).squared_length()); } + +private: + const CGAL::Triangulation_data_structure_2& tds; +}; + +template +class TDS2_vertex_id_map + : public boost::put_get_helper > +{ +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef typename CGAL::Triangulation_data_structure_2::Vertex_handle key_type; + + TDS2_vertex_id_map() {} + + long operator[](key_type vh) const { return vh->id(); } +}; + +template +class TDS2_halfedge_id_map + : public boost::put_get_helper > +{ + typedef typename CGAL::Triangulation_data_structure_2 TDS; + +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef CGAL::internal::T2_halfedge_descriptor key_type; + + typedef typename TDS::Face_handle face_descriptor; + + TDS2_halfedge_id_map() { } + + // Halfedge id is twice the edge id, and +0/+1 depending whether + // h.first is such that h.first < opposite(h).first --> different ids + value_type operator[](key_type h) const + { + const face_descriptor f1 = h.first; + const face_descriptor f2 = f1->neighbor(h.second); + + if(f1->id() < f2->id()) + return 2*(3 * f1->id() + h.second); + else + return 2*(3 * f2->id() + f2->index(f1)) + 1; + } +}; + +template +class TDS2_edge_id_map + : public boost::put_get_helper > +{ + typedef typename CGAL::Triangulation_data_structure_2 TDS; + +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef CGAL::internal::T2_edge_descriptor key_type; + + typedef typename TDS::Face_handle Face_handle; + + TDS2_edge_id_map() {} + + value_type operator[](key_type h) const + { + const Face_handle f1 = h.first; + const Face_handle f2 = f1->neighbor(h.second); + + if(f1->id() < f2->id()) + return 3 * f1->id() + h.second; + else + return 3 * f2->id() + f2->index(f1); + } +}; + +template +class TDS2_face_id_map + : public boost::put_get_helper > +{ + typedef typename CGAL::Triangulation_data_structure_2 TDS; + +public: + typedef boost::readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef typename TDS::Face_handle key_type; + + TDS2_face_id_map() { } + + value_type operator[](key_type f) const { return f->id(); } +}; + +template +struct TDS2_property_map { }; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_vertex_point_map type; + typedef internal::TDS2_vertex_point_map const_type; +}; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_edge_weight_map type; + typedef internal::TDS2_edge_weight_map const_type; +}; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_vertex_id_map type; + typedef internal::TDS2_vertex_id_map const_type; +}; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_vertex_id_map type; + typedef internal::TDS2_vertex_id_map const_type; +}; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_edge_id_map type; + typedef internal::TDS2_edge_id_map const_type; +}; + +template +struct TDS2_property_map +{ + typedef internal::TDS2_vertex_id_map type; + typedef internal::TDS2_vertex_id_map const_type; +}; + +} // end namespace internal + +template +struct graph_has_property, boost::vertex_point_t> + : CGAL::Tag_true{}; +template +struct graph_has_property, boost::edge_weight_t> + : CGAL::Tag_true{}; + +template +struct graph_has_property, boost::vertex_index_t> + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL::Triangulation_data_structure_2::Vertex + >::value + > +{}; +template +struct graph_has_property, boost::halfedge_index_t> + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL::Triangulation_data_structure_2::Face + >::value + > +{}; +template +struct graph_has_property, boost::edge_index_t> + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL::Triangulation_data_structure_2::Face + >::value + > +{}; +template +struct graph_has_property, boost::face_index_t> + : CGAL::Boolean_tag< + CGAL::internal::Has_member_id< + typename CGAL::Triangulation_data_structure_2::Face + >::value + > +{}; + +template +inline internal::TDS2_vertex_point_map +get(boost::vertex_point_t, const Triangulation_data_structure_2&) +{ + internal::TDS2_vertex_point_map m; + return m; +} + +template +inline internal::TDS2_edge_weight_map +get(boost::edge_weight_t, const Triangulation_data_structure_2& g) +{ + internal::TDS2_edge_weight_map m(g); + return m; +} + +template +inline internal::TDS2_vertex_id_map +get(boost::vertex_index_t, const Triangulation_data_structure_2&) +{ + internal::TDS2_vertex_id_map m; + return m; +} + +template +inline internal::TDS2_halfedge_id_map +get(boost::halfedge_index_t, const Triangulation_data_structure_2&) +{ + internal::TDS2_halfedge_id_map m; + return m; +} + +template +inline internal::TDS2_edge_id_map +get(boost::edge_index_t, const Triangulation_data_structure_2&) +{ + internal::TDS2_edge_id_map m; + return m; +} + +template +inline internal::TDS2_face_id_map +get(boost::face_index_t, const Triangulation_data_structure_2&) +{ + internal::TDS2_face_id_map m; + return m; +} + +} // namespace CGAL + +namespace boost { + +// g++ 'enumeral_type' in template unification not implemented workaround +template +struct property_map, Tag> +{ + typedef typename CGAL::internal::TDS2_property_map map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; +}; + +// see struct property_map in Polyehdron for an explanation +template +struct property_map, Tag> +{ + typedef typename CGAL::internal::TDS2_property_map map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; +}; + +} // namespace boost + +namespace CGAL { + +template +inline +typename boost::property_traits< +typename boost::property_map,PropertyTag>::const_type>::value_type +get(PropertyTag p, const Triangulation_data_structure_2& g, const Key& key) +{ + return get(get(p, g), key); +} + +template +inline void +put(PropertyTag p, Triangulation_data_structure_2& g, + const Key& key, const Value& value) +{ + typedef typename boost::property_map, PropertyTag>::type Map; + Map pmap = get(p, g); + put(pmap, key, value); +} + +} // namespace CGAL + +namespace boost { + +// What are those needed for ??? +template +struct edge_property_type > { + typedef void type; +}; + +template +struct vertex_property_type > { + typedef void type; +}; + +} // namespace boost + +#endif /* CGAL_PROPERTIES_TRIANGULATION_DATA_STRUCTURE_2_H */ diff --git a/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_hierarchy_2.h new file mode 100644 index 00000000000..ff55fd46bf5 --- /dev/null +++ b/Triangulation_2/include/CGAL/boost/graph/properties_Triangulation_hierarchy_2.h @@ -0,0 +1,30 @@ +// Copyright (c) 2019 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// 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$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// Author(s) : Mael Rouxel-Labbé + +#ifndef CGAL_PROPERTIES_TRIANGULATION_HIERARCHY_2_H +#define CGAL_PROPERTIES_TRIANGULATION_HIERARCHY_2_H + +#include + +#define CGAL_2D_TRIANGULATION_TEMPLATE_PARAMETERS typename Tr +#define CGAL_2D_TRIANGULATION CGAL::Triangulation_hierarchy_2 + +#include + +#endif /* CGAL_PROPERTIES_TRIANGULATION_HIERARCHY_2_H */ diff --git a/Triangulation_3/package_info/Triangulation_3/dependencies b/Triangulation_3/package_info/Triangulation_3/dependencies index df63288cf1d..e22da1bafd7 100644 --- a/Triangulation_3/package_info/Triangulation_3/dependencies +++ b/Triangulation_3/package_info/Triangulation_3/dependencies @@ -21,6 +21,7 @@ Number_types Polygon Profiling_tools Property_map +Random_numbers STL_Extension Spatial_sorting Stream_support