diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h new file mode 100644 index 000000000000..f4388e3b4a74 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -0,0 +1,799 @@ +// Copyright (c) 2024 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_BOOST_GRAPH_TRAITS_GEOMETRYCENTRAL_H +#define CGAL_BOOST_GRAPH_TRAITS_GEOMETRYCENTRAL_H + +#include +#include + + +#include +#include +#include + +namespace std { +template <> +struct iterator_traits> +{ + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef geometrycentral::surface::Vertex value_type; + typedef value_type* pointer; + typedef value_type & reference; +}; + +template <> +struct iterator_traits> +{ + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef geometrycentral::surface::Halfedge value_type; + typedef value_type* pointer; + typedef value_type & reference; +}; + +template <> +struct iterator_traits> +{ + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef geometrycentral::surface::Edge value_type; + typedef value_type* pointer; + typedef value_type & reference; +}; + +template <> +struct iterator_traits> +{ + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef geometrycentral::surface::Face value_type; + typedef value_type* pointer; + typedef value_type & reference; +}; +} + +namespace geometrycentral { +namespace surface { + +// As Edge is not BGL compliant, we need an alternative for BGL algorithms +template +class BGL_Edge { +public: + BGL_Edge(const geometrycentral::surface::Edge& e) + : halfedge_(e.halfedge()) + {} + + BGL_Edge() + : halfedge_() + {} + + explicit BGL_Edge(const Halfedge_handle& h) + : halfedge_(h) + {} + + Halfedge_handle halfedge() const + { + return halfedge_; + } + + + bool + operator==(const BGL_Edge& other) const + { + if(halfedge_ == other.halfedge_) { + return true; + } else if(halfedge_ != Halfedge_handle()) { + return halfedge_.twin() == other.halfedge_; + } else { + return false; + } + } + + operator geometrycentral::surface::Edge() const + { + return halfedge_.edge(); + } + + bool operator<(const BGL_Edge& other) const + { + return idx() < other.idx(); + } + + bool + operator!=(const BGL_Edge& other) const + { + return !(*this == other); + } + + std::size_t idx() const { return (std::min)(halfedge_.getIndex(), halfedge_.twin().getIndex()); } +private: + Halfedge_handle halfedge_; +}; +} +} + +namespace std { +template +struct hash > + : public CGAL::cpp98::unary_function, std::size_t> +{ + + std::size_t operator()(const geometrycentral::surface::BGL_Edge& e) const + { + return e.halfedge().getIndex(); + } +}; + +} + +namespace boost { + +template <> +struct graph_traits< geometrycentral::surface::ManifoldSurfaceMesh > +{ +private: + typedef geometrycentral::surface::ManifoldSurfaceMesh SM; + + struct SM_graph_traversal_category : public virtual boost::bidirectional_graph_tag, + public virtual boost::vertex_list_graph_tag, + public virtual boost::edge_list_graph_tag, + public virtual boost::adjacency_graph_tag + {}; + +public: + // Graph + typedef geometrycentral::surface::Vertex vertex_descriptor; + typedef boost::undirected_tag directed_category; + typedef boost::disallow_parallel_edge_tag edge_parallel_category; + typedef SM_graph_traversal_category traversal_category; + + // HalfedgeGraph + typedef geometrycentral::surface::Halfedge halfedge_descriptor; + + typedef geometrycentral::surface::BGL_Edge edge_descriptor; + + // FaceGraph + typedef geometrycentral::surface::Face face_descriptor; + + // VertexListGraph + typedef typename geometrycentral::RangeIteratorBase vertex_iterator; + typedef typename std::size_t vertices_size_type; + // EdgeListGraph + typedef typename geometrycentral::RangeIteratorBase edge_iterator; + + typedef typename std::size_t edges_size_type; + // HalfEdgeListGraph + typedef typename geometrycentral::RangeIteratorBase halfedge_iterator; + typedef typename std::size_t halfedges_size_type; + // FaceListGraph + typedef typename geometrycentral::RangeIteratorBase face_iterator; + typedef typename std::size_t faces_size_type; + + // IncidenceGraph + typedef typename std::size_t degree_size_type; + + + typedef CGAL::In_edge_iterator in_edge_iterator; + typedef CGAL::Out_edge_iterator out_edge_iterator; + + typedef CGAL::Vertex_around_target_iterator adjacency_iterator; + + + // 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< const geometrycentral::surface::ManifoldSurfaceMesh > + : public graph_traits< geometrycentral::surface::ManifoldSurfaceMesh > +{ }; + +} // namespace boost + +namespace geometrycentral { + +namespace surface { + + +// Forward declarations +typename boost::graph_traits::halfedge_descriptor +halfedge(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& ); + +typename boost::graph_traits::halfedge_descriptor +halfedge(typename boost::graph_traits::edge_descriptor e, + const geometrycentral::surface::ManifoldSurfaceMesh& ); + + +// Declarations + +typename boost::graph_traits::vertices_size_type +inline num_vertices(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.vertexIndexSize(); +} + + +typename boost::graph_traits::edges_size_type +inline num_edges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.edgeIndexSize(); +} + + +typename boost::graph_traits::degree_size_type +inline degree(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return v.degree(); +} + + +typename boost::graph_traits::degree_size_type +inline degree(typename boost::graph_traits::face_descriptor f, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return f.degree(); +} + + +typename boost::graph_traits::degree_size_type +inline out_degree(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return v.degree(); +} + + +typename boost::graph_traits::degree_size_type +inline in_degree(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return v.degree(); +} + + +typename boost::graph_traits::vertex_descriptor +inline source(typename boost::graph_traits::edge_descriptor e, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return halfedge(e,sm).tailVertex(); +} + + +typename boost::graph_traits::vertex_descriptor +inline source(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return h.tailVertex(); +} + + +typename boost::graph_traits::vertex_descriptor +inline target(typename boost::graph_traits::edge_descriptor e, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return halfedge(e,sm).tipVertex(); +} + + +typename boost::graph_traits::vertex_descriptor +inline target(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return h.tipVertex(); +} + + +CGAL::Iterator_range::vertex_iterator> +inline vertices(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + geometrycentral::surface::VertexSet vs = const_cast(sm).vertices(); + return CGAL::make_range(vs.begin(), vs.end()); +} + + +CGAL::Iterator_range::edge_iterator> +inline edges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + geometrycentral::surface::EdgeSet es = const_cast(sm).edges(); + return CGAL::make_range(es.begin(), es.end()); +} + + +CGAL::Iterator_range::in_edge_iterator> +inline in_edges(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + typedef typename boost::graph_traits::in_edge_iterator Iter; + + return make_range(Iter(halfedge(v,sm),sm), Iter(halfedge(v,sm),sm,1)); +} + + + +CGAL::Iterator_range::out_edge_iterator> +inline out_edges(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + typedef typename boost::graph_traits::out_edge_iterator Iter; + return make_range(Iter(halfedge(v,sm),sm), Iter(halfedge(v,sm),sm,1)); +} + + + +CGAL::Iterator_range::adjacency_iterator> +inline adjacent_vertices(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return CGAL::vertices_around_target(v,sm); +} + + +std::pair::edge_descriptor, + bool> +inline edge(typename boost::graph_traits::vertex_descriptor u, + typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) { + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + for(auto e : out_edges(u, sm)) { + if(target(e,sm) == v){ + return std::make_pair(e, true); + } + } + return std::make_pair(edge_descriptor(), false); +} + + +// +// HalfedgeGraph +// + +typename boost::graph_traits::halfedge_descriptor +inline next(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return h.next(); +} + + +typename boost::graph_traits::halfedge_descriptor +prev(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + typename boost::graph_traits::halfedge_descriptor res, it = h.next(); + while(it != h){ + res = it; + it = it.next(); + } + return res; +} + + +typename boost::graph_traits::halfedge_descriptor +inline opposite(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return h.twin(); +} + + +typename boost::graph_traits::edge_descriptor +inline edge(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return typename boost::graph_traits::edge_descriptor(h); +} + + +typename boost::graph_traits::halfedge_descriptor +inline halfedge(typename boost::graph_traits::edge_descriptor e, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return e.halfedge(); +} + + +typename boost::graph_traits::halfedge_descriptor +inline halfedge(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return v.halfedge().twin(); +} + + +// +// HalfedgeListGraph +// + +CGAL::Iterator_range::halfedge_iterator> +inline halfedges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + geometrycentral::surface::HalfedgeSet es = const_cast(sm).halfedges(); + return CGAL::make_range(es.begin(), es.end()); +} + + +typename boost::graph_traits::halfedges_size_type +inline num_halfedges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.nHalfedges(); +} + + +#if 0 +// +// MutableHalfedgeGraph +// +template +void +set_next(typename boost::graph_traits::halfedge_descriptor h1, + typename boost::graph_traits::halfedge_descriptor h2, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.set_next(h1, h2); +} + + + +template +void +set_target(typename boost::graph_traits::halfedge_descriptor h, + typename boost::graph_traits::vertex_descriptor v, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.set_target(h, v); +} + + +template +void +set_halfedge(typename boost::graph_traits::vertex_descriptor v, + typename boost::graph_traits::halfedge_descriptor h, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.set_halfedge(v, h); +} + + +template +typename boost::graph_traits::edge_descriptor +add_edge(geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.edge(sm.add_edge()); +} + +#endif + + + +void +inline collect_garbage(geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.compress(); +} + + +// +// FaceGraph +// +typename boost::graph_traits::halfedge_descriptor +inline halfedge(typename boost::graph_traits::face_descriptor f, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + return f.halfedge(); +} + + +typename boost::graph_traits::face_descriptor +inline face(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& ) +{ + if(h.isInterior()) + return h.face(); + return boost::graph_traits::null_face(); +} + +#if 0 + +// +// MutableFaceGraph +// +template +void +set_face(typename boost::graph_traits::halfedge_descriptor h, + typename boost::graph_traits::face_descriptor f, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.set_face(h, f); +} + + +template +void +set_halfedge(typename boost::graph_traits::face_descriptor f, + typename boost::graph_traits::halfedge_descriptor h, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.set_halfedge(f, h); +} + +#endif + + +// +// FaceListGraph +// + +typename boost::graph_traits::faces_size_type +inline num_faces(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.faceIndexSize(); +} + + +CGAL::Iterator_range::face_iterator> + +inline faces(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + geometrycentral::surface::FaceSet fs = const_cast(sm).faces(); + return CGAL::make_range(fs.begin(), fs.end()); +} + +#if 0 + +typename boost::graph_traits::vertex_descriptor +add_vertex(geometrycentral::surface::ManifoldSurfaceMesh& sm) { + return sm.add_vertex(); +} + + +typename boost::graph_traits::vertex_descriptor +add_vertex(const typename boost::graph_traits::vertex_property_type& p, geometrycentral::surface::ManifoldSurfaceMesh& sm) { + return sm.add_vertex(p); +} + +// MutableGraph +template +void +reserve(geometrycentral::surface::ManifoldSurfaceMesh& sm, + typename boost::graph_traits< geometrycentral::surface::ManifoldSurfaceMesh >::vertices_size_type nv, + typename boost::graph_traits< geometrycentral::surface::ManifoldSurfaceMesh >::edges_size_type ne, + typename boost::graph_traits< geometrycentral::surface::ManifoldSurfaceMesh >::faces_size_type nf) +{ + sm.reserve(nv, ne, nf); +} + + + +void +remove_vertex(typename boost::graph_traits::vertex_descriptor v, + geometrycentral::surface::ManifoldSurfaceMesh& sm) { + + sm.remove_vertex(v); +} + + +void +remove_edge(typename boost::graph_traits::vertex_descriptor u, + typename boost::graph_traits::vertex_descriptor v, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + typename boost::graph_traits::edge_descriptor e = edge(u, v, sm); + remove_edge(e,sm); +} + + +void +remove_edge(typename boost::graph_traits::edge_descriptor e, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.remove_edge(e); +} + + +void +remove_edge(typename boost::graph_traits::edge_iterator eiter, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + remove_edge(*eiter, sm); +} + +template +void +remove_face(typename boost::graph_traits::face_descriptor f, + geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.remove_face(f); +} + +template +void +remove_all_elements(geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + sm.clear_without_removing_property_maps(); +} + +template +typename boost::graph_traits::face_descriptor +add_face(geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.add_face(); +} + +template +typename boost::graph_traits::face_descriptor +add_face(InputIterator begin, InputIterator end, geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + std::vector::vertex_descriptor> + v(begin, end); + return sm.add_face(v); +} + +template +void normalize_border(const geometrycentral::surface::ManifoldSurfaceMesh&) +{} + + + +bool is_valid_vertex_descriptor(typename boost::graph_traits::vertex_descriptor v, + const geometrycentral::surface::ManifoldSurfaceMesh& g, + const bool verbose = false) +{ + if(!g.is_valid(v, verbose)) + return false; + + return BGL::is_valid_vertex_descriptor(v, g, verbose); +} + + +bool is_valid_halfedge_descriptor(typename boost::graph_traits::halfedge_descriptor h, + const geometrycentral::surface::ManifoldSurfaceMesh& g, + const bool verbose = true) +{ + if(!g.is_valid(h, verbose)) + return false; + + return BGL::is_valid_halfedge_descriptor(h, g, verbose); +} + + +bool is_valid_edge_descriptor(typename boost::graph_traits::edge_descriptor e, + const geometrycentral::surface::ManifoldSurfaceMesh& g, + const bool verbose = false) +{ + if(!g.is_valid(e, verbose)) + return false; + + return BGL::is_valid_edge_descriptor(e, g, verbose); +} + + +bool is_valid_face_descriptor(typename boost::graph_traits::face_descriptor f, + const geometrycentral::surface::ManifoldSurfaceMesh& g, + const bool verbose = false) +{ + if(!g.is_valid(f, verbose)) + return false; + + return BGL::is_valid_face_descriptor(f, g, verbose); +} +#endif + + +class GC_point_pmap +{ +public: + + typedef boost::read_write_property_map_tag category; + typedef CGAL::Exact_predicates_inexact_constructions_kernel::Point_3 P; + typedef P value_type; + typedef P reference; + + typedef typename boost::graph_traits::vertex_descriptor key_type; + + GC_point_pmap() + : vpg_(nullptr) + {} + + GC_point_pmap(const VertexPositionGeometry& vpg) + : vpg_(&vpg) + {} + + GC_point_pmap(const GC_point_pmap& pm) + : vpg_(pm.vpg_) + {} + + inline friend reference get(const GC_point_pmap& pm, key_type v) + { + CGAL_assertion(pm.vpg_!=nullptr); + typename Vector3 const& gcp = pm.vpg_->vertexPositions[v]; + return value_type(gcp[0], gcp[1], gcp[2]); + } + + inline friend void put(const GC_point_pmap& pm, key_type v, const value_type& p) + { + CGAL_precondition(pm.vpg_!=nullptr); + typedef double Scalar; + Vector3 vec; + vec.x = p.x(); + vec.y = p.y(); + vec.z = p.z(); + const_cast(*pm.vpg_).vertexPositions[v] = vec; + } + + private: + const VertexPositionGeometry* vpg_; +}; + +template +class GC_index_pmap +{ +public: + typedef boost::readable_property_map_tag category; + typedef std::size_t value_type; + typedef std::size_t reference; + typedef VEF key_type; + + GC_index_pmap() + {} + + value_type operator[](const key_type& vd) const + { + return vd.getIndex(); + } + + friend inline value_type get(const GC_index_pmap& m, const key_type& k) { return m[k]; } +}; + +} // namespace surface +} // namespace geometrycentral + +namespace boost { +template<> +struct property_map +{ + typedef geometrycentral::surface::GC_point_pmap type; + typedef type const_type; +}; + + +template <> +struct property_map +{ + typedef geometrycentral::surface::ManifoldSurfaceMesh Mesh; + typedef geometrycentral::surface::GC_index_pmap::vertex_descriptor> type; + typedef geometrycentral::surface::GC_index_pmap::vertex_descriptor> const_type; +}; + +} // namespace boost + + +namespace geometrycentral { +namespace surface { + + +GC_index_pmap::vertex_descriptor> +get(const boost::vertex_index_t&, const ManifoldSurfaceMesh&) +{ + typedef ManifoldSurfaceMesh Mesh; + return GC_index_pmap::vertex_descriptor>(); +} + +} + +} + +#endif diff --git a/BGL/test/BGL/CMakeLists.txt b/BGL/test/BGL/CMakeLists.txt index 2cf88ff3cbfd..4468c5551d06 100644 --- a/BGL/test/BGL/CMakeLists.txt +++ b/BGL/test/BGL/CMakeLists.txt @@ -82,3 +82,24 @@ if(3MF_LIBRARIES AND 3MF_INCLUDE_DIR AND EXISTS "${3MF_INCLUDE_DIR}/Model/COM/N else() message(STATUS "NOTICE: The test 'test_3mf_to_sm' requires the lib3MF library, and will not be compiled.") endif() + + +find_path(geometrycentral_INCLUDE_DIR + NAMES geometrycentral/surface/surface_mesh.h + DOC "Path to geometrycentral headers" + ) + +find_library(GEOMETRYCENTRAL_LIBRARY_DEBUG NAMES geometry-central DOC "Path to the goemetrycentral library (debug)") + + +find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater) +include(CGAL_Eigen3_support) +if(GEOMETRYCENTRAL_LIBRARY_DEBUG ) + include_directories(${geometrycentral_INCLUDE_DIR}) + create_single_source_cgal_program( graph_concept_geometrycentral.cpp ) + + target_link_libraries(graph_concept_geometrycentral PRIVATE ${GEOMETRYCENTRAL_LIBRARY_DEBUG}) + target_link_libraries(graph_concept_geometrycentral PUBLIC CGAL::Eigen3_support) +else() + message(STATUS "NOTICE: The test 'graph_concept_geometrycentral' requires the geometrycentral as well as the Eigen library, and will not be compiled.") +endif() \ No newline at end of file diff --git a/BGL/test/BGL/data/tetrahedron.off b/BGL/test/BGL/data/tetrahedron.off index e87dd57c03e9..e4f933825ef2 100644 --- a/BGL/test/BGL/data/tetrahedron.off +++ b/BGL/test/BGL/data/tetrahedron.off @@ -1,6 +1,5 @@ OFF 4 4 0 - 0 0 0 1 0 0 0 1 0 diff --git a/BGL/test/BGL/data/triangle.off b/BGL/test/BGL/data/triangle.off index e53dab5bd31b..db7884fdc87d 100644 --- a/BGL/test/BGL/data/triangle.off +++ b/BGL/test/BGL/data/triangle.off @@ -1,6 +1,5 @@ OFF 3 1 0 - 0 0 0 2 0 0 1 1 0 diff --git a/BGL/test/BGL/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp new file mode 100644 index 000000000000..18d308e6b379 --- /dev/null +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -0,0 +1,159 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using SurfaceMesh = geometrycentral::surface::ManifoldSurfaceMesh; +using VertexPositionGeometry = geometrycentral::surface::VertexPositionGeometry; + +using vertex_descriptor = boost::graph_traits::vertex_descriptor; +using edge_descriptor = boost::graph_traits::edge_descriptor; +using halfedge_descriptor = boost::graph_traits::halfedge_descriptor; +using face_descriptor = boost::graph_traits::face_descriptor; + + +using vertex_iterator = boost::graph_traits::vertex_iterator; + +void test_concepts() +{ + boost::function_requires< boost::GraphConcept >(); + boost::function_requires< boost::AdjacencyGraphConcept >(); + boost::function_requires< boost::VertexListGraphConcept >(); + boost::function_requires< boost::EdgeListGraphConcept >(); + boost::function_requires< boost::IncidenceGraphConcept >(); + boost::function_requires< boost::AdjacencyMatrixConcept >(); + boost::function_requires< boost::BidirectionalGraphConcept >(); +} + +void test_maps(const SurfaceMesh& sm) +{ + std::map vim; + std::unordered_map vium; + std::map him; + std::unordered_map hium; + std::map eim; + std::unordered_map eium; + std::map fim; + std::unordered_map fium; + + int i = 0, j = 0; + for(auto v : vertices(sm)){ + vim[v] = i++; + vium[v] = j++; + } + i = 0; j = 0; + for(auto v : vertices(sm)){ + assert(vim[v] == i++); + assert(vium[v] == j++); + } + + i = 0; j = 0; + for(auto v : halfedges(sm)){ + him[v] = i++; + hium[v] = j++; + } + i = 0; j = 0; + for(auto v : halfedges(sm)){ + assert(him[v] == i++); + assert(hium[v] == j++); + } + i = 0; j = 0; + for(auto v : edges(sm)){ + eim[v] = i++; + eium[v] = j++; + } + i = 0; j = 0; + for(auto v : edges(sm)){ + assert(eim[v] == i++); + assert(eium[v] == j++); + } + + i = 0; j = 0; + for(auto v : faces(sm)){ + fim[v] = i++; + fium[v] = j++; + } + i = 0; j = 0; + for(auto v : faces(sm)){ + assert(fim[v] == i++); + assert(fium[v] == j++); + } +} + +int main() +{ + test_concepts(); + + std::unique_ptr mesh; + std::unique_ptr geometry; + std::tie(mesh, geometry) = geometrycentral::surface::readManifoldSurfaceMesh("./data/tetrahedron.off"); + + test_maps(*mesh); + + std::cout << num_vertices(*mesh) << " vertices" << std::endl; + + for(auto h : halfedges(*mesh)){ + assert(halfedge(edge(h,*mesh),*mesh) == h); + if(CGAL::is_border(h,*mesh)){ std::cout << "b" << std::endl;}else{ std::cout << "nb" << std::endl;} + } + num_vertices(*mesh); + + for( auto v : mesh->vertices()){ + assert(v == v.halfedge().twin().tipVertex()); + for(auto e : out_edges(v,*mesh)){ + assert(v == source(e,*mesh)); + } + for(auto e : in_edges(v,*mesh)){ + assert(v == target(e,*mesh)); + } + } + + int index = 0; + std::map vim; + std::unordered_map vium; + std::pair vr = vertices(*mesh); + for (vertex_descriptor vd : vertices(*mesh)){ + vim[vd]= index; + vium[vd]= index; + ++index; + } + + // We can record the distance in a map, but also in VertexData + // std::map distance; + geometrycentral::surface::VertexData distance(*mesh); + + auto source = *(vertices(*mesh).first); + boost::breadth_first_search(*mesh, + source, + boost::visitor(boost::make_bfs_visitor(boost::record_distances(boost::make_assoc_property_map(distance), boost::on_tree_edge()))) + // .vertex_index_map(boost::associative_property_map>(mesh->getVertexIndices())) + ); + + for(auto v : mesh->vertices()){ + std::cout << v << " at distance " << distance[v] << std::endl; + } + + boost::property_map::const_type vpm(*geometry); + for(auto he : halfedges(*mesh)){ + std::cout << "edge length: " << CGAL::Polygon_mesh_processing::edge_length(he,*mesh, CGAL::parameters::vertex_point_map(vpm)) << std::endl; + } + + geometry->requireEdgeLengths(); + + geometrycentral::surface::VertexData predecessor(*mesh); + boost::prim_minimum_spanning_tree(*mesh, + boost::make_assoc_property_map(predecessor), + boost::root_vertex(source).weight_map(boost::make_assoc_property_map(geometry->edgeLengths))); + + return 0; +}