From 0ab64a295d934f860c62ecf1e236aa13e381b9cd Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 12 Sep 2024 14:33:53 +0100 Subject: [PATCH 01/11] Add graph_traits for geometrycentral --- .../graph/graph_traits_geometrycentral.h | 604 ++++++++++++++++++ BGL/test/BGL/CMakeLists.txt | 21 + .../BGL/graph_concept_geometrycentral.cpp | 73 +++ 3 files changed, 698 insertions(+) create mode 100644 BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h create mode 100644 BGL/test/BGL/graph_concept_geometrycentral.cpp 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..5b1213f07b99 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -0,0 +1,604 @@ + +// Author(s) : Andreas Fabri + +#pragma once + +#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 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 geometrycentral::surface::Edge edge_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; + + // 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& ); + + +// Declarations + +typename boost::graph_traits::vertices_size_type +inline num_vertices(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.nVertices(); +} + + +typename boost::graph_traits::edges_size_type +inline num_edges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return sm.nEdges(); +} + + +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& ) +{ + return e.halfedge().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 e.halfedge().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 : u.adjacentEdges()) { + if(e.otherVertex(u) == 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) +{ + return sm.prev(h); +} +*/ + + +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 h.edge(); +} + + +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> +geometrycentral::surface::HalfedgeSet +inline halfedges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) +{ + return const_cast(sm).halfedges(); +} + + + +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& ) +{ + return h.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.nFaces(); +} + + +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 = false) +{ + 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 + +} // namespace surface +} // namespace geometrycentral + 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/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp new file mode 100644 index 000000000000..5036d8055fed --- /dev/null +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -0,0 +1,73 @@ + +#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 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 >(); +} + + +int main() +{ + test_concepts(); + + std::unique_ptr mesh; + std::unique_ptr geometry; + std::tie(mesh, geometry) = geometrycentral::surface::readManifoldSurfaceMesh("./data/tetrahedron.off"); + num_vertices(*mesh); + + for( auto v : mesh->vertices()){ + assert(v == v.halfedge().twin().tipVertex()); + } + + 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; + } + + return 0; +} \ No newline at end of file From 670e5d6ab40f611fc362a226ed9929bc23590144 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 12 Sep 2024 14:38:44 +0100 Subject: [PATCH 02/11] license header --- .../boost/graph/graph_traits_geometrycentral.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index 5b1213f07b99..f6b8ca4a3bc9 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -1,7 +1,16 @@ - +// 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 -#pragma once +#ifndef CGAL_BOOST_GRAPH_TRAITS_GEOMETRYCENTRAL_H +#define CGAL_BOOST_GRAPH_TRAITS_GEOMETRYCENTRAL_H #include #include @@ -602,3 +611,4 @@ bool is_valid_face_descriptor(typename boost::graph_traits Date: Fri, 13 Sep 2024 14:00:26 +0100 Subject: [PATCH 03/11] Add vertex_point map --- .../graph/graph_traits_geometrycentral.h | 73 +++++++++++++++++-- .../BGL/graph_concept_geometrycentral.cpp | 7 +- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index f6b8ca4a3bc9..66c39a75ab45 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -18,6 +18,7 @@ #include #include +#include namespace std { template <> @@ -288,15 +289,18 @@ inline next(typename boost::graph_traits::halfedge_descriptor prev(typename boost::graph_traits::halfedge_descriptor h, const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return sm.prev(h); + 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 @@ -335,15 +339,14 @@ inline halfedge(typename boost::graph_traits::halfedge_iterator> -geometrycentral::surface::HalfedgeSet +CGAL::Iterator_range::halfedge_iterator> inline halfedges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return const_cast(sm).halfedges(); + 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) { @@ -608,7 +611,63 @@ bool is_valid_face_descriptor(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_->inputVertexPositions[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_).inputVertexPositions[v] = vec; + } + + private: + const VertexPositionGeometry* vpg_; +}; + + } // namespace surface } // namespace geometrycentral +namespace boost { +template<> +struct property_map +{ + typedef geometrycentral::surface::GC_point_pmap type; + typedef type const_type; +}; +} // namespace boost + #endif diff --git a/BGL/test/BGL/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp index 5036d8055fed..b716133eebdd 100644 --- a/BGL/test/BGL/graph_concept_geometrycentral.cpp +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -69,5 +70,9 @@ int main() std::cout << v << " at distance " << distance[v] << std::endl; } + geometrycentral::surface::GC_point_pmap vpm; + auto he = *(halfedges(*mesh).first); + CGAL::Polygon_mesh_processing::edge_length(he,*mesh, CGAL::parameters::vertex_point_map(vpm)); + return 0; -} \ No newline at end of file +} From bc3d02cd32d36744959dc6a9405fbbe458b03979 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 13 Sep 2024 14:24:10 +0100 Subject: [PATCH 04/11] GC does not ignore empty lines in off file --- BGL/test/BGL/data/tetrahedron.off | 1 - BGL/test/BGL/data/triangle.off | 1 - 2 files changed, 2 deletions(-) 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 From 5bb0831f8b9e6debd0d5f6ae8d54fe1fd90fae3b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 13 Sep 2024 14:30:42 +0100 Subject: [PATCH 05/11] Deal with border edges --- BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index 66c39a75ab45..060b2b1effa1 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -422,7 +422,9 @@ typename boost::graph_traits::fa inline face(typename boost::graph_traits::halfedge_descriptor h, const geometrycentral::surface::ManifoldSurfaceMesh& ) { - return h.face(); + if(h.isInterior()) + return h.face(); + return boost::graph_traits::null_face(); } #if 0 From 6ac69d303904e833751b29c6fd3e339fca16fe13 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 16 Sep 2024 08:45:32 +0100 Subject: [PATCH 06/11] Add BGL_edge and fixes for map/unordered_map --- .../graph/graph_traits_geometrycentral.h | 99 +++++++++++++++++-- .../BGL/graph_concept_geometrycentral.cpp | 81 ++++++++++++++- 2 files changed, 166 insertions(+), 14 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index 060b2b1effa1..17cb93c288d9 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -62,6 +62,80 @@ struct iterator_traits +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 gometrycentral::surface::Edge(halfedge_); + } + + 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 <> @@ -79,16 +153,17 @@ struct graph_traits< geometrycentral::surface::ManifoldSurfaceMesh > public: // Graph typedef geometrycentral::surface::Vertex vertex_descriptor; - typedef geometrycentral::surface::Edge edge_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::Halfedge halfedge_descriptor; + + typedef geometrycentral::surface::BGL_Edge edge_descriptor; // FaceGraph - typedef geometrycentral::surface::Face face_descriptor; + typedef geometrycentral::surface::Face face_descriptor; // VertexListGraph typedef typename geometrycentral::RangeIteratorBase vertex_iterator; @@ -137,6 +212,10 @@ typename boost::graph_traits::ha 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 @@ -188,9 +267,9 @@ inline in_degree(typename boost::graph_traits::vertex_descriptor inline source(typename boost::graph_traits::edge_descriptor e, - const geometrycentral::surface::ManifoldSurfaceMesh& ) + const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return e.halfedge().tailVertex(); + return halfedge(e,sm).tailVertex(); } @@ -206,7 +285,7 @@ typename boost::graph_traits::ve inline target(typename boost::graph_traits::edge_descriptor e, const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return e.halfedge().tipVertex(); + return halfedge(e,sm).tipVertex(); } @@ -269,8 +348,8 @@ inline edge(typename boost::graph_traits::vertex_descriptor v, const geometrycentral::surface::ManifoldSurfaceMesh& sm) { typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - for(auto e : u.adjacentEdges()) { - if(e.otherVertex(u) == v){ + for(auto e : out_edges(u, sm)) { + if(target(e,sm) == v){ return std::make_pair(e, true); } } @@ -315,7 +394,7 @@ typename boost::graph_traits::ed inline edge(typename boost::graph_traits::halfedge_descriptor h, const geometrycentral::surface::ManifoldSurfaceMesh& ) { - return h.edge(); + return typename boost::graph_traits::edge_descriptor(h); } @@ -582,7 +661,7 @@ bool is_valid_vertex_descriptor(typename boost::graph_traits::halfedge_descriptor h, const geometrycentral::surface::ManifoldSurfaceMesh& g, - const bool verbose = false) + const bool verbose = true) { if(!g.is_valid(h, verbose)) return false; diff --git a/BGL/test/BGL/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp index b716133eebdd..79cd594d7ae5 100644 --- a/BGL/test/BGL/graph_concept_geometrycentral.cpp +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -6,7 +6,6 @@ #include #include - #include #include @@ -18,6 +17,10 @@ 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; @@ -32,6 +35,60 @@ void test_concepts() 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() { @@ -40,10 +97,25 @@ int main() 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; @@ -70,9 +142,10 @@ int main() std::cout << v << " at distance " << distance[v] << std::endl; } - geometrycentral::surface::GC_point_pmap vpm; - auto he = *(halfedges(*mesh).first); - CGAL::Polygon_mesh_processing::edge_length(he,*mesh, CGAL::parameters::vertex_point_map(vpm)); + geometrycentral::surface::GC_point_pmap 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; + } return 0; } From 795e141bd3e182688cd2b2c9530aa8e0a77527a2 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 10 Oct 2024 16:20:44 +0100 Subject: [PATCH 07/11] Make num_vertices() work even for a mesh that is not compressed/garbage collected --- BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index 17cb93c288d9..d30982c7c6aa 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -222,14 +222,14 @@ halfedge(typename boost::graph_traits::vertices_size_type inline num_vertices(const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return sm.nVertices(); + return sm.vertexIndexSize(); } typename boost::graph_traits::edges_size_type inline num_edges(const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return sm.nEdges(); + return sm.edgeIndexSize(); } @@ -540,7 +540,7 @@ set_halfedge(typename boost::graph_traits::faces_size_type inline num_faces(const geometrycentral::surface::ManifoldSurfaceMesh& sm) { - return sm.nFaces(); + return sm.faceIndexSize(); } From c19c648682d023d680cb7231528c65c6f5e6bc70 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 10 Oct 2024 19:35:39 +0100 Subject: [PATCH 08/11] Add index_pmap --- .../graph/graph_traits_geometrycentral.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index d30982c7c6aa..8ed7d7c87993 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -738,6 +738,25 @@ class GC_point_pmap 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 From a8cfbedaa88399244e2988cc45aec69576833427 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 11 Oct 2024 07:48:29 +0100 Subject: [PATCH 09/11] Add a vertex index map using v.getIndex() --- .../graph/graph_traits_geometrycentral.h | 28 ++++++++++++++++++- .../BGL/graph_concept_geometrycentral.cpp | 3 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index 8ed7d7c87993..d25281780b90 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -738,7 +738,7 @@ class GC_point_pmap const VertexPositionGeometry* vpg_; }; -template +template class GC_index_pmap { public: @@ -768,6 +768,32 @@ struct property_map +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/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp index 79cd594d7ae5..0ea1f054603b 100644 --- a/BGL/test/BGL/graph_concept_geometrycentral.cpp +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -136,7 +136,8 @@ int main() 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()))); + // .vertex_index_map(boost::associative_property_map>(mesh->getVertexIndices())) + ); for(auto v : mesh->vertices()){ std::cout << v << " at distance " << distance[v] << std::endl; From 9366e38eeeeb6d5129afddcc4579ca3539a19581 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 11 Oct 2024 15:58:39 +0100 Subject: [PATCH 10/11] Use property_map<>::type instead of undocumented PM class name --- BGL/test/BGL/graph_concept_geometrycentral.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/test/BGL/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp index 0ea1f054603b..33da4ae096f3 100644 --- a/BGL/test/BGL/graph_concept_geometrycentral.cpp +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -143,7 +143,7 @@ int main() std::cout << v << " at distance " << distance[v] << std::endl; } - geometrycentral::surface::GC_point_pmap vpm(*geometry); + 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; } From 80019b0436e8fb33b5ac38e67436b0ce038cec24 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 11 Oct 2024 16:58:42 +0100 Subject: [PATCH 11/11] make mst work --- .../CGAL/boost/graph/graph_traits_geometrycentral.h | 6 +++--- BGL/test/BGL/graph_concept_geometrycentral.cpp | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h index d25281780b90..f4388e3b4a74 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_geometrycentral.h @@ -101,7 +101,7 @@ class BGL_Edge { operator geometrycentral::surface::Edge() const { - return gometrycentral::surface::Edge(halfedge_); + return halfedge_.edge(); } bool operator<(const BGL_Edge& other) const @@ -719,7 +719,7 @@ class GC_point_pmap inline friend reference get(const GC_point_pmap& pm, key_type v) { CGAL_assertion(pm.vpg_!=nullptr); - typename Vector3 const& gcp = pm.vpg_->inputVertexPositions[v]; + typename Vector3 const& gcp = pm.vpg_->vertexPositions[v]; return value_type(gcp[0], gcp[1], gcp[2]); } @@ -731,7 +731,7 @@ class GC_point_pmap vec.x = p.x(); vec.y = p.y(); vec.z = p.z(); - const_cast(*pm.vpg_).inputVertexPositions[v] = vec; + const_cast(*pm.vpg_).vertexPositions[v] = vec; } private: diff --git a/BGL/test/BGL/graph_concept_geometrycentral.cpp b/BGL/test/BGL/graph_concept_geometrycentral.cpp index 33da4ae096f3..18d308e6b379 100644 --- a/BGL/test/BGL/graph_concept_geometrycentral.cpp +++ b/BGL/test/BGL/graph_concept_geometrycentral.cpp @@ -8,7 +8,7 @@ #include #include #include - +#include #include #include #include @@ -148,5 +148,12 @@ int main() 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; }