be a bit less verbose
This commit is contained in:
parent
45027d5496
commit
7f0443243c
12 changed files with 210 additions and 45 deletions
|
@ -26,7 +26,7 @@ else()
|
|||
message(WARNING "Configuring without OpenMP!")
|
||||
set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wfatal-errors -Wextra -Wno-implicit-fallthrough -pedantic")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DLOGLEVEL=3")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DLOGLEVEL=3 -DPFAEDLE_DBG=1")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} -DLOGLEVEL=2")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -DLOGLEVEL=2")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} -g -DLOGLEVEL=3")
|
||||
|
@ -77,10 +77,10 @@ add_custom_target(
|
|||
# handles install target
|
||||
|
||||
install(
|
||||
FILES README.md pfaedle.cfg DESTINATION share/${PROJECT_NAME} PERMISSIONS WORLD_READ
|
||||
FILES pfaedle.cfg DESTINATION etc/${PROJECT_NAME} COMPONENT config PERMISSIONS WORLD_READ
|
||||
)
|
||||
|
||||
install(
|
||||
FILES build/pfaedle DESTINATION bin
|
||||
PERMISSIONS WORLD_EXECUTE
|
||||
PERMISSIONS WORLD_EXECUTE COMPONENT binaries
|
||||
)
|
||||
|
|
|
@ -56,14 +56,19 @@ int main(int argc, char** argv) {
|
|||
|
||||
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) {
|
||||
LOG(ERROR) << "Maximal one input feed allowed.";
|
||||
exit(1);
|
||||
std::cerr << "Maximally one input feed allowed." << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Read " << motCfgReader.getConfigs().size()
|
||||
|
@ -75,7 +80,7 @@ int main(int argc, char** argv) {
|
|||
singleTrip = gtfs.getTrips().get(cfg.shapeTripId);
|
||||
if (!singleTrip) {
|
||||
LOG(ERROR) << "Trip #" << cfg.shapeTripId << " not found.";
|
||||
exit(1);
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +89,7 @@ int main(int argc, char** argv) {
|
|||
BBoxIdx box(2500);
|
||||
if (cfg.feedPaths.size()) {
|
||||
box = ShapeBuilder::getPaddedGtfsBox(>fs, 2500, cmdCfgMots,
|
||||
cfg.shapeTripId);
|
||||
cfg.shapeTripId, true);
|
||||
}
|
||||
OsmBuilder osmBuilder;
|
||||
std::vector<pfaedle::osm::OsmReadOpts> opts;
|
||||
|
@ -96,6 +101,13 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
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<double> dfBins;
|
||||
|
|
|
@ -18,15 +18,21 @@ using std::string;
|
|||
using std::exception;
|
||||
using std::vector;
|
||||
|
||||
static const char* YEAR = __DATE__ + 7;
|
||||
static const char* COPY =
|
||||
"University of Freiburg - Chair of Algorithms and Data Structures";
|
||||
static const char* AUTHORS = "Patrick Brosi <brosi@informatik.uni-freiburg.de>";
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void ConfigReader::help() {
|
||||
void ConfigReader::help(const char* bin) {
|
||||
std::cout
|
||||
<< std::setfill(' ') << std::left
|
||||
<< "\033[1mpfaedle GTFS map matcher \033[22m\n"
|
||||
<< "pfaedle GTFS map matcher\n"
|
||||
<< VERSION_FULL << " (built " << __DATE__ << " " << __TIME__ << ")\n\n"
|
||||
<< "(C) 2018 University of Freiburg\n"
|
||||
<< "Author: Patrick Brosi <brosi@informatik.uni-freiburg.de>\n\n"
|
||||
<< "(C) " << YEAR << " " << COPY << "\n"
|
||||
<< "Authors: " << AUTHORS << "\n\n"
|
||||
<< "Usage: "
|
||||
<< bin
|
||||
<< " -x <OSM FILE> -c <CFG FILE> <GTFS FEED>\n\n"
|
||||
<< "Allowed options:\n\n"
|
||||
<< "General:\n"
|
||||
|
@ -163,14 +169,17 @@ void ConfigReader::read(Config* cfg, int argc, char** argv) {
|
|||
cfg->dbgOutputPath = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
std::cout << VERSION_FULL << " (built " << __DATE__ << " " << __TIME__
|
||||
<< ")\n\n";
|
||||
std::cout << "pfaedle " << VERSION_FULL << " (built " << __DATE__ << " "
|
||||
<< __TIME__ << ")\n"
|
||||
<< "(C) " << YEAR << " " << COPY << "\n"
|
||||
<< "Authors: " << AUTHORS << "\nGNU General Public "
|
||||
"License v3.0\n";
|
||||
exit(0);
|
||||
case 'p':
|
||||
printOpts = true;
|
||||
break;
|
||||
case 'h':
|
||||
help();
|
||||
help(argv[0]);
|
||||
exit(0);
|
||||
case ':':
|
||||
std::cerr << argv[optind - 1];
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace config {
|
|||
class ConfigReader {
|
||||
public:
|
||||
static void read(Config* targetConfig, int argc, char** argv);
|
||||
static void help();
|
||||
static void help(const char* bin);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
if (!bbox.size()) return;
|
||||
if (!fs->size()) return;
|
||||
|
||||
LOG(INFO) << "Reading OSM file " << path << " ... ";
|
||||
|
||||
NodeSet orphanStations;
|
||||
EdgTracks eTracks;
|
||||
{
|
||||
|
@ -210,7 +212,7 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
LOG(VDEBUG) << "Write dummy node self-edges...";
|
||||
writeSelfEdgs(g);
|
||||
|
||||
LOG(INFO) << "Graph has " << g->getNds()->size() << " nodes and " << comps
|
||||
LOG(DEBUG) << "Graph has " << g->getNds()->size() << " nodes and " << comps
|
||||
<< " connected component(s)";
|
||||
}
|
||||
|
||||
|
|
|
@ -187,9 +187,9 @@ pfaedle::router::Shape ShapeBuilder::shape(Trip* trip) {
|
|||
void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
||||
TrGraphEdgs gtfsGraph;
|
||||
|
||||
LOG(INFO) << "Clustering trips...";
|
||||
LOG(DEBUG) << "Clustering trips...";
|
||||
Clusters clusters = clusterTrips(_feed, _mots);
|
||||
LOG(INFO) << "Clustered trips into " << clusters.size() << " clusters.";
|
||||
LOG(DEBUG) << "Clustered trips into " << clusters.size() << " clusters.";
|
||||
|
||||
std::map<ad::cppgtfs::gtfs::Shape*, size_t> shpUsage;
|
||||
for (auto t : _feed->getTrips()) {
|
||||
|
@ -218,11 +218,18 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
{
|
||||
LOG(INFO) << "@ " << j << " / " << clusters.size() << " ("
|
||||
<< (static_cast<int>((j * 1.0) / clusters.size() * 100))
|
||||
<< "%, " << (EDijkstra::ITERS - oiters) << " iters, tput "
|
||||
<< "%, "
|
||||
<< (EDijkstra::ITERS - oiters) << " iters, "
|
||||
/**
|
||||
TODO: this is actually misleading. We are counting the
|
||||
Dijkstra iterations, but the measuring them against
|
||||
the total running time (including all overhead + HMM solve)
|
||||
<< tput "
|
||||
<< (static_cast<double>(EDijkstra::ITERS - oiters)) /
|
||||
TOOK(t1, TIME())
|
||||
<< " iters/ms"
|
||||
<< ", " << (10.0 / (TOOK(t1, TIME()) / 1000))
|
||||
<< " iters/ms, "
|
||||
**/
|
||||
<< "matching " << (10.0 / (TOOK(t1, TIME()) / 1000))
|
||||
<< " trips/sec)";
|
||||
|
||||
oiters = EDijkstra::ITERS;
|
||||
|
@ -265,19 +272,18 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Done.";
|
||||
LOG(INFO) << "Matched " << totNumTrips << " trips in " << clusters.size()
|
||||
<< " clusters.";
|
||||
LOG(INFO) << "Took " << (EDijkstra::ITERS - totiters)
|
||||
LOG(DEBUG) << "Took " << (EDijkstra::ITERS - totiters)
|
||||
<< " iterations in total.";
|
||||
LOG(INFO) << "Took " << TOOK(t2, TIME()) << " ms in total.";
|
||||
LOG(INFO) << "Total avg. tput "
|
||||
LOG(DEBUG) << "Took " << TOOK(t2, TIME()) << " ms in total.";
|
||||
LOG(DEBUG) << "Total avg. tput "
|
||||
<< (static_cast<double>(EDijkstra::ITERS - totiters)) /
|
||||
TOOK(t2, TIME())
|
||||
<< " iters/sec";
|
||||
LOG(INFO) << "Total avg. trip tput "
|
||||
LOG(DEBUG) << "Total avg. trip tput "
|
||||
<< (clusters.size() / (TOOK(t2, TIME()) / 1000)) << " trips/sec";
|
||||
LOG(INFO) << "Avg hop distance was "
|
||||
LOG(DEBUG) << "Avg hop distance was "
|
||||
<< (totAvgDist / static_cast<double>(clusters.size())) << " meters";
|
||||
|
||||
if (_cfg.buildTransitGraph) {
|
||||
|
@ -438,11 +444,13 @@ const RoutingAttrs& ShapeBuilder::getRAttrs(const Trip* trip) const {
|
|||
|
||||
// _____________________________________________________________________________
|
||||
BBoxIdx ShapeBuilder::getPaddedGtfsBox(const Feed* feed, double pad,
|
||||
const MOTs& mots,
|
||||
const std::string& tid) {
|
||||
const MOTs& mots, const std::string& tid,
|
||||
bool dropShapes) {
|
||||
osm::BBoxIdx box(pad);
|
||||
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())) {
|
||||
Box<float> cur = minbox<float>();
|
||||
for (const auto& st : t.second->getStopTimes()) {
|
||||
|
@ -458,10 +466,11 @@ BBoxIdx ShapeBuilder::getPaddedGtfsBox(const Feed* feed, double pad,
|
|||
|
||||
// _____________________________________________________________________________
|
||||
void ShapeBuilder::buildGraph() {
|
||||
LOG(INFO) << "Reading " << _cfg.osmPath << " ... ";
|
||||
osm::OsmBuilder osmBuilder;
|
||||
|
||||
osm::BBoxIdx box = getPaddedGtfsBox(_feed, 2500, _mots, _cfg.shapeTripId);
|
||||
osm::BBoxIdx box =
|
||||
getPaddedGtfsBox(_feed, 2500, _mots, _cfg.shapeTripId, _cfg.dropShapes);
|
||||
|
||||
|
||||
osmBuilder.read(_cfg.osmPath, _motCfg.osmBuildOpts, &_g, box, _cfg.gridSize,
|
||||
getFeedStops(), &_restr);
|
||||
|
@ -475,8 +484,6 @@ void ShapeBuilder::buildGraph() {
|
|||
_motCfg.routingOpts.nonOsmPen);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Done.";
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
@ -525,7 +532,6 @@ Clusters ShapeBuilder::clusterTrips(Feed* f, MOTs mots) {
|
|||
|
||||
Clusters ret;
|
||||
for (const auto& trip : f->getTrips()) {
|
||||
// if (trip.second->getId() != "L5Cvl_T01") continue;
|
||||
if (trip.second->getShape() && !_cfg.dropShapes) continue;
|
||||
if (trip.second->getStopTimes().size() < 2) continue;
|
||||
if (!mots.count(trip.second->getRoute()->getType()) ||
|
||||
|
|
|
@ -66,7 +66,8 @@ class ShapeBuilder {
|
|||
|
||||
static osm::BBoxIdx getPaddedGtfsBox(const Feed* feed, double pad,
|
||||
const MOTs& mots,
|
||||
const std::string& tid);
|
||||
const std::string& tid,
|
||||
bool dropShapes);
|
||||
|
||||
private:
|
||||
Feed* _feed;
|
||||
|
|
|
@ -21,21 +21,52 @@ StatInfo NodePL::_blockerSI = StatInfo();
|
|||
std::unordered_map<const Component*, size_t> NodePL::_comps;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
NodePL::NodePL() : _geom(0, 0), _si(0), _component(0), _vis(0) {}
|
||||
NodePL::NodePL()
|
||||
: _geom(0, 0),
|
||||
_si(0),
|
||||
_component(0)
|
||||
#ifdef PFAEDLE_DBG
|
||||
,
|
||||
_vis(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
NodePL::NodePL(const NodePL& pl)
|
||||
: _geom(pl._geom), _si(0), _component(pl._component), _vis(pl._vis) {
|
||||
: _geom(pl._geom),
|
||||
_si(0),
|
||||
_component(pl._component)
|
||||
#ifdef PFAEDLE_DBG
|
||||
,
|
||||
_vis(pl._vis)
|
||||
#endif
|
||||
{
|
||||
if (pl._si) setSI(*(pl._si));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
NodePL::NodePL(const util::geo::FPoint& geom)
|
||||
: _geom(geom), _si(0), _component(0), _vis(0) {}
|
||||
: _geom(geom),
|
||||
_si(0),
|
||||
_component(0)
|
||||
#ifdef PFAEDLE_DBG
|
||||
,
|
||||
_vis(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
NodePL::NodePL(const util::geo::FPoint& geom, const StatInfo& si)
|
||||
: _geom(geom), _si(0), _component(0), _vis(0) {
|
||||
: _geom(geom),
|
||||
_si(0),
|
||||
_component(0)
|
||||
#ifdef PFAEDLE_DBG
|
||||
,
|
||||
_vis(0)
|
||||
#endif
|
||||
{
|
||||
setSI(si);
|
||||
}
|
||||
|
||||
|
@ -52,7 +83,11 @@ NodePL::~NodePL() {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void NodePL::setVisited() const { _vis = true; }
|
||||
void NodePL::setVisited() const {
|
||||
#ifdef PFAEDLE_DBG
|
||||
_vis = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void NodePL::setNoStat() { _si = 0; }
|
||||
|
@ -81,7 +116,9 @@ void NodePL::setGeom(const util::geo::FPoint& geom) { _geom = geom; }
|
|||
// _____________________________________________________________________________
|
||||
void NodePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
||||
(*obj)["component"] = std::to_string(reinterpret_cast<size_t>(_component));
|
||||
#ifdef PFAEDLE_DBG
|
||||
(*obj)["dijkstra_vis"] = _vis ? "yes" : "no";
|
||||
#endif
|
||||
if (getSI()) {
|
||||
(*obj)["station_info_ptr"] = util::toString(_si);
|
||||
(*obj)["station_name"] = _si->getName();
|
||||
|
|
|
@ -62,19 +62,20 @@ class NodePL : public GeoNodePL<float> {
|
|||
bool isBlocker() const;
|
||||
|
||||
// Mark this node as visited (usefull for counting search space in Dijkstra)
|
||||
// (only works for DEBUG build type)
|
||||
void setVisited() const;
|
||||
|
||||
private:
|
||||
std::string _b;
|
||||
// 32bit floats are enough here
|
||||
util::geo::FPoint _geom;
|
||||
StatInfo* _si;
|
||||
const Component* _component;
|
||||
|
||||
static StatInfo _blockerSI;
|
||||
|
||||
#ifdef PFAEDLE_DBG
|
||||
mutable bool _vis;
|
||||
#endif
|
||||
|
||||
static StatInfo _blockerSI;
|
||||
static std::unordered_map<const Component*, size_t> _comps;
|
||||
};
|
||||
} // namespace trgraph
|
||||
|
|
|
@ -403,6 +403,14 @@ inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) {
|
|||
((crossProd(ls2.first, ls1) < 0) ^ (crossProd(ls2.second, ls1) < 0)));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool intersects(const Point<T>& a, const Point<T>& b, const Point<T>& c,
|
||||
const Point<T>& d) {
|
||||
// legacy function
|
||||
return intersects(LineSegment<T>(a, b), LineSegment<T>(c, d));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool intersects(const Line<T>& ls1, const Line<T>& ls2) {
|
||||
|
@ -605,6 +613,78 @@ inline double dist(double x1, double y1, double x2, double y2) {
|
|||
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const LineSegment<T>& ls, const Point<T>& p) {
|
||||
return distToSegment(ls, p);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Point<T>& p, const LineSegment<T>& ls) {
|
||||
return dist(ls, p);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const LineSegment<T>& ls1, const LineSegment<T>& ls2) {
|
||||
if (intersects(ls1, ls2)) return 0;
|
||||
double d1 = dist(ls1.first, ls2);
|
||||
double d2 = dist(ls1.second, ls2);
|
||||
double d3 = dist(ls2.first, ls1);
|
||||
double d4 = dist(ls2.second, ls1);
|
||||
return std::min(d1, std::min(d2, (std::min(d3, d4))));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Point<T>& p, const Line<T>& l) {
|
||||
double d = std::numeric_limits<double>::infinity();
|
||||
for (size_t i = 1; i < l.size(); i++) {
|
||||
double dTmp = distToSegment(l[i-1], l[i], p);
|
||||
if (dTmp < EPSILON) return 0;
|
||||
if (dTmp < d) d = dTmp;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Line<T>& l, const Point<T>& p) {
|
||||
return dist(p, l);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const LineSegment<T>& ls, const Line<T>& l) {
|
||||
double d = std::numeric_limits<double>::infinity();
|
||||
for (size_t i = 1; i < l.size(); i++) {
|
||||
double dTmp = dist(ls, LineSegment<T>(l[i-1], l[i]));
|
||||
if (dTmp < EPSILON) return 0;
|
||||
if (dTmp < d) d = dTmp;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Line<T>& l, const LineSegment<T>& ls) {
|
||||
return dist(ls, l);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Line<T>& la, const Line<T>& lb) {
|
||||
double d = std::numeric_limits<double>::infinity();
|
||||
for (size_t i = 1; i < la.size(); i++) {
|
||||
double dTmp = dist(LineSegment<T>(la[i-1], la[i]), lb);
|
||||
if (dTmp < EPSILON) return 0;
|
||||
if (dTmp < d) d = dTmp;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline double innerProd(double x1, double y1, double x2, double y2, double x3,
|
||||
double y3) {
|
||||
|
|
|
@ -33,7 +33,7 @@ class Polygon {
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
using MultiPolyon = std::vector<Polygon<T>>;
|
||||
using MultiPolygon = std::vector<Polygon<T>>;
|
||||
|
||||
} // namespace geo
|
||||
} // namespace util
|
||||
|
|
|
@ -1024,7 +1024,7 @@ CASE("geometry") {
|
|||
EXPECT(geo::dist(geo::centroid(Polygon<double>({{0, 0}, {3, 4}, {4,3}})), Point<double>(7.0/3.0,7.0/3.0)) == approx(0));
|
||||
|
||||
auto polyy = Polygon<double>({{0, 0}, {3, 4}, {4,3}});
|
||||
MultiPolyon<double> mpoly{polyy, polyy};
|
||||
MultiPolygon<double> mpoly{polyy, polyy};
|
||||
|
||||
EXPECT(geo::getWKT(polyy) == "POLYGON ((0 0, 3 4, 4 3, 0 0))");
|
||||
EXPECT(geo::getWKT(mpoly) == "MULTIPOLYGON (((0 0, 3 4, 4 3, 0 0)), ((0 0, 3 4, 4 3, 0 0)))");
|
||||
|
@ -1209,6 +1209,23 @@ CASE("geometry") {
|
|||
auto obox = geo::getOrientedEnvelope(geo::Line<double>{{0, 0}, {1, 1}, {1.5, 0.5}});
|
||||
EXPECT(geo::contains(geo::convexHull(obox), geo::Polygon<double>({{0.0, 0.0}, {1.0, 1.0}, {1.5, 0.5}, {0.5, -0.5}})));
|
||||
EXPECT(geo::contains(geo::Polygon<double>({{0.0, 0.0}, {1.0, 1.0}, {1.5, 0.5}, {0.5, -0.5}}), geo::convexHull(obox)));
|
||||
|
||||
EXPECT(geo::dist(geo::LineSegment<double>{{1, 1}, {3, 1}}, geo::LineSegment<double>{{2, 2}, {2, 0}}) == approx(0));
|
||||
EXPECT(geo::dist(geo::LineSegment<double>{{1, 1}, {3, 1}}, geo::LineSegment<double>{{2, 4}, {2, 2}}) == approx(1));
|
||||
EXPECT(geo::dist(geo::LineSegment<double>{{1, 1}, {3, 1}}, geo::LineSegment<double>{{1, 1}, {3, 1}}) == approx(0));
|
||||
EXPECT(geo::dist(geo::LineSegment<double>{{1, 1}, {3, 1}}, geo::LineSegment<double>{{1, 2}, {3, 2}}) == approx(1));
|
||||
EXPECT(geo::dist(geo::LineSegment<double>{{1, 1}, {3, 1}}, geo::LineSegment<double>{{1, 2}, {3, 5}}) == approx(1));
|
||||
|
||||
EXPECT(geo::dist(geo::Line<double>{{1, 1}, {3, 1}}, geo::Point<double>{2, 1}) == approx(0));
|
||||
EXPECT(geo::dist(geo::Line<double>{{1, 1}, {3, 1}}, geo::Point<double>{2, 2}) == approx(1));
|
||||
EXPECT(geo::dist(geo::Line<double>{{1, 1}, {3, 1}}, geo::Point<double>{3, 1}) == approx(0));
|
||||
EXPECT(geo::dist(geo::Line<double>{{1, 1}, {3, 1}}, geo::Point<double>{1, 1}) == approx(0));
|
||||
|
||||
EXPECT(geo::dist(Line<double>{{7, 7}, {7, -7}, {-7, -7}, {-7, 7}, {9, 0}, {-9, 0}, {0, 9}, {0, -9}}, Line<double>{{7, 7}, {7, -7}, {-7, -7}, {-7, 7}, {9, 0}, {-9, 0}, {0, 9}, {0, -9}}) == approx(0));
|
||||
EXPECT(geo::dist(Line<double>{{7, 7}, {7, -7}, {-7, -7}, {-7, 7}, {9, 0}, {-9, 0}, {0, 9}, {0, -9}}, LineSegment<double>{{6, 7}, {8, -7}}) == approx(0));
|
||||
EXPECT(geo::dist(Line<double>{{7, 7}, {7, -7}, {-7, -7}, {-7, 7}, {9, 0}, {-9, 0}, {0, 9}, {0, -9}}, Point<double>{7, 4}) == approx(0));
|
||||
EXPECT(geo::dist(Line<double>{{0, 0}, {1, 1}, {2, 0}}, Line<double>{{1.5, 0.5}, {1.5, 100}}) == approx(0));
|
||||
EXPECT(geo::dist(Line<double>{{0, 0}, {1, 1}, {2, 0}}, Line<double>{{2, 0.5}, {2, 100}}) == approx(0.353553));
|
||||
}
|
||||
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue