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
|
|
@ -60,11 +60,28 @@ inline double lineSimi(const std::string& a, const std::string& b) {
|
|||
|
||||
if (a.empty() || b.empty()) return 0;
|
||||
|
||||
// if one of the lines is completely contained in the other, return 1
|
||||
if (a.find(b) != std::string::npos) {
|
||||
return 1;
|
||||
} else if (b.find(a) != std::string::npos) {
|
||||
return 1;
|
||||
if (a.size() > b.size() + 1) {
|
||||
// check if a begins with b
|
||||
if (a.compare(0, b.size() + 1, b + " ") == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check if a ends with b
|
||||
if (a.compare(a.size() - (b.size() + 1), b.size() + 1, " " + b) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (b.size() > a.size() + 1) {
|
||||
// check if b begins with a
|
||||
if (b.compare(0, a.size() + 1, a + " ") == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check if b ends with a
|
||||
if (b.compare(b.size() - (a.size() + 1), a.size() + 1, " " + a) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -82,21 +82,6 @@ util::json::Dict EdgePL::getAttrs() const {
|
|||
obj["cost"] = std::to_string(_cost.getValue());
|
||||
obj["from_edge"] = util::toString(_startE);
|
||||
obj["to_edge"] = util::toString(_endE);
|
||||
obj["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
||||
obj["cost_m_lvl0"] = std::to_string(_cost.meterDist);
|
||||
obj["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
||||
obj["cost_m_lvl2"] = std::to_string(_cost.meterDistLvl2);
|
||||
obj["cost_m_lvl3"] = std::to_string(_cost.meterDistLvl3);
|
||||
obj["cost_m_lvl4"] = std::to_string(_cost.meterDistLvl4);
|
||||
obj["cost_m_lvl5"] = std::to_string(_cost.meterDistLvl5);
|
||||
obj["cost_m_lvl6"] = std::to_string(_cost.meterDistLvl6);
|
||||
obj["cost_m_lvl7"] = std::to_string(_cost.meterDistLvl7);
|
||||
obj["cost_fullturn"] = std::to_string(_cost.fullTurns);
|
||||
obj["cost_st_passthru"] = std::to_string(_cost.passThruStations);
|
||||
obj["cost_m_oneway"] = std::to_string(_cost.oneWayMeters);
|
||||
obj["cost_m_lineunmatch"] = std::to_string(_cost.lineUnmatchedMeters);
|
||||
obj["cost_reach_node_pen"] = std::to_string(_cost.reachPen);
|
||||
obj["cost_oneway_event"] = std::to_string(_cost.oneWayEdges);
|
||||
obj["dummy"] = _edges.size() ? "no" : "yes";
|
||||
|
||||
return obj;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ using util::geograph::GeoEdgePL;
|
|||
namespace pfaedle {
|
||||
namespace router {
|
||||
|
||||
class EdgePL : public GeoEdgePL<PFAEDLE_PRECISION> {
|
||||
class EdgePL {
|
||||
public:
|
||||
EdgePL() : _cost(), _start(0), _end(0), _startE(0), _endE(0) {}
|
||||
const LINE* getGeom() const;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "ad/cppgtfs/gtfs/Feed.h"
|
||||
#include "ad/cppgtfs/gtfs/Route.h"
|
||||
#include "pfaedle/trgraph/Graph.h"
|
||||
|
|
@ -67,90 +67,35 @@ inline bool operator==(const RoutingOpts& a, const RoutingOpts& b) {
|
|||
}
|
||||
|
||||
struct EdgeCost {
|
||||
EdgeCost()
|
||||
: meterDist(0),
|
||||
meterDistLvl1(0),
|
||||
meterDistLvl2(0),
|
||||
meterDistLvl3(0),
|
||||
meterDistLvl4(0),
|
||||
meterDistLvl5(0),
|
||||
meterDistLvl6(0),
|
||||
meterDistLvl7(0),
|
||||
fullTurns(0),
|
||||
passThruStations(0),
|
||||
oneWayMeters(0),
|
||||
oneWayEdges(0),
|
||||
lineUnmatchedMeters(0),
|
||||
reachPen(0),
|
||||
o(0) {}
|
||||
EdgeCost() : _cost(0) {}
|
||||
explicit EdgeCost(double cost) : _cost(cost) {}
|
||||
EdgeCost(double mDist, double mDistLvl1, double mDistLvl2, double mDistLvl3,
|
||||
double mDistLvl4, double mDistLvl5, double mDistLvl6,
|
||||
double mDistLvl7, uint32_t fullTurns, int32_t passThru,
|
||||
double oneWayMeters, size_t oneWayEdges, double lineUnmatchedMeters,
|
||||
double reachPen, const RoutingOpts* o)
|
||||
: meterDist(mDist),
|
||||
meterDistLvl1(mDistLvl1),
|
||||
meterDistLvl2(mDistLvl2),
|
||||
meterDistLvl3(mDistLvl3),
|
||||
meterDistLvl4(mDistLvl4),
|
||||
meterDistLvl5(mDistLvl5),
|
||||
meterDistLvl6(mDistLvl6),
|
||||
meterDistLvl7(mDistLvl7),
|
||||
fullTurns(fullTurns),
|
||||
passThruStations(passThru),
|
||||
oneWayMeters(oneWayMeters),
|
||||
oneWayEdges(oneWayEdges),
|
||||
lineUnmatchedMeters(lineUnmatchedMeters),
|
||||
reachPen(reachPen),
|
||||
o(o) {}
|
||||
double meterDist;
|
||||
double meterDistLvl1;
|
||||
double meterDistLvl2;
|
||||
double meterDistLvl3;
|
||||
double meterDistLvl4;
|
||||
double meterDistLvl5;
|
||||
double meterDistLvl6;
|
||||
double meterDistLvl7;
|
||||
uint32_t fullTurns;
|
||||
int32_t passThruStations;
|
||||
double oneWayMeters;
|
||||
size_t oneWayEdges;
|
||||
double lineUnmatchedMeters;
|
||||
double reachPen;
|
||||
const RoutingOpts* o;
|
||||
|
||||
double getValue() const {
|
||||
if (!o) return meterDist + reachPen;
|
||||
return meterDist * o->levelPunish[0] + meterDistLvl1 * o->levelPunish[1] +
|
||||
meterDistLvl2 * o->levelPunish[2] +
|
||||
meterDistLvl3 * o->levelPunish[3] +
|
||||
meterDistLvl4 * o->levelPunish[4] +
|
||||
meterDistLvl5 * o->levelPunish[5] +
|
||||
meterDistLvl6 * o->levelPunish[6] +
|
||||
meterDistLvl7 * o->levelPunish[7] +
|
||||
oneWayMeters * o->oneWayPunishFac +
|
||||
oneWayEdges * o->oneWayEdgePunish +
|
||||
lineUnmatchedMeters * o->lineUnmatchedPunishFact +
|
||||
fullTurns * o->fullTurnPunishFac +
|
||||
passThruStations * o->passThruStationsPunish + reachPen;
|
||||
double reachPen, const RoutingOpts* o) {
|
||||
if (!o) {
|
||||
_cost = mDist + reachPen;
|
||||
} else {
|
||||
_cost = mDist * o->levelPunish[0] + mDistLvl1 * o->levelPunish[1] +
|
||||
mDistLvl2 * o->levelPunish[2] + mDistLvl3 * o->levelPunish[3] +
|
||||
mDistLvl4 * o->levelPunish[4] + mDistLvl5 * o->levelPunish[5] +
|
||||
mDistLvl6 * o->levelPunish[6] + mDistLvl7 * o->levelPunish[7] +
|
||||
oneWayMeters * o->oneWayPunishFac +
|
||||
oneWayEdges * o->oneWayEdgePunish +
|
||||
lineUnmatchedMeters * o->lineUnmatchedPunishFact +
|
||||
fullTurns * o->fullTurnPunishFac +
|
||||
passThru * o->passThruStationsPunish + reachPen;
|
||||
}
|
||||
}
|
||||
|
||||
double getTotalMeters() const {
|
||||
return meterDist + meterDistLvl1 + meterDistLvl2 + meterDistLvl3 +
|
||||
meterDistLvl4 + meterDistLvl5 + meterDistLvl6 + meterDistLvl7;
|
||||
}
|
||||
float _cost;
|
||||
|
||||
double getValue() const { return _cost; }
|
||||
};
|
||||
|
||||
inline EdgeCost operator+(const EdgeCost& a, const EdgeCost& b) {
|
||||
return EdgeCost(
|
||||
a.meterDist + b.meterDist, a.meterDistLvl1 + b.meterDistLvl1,
|
||||
a.meterDistLvl2 + b.meterDistLvl2, a.meterDistLvl3 + b.meterDistLvl3,
|
||||
a.meterDistLvl4 + b.meterDistLvl4, a.meterDistLvl5 + b.meterDistLvl5,
|
||||
a.meterDistLvl6 + b.meterDistLvl6, a.meterDistLvl7 + b.meterDistLvl7,
|
||||
a.fullTurns + b.fullTurns, a.passThruStations + b.passThruStations,
|
||||
a.oneWayMeters + b.oneWayMeters, a.oneWayEdges + b.oneWayEdges,
|
||||
a.lineUnmatchedMeters + b.lineUnmatchedMeters, a.reachPen + b.reachPen,
|
||||
a.o ? a.o : b.o);
|
||||
return EdgeCost(a.getValue() + b.getValue());
|
||||
}
|
||||
|
||||
inline bool operator<=(const EdgeCost& a, const EdgeCost& b) {
|
||||
|
|
@ -165,9 +110,9 @@ inline bool operator>(const EdgeCost& a, const EdgeCost& b) {
|
|||
return a.getValue() > b.getValue();
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
template <typename F>
|
||||
inline bool angSmaller(const Point<F>& f, const Point<F>& m, const Point<F>& t,
|
||||
double ang) {
|
||||
double ang) {
|
||||
if (util::geo::innerProd(m, f, t) < ang) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ using util::geograph::GeoNodePL;
|
|||
namespace pfaedle {
|
||||
namespace router {
|
||||
|
||||
class NodePL : public GeoNodePL<PFAEDLE_PRECISION> {
|
||||
class NodePL {
|
||||
public:
|
||||
NodePL() : _n(0) {}
|
||||
NodePL(const pfaedle::trgraph::Node* n) : _n(n) {} // NOLINT
|
||||
|
|
|
|||
|
|
@ -191,7 +191,8 @@ double CombCostFunc::operator()(const router::Edge* from, const router::Node* n,
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
Router::Router(size_t numThreads) : _cache(numThreads) {
|
||||
Router::Router(size_t numThreads, bool caching)
|
||||
: _cache(numThreads), _caching(caching) {
|
||||
for (size_t i = 0; i < numThreads; i++) {
|
||||
_cache[i] = new Cache();
|
||||
}
|
||||
|
|
@ -219,6 +220,9 @@ bool Router::compConned(const NodeCandGroup& a, const NodeCandGroup& b) const {
|
|||
HopBand Router::getHopBand(const NodeCandGroup& a, const NodeCandGroup& b,
|
||||
const RoutingAttrs& rAttrs, const RoutingOpts& rOpts,
|
||||
const osm::Restrictor& rest) const {
|
||||
assert(a.size());
|
||||
assert(b.size());
|
||||
|
||||
double pend = 0;
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
for (size_t j = 0; j < b.size(); j++) {
|
||||
|
|
@ -231,6 +235,7 @@ HopBand Router::getHopBand(const NodeCandGroup& a, const NodeCandGroup& b,
|
|||
LOG(VDEBUG) << "Pending max hop distance is " << pend << " meters";
|
||||
|
||||
const trgraph::StatGroup* tgGrpTo = 0;
|
||||
|
||||
if (b.begin()->nd->pl().getSI())
|
||||
tgGrpTo = b.begin()->nd->pl().getSI()->getGroup();
|
||||
|
||||
|
|
@ -556,6 +561,7 @@ void Router::nestedCache(const EdgeList* el,
|
|||
const std::set<trgraph::Edge*>& froms,
|
||||
const CostFunc& cost,
|
||||
const RoutingAttrs& rAttrs) const {
|
||||
if (!_caching) return;
|
||||
if (el->size() == 0) return;
|
||||
// iterate over result edges backwards
|
||||
EdgeList curEdges;
|
||||
|
|
@ -586,7 +592,7 @@ std::set<pfaedle::trgraph::Edge*> Router::getCachedHops(
|
|||
const RoutingAttrs& rAttrs) const {
|
||||
std::set<trgraph::Edge*> ret;
|
||||
for (auto to : tos) {
|
||||
if ((*_cache[omp_get_thread_num()])[rAttrs][from].count(to)) {
|
||||
if (_caching && (*_cache[omp_get_thread_num()])[rAttrs][from].count(to)) {
|
||||
const auto& cv = (*_cache[omp_get_thread_num()])[rAttrs][from][to];
|
||||
(*rCosts)[to] = cv.first;
|
||||
*edgesRet.at(to) = cv.second;
|
||||
|
|
@ -601,6 +607,7 @@ std::set<pfaedle::trgraph::Edge*> Router::getCachedHops(
|
|||
// _____________________________________________________________________________
|
||||
void Router::cache(trgraph::Edge* from, trgraph::Edge* to, const EdgeCost& c,
|
||||
EdgeList* edges, const RoutingAttrs& rAttrs) const {
|
||||
if (!_caching) return;
|
||||
if (from == to) return;
|
||||
(*_cache[omp_get_thread_num()])[rAttrs][from][to] =
|
||||
std::pair<EdgeCost, EdgeList>(c, *edges);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ struct CombCostFunc
|
|||
class Router {
|
||||
public:
|
||||
// Init this router with caches for numThreads threads
|
||||
explicit Router(size_t numThreads);
|
||||
explicit Router(size_t numThreads, bool caching);
|
||||
~Router();
|
||||
|
||||
// Find the most likely path through the graph for a node candidate route.
|
||||
|
|
@ -163,6 +163,7 @@ class Router {
|
|||
|
||||
private:
|
||||
mutable std::vector<Cache*> _cache;
|
||||
bool _caching;
|
||||
HopBand getHopBand(const NodeCandGroup& a, const NodeCandGroup& b,
|
||||
const RoutingAttrs& rAttrs, const RoutingOpts& rOpts,
|
||||
const osm::Restrictor& rest) const;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#define omp_get_num_procs() 1
|
||||
#endif
|
||||
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
|
@ -16,6 +17,8 @@
|
|||
#include "ad/cppgtfs/gtfs/Feed.h"
|
||||
#include "pfaedle/Def.h"
|
||||
#include "pfaedle/eval/Collector.h"
|
||||
#include "pfaedle/gtfs/Feed.h"
|
||||
#include "pfaedle/gtfs/StopTime.h"
|
||||
#include "pfaedle/osm/OsmBuilder.h"
|
||||
#include "pfaedle/router/ShapeBuilder.h"
|
||||
#include "pfaedle/trgraph/StatGroup.h"
|
||||
|
|
@ -43,38 +46,36 @@ using pfaedle::router::EdgeListHops;
|
|||
using pfaedle::router::Clusters;
|
||||
using pfaedle::osm::BBoxIdx;
|
||||
using ad::cppgtfs::gtfs::Stop;
|
||||
using ad::cppgtfs::gtfs::Trip;
|
||||
using ad::cppgtfs::gtfs::Feed;
|
||||
using ad::cppgtfs::gtfs::StopTime;
|
||||
using pfaedle::gtfs::Trip;
|
||||
using pfaedle::gtfs::Feed;
|
||||
using pfaedle::gtfs::StopTime;
|
||||
using ad::cppgtfs::gtfs::ShapePoint;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
ShapeBuilder::ShapeBuilder(Feed* feed, MOTs mots,
|
||||
const config::MotConfig& motCfg,
|
||||
ShapeBuilder::ShapeBuilder(Feed* feed, ad::cppgtfs::gtfs::Feed* evalFeed,
|
||||
MOTs mots, const config::MotConfig& motCfg,
|
||||
eval::Collector* ecoll, const config::Config& cfg)
|
||||
: _feed(feed),
|
||||
_evalFeed(evalFeed),
|
||||
_mots(mots),
|
||||
_motCfg(motCfg),
|
||||
_ecoll(ecoll),
|
||||
_cfg(cfg),
|
||||
_crouter(omp_get_num_procs()),
|
||||
_crouter(omp_get_num_procs(), cfg.useCaching),
|
||||
_curShpCnt(0) {
|
||||
_numThreads = _crouter.getCacheNumber();
|
||||
writeMotStops();
|
||||
|
||||
// TODO(patrick): maybe do this on demand to avoid graph filtering / reading
|
||||
// for input where no routing is necessary (already shape'd)
|
||||
buildGraph();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void ShapeBuilder::writeMotStops() {
|
||||
for (auto t : _feed->getTrips()) {
|
||||
if (!_cfg.shapeTripId.empty() && t.second->getId() != _cfg.shapeTripId)
|
||||
continue;
|
||||
if (_mots.count(t.second->getRoute()->getType()) &&
|
||||
_motCfg.mots.count(t.second->getRoute()->getType())) {
|
||||
for (auto st : t.second->getStopTimes()) {
|
||||
if (!_cfg.shapeTripId.empty() && t.getId() != _cfg.shapeTripId) continue;
|
||||
if (_mots.count(t.getRoute()->getType()) &&
|
||||
_motCfg.mots.count(t.getRoute()->getType())) {
|
||||
for (auto st : t.getStopTimes()) {
|
||||
_stops[st.getStop()] = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -95,28 +96,34 @@ const NodeCandGroup& ShapeBuilder::getNodeCands(const Stop* s) const {
|
|||
// _____________________________________________________________________________
|
||||
LINE ShapeBuilder::shapeL(const router::NodeCandRoute& ncr,
|
||||
const router::RoutingAttrs& rAttrs) {
|
||||
const router::EdgeListHops& res = route(ncr, rAttrs);
|
||||
try {
|
||||
const router::EdgeListHops& res = route(ncr, rAttrs);
|
||||
|
||||
LINE l;
|
||||
for (const auto& hop : res) {
|
||||
const trgraph::Node* last = hop.start;
|
||||
if (hop.edges.size() == 0) {
|
||||
l.push_back(*hop.start->pl().getGeom());
|
||||
l.push_back(*hop.end->pl().getGeom());
|
||||
}
|
||||
for (auto i = hop.edges.rbegin(); i != hop.edges.rend(); i++) {
|
||||
const auto* e = *i;
|
||||
if ((e->getFrom() == last) ^ e->pl().isRev()) {
|
||||
l.insert(l.end(), e->pl().getGeom()->begin(), e->pl().getGeom()->end());
|
||||
} else {
|
||||
l.insert(l.end(), e->pl().getGeom()->rbegin(),
|
||||
e->pl().getGeom()->rend());
|
||||
LINE l;
|
||||
for (const auto& hop : res) {
|
||||
const trgraph::Node* last = hop.start;
|
||||
if (hop.edges.size() == 0) {
|
||||
l.push_back(*hop.start->pl().getGeom());
|
||||
l.push_back(*hop.end->pl().getGeom());
|
||||
}
|
||||
for (auto i = hop.edges.rbegin(); i != hop.edges.rend(); i++) {
|
||||
const auto* e = *i;
|
||||
if ((e->getFrom() == last) ^ e->pl().isRev()) {
|
||||
l.insert(l.end(), e->pl().getGeom()->begin(),
|
||||
e->pl().getGeom()->end());
|
||||
} else {
|
||||
l.insert(l.end(), e->pl().getGeom()->rbegin(),
|
||||
e->pl().getGeom()->rend());
|
||||
}
|
||||
last = e->getOtherNd(last);
|
||||
}
|
||||
last = e->getOtherNd(last);
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
return l;
|
||||
} catch (const std::runtime_error& e) {
|
||||
LOG(ERROR) << e.what();
|
||||
return LINE();
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
@ -193,9 +200,9 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
Clusters clusters = clusterTrips(_feed, _mots);
|
||||
LOG(DEBUG) << "Clustered trips into " << clusters.size() << " clusters.";
|
||||
|
||||
std::map<ad::cppgtfs::gtfs::Shape*, size_t> shpUsage;
|
||||
std::map<std::string, size_t> shpUsage;
|
||||
for (auto t : _feed->getTrips()) {
|
||||
if (t.second->getShape()) shpUsage[t.second->getShape()]++;
|
||||
if (!t.getShape().empty()) shpUsage[t.getShape()]++;
|
||||
}
|
||||
|
||||
// to avoid unfair load balance on threads
|
||||
|
|
@ -223,7 +230,7 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
<< "%, " << (EDijkstra::ITERS - oiters) << " iters, "
|
||||
/**
|
||||
TODO: this is actually misleading. We are counting the
|
||||
Dijkstra iterations, but the measuring them against
|
||||
Dijkstra iterations, but measuring them against
|
||||
the total running time (including all overhead + HMM solve)
|
||||
<< tput "
|
||||
<< (static_cast<double>(EDijkstra::ITERS - oiters)) /
|
||||
|
|
@ -249,7 +256,7 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
}
|
||||
|
||||
std::vector<double> distances;
|
||||
ad::cppgtfs::gtfs::Shape* shp =
|
||||
const ad::cppgtfs::gtfs::Shape& shp =
|
||||
getGtfsShape(cshp, clusters[i][0], &distances);
|
||||
|
||||
LOG(DEBUG) << "Took " << EDijkstra::ITERS - iters << " iterations.";
|
||||
|
|
@ -259,14 +266,14 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
|
||||
for (auto t : clusters[i]) {
|
||||
if (_cfg.evaluate) {
|
||||
_ecoll->add(t, t->getShape(), shp, distances);
|
||||
_ecoll->add(t, _evalFeed->getShapes().get(t->getShape()), shp,
|
||||
distances);
|
||||
}
|
||||
|
||||
if (t->getShape() && shpUsage[t->getShape()] > 0) {
|
||||
if (!t->getShape().empty() && shpUsage[t->getShape()] > 0) {
|
||||
shpUsage[t->getShape()]--;
|
||||
if (shpUsage[t->getShape()] == 0) {
|
||||
_feed->getShapes().remove(t->getShape()->getId());
|
||||
delete t->getShape();
|
||||
_feed->getShapes().remove(t->getShape());
|
||||
}
|
||||
}
|
||||
setShape(t, shp, distances);
|
||||
|
|
@ -295,27 +302,25 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void ShapeBuilder::setShape(Trip* t, ad::cppgtfs::gtfs::Shape* s,
|
||||
void ShapeBuilder::setShape(Trip* t, const ad::cppgtfs::gtfs::Shape& s,
|
||||
const std::vector<double>& distances) {
|
||||
assert(distances.size() == t->getStopTimes().size());
|
||||
// set distances
|
||||
size_t i = 0;
|
||||
for (const StopTime& st : t->getStopTimes()) {
|
||||
const_cast<StopTime&>(st).setShapeDistanceTravelled(distances[i]);
|
||||
for (const auto& st : t->getStopTimes()) {
|
||||
const_cast<StopTime<Stop>&>(st).setShapeDistanceTravelled(distances[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
t->setShape(s);
|
||||
|
||||
std::lock_guard<std::mutex> guard(_shpMutex);
|
||||
_feed->getShapes().add(s);
|
||||
// TODO(patrick):
|
||||
t->setShape(_feed->getShapes().add(s));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
ad::cppgtfs::gtfs::Shape* ShapeBuilder::getGtfsShape(
|
||||
ad::cppgtfs::gtfs::Shape ShapeBuilder::getGtfsShape(
|
||||
const Shape& shp, Trip* t, std::vector<double>* hopDists) {
|
||||
ad::cppgtfs::gtfs::Shape* ret =
|
||||
new ad::cppgtfs::gtfs::Shape(getFreeShapeId(t));
|
||||
ad::cppgtfs::gtfs::Shape ret(getFreeShapeId(t));
|
||||
|
||||
assert(shp.hops.size() == t->getStopTimes().size() - 1);
|
||||
|
||||
|
|
@ -338,7 +343,7 @@ ad::cppgtfs::gtfs::Shape* ShapeBuilder::getGtfsShape(
|
|||
last = *hop.start->pl().getGeom();
|
||||
|
||||
if (dist - lastDist > 0.01) {
|
||||
ret->addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
ret.addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
seq++;
|
||||
lastDist = dist;
|
||||
}
|
||||
|
|
@ -349,11 +354,12 @@ ad::cppgtfs::gtfs::Shape* ShapeBuilder::getGtfsShape(
|
|||
if (dist - lastDist > 0.01) {
|
||||
ll = webMercToLatLng<PFAEDLE_PRECISION>(
|
||||
hop.end->pl().getGeom()->getX(), hop.end->pl().getGeom()->getY());
|
||||
ret->addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
ret.addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
seq++;
|
||||
lastDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = hop.edges.rbegin(); i != hop.edges.rend(); i++) {
|
||||
const auto* e = *i;
|
||||
if ((e->getFrom() == l) ^ e->pl().isRev()) {
|
||||
|
|
@ -367,7 +373,7 @@ ad::cppgtfs::gtfs::Shape* ShapeBuilder::getGtfsShape(
|
|||
if (dist - lastDist > 0.01) {
|
||||
POINT ll =
|
||||
webMercToLatLng<PFAEDLE_PRECISION>(cur.getX(), cur.getY());
|
||||
ret->addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
ret.addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
seq++;
|
||||
lastDist = dist;
|
||||
}
|
||||
|
|
@ -383,7 +389,7 @@ ad::cppgtfs::gtfs::Shape* ShapeBuilder::getGtfsShape(
|
|||
if (dist - lastDist > 0.01) {
|
||||
POINT ll =
|
||||
webMercToLatLng<PFAEDLE_PRECISION>(cur.getX(), cur.getY());
|
||||
ret->addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
ret.addPoint(ShapePoint(ll.getY(), ll.getX(), dist, seq));
|
||||
seq++;
|
||||
lastDist = dist;
|
||||
}
|
||||
|
|
@ -447,33 +453,30 @@ const RoutingAttrs& ShapeBuilder::getRAttrs(const Trip* trip) const {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
BBoxIdx ShapeBuilder::getPaddedGtfsBox(const Feed* feed, double pad,
|
||||
const MOTs& mots, const std::string& tid,
|
||||
bool dropShapes) {
|
||||
osm::BBoxIdx box(pad);
|
||||
void ShapeBuilder::getGtfsBox(const Feed* feed, const MOTs& mots,
|
||||
const std::string& tid, bool dropShapes,
|
||||
osm::BBoxIdx* box) {
|
||||
for (const auto& t : feed->getTrips()) {
|
||||
if (!tid.empty() && t.second->getId() != tid) continue;
|
||||
if (tid.empty() && t.second->getShape() && !dropShapes) continue;
|
||||
if (t.second->getStopTimes().size() < 2) continue;
|
||||
if (mots.count(t.second->getRoute()->getType())) {
|
||||
if (!tid.empty() && t.getId() != tid) continue;
|
||||
if (tid.empty() && !t.getShape().empty() && !dropShapes) continue;
|
||||
if (t.getStopTimes().size() < 2) continue;
|
||||
if (mots.count(t.getRoute()->getType())) {
|
||||
DBox cur;
|
||||
for (const auto& st : t.second->getStopTimes()) {
|
||||
for (const auto& st : t.getStopTimes()) {
|
||||
cur = extendBox(DPoint(st.getStop()->getLng(), st.getStop()->getLat()),
|
||||
cur);
|
||||
}
|
||||
box.add(cur);
|
||||
box->add(cur);
|
||||
}
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void ShapeBuilder::buildGraph() {
|
||||
osm::OsmBuilder osmBuilder;
|
||||
|
||||
osm::BBoxIdx box =
|
||||
getPaddedGtfsBox(_feed, 2500, _mots, _cfg.shapeTripId, _cfg.dropShapes);
|
||||
osm::BBoxIdx box(BOX_PADDING);
|
||||
getGtfsBox(_feed, _mots, _cfg.shapeTripId, _cfg.dropShapes, &box);
|
||||
|
||||
osmBuilder.read(_cfg.osmPath, _motCfg.osmBuildOpts, &_g, box, _cfg.gridSize,
|
||||
getFeedStops(), &_restr);
|
||||
|
|
@ -497,6 +500,11 @@ NodeCandRoute ShapeBuilder::getNCR(Trip* trip) const {
|
|||
|
||||
for (const auto& st : trip->getStopTimes()) {
|
||||
ncr[i] = getNodeCands(st.getStop());
|
||||
if (ncr[i].size() == 0) {
|
||||
throw std::runtime_error("No node candidate found for station '" +
|
||||
st.getStop()->getName() + "' on trip '" +
|
||||
trip->getId() + "'");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return ncr;
|
||||
|
|
@ -535,29 +543,29 @@ Clusters ShapeBuilder::clusterTrips(Feed* f, MOTs mots) {
|
|||
size_t j = 0;
|
||||
|
||||
Clusters ret;
|
||||
for (const auto& trip : f->getTrips()) {
|
||||
if (trip.second->getShape() && !_cfg.dropShapes) continue;
|
||||
if (trip.second->getStopTimes().size() < 2) continue;
|
||||
if (!mots.count(trip.second->getRoute()->getType()) ||
|
||||
!_motCfg.mots.count(trip.second->getRoute()->getType()))
|
||||
for (auto& trip : f->getTrips()) {
|
||||
if (!trip.getShape().empty() && !_cfg.dropShapes) continue;
|
||||
if (trip.getStopTimes().size() < 2) continue;
|
||||
if (!mots.count(trip.getRoute()->getType()) ||
|
||||
!_motCfg.mots.count(trip.getRoute()->getType()))
|
||||
continue;
|
||||
bool found = false;
|
||||
auto spair = StopPair(trip.second->getStopTimes().begin()->getStop(),
|
||||
trip.second->getStopTimes().rbegin()->getStop());
|
||||
auto spair = StopPair(trip.getStopTimes().begin()->getStop(),
|
||||
trip.getStopTimes().rbegin()->getStop());
|
||||
const auto& c = clusterIdx[spair];
|
||||
|
||||
for (size_t i = 0; i < c.size(); i++) {
|
||||
j++;
|
||||
if (routingEqual(ret[c[i]][0], trip.second)) {
|
||||
ret[c[i]].push_back(trip.second);
|
||||
if (routingEqual(ret[c[i]][0], &trip)) {
|
||||
ret[c[i]].push_back(&trip);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ret.push_back({trip.second});
|
||||
ret.push_back(Cluster{&trip});
|
||||
// explicit call to write render attrs to cache
|
||||
getRAttrs(trip.second);
|
||||
getRAttrs(&trip);
|
||||
clusterIdx[spair].push_back(ret.size() - 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "pfaedle/config/MotConfig.h"
|
||||
#include "pfaedle/config/PfaedleConfig.h"
|
||||
#include "pfaedle/eval/Collector.h"
|
||||
#include "pfaedle/gtfs/Feed.h"
|
||||
#include "pfaedle/netgraph/Graph.h"
|
||||
#include "pfaedle/osm/Restrictor.h"
|
||||
#include "pfaedle/router/Misc.h"
|
||||
|
|
@ -27,8 +28,8 @@ namespace pfaedle {
|
|||
namespace router {
|
||||
|
||||
using ad::cppgtfs::gtfs::Stop;
|
||||
using ad::cppgtfs::gtfs::Trip;
|
||||
using ad::cppgtfs::gtfs::Feed;
|
||||
using pfaedle::gtfs::Trip;
|
||||
using pfaedle::gtfs::Feed;
|
||||
|
||||
struct Shape {
|
||||
router::EdgeListHops hops;
|
||||
|
|
@ -48,8 +49,9 @@ typedef std::unordered_map<const trgraph::Edge*, std::set<const Trip*>>
|
|||
*/
|
||||
class ShapeBuilder {
|
||||
public:
|
||||
ShapeBuilder(Feed* feed, MOTs mots, const config::MotConfig& motCfg,
|
||||
eval::Collector* ecoll, const config::Config& cfg);
|
||||
ShapeBuilder(Feed* feed, ad::cppgtfs::gtfs::Feed* evalFeed, MOTs mots,
|
||||
const config::MotConfig& motCfg, eval::Collector* ecoll,
|
||||
const config::Config& cfg);
|
||||
|
||||
void shape(pfaedle::netgraph::Graph* ng);
|
||||
|
||||
|
|
@ -66,12 +68,13 @@ class ShapeBuilder {
|
|||
|
||||
const trgraph::Graph* getGraph() const;
|
||||
|
||||
static osm::BBoxIdx getPaddedGtfsBox(const Feed* feed, double pad,
|
||||
const MOTs& mots, const std::string& tid,
|
||||
bool dropShapes);
|
||||
static void getGtfsBox(const Feed* feed, const MOTs& mots,
|
||||
const std::string& tid, bool dropShapes,
|
||||
osm::BBoxIdx* box);
|
||||
|
||||
private:
|
||||
Feed* _feed;
|
||||
ad::cppgtfs::gtfs::Feed* _evalFeed;
|
||||
MOTs _mots;
|
||||
config::MotConfig _motCfg;
|
||||
eval::Collector* _ecoll;
|
||||
|
|
@ -101,10 +104,10 @@ class ShapeBuilder {
|
|||
|
||||
std::string getFreeShapeId(Trip* t);
|
||||
|
||||
ad::cppgtfs::gtfs::Shape* getGtfsShape(const Shape& shp, Trip* t,
|
||||
ad::cppgtfs::gtfs::Shape getGtfsShape(const Shape& shp, Trip* t,
|
||||
std::vector<double>* hopDists);
|
||||
|
||||
void setShape(Trip* t, ad::cppgtfs::gtfs::Shape* s,
|
||||
void setShape(Trip* t, const ad::cppgtfs::gtfs::Shape& s,
|
||||
const std::vector<double>& dists);
|
||||
|
||||
router::NodeCandRoute getNCR(Trip* trip) const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue