Refactor segregated intersection classification to right module
This commit is contained in:
parent
353829a4cc
commit
25ee26de3b
@ -47,7 +47,6 @@ namespace extractor
|
|||||||
|
|
||||||
class ScriptingEnvironment;
|
class ScriptingEnvironment;
|
||||||
struct ProfileProperties;
|
struct ProfileProperties;
|
||||||
class NodeBasedGraphFactory;
|
|
||||||
|
|
||||||
class Extractor
|
class Extractor
|
||||||
{
|
{
|
||||||
@ -102,13 +101,6 @@ class Extractor
|
|||||||
void WriteConditionalRestrictions(
|
void WriteConditionalRestrictions(
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||||
|
|
||||||
// Find all "segregated" edges, e.g. edges that can be skipped in turn instructions.
|
|
||||||
// The main cases are:
|
|
||||||
// - middle edges between two osm ways in one logic road (U-turn)
|
|
||||||
// - staggered intersections (X-cross)
|
|
||||||
// - square/circle intersections
|
|
||||||
std::unordered_set<EdgeID> FindSegregatedNodes(NodeBasedGraphFactory &factory);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
class NameTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
class NodeBasedGraphFactory;
|
||||||
|
|
||||||
|
namespace guidance
|
||||||
|
{
|
||||||
|
// Find all "segregated" edges, e.g. edges that can be skipped in turn instructions.
|
||||||
|
// The main cases are:
|
||||||
|
// - middle edges between two osm ways in one logic road (U-turn)
|
||||||
|
// - staggered intersections (X-cross)
|
||||||
|
// - square/circle intersections
|
||||||
|
std::unordered_set<EdgeID> findSegregatedNodes(NodeBasedGraphFactory &factory, const util::NameTable& names);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,8 @@
|
|||||||
#include "extractor/restriction_parser.hpp"
|
#include "extractor/restriction_parser.hpp"
|
||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
|
#include "extractor/guidance/segregated_intersection_classification.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
@ -220,7 +222,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
util::Log() << "Find segregated edges in node-based graph ..." << std::flush;
|
util::Log() << "Find segregated edges in node-based graph ..." << std::flush;
|
||||||
TIMER_START(segregated);
|
TIMER_START(segregated);
|
||||||
|
|
||||||
auto segregated_edges = FindSegregatedNodes(node_based_graph_factory);
|
util::NameTable names(config.GetPath(".osrm.names").string());
|
||||||
|
auto segregated_edges = guidance::findSegregatedNodes(node_based_graph_factory, names);
|
||||||
|
|
||||||
TIMER_STOP(segregated);
|
TIMER_STOP(segregated);
|
||||||
util::Log() << "ok, after " << TIMER_SEC(segregated) << "s";
|
util::Log() << "ok, after " << TIMER_SEC(segregated) << "s";
|
||||||
@ -838,232 +841,7 @@ void Extractor::WriteCompressedNodeBasedGraph(const std::string &path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EdgeInfo
|
|
||||||
{
|
|
||||||
NodeID node;
|
|
||||||
|
|
||||||
util::StringView name;
|
|
||||||
|
|
||||||
// 0 - outgoing (forward), 1 - incoming (reverse), 2 - both outgoing and incoming
|
|
||||||
int direction;
|
|
||||||
|
|
||||||
ClassData road_class;
|
|
||||||
|
|
||||||
guidance::RoadPriorityClass::Enum road_priority_class;
|
|
||||||
|
|
||||||
struct LessName
|
|
||||||
{
|
|
||||||
bool operator()(EdgeInfo const &e1, EdgeInfo const &e2) const { return e1.name < e2.name; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
bool IsSegregated(std::vector<EdgeInfo> v1,
|
|
||||||
std::vector<EdgeInfo> v2,
|
|
||||||
EdgeInfo const ¤t,
|
|
||||||
double edgeLength)
|
|
||||||
{
|
|
||||||
if (v1.size() < 2 || v2.size() < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto const sort_by_name_fn = [](std::vector<EdgeInfo> &v) {
|
|
||||||
std::sort(v.begin(), v.end(), EdgeInfo::LessName());
|
|
||||||
};
|
|
||||||
|
|
||||||
sort_by_name_fn(v1);
|
|
||||||
sort_by_name_fn(v2);
|
|
||||||
|
|
||||||
// Internal edge with the name should be connected with any other neibour edge with the same
|
|
||||||
// name, e.g. isolated edge with unique name is not segregated.
|
|
||||||
// b - 'b' road continues here
|
|
||||||
// |
|
|
||||||
// - - a - |
|
|
||||||
// b - segregated edge
|
|
||||||
// - - a - |
|
|
||||||
if (!current.name.empty())
|
|
||||||
{
|
|
||||||
auto const findNameFn = [¤t](std::vector<EdgeInfo> const &v) {
|
|
||||||
return std::binary_search(v.begin(), v.end(), current, EdgeInfo::LessName());
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!findNameFn(v1) && !findNameFn(v2))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set_intersection like routine to get equal result pairs
|
|
||||||
std::vector<std::pair<EdgeInfo const *, EdgeInfo const *>> commons;
|
|
||||||
|
|
||||||
auto i1 = v1.begin();
|
|
||||||
auto i2 = v2.begin();
|
|
||||||
|
|
||||||
while (i1 != v1.end() && i2 != v2.end())
|
|
||||||
{
|
|
||||||
if (i1->name == i2->name)
|
|
||||||
{
|
|
||||||
if (!i1->name.empty())
|
|
||||||
commons.push_back(std::make_pair(&(*i1), &(*i2)));
|
|
||||||
|
|
||||||
++i1;
|
|
||||||
++i2;
|
|
||||||
}
|
|
||||||
else if (i1->name < i2->name)
|
|
||||||
++i1;
|
|
||||||
else
|
|
||||||
++i2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commons.size() < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto const check_equal_class = [](std::pair<EdgeInfo const *, EdgeInfo const *> const &e) {
|
|
||||||
// Or (e.first->road_class & e.second->road_class != 0)
|
|
||||||
return e.first->road_class == e.second->road_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t equal_class_count = 0;
|
|
||||||
for (auto const &e : commons)
|
|
||||||
if (check_equal_class(e))
|
|
||||||
++equal_class_count;
|
|
||||||
|
|
||||||
if (equal_class_count < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto const get_length_threshold = [](EdgeInfo const *e) {
|
|
||||||
switch (e->road_priority_class)
|
|
||||||
{
|
|
||||||
case guidance::RoadPriorityClass::MOTORWAY:
|
|
||||||
case guidance::RoadPriorityClass::TRUNK:
|
|
||||||
return 30.0;
|
|
||||||
case guidance::RoadPriorityClass::PRIMARY:
|
|
||||||
return 20.0;
|
|
||||||
case guidance::RoadPriorityClass::SECONDARY:
|
|
||||||
case guidance::RoadPriorityClass::TERTIARY:
|
|
||||||
return 10.0;
|
|
||||||
default:
|
|
||||||
return 5.0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
double threshold = std::numeric_limits<double>::max();
|
|
||||||
for (auto const &e : commons)
|
|
||||||
threshold =
|
|
||||||
std::min(threshold, get_length_threshold(e.first) + get_length_threshold(e.second));
|
|
||||||
|
|
||||||
return edgeLength <= threshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unordered_set<EdgeID> Extractor::FindSegregatedNodes(NodeBasedGraphFactory &factory)
|
|
||||||
{
|
|
||||||
util::NameTable names(config.GetPath(".osrm.names").string());
|
|
||||||
|
|
||||||
auto const &graph = factory.GetGraph();
|
|
||||||
auto const &annotation = factory.GetAnnotationData();
|
|
||||||
|
|
||||||
guidance::CoordinateExtractor coordExtractor(
|
|
||||||
graph, factory.GetCompressedEdges(), factory.GetCoordinates());
|
|
||||||
|
|
||||||
auto const get_edge_length = [&](NodeID from_node, EdgeID edgeID, NodeID to_node) {
|
|
||||||
auto const geom = coordExtractor.GetCoordinatesAlongRoad(from_node, edgeID, false, to_node);
|
|
||||||
double length = 0.0;
|
|
||||||
for (size_t i = 1; i < geom.size(); ++i)
|
|
||||||
{
|
|
||||||
length += osrm::util::coordinate_calculation::haversineDistance(geom[i - 1], geom[i]);
|
|
||||||
}
|
|
||||||
return length;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const get_edge_info = [&](NodeID node, auto const &edgeData) -> EdgeInfo {
|
|
||||||
/// @todo Make string normalization/lowercase/trim for comparison ...
|
|
||||||
|
|
||||||
auto const id = annotation[edgeData.annotation_data].name_id;
|
|
||||||
BOOST_ASSERT(id != INVALID_NAMEID);
|
|
||||||
auto const name = names.GetNameForID(id);
|
|
||||||
|
|
||||||
return {node,
|
|
||||||
name,
|
|
||||||
edgeData.reversed ? 1 : 0,
|
|
||||||
annotation[edgeData.annotation_data].classes,
|
|
||||||
edgeData.flags.road_classification.GetClass()};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const collect_edge_info_fn = [&](auto const &edges1, NodeID node2) {
|
|
||||||
std::vector<EdgeInfo> info;
|
|
||||||
|
|
||||||
for (auto const &e : edges1)
|
|
||||||
{
|
|
||||||
NodeID const target = graph.GetTarget(e);
|
|
||||||
if (target == node2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
info.push_back(get_edge_info(target, graph.GetEdgeData(e)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.empty())
|
|
||||||
return info;
|
|
||||||
|
|
||||||
std::sort(info.begin(), info.end(), [](EdgeInfo const &e1, EdgeInfo const &e2) {
|
|
||||||
return e1.node < e2.node;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Merge equal infos with correct direction.
|
|
||||||
auto curr = info.begin();
|
|
||||||
auto next = curr;
|
|
||||||
while (++next != info.end())
|
|
||||||
{
|
|
||||||
if (curr->node == next->node)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(curr->name == next->name);
|
|
||||||
BOOST_ASSERT(curr->road_class == next->road_class);
|
|
||||||
BOOST_ASSERT(curr->direction != next->direction);
|
|
||||||
curr->direction = 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
curr = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.erase(
|
|
||||||
std::unique(info.begin(),
|
|
||||||
info.end(),
|
|
||||||
[](EdgeInfo const &e1, EdgeInfo const &e2) { return e1.node == e2.node; }),
|
|
||||||
info.end());
|
|
||||||
|
|
||||||
return info;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto const isSegregatedFn = [&](auto const &edgeData,
|
|
||||||
auto const &edges1,
|
|
||||||
NodeID node1,
|
|
||||||
auto const &edges2,
|
|
||||||
NodeID node2,
|
|
||||||
double edgeLength) {
|
|
||||||
return IsSegregated(collect_edge_info_fn(edges1, node2),
|
|
||||||
collect_edge_info_fn(edges2, node1),
|
|
||||||
get_edge_info(node1, edgeData),
|
|
||||||
edgeLength);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::unordered_set<EdgeID> segregated_edges;
|
|
||||||
|
|
||||||
for (NodeID sourceID = 0; sourceID < graph.GetNumberOfNodes(); ++sourceID)
|
|
||||||
{
|
|
||||||
auto const sourceEdges = graph.GetAdjacentEdgeRange(sourceID);
|
|
||||||
for (EdgeID edgeID : sourceEdges)
|
|
||||||
{
|
|
||||||
auto const &edgeData = graph.GetEdgeData(edgeID);
|
|
||||||
|
|
||||||
if (edgeData.reversed)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
NodeID const targetID = graph.GetTarget(edgeID);
|
|
||||||
auto const targetEdges = graph.GetAdjacentEdgeRange(targetID);
|
|
||||||
|
|
||||||
double const length = get_edge_length(sourceID, edgeID, targetID);
|
|
||||||
if (isSegregatedFn(edgeData, sourceEdges, sourceID, targetEdges, targetID, length))
|
|
||||||
segregated_edges.insert(edgeID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return segregated_edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -0,0 +1,244 @@
|
|||||||
|
#include "extractor/guidance/segregated_intersection_classification.hpp"
|
||||||
|
#include "extractor/guidance/coordinate_extractor.hpp"
|
||||||
|
#include "extractor/node_based_graph_factory.hpp"
|
||||||
|
|
||||||
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
#include "util/name_table.hpp"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
namespace guidance
|
||||||
|
{
|
||||||
|
|
||||||
|
struct EdgeInfo
|
||||||
|
{
|
||||||
|
NodeID node;
|
||||||
|
|
||||||
|
util::StringView name;
|
||||||
|
|
||||||
|
// 0 - outgoing (forward), 1 - incoming (reverse), 2 - both outgoing and incoming
|
||||||
|
int direction;
|
||||||
|
|
||||||
|
ClassData road_class;
|
||||||
|
|
||||||
|
RoadPriorityClass::Enum road_priority_class;
|
||||||
|
|
||||||
|
struct LessName
|
||||||
|
{
|
||||||
|
bool operator()(EdgeInfo const &e1, EdgeInfo const &e2) const { return e1.name < e2.name; }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IsSegregated(std::vector<EdgeInfo> v1,
|
||||||
|
std::vector<EdgeInfo> v2,
|
||||||
|
EdgeInfo const ¤t,
|
||||||
|
double edgeLength)
|
||||||
|
{
|
||||||
|
if (v1.size() < 2 || v2.size() < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const sort_by_name_fn = [](std::vector<EdgeInfo> &v) {
|
||||||
|
std::sort(v.begin(), v.end(), EdgeInfo::LessName());
|
||||||
|
};
|
||||||
|
|
||||||
|
sort_by_name_fn(v1);
|
||||||
|
sort_by_name_fn(v2);
|
||||||
|
|
||||||
|
// Internal edge with the name should be connected with any other neibour edge with the same
|
||||||
|
// name, e.g. isolated edge with unique name is not segregated.
|
||||||
|
// b - 'b' road continues here
|
||||||
|
// |
|
||||||
|
// - - a - |
|
||||||
|
// b - segregated edge
|
||||||
|
// - - a - |
|
||||||
|
if (!current.name.empty())
|
||||||
|
{
|
||||||
|
auto const findNameFn = [¤t](std::vector<EdgeInfo> const &v) {
|
||||||
|
return std::binary_search(v.begin(), v.end(), current, EdgeInfo::LessName());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!findNameFn(v1) && !findNameFn(v2))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_intersection like routine to get equal result pairs
|
||||||
|
std::vector<std::pair<EdgeInfo const *, EdgeInfo const *>> commons;
|
||||||
|
|
||||||
|
auto i1 = v1.begin();
|
||||||
|
auto i2 = v2.begin();
|
||||||
|
|
||||||
|
while (i1 != v1.end() && i2 != v2.end())
|
||||||
|
{
|
||||||
|
if (i1->name == i2->name)
|
||||||
|
{
|
||||||
|
if (!i1->name.empty())
|
||||||
|
commons.push_back(std::make_pair(&(*i1), &(*i2)));
|
||||||
|
|
||||||
|
++i1;
|
||||||
|
++i2;
|
||||||
|
}
|
||||||
|
else if (i1->name < i2->name)
|
||||||
|
++i1;
|
||||||
|
else
|
||||||
|
++i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commons.size() < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const check_equal_class = [](std::pair<EdgeInfo const *, EdgeInfo const *> const &e) {
|
||||||
|
// Or (e.first->road_class & e.second->road_class != 0)
|
||||||
|
return e.first->road_class == e.second->road_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t equal_class_count = 0;
|
||||||
|
for (auto const &e : commons)
|
||||||
|
if (check_equal_class(e))
|
||||||
|
++equal_class_count;
|
||||||
|
|
||||||
|
if (equal_class_count < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const get_length_threshold = [](EdgeInfo const *e) {
|
||||||
|
switch (e->road_priority_class)
|
||||||
|
{
|
||||||
|
case RoadPriorityClass::MOTORWAY:
|
||||||
|
case RoadPriorityClass::TRUNK:
|
||||||
|
return 30.0;
|
||||||
|
case RoadPriorityClass::PRIMARY:
|
||||||
|
return 20.0;
|
||||||
|
case RoadPriorityClass::SECONDARY:
|
||||||
|
case RoadPriorityClass::TERTIARY:
|
||||||
|
return 10.0;
|
||||||
|
default:
|
||||||
|
return 5.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
double threshold = std::numeric_limits<double>::max();
|
||||||
|
for (auto const &e : commons)
|
||||||
|
threshold =
|
||||||
|
std::min(threshold, get_length_threshold(e.first) + get_length_threshold(e.second));
|
||||||
|
|
||||||
|
return edgeLength <= threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<EdgeID> findSegregatedNodes(NodeBasedGraphFactory &factory,
|
||||||
|
const util::NameTable &names)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto const &graph = factory.GetGraph();
|
||||||
|
auto const &annotation = factory.GetAnnotationData();
|
||||||
|
|
||||||
|
CoordinateExtractor coordExtractor(
|
||||||
|
graph, factory.GetCompressedEdges(), factory.GetCoordinates());
|
||||||
|
|
||||||
|
auto const get_edge_length = [&](NodeID from_node, EdgeID edgeID, NodeID to_node) {
|
||||||
|
auto const geom = coordExtractor.GetCoordinatesAlongRoad(from_node, edgeID, false, to_node);
|
||||||
|
double length = 0.0;
|
||||||
|
for (size_t i = 1; i < geom.size(); ++i)
|
||||||
|
{
|
||||||
|
length += util::coordinate_calculation::haversineDistance(geom[i - 1], geom[i]);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const get_edge_info = [&](NodeID node, auto const &edgeData) -> EdgeInfo {
|
||||||
|
/// @todo Make string normalization/lowercase/trim for comparison ...
|
||||||
|
|
||||||
|
auto const id = annotation[edgeData.annotation_data].name_id;
|
||||||
|
BOOST_ASSERT(id != INVALID_NAMEID);
|
||||||
|
auto const name = names.GetNameForID(id);
|
||||||
|
|
||||||
|
return {node,
|
||||||
|
name,
|
||||||
|
edgeData.reversed ? 1 : 0,
|
||||||
|
annotation[edgeData.annotation_data].classes,
|
||||||
|
edgeData.flags.road_classification.GetClass()};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const collect_edge_info_fn = [&](auto const &edges1, NodeID node2) {
|
||||||
|
std::vector<EdgeInfo> info;
|
||||||
|
|
||||||
|
for (auto const &e : edges1)
|
||||||
|
{
|
||||||
|
NodeID const target = graph.GetTarget(e);
|
||||||
|
if (target == node2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
info.push_back(get_edge_info(target, graph.GetEdgeData(e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.empty())
|
||||||
|
return info;
|
||||||
|
|
||||||
|
std::sort(info.begin(), info.end(), [](EdgeInfo const &e1, EdgeInfo const &e2) {
|
||||||
|
return e1.node < e2.node;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Merge equal infos with correct direction.
|
||||||
|
auto curr = info.begin();
|
||||||
|
auto next = curr;
|
||||||
|
while (++next != info.end())
|
||||||
|
{
|
||||||
|
if (curr->node == next->node)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(curr->name == next->name);
|
||||||
|
BOOST_ASSERT(curr->road_class == next->road_class);
|
||||||
|
BOOST_ASSERT(curr->direction != next->direction);
|
||||||
|
curr->direction = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
curr = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.erase(
|
||||||
|
std::unique(info.begin(),
|
||||||
|
info.end(),
|
||||||
|
[](EdgeInfo const &e1, EdgeInfo const &e2) { return e1.node == e2.node; }),
|
||||||
|
info.end());
|
||||||
|
|
||||||
|
return info;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const isSegregatedFn = [&](auto const &edgeData,
|
||||||
|
auto const &edges1,
|
||||||
|
NodeID node1,
|
||||||
|
auto const &edges2,
|
||||||
|
NodeID node2,
|
||||||
|
double edgeLength) {
|
||||||
|
return IsSegregated(collect_edge_info_fn(edges1, node2),
|
||||||
|
collect_edge_info_fn(edges2, node1),
|
||||||
|
get_edge_info(node1, edgeData),
|
||||||
|
edgeLength);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_set<EdgeID> segregated_edges;
|
||||||
|
|
||||||
|
for (NodeID sourceID = 0; sourceID < graph.GetNumberOfNodes(); ++sourceID)
|
||||||
|
{
|
||||||
|
auto const sourceEdges = graph.GetAdjacentEdgeRange(sourceID);
|
||||||
|
for (EdgeID edgeID : sourceEdges)
|
||||||
|
{
|
||||||
|
auto const &edgeData = graph.GetEdgeData(edgeID);
|
||||||
|
|
||||||
|
if (edgeData.reversed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NodeID const targetID = graph.GetTarget(edgeID);
|
||||||
|
auto const targetEdges = graph.GetAdjacentEdgeRange(targetID);
|
||||||
|
|
||||||
|
double const length = get_edge_length(sourceID, edgeID, targetID);
|
||||||
|
if (isSegregatedFn(edgeData, sourceEdges, sourceID, targetEdges, targetID, length))
|
||||||
|
segregated_edges.insert(edgeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return segregated_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user