clean up and refactor half-baked development commits and squash them into a new version.
Changes: * support for multiple GTFS feeds as input in filtering, read default global and local configuration files * be a bit more memory conservative * make caching optional * dont delete orphan edge if it would transform a degree 3 node with a possible full turn into a degree 2 node eligible for contraction * dedicated filters for funicular and gondola * make max snap level option more intuitive * allow filter rules for level 0 * additional fallback for station snapping * dont try to route for MOT unequal to trip in -T mode, force-snap to orphaned OSM station if not snap was possible * write bounds to filtered osm * remove unused surrounding heuristic * use bus lanes info * be a bit more tolerant for bus oneway streets * create missing directories * error if no cfg is present, clean up evaluation Makefile
This commit is contained in:
parent
2cc2d2dc23
commit
63f0b61ea1
60 changed files with 4532 additions and 1576 deletions
|
|
@ -37,6 +37,31 @@ BOX BBoxIdx::getFullWebMercBox() const {
|
|||
_root.box.getUpperRight().getY(), _root.box.getUpperRight().getX()));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
BOX BBoxIdx::getFullBox() const { return _root.box; }
|
||||
|
||||
// _____________________________________________________________________________
|
||||
std::vector<util::geo::Box<double>> BBoxIdx::getLeafs() const {
|
||||
std::vector<util::geo::Box<double>> ret;
|
||||
getLeafsRec(_root, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void BBoxIdx::getLeafsRec(const BBoxIdxNd& nd,
|
||||
std::vector<util::geo::Box<double>>* ret) const {
|
||||
if (!nd.childs.size()) {
|
||||
ret->push_back(nd.box);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& child : nd.childs) {
|
||||
getLeafsRec(child, ret);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
bool BBoxIdx::treeHas(const Point<double>& p, const BBoxIdxNd& nd) const {
|
||||
if (!nd.childs.size()) return util::geo::contains(p, nd.box);
|
||||
|
|
|
|||
|
|
@ -38,9 +38,15 @@ class BBoxIdx {
|
|||
// Return the full total bounding box of this index
|
||||
BOX getFullWebMercBox() const;
|
||||
|
||||
// Return the full total bounding box of this index
|
||||
BOX getFullBox() const;
|
||||
|
||||
// Return the size of this index
|
||||
size_t size() const;
|
||||
|
||||
// return the leaf bounding boxes of this idx
|
||||
std::vector<Box<double>> getLeafs() const;
|
||||
|
||||
private:
|
||||
double _padding;
|
||||
size_t _size;
|
||||
|
|
@ -50,6 +56,9 @@ class BBoxIdx {
|
|||
void addToTree(const Box<double>& box, BBoxIdxNd* nd, size_t lvl);
|
||||
bool treeHas(const Point<double>& p, const BBoxIdxNd& nd) const;
|
||||
|
||||
void getLeafsRec(const BBoxIdxNd& nd,
|
||||
std::vector<util::geo::Box<double>>* ret) const;
|
||||
|
||||
static const size_t MAX_LVL = 5;
|
||||
static constexpr double MIN_COM_AREA = 0.0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,8 +43,20 @@ using pfaedle::osm::OsmRel;
|
|||
using pfaedle::osm::OsmNode;
|
||||
using pfaedle::osm::EdgeGrid;
|
||||
using pfaedle::osm::NodeGrid;
|
||||
using pfaedle::osm::EqSearch;
|
||||
using pfaedle::osm::BlockSearch;
|
||||
using ad::cppgtfs::gtfs::Stop;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
bool EqSearch::operator()(const Node* cand, const StatInfo* si) const {
|
||||
if (orphanSnap && cand->pl().getSI() &&
|
||||
(!cand->pl().getSI()->getGroup() ||
|
||||
cand->pl().getSI()->getGroup()->getStops().size() == 0)) {
|
||||
return true;
|
||||
}
|
||||
return cand->pl().getSI() && cand->pl().getSI()->simi(si) > minSimi;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
OsmBuilder::OsmBuilder() {}
|
||||
|
||||
|
|
@ -140,7 +152,8 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
POINT geom = *s->pl().getGeom();
|
||||
NodePL pl = s->pl();
|
||||
pl.getSI()->setIsFromOsm(false);
|
||||
const auto& r = snapStation(g, &pl, &eg, &sng, opts, res, false, d);
|
||||
const auto& r =
|
||||
snapStation(g, &pl, &eg, &sng, opts, res, false, false, d);
|
||||
groupStats(r);
|
||||
for (auto n : r) {
|
||||
// if the snapped station is very near to the original OSM
|
||||
|
|
@ -153,32 +166,70 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<const Stop*> notSnapped;
|
||||
|
||||
for (size_t i = 0; i < opts.maxSnapDistances.size(); i++) {
|
||||
double d = opts.maxSnapDistances[i];
|
||||
for (auto& s : *fs) {
|
||||
auto pl = plFromGtfs(s.first, opts);
|
||||
|
||||
StatGroup* group =
|
||||
groupStats(snapStation(g, &pl, &eg, &sng, opts, res,
|
||||
i == opts.maxSnapDistances.size() - 1, d));
|
||||
StatGroup* group = groupStats(
|
||||
snapStation(g, &pl, &eg, &sng, opts, res,
|
||||
i == opts.maxSnapDistances.size() - 1, false, d));
|
||||
|
||||
if (group) {
|
||||
group->addStop(s.first);
|
||||
(*fs)[s.first] = *group->getNodes().begin();
|
||||
} else if (i == opts.maxSnapDistances.size() - 1) {
|
||||
LOG(VDEBUG) << "Could not snap station "
|
||||
<< "(" << pl.getSI()->getName() << ")"
|
||||
<< " (" << s.first->getLat() << "," << s.first->getLng()
|
||||
<< ") in normal run, trying again later in orphan mode.";
|
||||
notSnapped.push_back(s.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (notSnapped.size())
|
||||
LOG(VDEBUG) << notSnapped.size() << " stations could not be snapped in "
|
||||
"normal run, trying again in orphan "
|
||||
"mode.";
|
||||
|
||||
// try again, but aggressively snap to orphan OSM stations which have
|
||||
// not been assigned to any GTFS stop yet
|
||||
for (size_t i = 0; i < opts.maxSnapDistances.size(); i++) {
|
||||
double d = opts.maxSnapDistances[i];
|
||||
for (auto& s : notSnapped) {
|
||||
auto pl = plFromGtfs(s, opts);
|
||||
|
||||
StatGroup* group = groupStats(
|
||||
snapStation(g, &pl, &eg, &sng, opts, res,
|
||||
i == opts.maxSnapDistances.size() - 1, true, d));
|
||||
|
||||
if (group) {
|
||||
group->addStop(s);
|
||||
// add the added station name as an alt name to ensure future
|
||||
// similarity
|
||||
for (auto n : group->getNodes()) {
|
||||
if (n->pl().getSI())
|
||||
n->pl().getSI()->addAltName(pl.getSI()->getName());
|
||||
}
|
||||
(*fs)[s] = *group->getNodes().begin();
|
||||
} else if (i ==
|
||||
opts.maxSnapDistances.size() - 1) { // only fail on last
|
||||
// finally give up
|
||||
|
||||
// add a group with only this stop in it
|
||||
StatGroup* dummyGroup = new StatGroup();
|
||||
Node* dummyNode = g->addNd(pl);
|
||||
|
||||
dummyNode->pl().getSI()->setGroup(dummyGroup);
|
||||
dummyGroup->addNode(dummyNode);
|
||||
dummyGroup->addStop(s.first);
|
||||
(*fs)[s.first] = dummyNode;
|
||||
dummyGroup->addStop(s);
|
||||
(*fs)[s] = dummyNode;
|
||||
LOG(WARN) << "Could not snap station "
|
||||
<< "(" << pl.getSI()->getName() << ")"
|
||||
<< " (" << s.first->getLat() << "," << s.first->getLng()
|
||||
<< ")";
|
||||
<< " (" << s->getLat() << "," << s->getLng() << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,7 +239,7 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
deleteOrphNds(g);
|
||||
|
||||
LOG(VDEBUG) << "Deleting orphan edges...";
|
||||
deleteOrphEdgs(g);
|
||||
deleteOrphEdgs(g, opts);
|
||||
|
||||
LOG(VDEBUG) << "Collapsing edges...";
|
||||
collapseEdges(g);
|
||||
|
|
@ -197,7 +248,7 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
deleteOrphNds(g);
|
||||
|
||||
LOG(VDEBUG) << "Deleting orphan edges...";
|
||||
deleteOrphEdgs(g);
|
||||
deleteOrphEdgs(g, opts);
|
||||
|
||||
LOG(VDEBUG) << "Writing graph components...";
|
||||
// the restrictor is needed here to prevent connections in the graph
|
||||
|
|
@ -223,6 +274,89 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
<< " edges and " << comps << " connected component(s)";
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void OsmBuilder::overpassQryWrite(std::ostream* out,
|
||||
const std::vector<OsmReadOpts>& opts,
|
||||
const BBoxIdx& latLngBox) const {
|
||||
OsmIdSet bboxNodes, noHupNodes;
|
||||
MultAttrMap emptyF;
|
||||
|
||||
RelLst rels;
|
||||
OsmIdList ways;
|
||||
RelMap nodeRels, wayRels;
|
||||
|
||||
// TODO(patrick): not needed here!
|
||||
Restrictions rests;
|
||||
|
||||
NIdMap nodes;
|
||||
|
||||
// always empty
|
||||
NIdMultMap multNodes;
|
||||
util::xml::XmlWriter wr(out, true, 4);
|
||||
|
||||
*out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
wr.openComment();
|
||||
wr.writeText(" - written by pfaedle -");
|
||||
wr.closeTag();
|
||||
wr.openTag("osm-script",
|
||||
{{"timeout", "99999"}, {"element-limit", "1073741824"}});
|
||||
|
||||
OsmFilter filter;
|
||||
|
||||
for (const OsmReadOpts& o : opts) {
|
||||
filter = filter.merge(OsmFilter(o.keepFilter, o.dropFilter));
|
||||
}
|
||||
|
||||
wr.openTag("union");
|
||||
size_t c = 0;
|
||||
for (auto box : latLngBox.getLeafs()) {
|
||||
if (box.getLowerLeft().getX() > box.getUpperRight().getX()) continue;
|
||||
c++;
|
||||
wr.openComment();
|
||||
wr.writeText(std::string("Bounding box #") + std::to_string(c) + " (" +
|
||||
std::to_string(box.getLowerLeft().getY()) + ", " +
|
||||
std::to_string(box.getLowerLeft().getX()) + ", " +
|
||||
std::to_string(box.getUpperRight().getY()) + ", " +
|
||||
std::to_string(box.getUpperRight().getX()) + ")");
|
||||
wr.closeTag();
|
||||
for (auto t : std::vector<std::string>{"way", "node", "relation"}) {
|
||||
for (auto r : filter.getKeepRules()) {
|
||||
for (auto val : r.second) {
|
||||
if (t == "way" && (val.second & OsmFilter::WAY)) continue;
|
||||
if (t == "relation" && (val.second & OsmFilter::REL)) continue;
|
||||
if (t == "node" && (val.second & OsmFilter::NODE)) continue;
|
||||
|
||||
wr.openTag("query", {{"type", t}});
|
||||
if (val.first == "*")
|
||||
wr.openTag("has-kv", {{"k", r.first}});
|
||||
else
|
||||
wr.openTag("has-kv", {{"k", r.first}, {"v", val.first}});
|
||||
wr.closeTag();
|
||||
wr.openTag("bbox-query",
|
||||
{{"s", std::to_string(box.getLowerLeft().getY())},
|
||||
{"w", std::to_string(box.getLowerLeft().getX())},
|
||||
{"n", std::to_string(box.getUpperRight().getY())},
|
||||
{"e", std::to_string(box.getUpperRight().getX())}});
|
||||
wr.closeTag();
|
||||
wr.closeTag();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wr.closeTag();
|
||||
|
||||
wr.openTag("union");
|
||||
wr.openTag("item");
|
||||
wr.closeTag();
|
||||
wr.openTag("recurse", {{"type", "down"}});
|
||||
wr.closeTag();
|
||||
wr.closeTag();
|
||||
wr.openTag("print");
|
||||
|
||||
wr.closeTags();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void OsmBuilder::filterWrite(const std::string& in, const std::string& out,
|
||||
const std::vector<OsmReadOpts>& opts,
|
||||
|
|
@ -250,8 +384,15 @@ void OsmBuilder::filterWrite(const std::string& in, const std::string& out,
|
|||
|
||||
outstr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
wr.openTag("osm");
|
||||
|
||||
// TODO(patrick): write bounding box tag
|
||||
wr.openTag(
|
||||
"bounds",
|
||||
{{"minlat", std::to_string(latLngBox.getFullBox().getLowerLeft().getY())},
|
||||
{"minlon", std::to_string(latLngBox.getFullBox().getLowerLeft().getX())},
|
||||
{"maxlat",
|
||||
std::to_string(latLngBox.getFullBox().getUpperRight().getY())},
|
||||
{"maxlon",
|
||||
std::to_string(latLngBox.getFullBox().getUpperRight().getX())}});
|
||||
wr.closeTag();
|
||||
|
||||
OsmFilter filter;
|
||||
AttrKeySet attrKeys[3] = {};
|
||||
|
|
@ -1071,8 +1212,7 @@ EdgeGrid OsmBuilder::buildEdgeIdx(Graph* g, size_t size,
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
NodeGrid OsmBuilder::buildNodeIdx(Graph* g, size_t size,
|
||||
const BOX& webMercBox,
|
||||
NodeGrid OsmBuilder::buildNodeIdx(Graph* g, size_t size, const BOX& webMercBox,
|
||||
bool which) const {
|
||||
NodeGrid ret(size, size, webMercBox, false);
|
||||
for (auto* n : *g->getNds()) {
|
||||
|
|
@ -1158,9 +1298,10 @@ bool OsmBuilder::isBlocked(const Edge* e, const StatInfo* si, const POINT& p,
|
|||
|
||||
// _____________________________________________________________________________
|
||||
Node* OsmBuilder::eqStatReach(const Edge* e, const StatInfo* si, const POINT& p,
|
||||
double maxD, int maxFullTurns,
|
||||
double minAngle) const {
|
||||
return depthSearch(e, si, p, maxD, maxFullTurns, minAngle, EqSearch());
|
||||
double maxD, int maxFullTurns, double minAngle,
|
||||
bool orphanSnap) const {
|
||||
return depthSearch(e, si, p, maxD, maxFullTurns, minAngle,
|
||||
EqSearch(orphanSnap));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
@ -1187,8 +1328,7 @@ std::set<Node*> OsmBuilder::getMatchingNds(const NodePL& s, NodeGrid* ng,
|
|||
std::set<Node*> ret;
|
||||
double distor = webMercDistFactor(*s.getGeom());
|
||||
std::set<Node*> neighs;
|
||||
BOX box =
|
||||
util::geo::pad(util::geo::getBoundingBox(*s.getGeom()), d / distor);
|
||||
BOX box = util::geo::pad(util::geo::getBoundingBox(*s.getGeom()), d / distor);
|
||||
ng->get(box, &neighs);
|
||||
|
||||
for (auto* n : neighs) {
|
||||
|
|
@ -1205,8 +1345,7 @@ std::set<Node*> OsmBuilder::getMatchingNds(const NodePL& s, NodeGrid* ng,
|
|||
Node* OsmBuilder::getMatchingNd(const NodePL& s, NodeGrid* ng, double d) const {
|
||||
double distor = webMercDistFactor(*s.getGeom());
|
||||
std::set<Node*> neighs;
|
||||
BOX box =
|
||||
util::geo::pad(util::geo::getBoundingBox(*s.getGeom()), d / distor);
|
||||
BOX box = util::geo::pad(util::geo::getBoundingBox(*s.getGeom()), d / distor);
|
||||
ng->get(box, &neighs);
|
||||
|
||||
Node* ret = 0;
|
||||
|
|
@ -1229,7 +1368,7 @@ Node* OsmBuilder::getMatchingNd(const NodePL& s, NodeGrid* ng, double d) const {
|
|||
std::set<Node*> OsmBuilder::snapStation(Graph* g, NodePL* s, EdgeGrid* eg,
|
||||
NodeGrid* sng, const OsmReadOpts& opts,
|
||||
Restrictor* restor, bool surrHeur,
|
||||
double d) const {
|
||||
bool orphSnap, double d) const {
|
||||
assert(s->getSI());
|
||||
std::set<Node*> ret;
|
||||
|
||||
|
|
@ -1239,10 +1378,14 @@ std::set<Node*> OsmBuilder::snapStation(Graph* g, NodePL* s, EdgeGrid* eg,
|
|||
|
||||
if (pq.empty() && surrHeur) {
|
||||
// no station found in the first round, try again with the nearest
|
||||
// surrounding
|
||||
// station with matching name
|
||||
// surrounding station with matching name
|
||||
const Node* best = getMatchingNd(*s, sng, opts.maxSnapFallbackHeurDistance);
|
||||
if (best) getEdgCands(*best->pl().getGeom(), &pq, eg, d);
|
||||
if (best) {
|
||||
getEdgCands(*best->pl().getGeom(), &pq, eg, d);
|
||||
} else {
|
||||
// if still no luck, get edge cands in fallback snap distance
|
||||
getEdgCands(*s->getGeom(), &pq, eg, opts.maxSnapFallbackHeurDistance);
|
||||
}
|
||||
}
|
||||
|
||||
while (!pq.empty()) {
|
||||
|
|
@ -1254,7 +1397,7 @@ std::set<Node*> OsmBuilder::snapStation(Graph* g, NodePL* s, EdgeGrid* eg,
|
|||
|
||||
Node* eq = 0;
|
||||
if (!(eq = eqStatReach(e, s->getSI(), geom, 2 * d, 0,
|
||||
opts.maxAngleSnapReach))) {
|
||||
opts.maxAngleSnapReach, orphSnap))) {
|
||||
if (e->pl().lvl() > opts.maxSnapLevel) continue;
|
||||
if (isBlocked(e, s->getSI(), geom, opts.maxBlockDistance, 0,
|
||||
opts.maxAngleSnapReach)) {
|
||||
|
|
@ -1309,11 +1452,6 @@ std::set<Node*> OsmBuilder::snapStation(Graph* g, NodePL* s, EdgeGrid* eg,
|
|||
}
|
||||
}
|
||||
|
||||
// get surrounding nodes
|
||||
// TODO(patrick): own distance configuration for this!
|
||||
const auto& sur = getMatchingNds(*s, sng, opts.maxGroupSearchDistance);
|
||||
ret.insert(sur.begin(), sur.end());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1336,7 +1474,10 @@ StatGroup* OsmBuilder::groupStats(const NodeSet& s) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (!used) delete ret;
|
||||
if (!used) {
|
||||
delete ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1507,7 +1648,7 @@ void OsmBuilder::getKeptAttrKeys(const OsmReadOpts& opts,
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void OsmBuilder::deleteOrphEdgs(Graph* g) const {
|
||||
void OsmBuilder::deleteOrphEdgs(Graph* g, const OsmReadOpts& opts) const {
|
||||
size_t ROUNDS = 3;
|
||||
for (size_t c = 0; c < ROUNDS; c++) {
|
||||
for (auto i = g->getNds()->begin(); i != g->getNds()->end();) {
|
||||
|
|
@ -1515,6 +1656,15 @@ void OsmBuilder::deleteOrphEdgs(Graph* g) const {
|
|||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the removal of this edge would transform a steep angle
|
||||
// full turn at an intersection into a node 2 eligible for contraction
|
||||
// if so, dont delete
|
||||
if (keepFullTurn(*i, opts.fullTurnAngle)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = g->delNd(*i);
|
||||
continue;
|
||||
i++;
|
||||
|
|
@ -1706,3 +1856,43 @@ void OsmBuilder::writeSelfEdgs(Graph* g) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
bool OsmBuilder::keepFullTurn(const trgraph::Node* n, double ang) const {
|
||||
if (n->getInDeg() + n->getOutDeg() != 1) return false;
|
||||
|
||||
const trgraph::Edge* e = 0;
|
||||
if (n->getOutDeg())
|
||||
e = n->getAdjListOut().front();
|
||||
else
|
||||
e = n->getAdjListIn().front();
|
||||
|
||||
auto other = e->getOtherNd(n);
|
||||
|
||||
if (other->getInDeg() + other->getOutDeg() == 3) {
|
||||
const trgraph::Edge* a = 0;
|
||||
const trgraph::Edge* b = 0;
|
||||
for (auto f : other->getAdjListIn()) {
|
||||
if (f != e && !a)
|
||||
a = f;
|
||||
else if (f != e && !b)
|
||||
b = f;
|
||||
}
|
||||
|
||||
for (auto f : other->getAdjListOut()) {
|
||||
if (f != e && !a)
|
||||
a = f;
|
||||
else if (f != e && !b)
|
||||
b = f;
|
||||
}
|
||||
|
||||
auto ap = a->pl().backHop();
|
||||
auto bp = b->pl().backHop();
|
||||
if (a->getTo() != other) ap = a->pl().frontHop();
|
||||
if (b->getTo() != other) bp = b->pl().frontHop();
|
||||
|
||||
return router::angSmaller(ap, *other->pl().getGeom(), bp, ang);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ struct SearchFunc {
|
|||
};
|
||||
|
||||
struct EqSearch : public SearchFunc {
|
||||
explicit EqSearch(bool orphanSnap) : orphanSnap(orphanSnap) {}
|
||||
double minSimi = 0.9;
|
||||
bool operator()(const Node* cand, const StatInfo* si) const {
|
||||
return cand->pl().getSI() && cand->pl().getSI()->simi(si) > minSimi;
|
||||
}
|
||||
bool orphanSnap;
|
||||
bool operator()(const Node* cand, const StatInfo* si) const;
|
||||
};
|
||||
|
||||
struct BlockSearch : public SearchFunc {
|
||||
|
|
@ -91,6 +91,11 @@ class OsmBuilder {
|
|||
const BBoxIdx& box, size_t gridSize, router::FeedStops* fs,
|
||||
Restrictor* res);
|
||||
|
||||
// Based on the list of options, output an overpass XML query for getting
|
||||
// the data needed for routing
|
||||
void overpassQryWrite(std::ostream* out, const std::vector<OsmReadOpts>& opts,
|
||||
const BBoxIdx& latLngBox) const;
|
||||
|
||||
// Based on the list of options, read an OSM file from in and output an
|
||||
// OSM file to out which contains exactly the entities that are needed
|
||||
// from the file at in
|
||||
|
|
@ -170,7 +175,7 @@ class OsmBuilder {
|
|||
|
||||
void writeGeoms(Graph* g) const;
|
||||
void deleteOrphNds(Graph* g) const;
|
||||
void deleteOrphEdgs(Graph* g) const;
|
||||
void deleteOrphEdgs(Graph* g, const OsmReadOpts& opts) const;
|
||||
double dist(const Node* a, const Node* b) const;
|
||||
double webMercDist(const Node* a, const Node* b) const;
|
||||
double webMercDistFactor(const POINT& a) const;
|
||||
|
|
@ -198,13 +203,14 @@ class OsmBuilder {
|
|||
|
||||
NodeSet snapStation(Graph* g, NodePL* s, EdgeGrid* eg, NodeGrid* sng,
|
||||
const OsmReadOpts& opts, Restrictor* restor, bool surHeur,
|
||||
double maxD) const;
|
||||
bool orphSnap, double maxD) const;
|
||||
|
||||
// Checks if from the edge e, a station similar to si can be reach with less
|
||||
// than maxD distance and less or equal to "maxFullTurns" full turns. If
|
||||
// such a station exists, it is returned. If not, 0 is returned.
|
||||
Node* eqStatReach(const Edge* e, const StatInfo* si, const POINT& p,
|
||||
double maxD, int maxFullTurns, double maxAng) const;
|
||||
double maxD, int maxFullTurns, double maxAng,
|
||||
bool orph) const;
|
||||
|
||||
Node* depthSearch(const Edge* e, const StatInfo* si, const POINT& p,
|
||||
double maxD, int maxFullTurns, double minAngle,
|
||||
|
|
@ -243,6 +249,8 @@ class OsmBuilder {
|
|||
|
||||
bool relKeep(osmid id, const RelMap& rels, const FlatRels& fl) const;
|
||||
|
||||
bool keepFullTurn(const trgraph::Node* n, double ang) const;
|
||||
|
||||
std::map<TransitEdgeLine, TransitEdgeLine*> _lines;
|
||||
std::map<size_t, TransitEdgeLine*> _relLines;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -102,12 +102,12 @@ uint64_t OsmFilter::contained(const AttrMap& attrs, const Attr& attr) {
|
|||
// _____________________________________________________________________________
|
||||
uint8_t OsmFilter::level(const AttrMap& attrs) const {
|
||||
// the best matching level is always returned
|
||||
for (int16_t i = 0; i < 7; i++) {
|
||||
for (int16_t i = 0; i < 8; i++) {
|
||||
for (const auto& kv : attrs) {
|
||||
const auto& lkv = (_levels + i)->find(kv.first);
|
||||
if (lkv != (_levels + i)->end()) {
|
||||
for (const auto& val : lkv->second) {
|
||||
if (valMatches(kv.second, val.first)) return i + 1;
|
||||
if (valMatches(kv.second, val.first)) return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ std::vector<std::string> OsmFilter::getAttrKeys() const {
|
|||
for (const auto& kv : _noRestr) {
|
||||
ret.push_back(kv.first);
|
||||
}
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
for (const auto& kv : *(_levels + i)) {
|
||||
ret.push_back(kv.first);
|
||||
}
|
||||
|
|
@ -191,27 +191,6 @@ OsmFilter OsmFilter::merge(const OsmFilter& other) const {
|
|||
keep[kv.first].insert(kv.second.begin(), kv.second.end());
|
||||
}
|
||||
|
||||
// TODO(patrick): multi-level combination for filters. otherwise
|
||||
// filter drop filters meant as a refinement for keep filters
|
||||
// interfere with other keeps
|
||||
|
||||
// const auto* d = &_drop;
|
||||
|
||||
// for (size_t i = 0; i < 2; i++) {
|
||||
// for (const auto& kv : *d) {
|
||||
// if (keep.find(kv.first) != keep.end()) {
|
||||
// for (const auto& val : kv.second) {
|
||||
// if (keep[kv.first].find(val.first) == keep[kv.first].end()) {
|
||||
// drop[kv.first].insert(val);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// drop[kv.first].insert(kv.second.begin(), kv.second.end());
|
||||
// }
|
||||
// }
|
||||
// d = &other._drop;
|
||||
// }
|
||||
|
||||
return OsmFilter(keep, drop);
|
||||
}
|
||||
|
||||
|
|
@ -258,3 +237,13 @@ uint64_t OsmFilter::posRestr(const AttrMap& attrs) const {
|
|||
if (contained(attrs, _noRestr, ALL)) return false;
|
||||
return (contained(attrs, _posRestr, ALL));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
const pfaedle::osm::MultAttrMap& OsmFilter::getKeepRules() const {
|
||||
return _keep;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
const pfaedle::osm::MultAttrMap& OsmFilter::getDropRules() const {
|
||||
return _drop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ class OsmFilter {
|
|||
|
||||
OsmFilter merge(const OsmFilter& other) const;
|
||||
|
||||
const MultAttrMap& getKeepRules() const;
|
||||
const MultAttrMap& getDropRules() const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
static bool valMatches(const std::string& a, const std::string& b, bool m);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ struct OsmReadOpts {
|
|||
|
||||
MultAttrMap noHupFilter;
|
||||
MultAttrMap keepFilter;
|
||||
MultAttrMap levelFilters[7];
|
||||
MultAttrMap levelFilters[8];
|
||||
MultAttrMap dropFilter;
|
||||
MultAttrMap oneWayFilter;
|
||||
MultAttrMap oneWayFilterRev;
|
||||
|
|
@ -136,7 +136,6 @@ struct OsmReadOpts {
|
|||
double maxAngleSnapReach;
|
||||
std::vector<double> maxSnapDistances;
|
||||
double maxSnapFallbackHeurDistance;
|
||||
double maxGroupSearchDistance;
|
||||
double maxBlockDistance;
|
||||
|
||||
double maxOsmStationDistance;
|
||||
|
|
@ -144,6 +143,8 @@ struct OsmReadOpts {
|
|||
// TODO(patrick): this is not implemented yet
|
||||
double levelSnapPunishFac[7] = {0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
double fullTurnAngle;
|
||||
|
||||
// restriction system
|
||||
MultAttrMap restrPosRestr;
|
||||
MultAttrMap restrNegRestr;
|
||||
|
|
@ -179,7 +180,6 @@ inline bool operator==(const OsmReadOpts& a, const OsmReadOpts& b) {
|
|||
fabs(a.maxOsmStationDistance - b.maxOsmStationDistance) < 0.1 &&
|
||||
fabs(a.maxSnapFallbackHeurDistance - b.maxSnapFallbackHeurDistance) <
|
||||
0.1 &&
|
||||
fabs(a.maxGroupSearchDistance - b.maxGroupSearchDistance) < 0.1 &&
|
||||
fabs(a.maxBlockDistance - b.maxBlockDistance) < 0.1 &&
|
||||
fabs(a.levelSnapPunishFac[0] - b.levelSnapPunishFac[0]) < 0.1 &&
|
||||
fabs(a.levelSnapPunishFac[1] - b.levelSnapPunishFac[1]) < 0.1 &&
|
||||
|
|
@ -188,6 +188,7 @@ inline bool operator==(const OsmReadOpts& a, const OsmReadOpts& b) {
|
|||
fabs(a.levelSnapPunishFac[4] - b.levelSnapPunishFac[4]) < 0.1 &&
|
||||
fabs(a.levelSnapPunishFac[5] - b.levelSnapPunishFac[5]) < 0.1 &&
|
||||
fabs(a.levelSnapPunishFac[6] - b.levelSnapPunishFac[6]) < 0.1 &&
|
||||
fabs(a.fullTurnAngle - b.fullTurnAngle) < 0.1 &&
|
||||
a.restrPosRestr == b.restrPosRestr &&
|
||||
a.restrNegRestr == b.restrNegRestr &&
|
||||
a.noRestrFilter == b.noRestrFilter;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue