// Copyright 2018, University of Freiburg, // Chair of Algorithms and Data Structures. // Authors: Patrick Brosi #include #include #include #include #include #include #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/Writer.h" #include "util/log/Log.h" 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); std::string getFileNameMotStr(const MOTs& mots); 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); if (cfg.osmPath.empty()) { std::cerr << "No OSM input file specified (-x), see --help." << std::endl; exit(5); } 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) { std::cerr << "Maximally one input feed allowed." << std::endl; exit(2); } 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."; exit(3); } } 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, cfg.shapeTripId, true); } OsmBuilder osmBuilder; std::vector 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); } 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."; } std::vector 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()) { std::string filePost; auto usedMots = getContMots(motCfg, cmdCfgMots); if (!usedMots.size()) continue; if (motCfgReader.getConfigs().size() > 1) filePost = getFileNameMotStr(usedMots); std::string motStr = getMotStr(usedMots); LOG(INFO) << "Calculating shapes for mots " << motStr; ShapeBuilder shapeBuilder(>fs, cmdCfgMots, motCfg, &ecoll, cfg); if (cfg.writeGraph) { LOG(INFO) << "Outputting graph.json..."; 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, util::json::Dict{{"ver", "old"}}); } o.print(l, util::json::Dict{{"ver", "new"}}); o.flush(); pstr.close(); exit(0); } pfaedle::netgraph::Graph ng; shapeBuilder.shape(&ng); if (cfg.buildTransitGraph) { util::geo::output::GeoGraphJsonOutput out; LOG(INFO) << "Outputting trgraph" + filePost + ".json..."; std::ofstream fstr(cfg.dbgOutputPath + "/trgraph" + filePost + ".json"); out.print(ng, fstr); fstr.close(); } } if (cfg.evaluate) ecoll.printStats(&std::cout); if (cfg.feedPaths.size()) { LOG(INFO) << "Writing output GTFS to " << cfg.outputPath << " ..."; 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; } // _____________________________________________________________________________ std::string getFileNameMotStr(const MOTs& mots) { std::string motStr; for (const auto& mot : mots) { motStr += "-" + Route::getTypeString(mot); } return motStr; } // _____________________________________________________________________________ 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; }