update segmentation in shapevl, add --unique mode
This commit is contained in:
parent
c3bc12eb8c
commit
15e84d930a
11 changed files with 177 additions and 95 deletions
|
|
@ -27,6 +27,7 @@ using util::geo::output::GeoJsonOutput;
|
|||
double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
||||
const Shape* newS) {
|
||||
// This adds a new trip with a new shape to our evaluation.
|
||||
// if (oldT->getId() != "pse-a779ac00") return 0;
|
||||
|
||||
_trips++;
|
||||
|
||||
|
|
@ -36,7 +37,6 @@ double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (auto st : oldT->getStopTimes()) {
|
||||
if (st.getShapeDistanceTravelled() < 0) {
|
||||
// we cannot safely compare trips without shape dist travelled
|
||||
|
|
@ -82,7 +82,6 @@ double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::pair<double, double>> newLenDists;
|
||||
std::vector<std::pair<double, double>> oldLenDists;
|
||||
|
||||
|
|
@ -111,8 +110,10 @@ double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
|||
double f = util::geo::webMercDistFactor(oldLCut.front());
|
||||
|
||||
// roughly half a meter
|
||||
auto oldLCutS = util::geo::simplify(oldLCut, f * (0.5 / util::geo::M_PER_DEG));
|
||||
auto newLCutS = util::geo::simplify(newLCut, f * (0.5 / util::geo::M_PER_DEG));
|
||||
auto oldLCutS =
|
||||
util::geo::simplify(oldLCut, f * (0.5 / util::geo::M_PER_DEG));
|
||||
auto newLCutS =
|
||||
util::geo::simplify(newLCut, f * (0.5 / util::geo::M_PER_DEG));
|
||||
|
||||
auto old = _dCache.find(oldLCutS);
|
||||
if (old != _dCache.end()) {
|
||||
|
|
@ -156,6 +157,7 @@ double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
|||
if (AN <= 0.0001) _an0++;
|
||||
if (AN <= 0.05) _an5++;
|
||||
if (AN <= 0.1) _an10++;
|
||||
if (AN <= 0.2) _an20++;
|
||||
if (AN <= 0.3) _an30++;
|
||||
if (AN <= 0.5) _an50++;
|
||||
if (AN <= 0.7) _an70++;
|
||||
|
|
@ -167,9 +169,17 @@ double Collector::add(const Trip* oldT, const Shape* oldS, const Trip* newT,
|
|||
<< totL << " = " << AL << " d_f = " << avgFd;
|
||||
|
||||
if (_reportOut) {
|
||||
(*_reportOut) << std::fixed << std::setprecision(6);
|
||||
(*_reportOut) << oldT->getId() << "\t" << AN << "\t" << AL << "\t" << avgFd
|
||||
<< "\t" << util::geo::getWKT(oldSegs) << "\t"
|
||||
<< util::geo::getWKT(newSegs) << "\n";
|
||||
<< util::geo::getWKT(newSegs) << "\t" << oldT->getRoute()->getShortName() << "\t";
|
||||
|
||||
for (const auto& st : oldT->getStopTimes()) {
|
||||
(*_reportOut) << st.getStop()->getName() << "\t"
|
||||
<< st.getStop()->getLat() << "\t"
|
||||
<< st.getStop()->getLng() << "\t";
|
||||
}
|
||||
(*_reportOut) << "\n";
|
||||
}
|
||||
|
||||
return avgFd;
|
||||
|
|
@ -189,33 +199,32 @@ std::vector<LINE> Collector::segmentize(
|
|||
size_t i = 0;
|
||||
for (auto st : t->getStopTimes()) {
|
||||
cuts.push_back(std::pair<POINT, double>(
|
||||
{st.getStop()->getLng(),
|
||||
st.getStop()->getLat()},
|
||||
{st.getStop()->getLng(), st.getStop()->getLat()},
|
||||
st.getShapeDistanceTravelled()));
|
||||
i++;
|
||||
}
|
||||
|
||||
// get first half of geometry, and search for start point there!
|
||||
size_t before = std::upper_bound(dists.begin(), dists.end(), cuts[1].second) -
|
||||
|
||||
size_t to = std::upper_bound(dists.begin(), dists.end(), cuts[0].second) -
|
||||
dists.begin();
|
||||
if (before + 1 > shape.size()) before = shape.size() - 1;
|
||||
assert(shape.begin() + before + 1 <= shape.end());
|
||||
POLYLINE l(LINE(shape.begin(), shape.begin() + before + 1));
|
||||
auto lastLp = l.projectOn(cuts.front().first);
|
||||
if (to >= dists.size()) to = dists.size() - 1;
|
||||
double progr = (cuts[0].second - dists[to - 1]) / (dists[to] - dists[to - 1]);
|
||||
auto lastP = shape[to - 1];
|
||||
lastP.setX(lastP.getX() + progr * util::geo::dist(shape[to-1], shape[to]));
|
||||
lastP.setY(lastP.getY() + progr * util::geo::dist(shape[to-1], shape[to]));
|
||||
|
||||
for (size_t i = 1; i < cuts.size(); i++) {
|
||||
size_t before = shape.size();
|
||||
if (i < cuts.size() - 1 && cuts[i + 1].second > -0.5) {
|
||||
before =
|
||||
std::upper_bound(dists.begin(), dists.end(), cuts[i + 1].second) -
|
||||
dists.begin();
|
||||
}
|
||||
|
||||
POLYLINE afterPl(LINE(shape.begin(), shape.begin() + before));
|
||||
size_t to = std::upper_bound(dists.begin(), dists.end(), cuts[i].second) -
|
||||
dists.begin();
|
||||
if (to >= dists.size()) to = dists.size() - 1;
|
||||
double progr = (cuts[i].second - dists[to - 1]) / (dists[to] - dists[to - 1]);
|
||||
// std::cout << t->getId() << ": " << dists[to] << " vs " << cuts[i].second << ", " << dists[to - 1] << " (" << progr << ")" << std::endl;
|
||||
auto curP = shape[to - 1];
|
||||
curP.setX(curP.getX() + progr * util::geo::dist(shape[to-1], shape[to]));
|
||||
curP.setY(curP.getY() + progr * util::geo::dist(shape[to-1], shape[to]));
|
||||
|
||||
auto curLp = afterPl.projectOnAfter(cuts[i].first, lastLp.lastIndex);
|
||||
|
||||
auto curL = pl.getSegment(lastLp, curLp).getLine();
|
||||
auto curL = pl.getSegment(lastP, curP).getLine();
|
||||
|
||||
double dist =
|
||||
util::geo::haversine(t->getStopTimes()[i - 1].getStop()->getLat(),
|
||||
|
|
@ -226,7 +235,7 @@ std::vector<LINE> Collector::segmentize(
|
|||
lenDist.push_back({dist, len});
|
||||
|
||||
ret.push_back(curL);
|
||||
lastLp = curLp;
|
||||
lastP = curP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -275,6 +284,10 @@ void Collector::printShortStats(std::ostream* os) const {
|
|||
static_cast<double>(_results.size())) *
|
||||
100
|
||||
<< ",";
|
||||
(*os) << (static_cast<double>(_an20) /
|
||||
static_cast<double>(_results.size())) *
|
||||
100
|
||||
<< ",";
|
||||
(*os) << (static_cast<double>(_an30) /
|
||||
static_cast<double>(_results.size())) *
|
||||
100
|
||||
|
|
@ -332,6 +345,12 @@ void Collector::printStats(std::ostream* os) const {
|
|||
100
|
||||
<< " %"
|
||||
<< "\n";
|
||||
(*os) << " an-20: "
|
||||
<< (static_cast<double>(_an20) /
|
||||
static_cast<double>(_results.size())) *
|
||||
100
|
||||
<< " %"
|
||||
<< "\n";
|
||||
(*os) << " acc-30: "
|
||||
<< (static_cast<double>(_an30) /
|
||||
static_cast<double>(_results.size())) *
|
||||
|
|
@ -398,6 +417,8 @@ std::map<string, double> Collector::getStats() {
|
|||
(static_cast<double>(_an5) / static_cast<double>(_results.size())) * 100;
|
||||
stats["an-10"] =
|
||||
(static_cast<double>(_an10) / static_cast<double>(_results.size())) * 100;
|
||||
stats["an-20"] =
|
||||
(static_cast<double>(_an20) / static_cast<double>(_results.size())) * 100;
|
||||
stats["an-30"] =
|
||||
(static_cast<double>(_an30) / static_cast<double>(_results.size())) * 100;
|
||||
stats["an-50"] =
|
||||
|
|
@ -419,7 +440,7 @@ std::pair<size_t, double> Collector::getDa(const std::vector<LINE>& a,
|
|||
// convert (roughly) to degrees
|
||||
double SEGL = 25 / util::geo::M_PER_DEG;
|
||||
|
||||
double MAX = 50;
|
||||
double MAX = 100;
|
||||
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
double fdMeter = 0;
|
||||
|
|
@ -440,8 +461,8 @@ std::pair<size_t, double> Collector::getDa(const std::vector<LINE>& a,
|
|||
_dACache[aSimpl][bSimpl] = fdMeter;
|
||||
}
|
||||
} else {
|
||||
fdMeter = util::geo::frechetDistHav(aSimpl, bSimpl, SEGL);
|
||||
_dACache[aSimpl][bSimpl] = fdMeter;
|
||||
fdMeter = util::geo::frechetDistHav(aSimpl, bSimpl, SEGL);
|
||||
_dACache[aSimpl][bSimpl] = fdMeter;
|
||||
}
|
||||
|
||||
if (fdMeter >= MAX) {
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class Collector {
|
|||
size_t _an0;
|
||||
size_t _an5;
|
||||
size_t _an10;
|
||||
size_t _an20;
|
||||
size_t _an30;
|
||||
size_t _an50;
|
||||
size_t _an70;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@
|
|||
#include <thread>
|
||||
#include <vector>
|
||||
#include "ad/cppgtfs/Parser.h"
|
||||
#include "pfaedle/router/TripTrie.h"
|
||||
#include "shapevl/Collector.h"
|
||||
#include "util/Misc.h"
|
||||
#include "util/json/Writer.h"
|
||||
#include "util/log/Log.h"
|
||||
|
||||
using pfaedle::router::TripTrie;
|
||||
|
||||
std::atomic<int> count(0);
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
@ -37,7 +40,7 @@ void printHelp(int argc, char** argv) {
|
|||
void eval(const std::vector<std::string>* paths,
|
||||
std::vector<pfaedle::eval::Collector>* colls,
|
||||
const std::set<Route::TYPE>* mots,
|
||||
const ad::cppgtfs::gtfs::Feed* evalFeed) {
|
||||
const ad::cppgtfs::gtfs::Feed* evalFeed, bool unique) {
|
||||
while (1) {
|
||||
int myFeed = count-- - 1;
|
||||
if (myFeed < 0) return;
|
||||
|
|
@ -54,18 +57,59 @@ void eval(const std::vector<std::string>* paths,
|
|||
exit(1);
|
||||
}
|
||||
|
||||
std::vector<ad::cppgtfs::gtfs::Trip*> trips;
|
||||
|
||||
if (unique) {
|
||||
std::map<const ad::cppgtfs::gtfs::Route*,
|
||||
std::vector<TripTrie<ad::cppgtfs::gtfs::Trip>>>
|
||||
forest;
|
||||
for (auto t : evalFeed->getTrips()) {
|
||||
auto& subForest = forest[t.second->getRoute()];
|
||||
bool ins = false;
|
||||
for (auto& trie : subForest) {
|
||||
if (trie.addTrip(t.second,
|
||||
pfaedle::router::RoutingAttrs{
|
||||
t.second->getRoute()->getId(), "", ""},
|
||||
false, false)) {
|
||||
ins = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ins) {
|
||||
subForest.resize(subForest.size() + 1);
|
||||
subForest.back().addTrip(t.second,
|
||||
pfaedle::router::RoutingAttrs{
|
||||
t.second->getRoute()->getId(), "", ""},
|
||||
false, false);
|
||||
}
|
||||
}
|
||||
for (auto f : forest) {
|
||||
for (auto sf : f.second) {
|
||||
for (auto leaf : sf.getNdTrips()) {
|
||||
// only one reference node
|
||||
trips.push_back(leaf.second.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto t : evalFeed->getTrips()) {
|
||||
trips.push_back(t.second);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Evaluating " << path << "...";
|
||||
size_t i = 0;
|
||||
for (const auto& oldTrip : evalFeed->getTrips()) {
|
||||
LOG(DEBUG) << "@ " << ++i << "/" << evalFeed->getTrips().size();
|
||||
if (!mots->count(oldTrip.second->getRoute()->getType())) continue;
|
||||
auto newTrip = feed.getTrips().get(oldTrip.first);
|
||||
for (const auto& oldTrip : trips) {
|
||||
LOG(DEBUG) << "@ " << ++i << "/" << trips.size();
|
||||
if (!mots->count(oldTrip->getRoute()->getType())) continue;
|
||||
auto newTrip = feed.getTrips().get(oldTrip->getId());
|
||||
if (!newTrip) {
|
||||
LOG(ERROR) << "Trip #" << oldTrip.first << " not present in " << path
|
||||
LOG(ERROR) << "Trip #" << oldTrip->getId() << " not present in " << path
|
||||
<< ", skipping...";
|
||||
continue;
|
||||
}
|
||||
(*colls)[myFeed].add(oldTrip.second, oldTrip.second->getShape(), newTrip,
|
||||
(*colls)[myFeed].add(oldTrip, oldTrip->getShape(), newTrip,
|
||||
newTrip->getShape());
|
||||
}
|
||||
}
|
||||
|
|
@ -90,6 +134,7 @@ int main(int argc, char** argv) {
|
|||
bool summarize = false;
|
||||
bool json = false;
|
||||
bool avg = false;
|
||||
bool unique = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::string cur = argv[i];
|
||||
|
|
@ -106,6 +151,8 @@ int main(int argc, char** argv) {
|
|||
summarize = true;
|
||||
} else if (cur == "--json") {
|
||||
json = true;
|
||||
} else if (cur == "--unique") {
|
||||
unique = true;
|
||||
} else if (cur == "--avg") {
|
||||
avg = true;
|
||||
} else if (cur == "-f") {
|
||||
|
|
@ -169,8 +216,8 @@ int main(int argc, char** argv) {
|
|||
|
||||
std::vector<std::thread> thrds(THREADS);
|
||||
for (auto& thr : thrds)
|
||||
thr =
|
||||
std::thread(&eval, &evlFeedPaths, &evalColls, &mots, &groundTruthFeed);
|
||||
thr = std::thread(&eval, &evlFeedPaths, &evalColls, &mots, &groundTruthFeed,
|
||||
unique);
|
||||
|
||||
for (auto& thr : thrds) thr.join();
|
||||
|
||||
|
|
@ -188,9 +235,7 @@ int main(int argc, char** argv) {
|
|||
util::json::Dict jsonStats;
|
||||
|
||||
if (evalColls.size() == 1) {
|
||||
jsonStats = {
|
||||
{"statistics", stats[evlFeedPaths[0]]
|
||||
}};
|
||||
jsonStats = {{"statistics", stats[evlFeedPaths[0]]}};
|
||||
} else {
|
||||
if (avg) {
|
||||
double count = evalColls.size();
|
||||
|
|
@ -206,13 +251,9 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
avgStats[k] = sum / count;
|
||||
}
|
||||
jsonStats = {
|
||||
{"statistics", avgStats
|
||||
}};
|
||||
jsonStats = {{"statistics", avgStats}};
|
||||
} else {
|
||||
jsonStats = {
|
||||
{"statistics", stats
|
||||
}};
|
||||
jsonStats = {{"statistics", stats}};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue