diff --git a/include/drivers/driving_distance/withPoints_dd_driver.h b/include/drivers/driving_distance/withPoints_dd_driver.h index 1f7a35e5ce..961a392075 100644 --- a/include/drivers/driving_distance/withPoints_dd_driver.h +++ b/include/drivers/driving_distance/withPoints_dd_driver.h @@ -40,12 +40,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. using Point_on_edge_t = struct Point_on_edge_t; using Edge_t = struct Edge_t; using Path_rt = struct Path_rt; +using MST_rt = struct MST_rt; #else # include # include typedef struct Point_on_edge_t Point_on_edge_t; typedef struct Edge_t Edge_t; typedef struct Path_rt Path_rt; +typedef struct MST_rt MST_rt; #endif #ifdef __cplusplus @@ -68,7 +70,7 @@ extern "C" { bool, bool, bool, - Path_rt**, size_t*, + MST_rt**, size_t*, char**, char**, char **); diff --git a/include/driving_distance/withPointsDD.hpp b/include/driving_distance/withPointsDD.hpp index 892e841ce6..c6d5298815 100644 --- a/include/driving_distance/withPointsDD.hpp +++ b/include/driving_distance/withPointsDD.hpp @@ -52,34 +52,33 @@ class ShortestPath_tree{ public: - std::deque generate( - G &graph, - std::deque paths, - std::vector start_vids); + std::deque get_depths( + G&, + std::deque, + bool); private: /* Functions */ - void clear() { - m_roots.clear(); - } template std::deque get_results( - T order, - int64_t p_root, - const G &graph); + T, + int64_t, + const G&); - std::deque dfs_order(const G &graph); + std::deque dfs_order( + const G&, + int64_t); - void get_edges_from_paths( - const G& graph, - const std::deque paths); + void get_edges_from_path( + const G&, + const Path); private: /* Member */ - std::vector m_roots; + bool m_details; struct InSpanning { std::set edges; @@ -92,7 +91,7 @@ class ShortestPath_tree{ template template std::deque -ShortestPath_tree::get_results(// TODO: can be simplified +ShortestPath_tree::get_results( T order, int64_t p_root, const G &graph) { @@ -110,6 +109,7 @@ ShortestPath_tree::get_results(// TODO: can be simplified } if (depth[u] == 0 && depth[v] == 0) { + if (graph[u].id != root) std::swap(u, v); if (!p_root && graph[u].id > graph[v].id) std::swap(u, v); root = p_root? p_root: graph[u].id; @@ -122,84 +122,110 @@ ShortestPath_tree::get_results(// TODO: can be simplified 0.0, 0.0 }); } - agg_cost[v] = agg_cost[u] + graph[edge].cost; depth[v] = depth[u] == -1? 1 : depth[u] + 1; - results.push_back({ - root, - 0, - graph[v].id, - graph[edge].id, - graph[edge].cost, - agg_cost[v] - }); + if (!m_details && graph[v].id < 0) depth[v] = depth[u]; + if (m_details || graph[v].id > 0){ + results.push_back({ + root, + depth[v], + graph[v].id, + graph[edge].id, + graph[edge].cost, + agg_cost[v] + }); + } } return results; } template std::deque -ShortestPath_tree::dfs_order(const G &graph) { +ShortestPath_tree::dfs_order(const G &graph, int64_t root) { boost::filtered_graph mstGraph(graph.graph, m_spanning_tree, {}); std::deque results; - for (const auto root : m_roots) { - std::vector visited_order; - - using dfs_visitor = visitors::Dfs_visitor_with_root; - if (graph.has_vertex(root)) { - /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ - CHECK_FOR_INTERRUPTS(); - try { - boost::depth_first_search( - mstGraph, - visitor(dfs_visitor(graph.get_V(root), visited_order)) - .root_vertex(graph.get_V(root))); - } catch(found_goals &) { - {} - } catch (boost::exception const& ex) { - (void)ex; - throw; - } catch (std::exception &e) { - (void)e; - throw; - } catch (...) { - throw; - } - auto result = get_results(visited_order, root, graph); - results.insert(results.end(), result.begin(), result.end()); - } else { - results.push_back({root, 0, root, -1, 0.0, 0.0}); + std::vector visited_order; + + using dfs_visitor = visitors::Dfs_visitor_with_root; + if (graph.has_vertex(root)) { + /* abort in case of an interruption occurs (e.g. the query is being cancelled) */ + CHECK_FOR_INTERRUPTS(); + try { + boost::depth_first_search( + mstGraph, + visitor(dfs_visitor(graph.get_V(root), visited_order)) + .root_vertex(graph.get_V(root))); + } catch(found_goals &) { + {} + } catch (boost::exception const& ex) { + (void)ex; + throw; + } catch (std::exception &e) { + (void)e; + throw; + } catch (...) { + throw; } + auto result = get_results(visited_order, root, graph); + results.insert(results.end(), result.begin(), result.end()); + } else { + results.push_back({root, 0, root, -1, 0.0, 0.0}); } + return results; } template void -ShortestPath_tree::get_edges_from_paths( +ShortestPath_tree::get_edges_from_path( const G& graph, - const std::deque paths){ - - // TODO: - // Extract the corresponding edges from paths and store them in m_spanning_tree + const Path path){ + m_spanning_tree.clear(); + + for (size_t i = 0; i < path.size(); i++){ + auto u = graph.get_V(path[i].node); + + for (size_t j = i+1; j < path.size(); j++){ + auto v = graph.get_V(path[j].node); + double cost = path[j].cost; + auto edge = graph.get_edge(u, v, cost); + if(graph.target(edge) == v + && path[i].agg_cost+cost == path[j].agg_cost + && graph[edge].id == path[j].edge){ + this->m_spanning_tree.edges.insert(edge); + } + } + } } template std::deque -ShortestPath_tree::generate( +ShortestPath_tree::get_depths( G &graph, std::deque paths, - std::vector start_vids) { + bool details) { + m_details = details; + std::deque results; - clear(); - this->m_roots = start_vids; - get_edges_from_paths(graph, paths); + for (const Path& path : paths) { + get_edges_from_path(graph, path); + int64_t root = path.start_id(); + auto result = this->dfs_order(graph, root); - return this->dfs_order(graph); + std::sort(result.begin(), result.end(), + [](const MST_rt &l, const MST_rt &r) + {return l.node < r.node;}); + std::stable_sort(result.begin(), result.end(), + [](const MST_rt &l, const MST_rt &r) + {return l.agg_cost < r.agg_cost;}); + + results.insert(results.end(), result.begin(), result.end()); + } + return results; } diff --git a/sql/driving_distance/_withPointsDD.sql b/sql/driving_distance/_withPointsDD.sql index e0bcab5875..ad78b1e7f3 100644 --- a/sql/driving_distance/_withPointsDD.sql +++ b/sql/driving_distance/_withPointsDD.sql @@ -47,6 +47,7 @@ CREATE FUNCTION _pgr_v4withPointsDD( equicost BOOLEAN DEFAULT false, OUT seq INTEGER, + OUT depth BIGINT, OUT start_vid BIGINT, OUT node BIGINT, OUT edge BIGINT, diff --git a/sql/driving_distance/withPointsDD.sql b/sql/driving_distance/withPointsDD.sql index 3d9a2a56bc..720e9a1616 100644 --- a/sql/driving_distance/withPointsDD.sql +++ b/sql/driving_distance/withPointsDD.sql @@ -40,6 +40,7 @@ CREATE FUNCTION pgr_withPointsDD( details BOOLEAN DEFAULT false, OUT seq INTEGER, + OUT depth BIGINT, OUT start_vid BIGINT, OUT node BIGINT, OUT edge BIGINT, @@ -68,6 +69,7 @@ CREATE FUNCTION pgr_withPointsDD( equicost BOOLEAN DEFAULT false, OUT seq INTEGER, + OUT depth BIGINT, OUT start_vid BIGINT, OUT node BIGINT, OUT edge BIGINT, @@ -140,6 +142,7 @@ RETURNS SETOF RECORD AS $BODY$ BEGIN RAISE WARNING 'pgr_withpointsdd(text,text,bigint,double precision,boolean,character,boolean) is been deprecated'; + RETURN QUERY SELECT seq, node, edge, cost, agg_cost FROM _pgr_withPointsDD(_pgr_get_statement($1), _pgr_get_statement($2), ARRAY[$3]::BIGINT[], $4, $5, $6, $7, false); END; @@ -171,6 +174,7 @@ RETURNS SETOF RECORD AS $BODY$ BEGIN RAISE WARNING 'pgr_withpointsdd(text,text,anyarray,double precision,boolean,character,boolean,boolean) is been deprecated'; + RETURN QUERY SELECT * FROM _pgr_withPointsDD(_pgr_get_statement($1), _pgr_get_statement($2), $3, $4, $5, $6, $7, $8); END; diff --git a/src/driving_distance/v4withPointsDD.c b/src/driving_distance/v4withPointsDD.c index 9b3087ec99..6e19e98942 100644 --- a/src/driving_distance/v4withPointsDD.c +++ b/src/driving_distance/v4withPointsDD.c @@ -32,12 +32,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include #include "c_common/postgres_connection.h" -#include "c_types/path_rt.h" #include "c_common/debug_macro.h" #include "c_common/e_report.h" #include "c_common/time_msg.h" - #include "c_common/pgdata_getters.h" +#include "c_types/mst_rt.h" #include "drivers/withPoints/get_new_queries.h" #include "drivers/driving_distance/withPoints_dd_driver.h" @@ -58,9 +57,8 @@ void process( bool details, bool equicost, - Path_rt **result_tuples, + MST_rt **result_tuples, size_t *result_count) { - pgr_SPI_connect(); char* log_msg = NULL; char* notice_msg = NULL; @@ -154,10 +152,10 @@ void process( PGDLLEXPORT Datum _pgr_v4withpointsdd(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; - TupleDesc tuple_desc; + TupleDesc tuple_desc; /**********************************************************************/ - Path_rt *result_tuples = 0; + MST_rt *result_tuples = NULL; size_t result_count = 0; /**********************************************************************/ @@ -181,7 +179,7 @@ _pgr_v4withpointsdd(PG_FUNCTION_ARGS) { // equicost BOOLEAN -- DEFAULT false, - PGR_DBG("Calling driving_many_to_dist_driver"); + PGR_DBG("Calling withPoints_dd_driver"); process( text_to_cstring(PG_GETARG_TEXT_P(0)), text_to_cstring(PG_GETARG_TEXT_P(1)), @@ -214,16 +212,16 @@ _pgr_v4withpointsdd(PG_FUNCTION_ARGS) { funcctx = SRF_PERCALL_SETUP(); tuple_desc = funcctx->tuple_desc; - result_tuples = (Path_rt*) funcctx->user_fctx; + result_tuples = (MST_rt*) funcctx->user_fctx; if (funcctx->call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; - Datum *values; - bool* nulls; + Datum *values; + bool* nulls; /**********************************************************************/ - size_t numb = 6; + size_t numb = 7; values = palloc(numb * sizeof(Datum)); nulls = palloc(numb * sizeof(bool)); @@ -233,11 +231,12 @@ _pgr_v4withpointsdd(PG_FUNCTION_ARGS) { } values[0] = Int32GetDatum(funcctx->call_cntr + 1); - values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].start_id); - values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].node); - values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge); - values[4] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost); - values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost); + values[1] = Int64GetDatum(result_tuples[funcctx->call_cntr].depth); + values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].from_v); + values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].node); + values[4] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge); + values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost); + values[6] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost); /**********************************************************************/ diff --git a/src/driving_distance/v4withPoints_dd_driver.cpp b/src/driving_distance/v4withPoints_dd_driver.cpp index 44e98ec42a..d6581a8257 100644 --- a/src/driving_distance/v4withPoints_dd_driver.cpp +++ b/src/driving_distance/v4withPoints_dd_driver.cpp @@ -39,28 +39,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "dijkstra/drivingDist.hpp" #include "withPoints/pgr_withPoints.hpp" - - +#include "driving_distance/withPointsDD.hpp" +#include "c_types/mst_rt.h" #include "cpp_common/pgr_alloc.hpp" char -estimate_drivingSide_dd(char driving_side, bool directed, char** err_msg){ +estimate_drivingSide_dd(char driving_side, bool directed, char** err_msg) { using pgrouting::pgr_msg; try { char d_side = static_cast(tolower(driving_side)); if (strchr("rlb", d_side) == NULL) { throw std::string("Invalid driving side specified!"); - } - else if (directed && d_side == 'b') { + } else if (directed && d_side == 'b') { throw std::string("Cannot use 'b' driving side with directed graph!"); - } - else{ + } else { return d_side; } } catch (const std::string &ex) { *err_msg = pgr_msg(ex.c_str()); - return '\0'; // Or some other appropriate default value + return '\0'; } catch(...) { *err_msg = pgr_msg("Caught unknown exception!"); return '\0'; @@ -68,9 +66,6 @@ estimate_drivingSide_dd(char driving_side, bool directed, char** err_msg){ } - - - /**********************************************************************/ // CREATE OR REPLACE FUNCTION pgr_withPointsDD( // edges_sql TEXT, @@ -98,7 +93,7 @@ do_withPointsDD( bool details, bool equiCost, - Path_rt **return_tuples, size_t *return_count, + MST_rt **return_tuples, size_t *return_count, char** log_msg, char** notice_msg, char** err_msg) { @@ -152,14 +147,18 @@ do_withPointsDD( graphType gType = directed? DIRECTED: UNDIRECTED; - std::deque< Path >paths; + std::deque paths; + std::deque results; if (directed) { 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, log); + pgrouting::functions::ShortestPath_tree spt; + results = spt.get_depths(digraph, paths, details); } else { pgrouting::UndirectedGraph undigraph(gType); undigraph.insert_edges(edges, total_edges); @@ -167,25 +166,12 @@ do_withPointsDD( paths = pgr_drivingDistance( undigraph, start_vids, distance, equiCost, log); - } - for (auto &path : paths) { - log << path; - - if (!details) { - pg_graph.eliminate_details_dd(path); - } - log << path; - 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;}); - log << path; + pgrouting::functions::ShortestPath_tree spt; + results = spt.get_depths(undigraph, paths, details); } - size_t count(count_tuples(paths)); + size_t count(results.size()); if (count == 0) { @@ -193,7 +179,11 @@ do_withPointsDD( return; } *return_tuples = pgr_alloc(count, (*return_tuples)); - *return_count = collapse_paths(return_tuples, paths); + for (size_t i = 0; i < count; i++) { + *((*return_tuples) + i) = results[i]; + } + (*return_count) = count; + *log_msg = log.str().empty()? *log_msg : pgr_msg(log.str().c_str());