From a3000a5fce14c37a10c88543e5124355c12e985c Mon Sep 17 00:00:00 2001 From: Vicky Vergara Date: Wed, 3 Jan 2024 22:07:18 -0600 Subject: [PATCH] Drivingdistance cleanup (#2599) * Enhancement of drivingDist.hpp * Adjusting code to changes * Updating release notes & NEWS --- NEWS | 9 +- doc/src/release_notes.rst | 9 +- .../withPoints/doc-pgr_withPointsDD.result | 16 +- include/dijkstra/drivingDist.hpp | 763 ++++++++---------- include/visitors/dijkstra_visitors.hpp | 35 +- src/driving_distance/drivedist_driver.cpp | 7 +- src/driving_distance/withPoints_dd_driver.cpp | 7 +- 7 files changed, 360 insertions(+), 486 deletions(-) diff --git a/NEWS b/NEWS index 63edbf0835..6d9cfc0007 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,14 @@ pgRouting 3.7.0 Release Notes ------------------------------------------------------------------------------- -No Changes Yet +To see all issues & pull requests closed by this release see the `Git closed +milestone for 3.7.0 +`_ + +**Code enhancement** + +* [#2599](https://github.com/pgRouting/pgrouting/pull/2599) Driving distance + cleanup pgRouting 3.6.1 Release Notes ------------------------------------------------------------------------------- diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 07561006d2..111b7c095d 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -24,7 +24,14 @@ To see the full list of changes check the list of `Git commits pgRouting 3.7.0 Release Notes ------------------------------------------------------------------------------- -No Changes Yet +To see all issues & pull requests closed by this release see the `Git closed +milestone for 3.7.0 +`_ + +.. rubric:: Code enhancement + +* `#2599 `__ Driving distance + cleanup pgRouting 3.6.1 Release Notes ------------------------------------------------------------------------------- diff --git a/docqueries/withPoints/doc-pgr_withPointsDD.result b/docqueries/withPoints/doc-pgr_withPointsDD.result index efef2cd6ba..73feef7dec 100644 --- a/docqueries/withPoints/doc-pgr_withPointsDD.result +++ b/docqueries/withPoints/doc-pgr_withPointsDD.result @@ -83,8 +83,8 @@ SELECT * FROM pgr_withPointsDD( 1 | 0 | -2 | -2 | -2 | -1 | 0 | 0 2 | 1 | -2 | -2 | 11 | 8 | 0.1 | 0.1 3 | 2 | -2 | 11 | 16 | 9 | 1 | 1.1 - 4 | 2 | -2 | 11 | 7 | 8 | 1 | 1.1 - 5 | 2 | -2 | 11 | 12 | 11 | 1 | 1.1 + 4 | 2 | -2 | 11 | 12 | 11 | 1 | 1.1 + 5 | 2 | -2 | 11 | 7 | 8 | 1 | 1.1 6 | 3 | -2 | 12 | 17 | 13 | 1 | 2.1 7 | 3 | -2 | 16 | 15 | 16 | 1 | 2.1 8 | 3 | -2 | 7 | 8 | 10 | 1 | 2.1 @@ -93,14 +93,14 @@ SELECT * FROM pgr_withPointsDD( 11 | 0 | -1 | -1 | -1 | -1 | 0 | 0 12 | 1 | -1 | -1 | 11 | 5 | 0.2 | 0.2 13 | 2 | -1 | 11 | 7 | 8 | 1 | 1.2 - 14 | 2 | -1 | 11 | 12 | 11 | 1 | 1.2 - 15 | 2 | -1 | 11 | 16 | 9 | 1 | 1.2 + 14 | 2 | -1 | 11 | 16 | 9 | 1 | 1.2 + 15 | 2 | -1 | 11 | 12 | 11 | 1 | 1.2 16 | 3 | -1 | 7 | -2 | 8 | 0.9 | 2.1 - 17 | 3 | -1 | 12 | 17 | 13 | 1 | 2.2 - 18 | 3 | -1 | 16 | 15 | 16 | 1 | 2.2 + 17 | 3 | -1 | 7 | 3 | 7 | 1 | 2.2 + 18 | 3 | -1 | 7 | 6 | 4 | 1 | 2.2 19 | 3 | -1 | 7 | 8 | 10 | 1 | 2.2 - 20 | 3 | -1 | 7 | 6 | 4 | 1 | 2.2 - 21 | 3 | -1 | 7 | 3 | 7 | 1 | 2.2 + 20 | 3 | -1 | 16 | 15 | 16 | 1 | 2.2 + 21 | 3 | -1 | 12 | 17 | 13 | 1 | 2.2 (21 rows) /* -- q6 */ diff --git a/include/dijkstra/drivingDist.hpp b/include/dijkstra/drivingDist.hpp index a8e16543cc..9c9e02d314 100644 --- a/include/dijkstra/drivingDist.hpp +++ b/include/dijkstra/drivingDist.hpp @@ -41,13 +41,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include #include -#include -#include #include #include #include #include -#include + #include #include @@ -59,6 +57,102 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "visitors/dijkstra_visitors.hpp" +namespace bg_detail { + +/** @brief Dijkstra 1 to distance + * + * Used on: + * - 1 to distance + * - many to distance + * - On the first call of many to distance with equi_cost + * + * @param [in] bg boost graph + * @param [in] root vertex root of the spanning tree + * @param [in] distance maximum distance. + * @param [in] predecessors predecessors list + * @param [in] distances distances from root + */ +template +void dijkstra_1_to_distance( + const B_G &bg, + V root, + std::vector &predecessors, + std::vector &distances, + double distance) { + CHECK_FOR_INTERRUPTS(); + try { + boost::dijkstra_shortest_paths(bg, root, + boost::predecessor_map(&predecessors[0]) + .weight_map(get(&T_E::cost, bg)) + .distance_map(&distances[0]) + .visitor(pgrouting::visitors::dijkstra_distance_visitor(distance, distances))); + } catch(pgrouting::found_goals &) { + /*No op*/ + } catch (boost::exception const&) { + throw; + } catch (std::exception&) { + throw; + } catch (...) { + throw; + } +} + +/** @brief Dijkstra 1 to distance no initialization + * + * Used on: + * On the subsequent calls of many to distance with equi_cost + * + * @param [in] bg boost graph + * @param [in] root vertex root of the spanning tree + * @param [in] distance maximum distance. + * @param [in] predecessors predecessors list + * @param [in] distances distances from root + */ +template +void dijkstra_1_to_distance_no_init( + const B_G &bg, + V root, + std::vector &predecessors, + std::vector &distances, + double distance) { + pgassert(predecessors.size() == num_vertices(bg)); + pgassert(distances.size() == num_vertices(bg)); + + distances[root] = 0; + /* + * Not using the default, because vertices visited from other roots are marked color black + */ + std::vector color_map(num_vertices(bg)); + auto vidx(boost::get(boost::vertex_index, bg)); + + CHECK_FOR_INTERRUPTS(); + try { + boost::dijkstra_shortest_paths_no_init(bg, root, + make_iterator_property_map(predecessors.begin(), vidx), + make_iterator_property_map(distances.begin(), vidx), + get(&G_T_E::cost, bg), + vidx, + std::less(), + boost::closed_plus(), + static_cast(0), + pgrouting::visitors::dijkstra_distance_visitor_no_init(root, distance, predecessors, distances, + color_map), + make_iterator_property_map(color_map.begin(), vidx, color_map[0])); + } catch(pgrouting::found_goals &) { + /* no op */ + } catch (boost::exception const& ex) { + (void)ex; + throw; + } catch (std::exception &e) { + (void)e; + throw; + } catch (...) { + throw; + } +} + +} // namespace bg_detail + namespace detail { /* notation: @@ -68,12 +162,13 @@ namespace detail { */ template void remove_details(const G &graph, - std::vector &distances, - std::vector &predecessors) { + const std::vector &distances, + std::vector &predecessors) { /* * find all the points that are predecessors */ std::set node_with_predecessor_point; + CHECK_FOR_INTERRUPTS(); for (V v = 0; v < predecessors.size() ; ++v) { /* * skipping unreachable nodes and or initial node @@ -97,10 +192,10 @@ void remove_details(const G &graph, pgassert(graph[u].id < 0); /* - * while u is a point and its predecessor is not itself + * while u is a point and it's predecessor is not itself */ + CHECK_FOR_INTERRUPTS(); while (graph[u].id < 0 && predecessors[u] != u) { - CHECK_FOR_INTERRUPTS(); pgassert(graph[u].id < 0); pgassert(distances[v] != std::numeric_limits::infinity()); v = u; @@ -119,13 +214,14 @@ void remove_details(const G &graph, * @param [in] distances An array of vertices @b id * @param [in] predecessors an array of predecessors * @param [in] distance the max distance + * @param [in] details the max distance */ template std::map get_depth( const G &graph, V root, - std::vector &distances, - std::vector &predecessors, + const std::vector& distances, + std::vector& predecessors, double distance, bool details) { std::map depth; @@ -179,458 +275,239 @@ std::map get_depth( return depth; } -} // namespace detail +/** @brief gets results for many vertices and equi costs + * + * @param [in] graph The graph that is being worked + * @param [in] roots a set of roots + * @param [in] predecessors an array of predecessors + * @param [in] noDetailsPredecessors veritces that do not have a predecessor + * @param [in] distances a map of distances + * @param [in] distance maximum distance + * @param [in] details flag to indicate to include points + * + * @pre one predecessor per root + */ +template +std::deque get_drivingDistance_with_equicost_paths( + const G &graph, + const std::set &roots, + std::deque> &predecessors, + std::vector &distances, + std::deque> &noDetailsPredecessors, + double distance, bool details) { + using Path = pgrouting::Path; + pgassert(roots.size() == predecessors.size()); -namespace pgrouting { -// TODO(v4) convert to functions + /* + * Creating all the result "paths" + */ + std::deque paths; + for (const auto r : roots) { + paths.push_back(Path(r, r)); + paths.back().push_back({r, -1, 0, 0, r}); + } -namespace algorithm { -template < class G > class Pgr_dijkstra; -} // namespace algorithm + /* + * Ciclying the vertices: + * To which vertex do they belong to? + */ + for (V v = 0; v < distances.size(); ++v) { + /* + * Sikiping distances greater than the one asked for + */ + if (!(distances[v] <= distance)) continue; + + for (auto i = roots.size(); i > 0; --i) { + const auto &predecessor = predecessors[i - 1]; + /* + * The vertex does not exist on the graph + * The predecessor = current then its unreachable to this vertex + */ + if (predecessor.empty()) break; + if (predecessor[v] == v) continue; -template -std::deque -pgr_drivingdistance( + auto u = details? predecessor[v] : noDetailsPredecessors[i - 1][v]; + /* + * precalculating cost to find the edge + */ + auto cost = distances[v] - distances[predecessor[v]]; + auto edge_id = graph.get_edge_id(predecessor[v], v, cost); + pgassert(edge_id != -1); + /* + * real cost is with real predecessor + */ + cost = details? cost : distances[v] - distances[u]; + paths[i - 1].push_back({graph[v].id, edge_id, cost, distances[v], graph[u].id}); + break; + } + } + + for (auto &path : paths) { + path.sort_by_node_agg_cost(); + } + return paths; +} + +/* preparation for many to distance with equicost + * + * The distances vector does not change + * The predecessors vector does not change + * The first @b valid execution is done normally: + * - The distances will have: + * - inf + * - values < distance + * - values > distance + * Subsequent @b valid executions + * - will not change the: + * - values < distance + * Don't know yet what happens to predecessors + */ +template +std::deque drivingDistance_with_equicost( G &graph, - const std::vector &start_vids, - double distance, - bool equicost, + const std::set &roots, std::vector> &depths, - bool details) { - algorithm::Pgr_dijkstra fn_dijkstra; - return fn_dijkstra.drivingDistance(graph, start_vids, distance, equicost, depths, details); -} + double distance, bool details) { + using V = typename G::V; + using E = typename G::E; + using T_E = typename G::G_T_E; + using B_G = typename G::B_G; -namespace algorithm { + depths.resize(roots.size()); + std::vector predecessors(graph.num_vertices()); + std::vector distances(graph.num_vertices(), std::numeric_limits::infinity()); -template < class G > -class Pgr_dijkstra { - public: - typedef typename G::V V; - typedef typename G::E E; - - //! @name drivingDistance - //@{ - //! 1 to distance - Path drivingDistance( - G &graph, - int64_t start_vertex, - double distance) { - if (execute_drivingDistance( - graph, - start_vertex, - distance)) { - auto path = Path(graph, - start_vertex, - distance, - predecessors, - distances); - - std::sort(path.begin(), path.end(), - [](const Path_t &l, const Path_t &r) - {return l.node < r.node;}); - std::stable_sort(path.begin(), path.end(), - [](const Path_t &l, const Path_t &r) - {return l.agg_cost < r.agg_cost;}); - return path; + std::deque> pred(roots.size()); + std::deque> noDetailsPredecessors(roots.size()); + + size_t i = 0; + for (const auto &root : roots) { + /* + * The vertex does not exist Nothing to do + */ + if (!(graph.has_vertex(root))) continue; + + std::iota(predecessors.begin(), predecessors.end(), 0); + bg_detail::dijkstra_1_to_distance_no_init(graph.graph, graph.get_V(root), predecessors, + distances, distance); + + pred[i] = predecessors; + depths[i] = detail::get_depth(graph, graph.get_V(root), distances, predecessors, distance, details); + if (!details) { + noDetailsPredecessors[i] = predecessors; } + ++i; + } - /* The result is empty */ - Path p(start_vertex, start_vertex); - p.push_back({start_vertex, -1, 0, 0}); - return p; - } - - // preparation for many to distance - std::deque drivingDistance( - G &graph, - const std::vector &start_vertex, - double distance, - bool equicost, - std::vector> &depths, - bool details) { - if (equicost) { - return drivingDistance_with_equicost( - graph, - start_vertex, - depths, - distance, details); - } else { - return drivingDistance_no_equicost( - graph, - start_vertex, - depths, - distance, details); - } - } - - - - - - - //@} - - - private: - /** Call to Dijkstra 1 to distance - * - * Used on: - * 1 to distance - * many to distance - * On the first call of many to distance with equi_cost - */ - bool dijkstra_1_to_distance( - G &graph, - V source, - double distance) { - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - try { - boost::dijkstra_shortest_paths(graph.graph, source, - boost::predecessor_map(&predecessors[0]) - .weight_map(get(&G::G_T_E::cost, graph.graph)) - .distance_map(&distances[0]) - .visitor(visitors::dijkstra_distance_visitor(distance, nodesInDistance, distances))); - } catch(found_goals &) { - /*No op*/ - } catch (boost::exception const&) { - throw; - } catch (std::exception&) { - throw; - } catch (...) { - throw; - } - return true; - } - - /** Call to Dijkstra 1 to distance no init - * - * Used on: - * On the subsequent calls of many to distance with equi_cost - */ - bool dijkstra_1_to_distance_no_init( - G &graph, - V source, - double distance) { - pgassert(predecessors.size() == graph.num_vertices()); - pgassert(distances.size() == graph.num_vertices()); - distances[source] = 0; - std::vector color_map(graph.num_vertices()); - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - try { - boost::dijkstra_shortest_paths_no_init(graph.graph, source, - make_iterator_property_map( - predecessors.begin(), - graph.vertIndex), - make_iterator_property_map( - distances.begin(), - graph.vertIndex), - get(&G::G_T_E::cost, graph.graph), - graph.vertIndex, - std::less(), - boost::closed_plus(), - static_cast(0), - visitors::dijkstra_distance_visitor_no_init(log, source, distance, predecessors, distances, - color_map), - boost::make_iterator_property_map( - color_map.begin(), - graph.vertIndex, - color_map[0])); - } catch(found_goals &) { - return true; - } catch (boost::exception const& ex) { - (void)ex; - throw; - } catch (std::exception &e) { - (void)e; - throw; - } catch (...) { - throw; - } + /* + * predecessors of root vertices are themselves + */ + for (const auto &root : roots) { + for (auto &p : pred) { + if (!p.empty() && graph.has_vertex(root)) + p[graph.get_V(root)] = graph.get_V(root); + } + } - return true; - } - - - /** @brief to use with driving distance - * - * Prepares the execution for a driving distance: - * - * @param graph - * @param start_vertex - * @param distance - * - * Results are kept on predecessor & distances - * - * @returns bool @b True when results are found - */ - bool execute_drivingDistance( - G &graph, - int64_t start_vertex, - double distance) { - clear(); - - predecessors.resize(graph.num_vertices()); - distances.resize( - graph.num_vertices(), - std::numeric_limits::infinity()); - - // get source; - if (!graph.has_vertex(start_vertex)) { - return false; - } + return get_drivingDistance_with_equicost_paths( + graph, + roots, + pred, + distances, + noDetailsPredecessors, + distance, details); +} - return dijkstra_1_to_distance( - graph, - graph.get_V(start_vertex), - distance); - } - - - /** @brief to use with driving distance - * - * Prepares the execution for a driving distance: - * - * @param graph - * @param start_vertex - * @param distance - * - * Results are kept on predecessor & distances - * - * @returns bool @b True when results are found - */ - bool execute_drivingDistance_no_init( - G &graph, - V start_vertex, - double distance) { - pgassert(predecessors.size() == graph.num_vertices()); - pgassert(distances.size() == graph.num_vertices()); - - std::iota(predecessors.begin(), predecessors.end(), 0); - - return dijkstra_1_to_distance_no_init( - graph, - start_vertex, - distance); - } - - /* preparation for many to distance with equicost - * - * Idea: - * The distances vector does not change - * The predecessors vector does not change - * The first @b valid execution is done normally: - * - The distances will have: - * - inf - * - values < distance - * - values > distance - * Subsequent @b valid executions - * - will not change the: - * - values < distance - * Don't know yet what happens to predecessors - */ - std::deque drivingDistance_with_equicost( - G &graph, - const std::vector &start_vertex, - std::vector> &depths, - double distance, bool details) { - clear(); - log << "Number of edges:" << boost::num_edges(graph.graph) << "\n"; - - depths.resize(start_vertex.size()); - predecessors.resize(graph.num_vertices()); - distances.resize( - graph.num_vertices(), - std::numeric_limits::infinity()); - - /* - * Vector to store the different predessesors - * each is of size = graph.num_vertices() - * - * TODO(gsoc) - * - figure out less storage if possible - */ - std::deque< std::vector> pred(start_vertex.size()); - std::deque< std::vector> nodetailspred(start_vertex.size()); - - // perform the algorithm - size_t i = 0; - for (const auto &vertex : start_vertex) { - nodesInDistance.clear(); - /* - * The vertex does not exist - * Nothing to do - */ - if (!(graph.has_vertex(vertex))) continue; - - if (execute_drivingDistance_no_init( - graph, graph.get_V(vertex), distance)) { - pred[i] = predecessors; - depths[i] = detail::get_depth(graph, graph.get_V(vertex), distances, predecessors, distance, details); - if (!details) { - nodetailspred[i] = predecessors; - } - } - ++i; - } +/** @brief gets results for many vertices and equi costs + * + * @param [in] graph The graph that is being worked + * @param [in] roots a set of roots + * @param [in] depths a vector of map of depths + * @param [in] distance maximum distance + * @param [in] details flag to indicate to include points + */ +template +std::deque drivingDistance_no_equicost( + const G &graph, + const std::set &roots, + std::vector> &depths, + double distance, bool details) { + using Path = pgrouting::Path; + using B_G = typename G::B_G; + using V = typename G::V; + using T_E = typename G::G_T_E; + std::deque paths; - /* - * predecessors of vertices in the set are themselves - */ - for (const auto &vertex : start_vertex) { - for (auto &p : pred) { - if (!p.empty() && graph.has_vertex(vertex)) - p[graph.get_V(vertex)] = graph.get_V(vertex); - } - } + for (const auto &root : roots) { + if (graph.has_vertex(root)) { + std::vector predecessors(graph.num_vertices()); + std::vector distances(graph.num_vertices(), std::numeric_limits::infinity()); + bg_detail::dijkstra_1_to_distance( + graph.graph, graph.get_V(root), predecessors, distances, distance); - return get_drivingDistance_with_equicost_paths( - graph, - start_vertex, - pred, - nodetailspred, - distance, details); - } - - /** @brief gets results in form of a container of paths - * - * @param [in] graph The graph that is being worked - * @param [in] start_vertex An array of vertices @b id - * @param [in] pred an array of predecessors - * @param [in] distance the max distance - * @pre one predecessor per root - */ - std::deque< Path > get_drivingDistance_with_equicost_paths( - G &graph, - const std::vector &start_vertex, - std::deque> &pred, - std::deque> &nodetailspred, - double distance, bool details) { - /* - * precondition - */ - pgassert(start_vertex.size() == pred.size()); - - - /* - * Creating all the result "paths" - */ - std::deque paths; - for (const auto vertex : start_vertex) { - paths.push_back(Path(vertex, vertex)); - paths.back().push_back({vertex, -1, 0, 0, vertex}); - } + auto path = Path(graph, root, distance, predecessors, distances); + path.sort_by_node_agg_cost(); + depths.push_back(detail::get_depth(graph, graph.get_V(root), distances, predecessors, distance, details)); + /* + * When details are not wanted update costs + */ + if (!details) { + for (auto &pathstop : path) { + auto node = graph.get_V(pathstop.node); - /* - * Ciclying the distances: - * To which vertex do they belong to? - */ - for (V d = 0; d < distances.size(); ++d) { - /* - * Sikiping distances greater than the one asked for - */ - if (!(distances[d] <= distance)) continue; - - for (auto i = start_vertex.size(); i > 0; --i) { - /* - * The vertex does not exist on the graph - */ - if (pred[i - 1].empty()) break; - - - /* - * The predecessor = current then - * its unreachable to this vertex - */ - if (pred[i - 1][d] == d) continue; - - auto cost = distances[d] - distances[pred[i - 1][d]]; - auto edge_id = graph.get_edge_id(pred[i - 1][d], d, cost); - int64_t pred_node = details? graph[pred[i - 1][d]].id : graph[nodetailspred[i - 1][d]].id; - pgassert(edge_id != -1); - paths[i - 1].push_back( - {graph[d].id, - edge_id, - details? cost : distances[d] - distances[nodetailspred[i - 1][d]], - distances[d], pred_node}); - break; - } - } + /* skip points */ + if (graph[node].id < 0) continue; - for (auto &path : paths) { - path.sort_by_node_agg_cost(); - } - return paths; - } - - - // preparation for many to distance No equicost - std::deque drivingDistance_no_equicost( - G &graph, - const std::vector< int64_t > &start_vertex, - std::vector> &depths, - double distance, bool details) { - // perform the algorithm - std::deque paths; - for (const auto &vertex : start_vertex) { - if (execute_drivingDistance(graph, vertex, distance)) { - auto path = Path( - graph, - vertex, - distance, - predecessors, - distances); - path.sort_by_node_agg_cost(); - auto root = graph.get_V(vertex); - depths.push_back(detail::get_depth(graph, root, distances, predecessors, distance, details)); - /* - * When details are not wanted update costs - */ - if (!details) { - for (auto &pathstop : path) { - auto node = graph.get_V(pathstop.node); - - /* skip points */ - if (graph[node].id < 0) continue; - - pathstop.cost = distances[node] - distances[predecessors[node]]; - } - log << "Updated costs of path " << path; - } - paths.push_back(path); - - } else { - Path p(vertex, vertex); - p.push_back({vertex, -1, 0, 0, vertex}); - paths.push_back(p); - std::map m; - m[vertex] = 0; - depths.push_back(m); - } - } - return paths; - } - - - void clear() { - predecessors.clear(); - distances.clear(); - nodesInDistance.clear(); - } - - //! @name members - //@{ - std::vector predecessors; - std::vector distances; - std::deque nodesInDistance; - std::ostringstream log; - //@} -}; + pathstop.cost = distances[node] - distances[predecessors[node]]; + } + } + paths.push_back(path); + + } else { + Path p(root, root); + p.push_back({root, -1, 0, 0, root}); + paths.push_back(p); + + std::map m; + m[root] = 0; + depths.push_back(m); + } + } + return paths; +} + + +} // namespace detail + + +namespace pgrouting { +namespace algorithm { + +template +std::deque drivingDistance( + const G &graph, + const std::set &roots, + double distance, + bool equicost, + std::vector> &depths, + bool details) { + if (equicost) { + return detail::drivingDistance_with_equicost( + graph, + roots, + depths, + distance, details); + } else { + return detail::drivingDistance_no_equicost( + graph, + roots, + depths, + distance, details); + } +} } // namespace algorithm } // namespace pgrouting diff --git a/include/visitors/dijkstra_visitors.hpp b/include/visitors/dijkstra_visitors.hpp index 58db9b9d7c..35fc1f195b 100644 --- a/include/visitors/dijkstra_visitors.hpp +++ b/include/visitors/dijkstra_visitors.hpp @@ -92,12 +92,9 @@ class dijkstra_distance_visitor : public boost::default_dijkstra_visitor { public: explicit dijkstra_distance_visitor( double distance_goal, - std::deque &nodesInDistance, std::vector &distances) : m_distance_goal(distance_goal), - m_nodes(nodesInDistance), m_dist(distances) { - pgassert(m_nodes.empty()); pgassert(m_distance_goal > 0); } template @@ -105,12 +102,10 @@ class dijkstra_distance_visitor : public boost::default_dijkstra_visitor { if (m_dist[u] > m_distance_goal) { throw found_goals(); } - m_nodes.push_back(u); } private: double m_distance_goal; - std::deque &m_nodes; std::vector &m_dist; }; @@ -118,69 +113,55 @@ template class dijkstra_distance_visitor_no_init : public boost::default_dijkstra_visitor { public: explicit dijkstra_distance_visitor_no_init( - std::ostringstream &p_log, - V source, + V root, double distance_goal, std::vector &predecessors, std::vector &distances, std::vector &color_map) : - log(p_log), - first(source), + m_root(root), m_distance_goal(distance_goal), m_num_examined(0), m_predecessors(predecessors), m_dist(distances), m_color(color_map) { - pgassert(m_num_examined == 0); pgassert(m_distance_goal > 0); } template void examine_vertex(V u, B_G &) { - if ( 0 == m_num_examined++) first = u; + if ( 0 == m_num_examined++) m_root = u; if (m_dist[u] > m_distance_goal) { throw found_goals(); } - if (u != first && m_predecessors[u] == u) { + if (u != m_root && m_predecessors[u] == u) { m_color[u] = boost::black_color; } } template void examine_edge(E e, B_G &g) { - if (source(e, g) != first - && m_predecessors[source(e, g)] == source(e, g)) { + if (source(e, g) != m_root && m_predecessors[source(e, g)] == source(e, g)) { m_color[target(e, g)] = boost::black_color; } } - template - void edge_relaxed(E, B_G &) { - } - template void edge_not_relaxed(E e, B_G &g) { - if (source(e, g) != first - && m_predecessors[source(e, g)] == source(e, g)) { + if (source(e, g) != m_root && m_predecessors[source(e, g)] == source(e, g)) { m_color[target(e, g)] = boost::black_color; } } - template - void finish_vertex(V, B_G &) { - } - template void discover_vertex(V u, B_G &) { - if (u != first && m_predecessors[u] == u) { + if (u != m_root && m_predecessors[u] == u) { m_color[u] = boost::black_color; } } private: - std::ostringstream &log; - V first; + V m_root; double m_distance_goal; size_t m_num_examined; std::vector &m_predecessors; diff --git a/src/driving_distance/drivedist_driver.cpp b/src/driving_distance/drivedist_driver.cpp index b9500c4c6f..dfea2383c0 100644 --- a/src/driving_distance/drivedist_driver.cpp +++ b/src/driving_distance/drivedist_driver.cpp @@ -55,6 +55,7 @@ pgr_do_drivingdist( using pgrouting::pgr_alloc; using pgrouting::pgr_msg; using pgrouting::pgr_free; + using pgrouting::algorithm::drivingDistance; std::ostringstream log; std::ostringstream err; @@ -72,18 +73,18 @@ pgr_do_drivingdist( graphType gType = directedFlag? DIRECTED: UNDIRECTED; std::deque paths; - std::vector start_vertices(start_vertex, start_vertex + s_len); + std::set start_vertices(start_vertex, start_vertex + s_len); std::vector> depths; if (directedFlag) { pgrouting::DirectedGraph digraph(gType); digraph.insert_edges(data_edges, total_edges); - paths = pgr_drivingdistance(digraph, start_vertices, distance, equiCostFlag, depths, true); + paths = drivingDistance(digraph, start_vertices, distance, equiCostFlag, depths, true); } else { pgrouting::UndirectedGraph undigraph(gType); undigraph.insert_edges(data_edges, total_edges); - paths = pgr_drivingdistance(undigraph, start_vertices, distance, equiCostFlag, depths, true); + paths = drivingDistance(undigraph, start_vertices, distance, equiCostFlag, depths, true); } size_t count(count_tuples(paths)); diff --git a/src/driving_distance/withPoints_dd_driver.cpp b/src/driving_distance/withPoints_dd_driver.cpp index 3a38abf6cc..bb50bfdb4f 100644 --- a/src/driving_distance/withPoints_dd_driver.cpp +++ b/src/driving_distance/withPoints_dd_driver.cpp @@ -66,6 +66,7 @@ pgr_do_withPointsDD( using pgrouting::pgr_alloc; using pgrouting::pgr_msg; using pgrouting::pgr_free; + using pgrouting::algorithm::drivingDistance; std::ostringstream log; std::ostringstream notice; @@ -99,7 +100,7 @@ pgr_do_withPointsDD( return; } - std::vector start_vids(start_pidsArr, start_pidsArr + s_len); + std::set start_vids(start_pidsArr, start_pidsArr + s_len); graphType gType = directed? DIRECTED: UNDIRECTED; @@ -110,12 +111,12 @@ pgr_do_withPointsDD( pgrouting::DirectedGraph digraph(gType); digraph.insert_edges(edges, total_edges); digraph.insert_edges(pg_graph.new_edges()); - paths = pgr_drivingdistance(digraph, start_vids, distance, equiCost, depths, details); + paths = drivingDistance(digraph, start_vids, distance, equiCost, depths, details); } else { pgrouting::UndirectedGraph undigraph(gType); undigraph.insert_edges(edges, total_edges); undigraph.insert_edges(pg_graph.new_edges()); - paths = pgr_drivingdistance(undigraph, start_vids, distance, equiCost, depths, details); + paths = drivingDistance(undigraph, start_vids, distance, equiCost, depths, details); } if (!details) {