// 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_DIJKSTRA_SHORTEST_PATH_H #define CGAL_BOOST_GRAPH_DIJKSTRA_SHORTEST_PATH_H #include #include #include #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 : public 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; VertexEdgeMap& relaxed_edges; Stop_at_target_Dijkstra_visitor(vertex_descriptor destination_vd, VertexEdgeMap& relaxed_edges) : destination_vd(destination_vd), relaxed_edges(relaxed_edges) {} void edge_relaxed(const edge_descriptor& e, const Graph& g) const { relaxed_edges[target(e, g)] = e; } void finish_vertex(const vertex_descriptor& vd, const Graph& /* g*/) const { if (vd == destination_vd) throw Dijkstra_end_exception(); } }; } // namespace internal /*! * \ingroup PkgBGLTraversal * computes the shortest path between two vertices in a graph `g`, where the vertices must belong to the same connected component of `g`. * * @tparam Graph a model of the concept `HalfedgeListGraph` * @tparam OutputIterator an output iterator with value type `boost::graph_traits::%halfedge_descriptor` * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" * * @param vs source vertex * @param vt target vertex * @param g the graph * @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 * * \cgalNamedParamsBegin * \cgalParamNBegin{edge_weight_map} * \cgalParamDescription{a property map associating to each edge in the graph its weight or "length". * The weights must all be non-negative.} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%edge_descriptor` * as key type and a value type which as specified in the named parameter `distance_map`of the function `boost::graph::dijkstra_shortest_paths()`, with any model of `RingNumberType` fulfilling the requirements. } * \cgalParamDefault{`get(boost::edge_weight, mesh)`} * \cgalParamNEnd * * \cgalParamNBegin{vertex_index_map} * \cgalParamDescription{a property map associating to each vertex of `g` a unique index between `0` and `num_vertices(g) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamNEnd * \cgalNamedParamsEnd */ template OutputIterator dijkstra_shortest_path( 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 edge_descriptor = typename boost::graph_traits::edge_descriptor; using Pred_umap = std::unordered_map; 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, g)); const auto vim = get_initialized_vertex_index_map(g, np); Pred_umap predecessor; Pred_pmap pred_pmap(predecessor); using VEMap = std::unordered_map; VEMap relaxed_edges_map; internal::Stop_at_target_Dijkstra_visitor vis(vt, relaxed_edges_map); try { boost::dijkstra_shortest_paths(g, vs, boost::predecessor_map(pred_pmap) .visitor(vis) .weight_map(w_map) .vertex_index_map(vim)); } catch (const internal::Dijkstra_end_exception& ){} std::list path; vertex_descriptor t = vt; do { path.push_front(halfedge(relaxed_edges_map[t],g)); t = get(pred_pmap, t); }while (t != vs); for(auto he : path){ *halfedge_sequence_oit++ = he; } return halfedge_sequence_oit; } } // namespace CGAL #endif //CGAL_BOOST_GRAPH_DIJKSTRA_SHORTEST_PATH_H