From c935b7625fd643865fdfcba82c9415cd9448bfb8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 31 Jan 2025 14:25:59 +0100 Subject: [PATCH 1/7] first version of shortest_path(vs, vt, mesh) --- BGL/examples/BGL_surface_mesh/CMakeLists.txt | 1 + .../BGL_surface_mesh/shortest_path.cpp | 79 ++++++++++ BGL/include/CGAL/boost/graph/shortest_path.h | 138 ++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 BGL/examples/BGL_surface_mesh/shortest_path.cpp create mode 100644 BGL/include/CGAL/boost/graph/shortest_path.h diff --git a/BGL/examples/BGL_surface_mesh/CMakeLists.txt b/BGL/examples/BGL_surface_mesh/CMakeLists.txt index 921104583dc8..59a667234ec5 100644 --- a/BGL/examples/BGL_surface_mesh/CMakeLists.txt +++ b/BGL/examples/BGL_surface_mesh/CMakeLists.txt @@ -9,6 +9,7 @@ create_single_source_cgal_program("seam_mesh.cpp") create_single_source_cgal_program("write_inp.cpp") create_single_source_cgal_program("surface_mesh_dual.cpp") create_single_source_cgal_program("connected_components.cpp") +create_single_source_cgal_program("shortest_path.cpp") find_package(METIS QUIET) include(CGAL_METIS_support) diff --git a/BGL/examples/BGL_surface_mesh/shortest_path.cpp b/BGL/examples/BGL_surface_mesh/shortest_path.cpp new file mode 100644 index 000000000000..f85d41b3a7e7 --- /dev/null +++ b/BGL/examples/BGL_surface_mesh/shortest_path.cpp @@ -0,0 +1,79 @@ +#include +#include +#include + +#include +#include + + +#include +#include +#include +#include +#include + +using K = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point = K::Point_3; +using Mesh = CGAL::Surface_mesh; + +using vertex_descriptor = boost::graph_traits::vertex_descriptor; +using edge_descriptor = boost::graph_traits::edge_descriptor; +using halfedge_descriptor = boost::graph_traits::halfedge_descriptor; + +namespace PMP = CGAL::Polygon_mesh_processing; +namespace params = CGAL::parameters; + + +// Example main +int main(int argc, char** argv) +{ + const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/elephant.off"); + + // Try building a surface_mesh + Mesh sm; + bool ok = CGAL::IO::read_polygon_mesh(filename, sm); + if (!ok || !sm.is_valid() || sm.is_empty()) + { + std::cerr << "Error: Invalid facegraph" << std::endl; + std::cerr << "Filename = " << filename << std::endl; + return EXIT_FAILURE; + } + + const std::size_t i0 = 0; + const std::size_t i1 = num_vertices(sm) / 2; + + + // Get the vertex descriptors of the source and target vertices + const vertex_descriptor vs = *vertices(sm).first; + vertex_descriptor vt; + std::size_t vid = 0; + for (const vertex_descriptor v : vertices(sm)) + { + if (vid++ == i1) + { + vt = v; + break; + } + } + + std::vector halfedge_sequence; + CGAL::shortest_path_between_two_vertices(vs, vt, sm, halfedge_sequence); + + // dump + std::cout << "Shortest path between vertices " << i0 << " and " << i1 + << " is made of " << halfedge_sequence.size() << " halfedges." << std::endl; + + // Get the property map of the points of the mesh + auto vpmap = get(CGAL::vertex_point, sm); + + std::ofstream out("shortest_path.polylines.txt"); + for (const halfedge_descriptor he : halfedge_sequence) + { + const vertex_descriptor v0 = source(he, sm); + const vertex_descriptor v1 = target(he, sm); + out << "2 " << get(vpmap, v0) << " " << get(vpmap, v1) << std::endl; + } + out.close(); + + return EXIT_SUCCESS; +} diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h new file mode 100644 index 000000000000..349f1279c31c --- /dev/null +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -0,0 +1,138 @@ +// Copyright (c) 2025 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) : Jane Tournois, Andreas Fabri +// + +#ifndef CGAL_BOOST_GRAPH_SHORTEST_PATH_H +#define CGAL_BOOST_GRAPH_SHORTEST_PATH_H + +#include + +#include +#include +#include + +namespace CGAL { +namespace internal { + + /// An exception used while catching a throw that stops Dijkstra's algorithm + /// once the shortest path to a target has been found. + class Dijkstra_end_exception : public std::exception + { + const char* what() const throw () + { + return "Dijkstra shortest path: reached the target vertex."; + } + }; + + /// Visitor to stop Dijkstra's algorithm once the given target turns 'BLACK', + /// that is when the target has been examined through all its incident edges and + /// the shortest path is thus known. + template + class Stop_at_target_Dijkstra_visitor : boost::default_dijkstra_visitor + { + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using edge_descriptor = typename boost::graph_traits::edge_descriptor; + + public: + vertex_descriptor destination_vd; + + void initialize_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} + void examine_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} + void examine_edge(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} + void edge_relaxed(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} + void discover_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} + void edge_not_relaxed(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} + void finish_vertex(const vertex_descriptor& vd, const Mesh& /* mesh*/) const + { + if (vd == destination_vd) + throw Dijkstra_end_exception(); + } + }; +} // namespace internal + +/*! +*@tparam Mesh a model of the concept `HalfedgeListGraph` +* @param vs source vertex +* @param vt target vertex +* @param mesh the mesh +* @param halfedge_sequence the sequence of halfedges that form the shortest path on `mesh` +*/ +template +void shortest_path_between_two_vertices( + const typename boost::graph_traits::vertex_descriptor vs,//source + const typename boost::graph_traits::vertex_descriptor vt,//target + const Mesh& mesh, + std::vector::halfedge_descriptor>& halfedge_sequence) +{ + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; + + using Pred_umap = std::unordered_map; + using Pred_pmap = boost::associative_property_map; + + Pred_umap predecessor; + Pred_pmap pred_pmap(predecessor); + + internal::Stop_at_target_Dijkstra_visitor vis; + vis.destination_vd = vt; + try + { + boost::dijkstra_shortest_paths(mesh, vs, + boost::predecessor_map(pred_pmap).visitor(vis)); + } + catch (const std::exception& e) + { + std::cout << e.what() << std::endl; + } + + // Walk back from target to source and collect vertices along the way + struct vertex_on_path + { + vertex_descriptor vertex; + bool is_constrained; + }; + + std::vector constrained_vertices = { vs }; + vertex_descriptor t = vt; + std::vector path; + do + { + const bool is_new_vertex = (constrained_vertices.end() + == std::find(constrained_vertices.begin(), constrained_vertices.end(), t)); + + vertex_on_path vop; + vop.vertex = t; + vop.is_constrained = !is_new_vertex; + path.push_back(vop); + + t = get(pred_pmap, t); + } + while (t != vs); + + // Add the last vertex + vertex_on_path vop; + vop.vertex = constrained_vertices.back(); + vop.is_constrained = true; + path.push_back(vop); + + // Display path + for (auto path_it = path.begin(); path_it != path.end() - 1; ++path_it) + { + const std::pair + h = halfedge((path_it + 1)->vertex, path_it->vertex, mesh); + if (h.second) + halfedge_sequence.push_back(h.first); + } +} + +} // namespace CGAL + + +#endif //CGAL_BOOST_GRAPH_SHORTEST_PATH_H From c3cf48ca4055d95a2658fca4860b1e10ca4f86d6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 31 Jan 2025 15:54:05 +0100 Subject: [PATCH 2/7] add np and return output iterator --- .../BGL_surface_mesh/shortest_path.cpp | 3 ++- BGL/include/CGAL/boost/graph/shortest_path.h | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/BGL/examples/BGL_surface_mesh/shortest_path.cpp b/BGL/examples/BGL_surface_mesh/shortest_path.cpp index f85d41b3a7e7..ab568ee5efff 100644 --- a/BGL/examples/BGL_surface_mesh/shortest_path.cpp +++ b/BGL/examples/BGL_surface_mesh/shortest_path.cpp @@ -57,7 +57,8 @@ int main(int argc, char** argv) } std::vector halfedge_sequence; - CGAL::shortest_path_between_two_vertices(vs, vt, sm, halfedge_sequence); + CGAL::shortest_path_between_two_vertices(vs, vt, sm, + std::back_inserter(halfedge_sequence)); // dump std::cout << "Shortest path between vertices " << i0 << " and " << i1 diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h index 349f1279c31c..e48e3256386a 100644 --- a/BGL/include/CGAL/boost/graph/shortest_path.h +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -14,6 +14,9 @@ #include +#include +#include + #include #include #include @@ -64,12 +67,15 @@ namespace internal { * @param mesh the mesh * @param halfedge_sequence the sequence of halfedges that form the shortest path on `mesh` */ -template -void shortest_path_between_two_vertices( +template +OutputIterator shortest_path_between_two_vertices( const typename boost::graph_traits::vertex_descriptor vs,//source const typename boost::graph_traits::vertex_descriptor vt,//target const Mesh& mesh, - std::vector::halfedge_descriptor>& halfedge_sequence) + OutputIterator halfedge_sequence_oit, + const NamedParameters& np = parameters::default_values()) { using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; @@ -87,10 +93,7 @@ void shortest_path_between_two_vertices( boost::dijkstra_shortest_paths(mesh, vs, boost::predecessor_map(pred_pmap).visitor(vis)); } - catch (const std::exception& e) - { - std::cout << e.what() << std::endl; - } + catch (const std::exception& e){} // Walk back from target to source and collect vertices along the way struct vertex_on_path @@ -128,8 +131,9 @@ void shortest_path_between_two_vertices( const std::pair h = halfedge((path_it + 1)->vertex, path_it->vertex, mesh); if (h.second) - halfedge_sequence.push_back(h.first); + *halfedge_sequence_oit++ = h.first; } + return halfedge_sequence_oit; } } // namespace CGAL From 0a8d61bbd17502da5666220c5ff6eed74a9bb66a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 3 Feb 2025 11:59:04 +0100 Subject: [PATCH 3/7] add edge_weight property map --- BGL/include/CGAL/boost/graph/shortest_path.h | 16 +++++++++++++++- .../internal/parameters_interface.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h index e48e3256386a..a97f89f915dd 100644 --- a/BGL/include/CGAL/boost/graph/shortest_path.h +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -66,6 +68,10 @@ namespace internal { * @param vt target vertex * @param mesh the mesh * @param halfedge_sequence the sequence of halfedges that form the shortest path on `mesh` +* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below +* ** edge_weight_map : @todo deal with input mesh with no internal pmap. +* default in boost is `get(boost::edge_weight, mesh)` +* */ template; using Pred_pmap = boost::associative_property_map; + using parameters::get_parameter; + using parameters::choose_parameter; + + const auto w_map = choose_parameter(get_parameter(np, internal_np::edge_weight), + get(boost::edge_weight, mesh)); + Pred_umap predecessor; Pred_pmap pred_pmap(predecessor); @@ -91,7 +103,9 @@ OutputIterator shortest_path_between_two_vertices( try { boost::dijkstra_shortest_paths(mesh, vs, - boost::predecessor_map(pred_pmap).visitor(vis)); + boost::predecessor_map(pred_pmap) + .visitor(vis) + .weight_map(w_map)); } catch (const std::exception& e){} diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index c95d2933e893..f35295c32cb8 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -28,6 +28,7 @@ CGAL_add_named_parameter(use_binary_mode_t, use_binary_mode, use_binary_mode) CGAL_add_named_parameter(metis_options_t, METIS_options, METIS_options) CGAL_add_named_parameter(vertex_partition_id_t, vertex_partition_id, vertex_partition_id_map) CGAL_add_named_parameter(face_partition_id_t, face_partition_id, face_partition_id_map) +CGAL_add_named_parameter(edge_weight_t, edge_weight, edge_weight_map) CGAL_add_named_parameter(vertex_output_iterator_t, vertex_output_iterator, vertex_output_iterator) CGAL_add_named_parameter(face_output_iterator_t, face_output_iterator, face_output_iterator) From 96cd968423d866982139048bf50c3d1986a5d978 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 3 Feb 2025 12:41:19 +0100 Subject: [PATCH 4/7] a little bit of doc + rename "mesh" to "graph" --- BGL/doc/BGL/PackageDescription.txt | 6 +++ BGL/include/CGAL/boost/graph/shortest_path.h | 49 +++++++++++--------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index e058589c3bf4..1fa0ec3fca22 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -467,6 +467,9 @@ the requirement for traversal of all faces in a graph. /// \defgroup PkgBGLPartition Partitioning Operations /// \ingroup PkgBGLRef +/// \defgroup PkgBGLTraversal Graph Traversal +/// \ingroup PkgBGLRef + /// \defgroup PkgBGLIOFct I/O Functions /// \ingroup PkgBGLRef @@ -761,6 +764,9 @@ user might encounter. \cgalCRPSection{Conversion Functions} - `CGAL::split_graph_into_polylines()` +\cgalCRPSection{Graph Traversal} +- `CGAL::shortest_path_between_two_vertices()` + \cgalCRPSection{Graph Adaptors} - `CGAL::Dual` - `CGAL::Face_filtered_graph` diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h index a97f89f915dd..e7bf84c7fc52 100644 --- a/BGL/include/CGAL/boost/graph/shortest_path.h +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -39,22 +39,22 @@ namespace internal { /// Visitor to stop Dijkstra's algorithm once the given target turns 'BLACK', /// that is when the target has been examined through all its incident edges and /// the shortest path is thus known. - template + template class Stop_at_target_Dijkstra_visitor : boost::default_dijkstra_visitor { - using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; - using edge_descriptor = typename boost::graph_traits::edge_descriptor; + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using edge_descriptor = typename boost::graph_traits::edge_descriptor; public: vertex_descriptor destination_vd; - void initialize_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} - void examine_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} - void examine_edge(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} - void edge_relaxed(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} - void discover_vertex(const vertex_descriptor& /*s*/, const Mesh& /*mesh*/) const {} - void edge_not_relaxed(const edge_descriptor& /*e*/, const Mesh& /*mesh*/) const {} - void finish_vertex(const vertex_descriptor& vd, const Mesh& /* mesh*/) const + void initialize_vertex(const vertex_descriptor& /*s*/, const Graph& /*g*/) const {} + void examine_vertex(const vertex_descriptor& /*s*/, const Graph& /*g*/) const {} + void examine_edge(const edge_descriptor& /*e*/, const Graph& /*g*/) const {} + void edge_relaxed(const edge_descriptor& /*e*/, const Graph& /*g*/) const {} + void discover_vertex(const vertex_descriptor& /*s*/, const Graph& /*g*/) const {} + void edge_not_relaxed(const edge_descriptor& /*e*/, const Graph& /*g*/) const {} + void finish_vertex(const vertex_descriptor& vd, const Graph& /* g*/) const { if (vd == destination_vd) throw Dijkstra_end_exception(); @@ -63,28 +63,31 @@ namespace internal { } // namespace internal /*! -*@tparam Mesh a model of the concept `HalfedgeListGraph` +* \ingroup PkgBGLTraversal +* Computes the shortest path between two vertices in a graph `g` +* +*@tparam Graph a model of the concept `HalfedgeListGraph` * @param vs source vertex * @param vt target vertex -* @param mesh the mesh -* @param halfedge_sequence the sequence of halfedges that form the shortest path on `mesh` +* @param g the graph +* @param halfedge_sequence the sequence of halfedges that form the shortest path on `g` * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * ** edge_weight_map : @todo deal with input mesh with no internal pmap. * default in boost is `get(boost::edge_weight, mesh)` * */ -template OutputIterator shortest_path_between_two_vertices( - const typename boost::graph_traits::vertex_descriptor vs,//source - const typename boost::graph_traits::vertex_descriptor vt,//target - const Mesh& mesh, + const typename boost::graph_traits::vertex_descriptor vs,//source + const typename boost::graph_traits::vertex_descriptor vt,//target + const Graph& g, OutputIterator halfedge_sequence_oit, const NamedParameters& np = parameters::default_values()) { - using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; - using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; using Pred_umap = std::unordered_map; using Pred_pmap = boost::associative_property_map; @@ -93,16 +96,16 @@ OutputIterator shortest_path_between_two_vertices( using parameters::choose_parameter; const auto w_map = choose_parameter(get_parameter(np, internal_np::edge_weight), - get(boost::edge_weight, mesh)); + get(boost::edge_weight, g)); Pred_umap predecessor; Pred_pmap pred_pmap(predecessor); - internal::Stop_at_target_Dijkstra_visitor vis; + internal::Stop_at_target_Dijkstra_visitor vis; vis.destination_vd = vt; try { - boost::dijkstra_shortest_paths(mesh, vs, + boost::dijkstra_shortest_paths(g, vs, boost::predecessor_map(pred_pmap) .visitor(vis) .weight_map(w_map)); @@ -143,7 +146,7 @@ OutputIterator shortest_path_between_two_vertices( for (auto path_it = path.begin(); path_it != path.end() - 1; ++path_it) { const std::pair - h = halfedge((path_it + 1)->vertex, path_it->vertex, mesh); + h = halfedge((path_it + 1)->vertex, path_it->vertex, g); if (h.second) *halfedge_sequence_oit++ = h.first; } From dc3fabfb66f31c4c8e86b573d1f9c97d0a6d063a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 3 Feb 2025 15:42:44 +0100 Subject: [PATCH 5/7] use shortest_path_between_two_vertices() in demo --- .../Lab/Scene_polyhedron_selection_item.cpp | 99 +++---------------- 1 file changed, 14 insertions(+), 85 deletions(-) diff --git a/Lab/demo/Lab/Scene_polyhedron_selection_item.cpp b/Lab/demo/Lab/Scene_polyhedron_selection_item.cpp index 7df511b6169b..6bac6f095c66 100644 --- a/Lab/demo/Lab/Scene_polyhedron_selection_item.cpp +++ b/Lab/demo/Lab/Scene_polyhedron_selection_item.cpp @@ -31,6 +31,7 @@ #include "triangulate_primitive.h" #include #include +#include #include using namespace CGAL::Three; @@ -1486,103 +1487,31 @@ void Scene_polyhedron_selection_item::emitTempInstruct() Q_EMIT updateInstructions(QString("%1").arg(d->m_temp_instructs)); } -/// An exception used while catching a throw that stops Dijkstra's algorithm -/// once the shortest path to a target has been found. -class Dijkstra_end_exception : public std::exception -{ - const char* what() const throw () - { - return "Dijkstra shortest path: reached the target vertex."; - } -}; - -/// Visitor to stop Dijkstra's algorithm once the given target turns 'BLACK', -/// that is when the target has been examined through all its incident edges and -/// the shortest path is thus known. -class Stop_at_target_Dijkstra_visitor : boost::default_dijkstra_visitor -{ - fg_vertex_descriptor destination_vd; - -public: - Stop_at_target_Dijkstra_visitor(fg_vertex_descriptor destination_vd) - : destination_vd(destination_vd) - { } - - void initialize_vertex(const fg_vertex_descriptor& /*s*/, const Face_graph& /*mesh*/) const { } - void examine_vertex(const fg_vertex_descriptor& /*s*/, const Face_graph& /*mesh*/) const { } - void examine_edge(const fg_edge_descriptor& /*e*/, const Face_graph& /*mesh*/) const { } - void edge_relaxed(const fg_edge_descriptor& /*e*/, const Face_graph& /*mesh*/) const { } - void discover_vertex(const fg_vertex_descriptor& /*s*/, const Face_graph& /*mesh*/) const { } - void edge_not_relaxed(const fg_edge_descriptor& /*e*/, const Face_graph& /*mesh*/) const { } - void finish_vertex(const fg_vertex_descriptor &vd, const Face_graph& /* mesh*/) const - { - if(vd == destination_vd) - throw Dijkstra_end_exception(); - } -}; void Scene_polyhedron_selection_item_priv::computeAndDisplayPath() { - item->temp_selected_edges.clear(); - path.clear(); - - typedef std::unordered_map Pred_umap; - typedef boost::associative_property_map Pred_pmap; - - Pred_umap predecessor; - Pred_pmap pred_pmap(predecessor); - - vertex_on_path vop; - QList::iterator it; - for(it = constrained_vertices.begin(); it!=constrained_vertices.end()-1; ++it) + const auto& mesh = *item->polyhedron(); + std::vector path_halfedges; + for(auto it = constrained_vertices.begin(); it!=constrained_vertices.end()-1; ++it) { fg_vertex_descriptor t(*it), s(*(it+1)); - Stop_at_target_Dijkstra_visitor vis(t); - - try - { - boost::dijkstra_shortest_paths(*item->polyhedron(), s, - boost::predecessor_map(pred_pmap).visitor(vis)); - } - catch (const std::exception& e) - { - std::cout << e.what() << std::endl; - } - // Walk back from target to source and collect vertices along the way - do - { - vop.vertex = t; - if(constrained_vertices.contains(t)) - { - vop.is_constrained = true; - } - else - vop.is_constrained = false; - path.append(vop); - t = get(pred_pmap, t); - } - while(t != s); + CGAL::shortest_path_between_two_vertices(s, t, mesh, + std::back_inserter(path_halfedges)); } - // Add the last vertex - vop.vertex = constrained_vertices.last(); - vop.is_constrained = true; - path.append(vop); + item->temp_selected_edges.clear(); + path.clear(); // Display path double path_length = 0; - QList::iterator path_it; - for(path_it = path.begin(); path_it!=path.end()-1; ++path_it) + VPmap vpm = get(CGAL::vertex_point, mesh); + for(auto h : path_halfedges) { - std::pair h = halfedge((path_it+1)->vertex,path_it->vertex,*item->polyhedron()); - if(h.second) - { - VPmap vpm = get(CGAL::vertex_point,*polyhedron()); - Point p1(get(vpm, (path_it+1)->vertex)), p2(get(vpm, path_it->vertex)); - path_length += CGAL::sqrt(Vector(p1,p2).squared_length()); - item->temp_selected_edges.insert(edge(h.first, *item->polyhedron())); - } + const Point& p1 = get(vpm, target(h, mesh)); + const Point& p2 = get(vpm, source(h, mesh)); + path_length += CGAL::approximate_sqrt(CGAL::squared_distance(p1, p2)); + item->temp_selected_edges.insert(edge(h, *item->polyhedron())); } item->printMessage(QString("New path length: %1").arg(path_length)); } From a64af9881afb5c27f63efc296114e5aad4860ef6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 3 Feb 2025 15:43:00 +0100 Subject: [PATCH 6/7] doc --- BGL/include/CGAL/boost/graph/shortest_path.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h index e7bf84c7fc52..ac62a1534a77 100644 --- a/BGL/include/CGAL/boost/graph/shortest_path.h +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -70,7 +70,8 @@ namespace internal { * @param vs source vertex * @param vt target vertex * @param g the graph -* @param halfedge_sequence the sequence of halfedges that form the shortest path on `g` +* @param halfedge_sequence_oit the output iterator holding the output sequence +* of halfedges that form the shortest path from `vs` to `vt` on `g` * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * ** edge_weight_map : @todo deal with input mesh with no internal pmap. * default in boost is `get(boost::edge_weight, mesh)` From f24d3ca97f583b61951116bbf8cfe16975d64fdf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2025 18:50:34 +0100 Subject: [PATCH 7/7] use Dijkstra_end_exception instead of std::exception --- BGL/include/CGAL/boost/graph/shortest_path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BGL/include/CGAL/boost/graph/shortest_path.h b/BGL/include/CGAL/boost/graph/shortest_path.h index ac62a1534a77..6c6c11bb413b 100644 --- a/BGL/include/CGAL/boost/graph/shortest_path.h +++ b/BGL/include/CGAL/boost/graph/shortest_path.h @@ -111,7 +111,7 @@ OutputIterator shortest_path_between_two_vertices( .visitor(vis) .weight_map(w_map)); } - catch (const std::exception& e){} + catch (const internal::Dijkstra_end_exception& ){} // Walk back from target to source and collect vertices along the way struct vertex_on_path