2018-06-09 15:14:08 +00:00
|
|
|
// Copyright 2018, University of Freiburg,
|
|
|
|
// Chair of Algorithms and Data Structures.
|
|
|
|
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fstream>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include "ad/cppgtfs/Parser.h"
|
|
|
|
#include "ad/cppgtfs/Writer.h"
|
|
|
|
#include "ad/cppgtfs/gtfs/Feed.h"
|
|
|
|
#include "pfaedle/config/ConfigReader.h"
|
|
|
|
#include "pfaedle/config/MotConfig.h"
|
|
|
|
#include "pfaedle/config/MotConfigReader.h"
|
|
|
|
#include "pfaedle/eval/Collector.h"
|
|
|
|
#include "pfaedle/netgraph/Graph.h"
|
|
|
|
#include "pfaedle/osm/OsmIdSet.h"
|
|
|
|
#include "pfaedle/router/ShapeBuilder.h"
|
|
|
|
#include "pfaedle/trgraph/Graph.h"
|
|
|
|
#include "util/geo/output/GeoGraphJsonOutput.h"
|
|
|
|
#include "util/geo/output/GeoJsonOutput.h"
|
|
|
|
#include "util/json/JsonWriter.h"
|
|
|
|
#include "util/log/Log.h"
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
using pfaedle::router::MOTs;
|
|
|
|
using pfaedle::osm::BBoxIdx;
|
|
|
|
using pfaedle::osm::OsmBuilder;
|
|
|
|
using pfaedle::config::MotConfig;
|
|
|
|
using pfaedle::config::Config;
|
|
|
|
using pfaedle::router::ShapeBuilder;
|
|
|
|
using pfaedle::config::MotConfigReader;
|
|
|
|
using pfaedle::config::ConfigReader;
|
|
|
|
using pfaedle::eval::Collector;
|
|
|
|
|
|
|
|
std::string getMotStr(const MOTs& mots);
|
2018-07-25 18:14:46 +00:00
|
|
|
std::string getFileNameMotStr(const MOTs& mots);
|
2018-06-09 15:14:08 +00:00
|
|
|
MOTs getContMots(const MotConfig& motCfg, const MOTs& mots);
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
// disable output buffering for standard output
|
|
|
|
setbuf(stdout, NULL);
|
|
|
|
|
|
|
|
// initialize randomness
|
|
|
|
srand(time(NULL) + rand()); // NOLINT
|
|
|
|
|
|
|
|
Config cfg;
|
|
|
|
MotConfigReader motCfgReader;
|
|
|
|
|
|
|
|
ConfigReader cr;
|
|
|
|
cr.read(&cfg, argc, argv);
|
|
|
|
|
|
|
|
ad::cppgtfs::gtfs::Feed gtfs;
|
|
|
|
|
|
|
|
motCfgReader.parse(cfg.configPaths);
|
|
|
|
|
2018-07-24 17:33:18 +00:00
|
|
|
if (cfg.osmPath.empty()) {
|
|
|
|
std::cerr << "No OSM input file specified (-x), see --help." << std::endl;
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
|
2018-06-09 15:14:08 +00:00
|
|
|
if (cfg.feedPaths.size() == 1) {
|
|
|
|
LOG(INFO) << "Reading " << cfg.feedPaths[0] << " ...";
|
|
|
|
ad::cppgtfs::Parser p;
|
|
|
|
p.parse(>fs, cfg.feedPaths[0]);
|
|
|
|
LOG(INFO) << "Done.";
|
|
|
|
} else if (cfg.feedPaths.size() > 1) {
|
2018-07-24 17:33:18 +00:00
|
|
|
std::cerr << "Maximally one input feed allowed." << std::endl;
|
|
|
|
exit(2);
|
2018-06-09 15:14:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOG(DEBUG) << "Read " << motCfgReader.getConfigs().size()
|
|
|
|
<< " unique MOT configs.";
|
|
|
|
MOTs cmdCfgMots = cfg.mots;
|
|
|
|
ad::cppgtfs::gtfs::Trip* singleTrip = 0;
|
|
|
|
|
|
|
|
if (cfg.shapeTripId.size()) {
|
|
|
|
singleTrip = gtfs.getTrips().get(cfg.shapeTripId);
|
|
|
|
if (!singleTrip) {
|
|
|
|
LOG(ERROR) << "Trip #" << cfg.shapeTripId << " not found.";
|
2018-07-24 17:33:18 +00:00
|
|
|
exit(3);
|
2018-06-09 15:14:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg.writeOsm.size()) {
|
|
|
|
LOG(INFO) << "Writing filtered XML to " << cfg.writeOsm << " ...";
|
|
|
|
BBoxIdx box(2500);
|
|
|
|
if (cfg.feedPaths.size()) {
|
|
|
|
box = ShapeBuilder::getPaddedGtfsBox(>fs, 2500, cmdCfgMots,
|
2018-07-24 17:33:18 +00:00
|
|
|
cfg.shapeTripId, true);
|
2018-06-09 15:14:08 +00:00
|
|
|
}
|
|
|
|
OsmBuilder osmBuilder;
|
|
|
|
std::vector<pfaedle::osm::OsmReadOpts> opts;
|
|
|
|
for (const auto& o : motCfgReader.getConfigs()) {
|
|
|
|
if (std::find_first_of(o.mots.begin(), o.mots.end(), cmdCfgMots.begin(),
|
|
|
|
cmdCfgMots.end()) != o.mots.end()) {
|
|
|
|
opts.push_back(o.osmBuildOpts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
osmBuilder.filterWrite(cfg.osmPath, cfg.writeOsm, opts, box);
|
|
|
|
exit(0);
|
2018-07-24 17:33:18 +00:00
|
|
|
} else if (!cfg.feedPaths.size()) {
|
|
|
|
std::cout << "No input feed specified, see --help" << std::endl;
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (motCfgReader.getConfigs().size() == 0) {
|
|
|
|
LOG(WARN) << "No MOT configurations specified, see --help.";
|
2018-06-09 15:14:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<double> dfBins;
|
|
|
|
auto dfBinStrings = util::split(std::string(cfg.evalDfBins), ',');
|
|
|
|
for (auto st : dfBinStrings) dfBins.push_back(atof(st.c_str()));
|
|
|
|
Collector ecoll(cfg.evalPath, dfBins);
|
|
|
|
|
|
|
|
for (const auto& motCfg : motCfgReader.getConfigs()) {
|
2018-07-25 18:14:46 +00:00
|
|
|
std::string filePost;
|
2018-06-09 15:14:08 +00:00
|
|
|
auto usedMots = getContMots(motCfg, cmdCfgMots);
|
|
|
|
if (!usedMots.size()) continue;
|
2018-07-25 18:14:46 +00:00
|
|
|
if (motCfgReader.getConfigs().size() > 1)
|
|
|
|
filePost = getFileNameMotStr(usedMots);
|
2018-06-09 15:14:08 +00:00
|
|
|
|
|
|
|
std::string motStr = getMotStr(usedMots);
|
|
|
|
LOG(INFO) << "Calculating shapes for mots " << motStr;
|
|
|
|
|
|
|
|
ShapeBuilder shapeBuilder(>fs, cmdCfgMots, motCfg, &ecoll, cfg);
|
|
|
|
|
|
|
|
if (cfg.writeGraph) {
|
2018-07-25 18:14:46 +00:00
|
|
|
LOG(INFO) << "Outputting graph" + filePost + ".json...";
|
2018-06-09 15:14:08 +00:00
|
|
|
util::geo::output::GeoGraphJsonOutput out;
|
|
|
|
std::ofstream fstr(cfg.dbgOutputPath + "/graph.json");
|
|
|
|
out.print(*shapeBuilder.getGraph(), fstr);
|
|
|
|
fstr.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (singleTrip) {
|
|
|
|
LOG(INFO) << "Outputting path.json...";
|
|
|
|
std::ofstream pstr(cfg.dbgOutputPath + "/path.json");
|
|
|
|
util::geo::output::GeoJsonOutput o(pstr);
|
|
|
|
|
|
|
|
auto l = shapeBuilder.shapeL(singleTrip);
|
|
|
|
|
|
|
|
if (singleTrip->getShape()) {
|
|
|
|
auto orig = Collector::getWebMercLine(singleTrip->getShape(), -1, -1);
|
|
|
|
o.print(orig, {{"ver", "old"}});
|
|
|
|
}
|
|
|
|
|
|
|
|
o.print(l, {{"ver", "new"}});
|
|
|
|
o.flush();
|
|
|
|
pstr.close();
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pfaedle::netgraph::Graph ng;
|
|
|
|
shapeBuilder.shape(&ng);
|
|
|
|
|
|
|
|
if (cfg.buildTransitGraph) {
|
|
|
|
util::geo::output::GeoGraphJsonOutput out;
|
2018-07-25 18:14:46 +00:00
|
|
|
LOG(INFO) << "Outputting trgraph" + filePost + ".json...";
|
|
|
|
std::ofstream fstr(cfg.dbgOutputPath + "/trgraph" + filePost + ".json");
|
2018-06-09 15:14:08 +00:00
|
|
|
out.print(ng, fstr);
|
|
|
|
fstr.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg.evaluate) ecoll.printStats(&std::cout);
|
|
|
|
|
|
|
|
if (cfg.feedPaths.size()) {
|
2018-07-22 15:17:53 +00:00
|
|
|
LOG(INFO) << "Writing output GTFS to " << cfg.outputPath << " ...";
|
2018-06-09 15:14:08 +00:00
|
|
|
ad::cppgtfs::Writer w;
|
|
|
|
w.write(>fs, cfg.outputPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// _____________________________________________________________________________
|
|
|
|
std::string getMotStr(const MOTs& mots) {
|
|
|
|
bool first = false;
|
|
|
|
std::string motStr;
|
|
|
|
for (const auto& mot : mots) {
|
|
|
|
if (first) motStr += ", ";
|
|
|
|
motStr += "<" + Route::getTypeString(mot) + ">";
|
|
|
|
first = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return motStr;
|
|
|
|
}
|
|
|
|
|
2018-07-25 18:14:46 +00:00
|
|
|
// _____________________________________________________________________________
|
|
|
|
std::string getFileNameMotStr(const MOTs& mots) {
|
|
|
|
std::string motStr;
|
|
|
|
for (const auto& mot : mots) {
|
|
|
|
motStr += "-" + Route::getTypeString(mot);
|
|
|
|
}
|
|
|
|
|
|
|
|
return motStr;
|
|
|
|
}
|
|
|
|
|
2018-06-09 15:14:08 +00:00
|
|
|
// _____________________________________________________________________________
|
|
|
|
MOTs getContMots(const MotConfig& motCfg, const MOTs& mots) {
|
|
|
|
MOTs ret;
|
|
|
|
for (const auto& mot : mots) {
|
|
|
|
if (motCfg.mots.count(mot)) {
|
|
|
|
ret.insert(mot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|