refactoring
This commit is contained in:
parent
04e87c1d9c
commit
64b83f569c
24 changed files with 186 additions and 310 deletions
|
@ -21,10 +21,10 @@ endif()
|
||||||
|
|
||||||
# set compiler flags, see http://stackoverflow.com/questions/7724569/debug-vs-release-in-cmake
|
# set compiler flags, see http://stackoverflow.com/questions/7724569/debug-vs-release-in-cmake
|
||||||
if(OPENMP_FOUND)
|
if(OPENMP_FOUND)
|
||||||
set(CMAKE_CXX_FLAGS "-fopenmp -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")
|
set(CMAKE_CXX_FLAGS "-fopenmp -Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic")
|
||||||
else()
|
else()
|
||||||
message(WARNING "Configuring without OpenMP!")
|
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")
|
set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DLOGLEVEL=3 -DPFAEDLE_DBG=1")
|
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_MINSIZEREL "${CMAKE_CXX_FLAGS} -DLOGLEVEL=2")
|
||||||
|
|
|
@ -333,8 +333,10 @@ osm_filter_lvl4:
|
||||||
highway=living_street
|
highway=living_street
|
||||||
highway=pedestrian
|
highway=pedestrian
|
||||||
highway=service
|
highway=service
|
||||||
|
psv=no
|
||||||
|
|
||||||
osm_filter_lvl5:
|
osm_filter_lvl5:
|
||||||
|
bus=no
|
||||||
service=siding
|
service=siding
|
||||||
access=permissive
|
access=permissive
|
||||||
access=private
|
access=private
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "pfaedle/trgraph/Graph.h"
|
#include "pfaedle/trgraph/Graph.h"
|
||||||
#include "util/geo/output/GeoGraphJsonOutput.h"
|
#include "util/geo/output/GeoGraphJsonOutput.h"
|
||||||
#include "util/geo/output/GeoJsonOutput.h"
|
#include "util/geo/output/GeoJsonOutput.h"
|
||||||
#include "util/json/JsonWriter.h"
|
#include "util/json/Writer.h"
|
||||||
#include "util/log/Log.h"
|
#include "util/log/Log.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
@ -145,10 +145,10 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
if (singleTrip->getShape()) {
|
if (singleTrip->getShape()) {
|
||||||
auto orig = Collector::getWebMercLine(singleTrip->getShape(), -1, -1);
|
auto orig = Collector::getWebMercLine(singleTrip->getShape(), -1, -1);
|
||||||
o.print(orig, {{"ver", "old"}});
|
o.print(orig, util::json::Dict{{"ver", "old"}});
|
||||||
}
|
}
|
||||||
|
|
||||||
o.print(l, {{"ver", "new"}});
|
o.print(l, util::json::Dict{{"ver", "new"}});
|
||||||
o.flush();
|
o.flush();
|
||||||
pstr.close();
|
pstr.close();
|
||||||
|
|
||||||
|
|
|
@ -107,11 +107,11 @@ double Collector::add(const Trip* t, const Shape* oldS, const Shape* newS,
|
||||||
FLine newLCut;
|
FLine newLCut;
|
||||||
|
|
||||||
for (auto oldL : oldSegs) {
|
for (auto oldL : oldSegs) {
|
||||||
gjout.print(oldL, {{"ver", "old"}});
|
gjout.print(oldL, util::json::Dict{{"ver", "old"}});
|
||||||
oldLCut.insert(oldLCut.end(), oldL.begin(), oldL.end());
|
oldLCut.insert(oldLCut.end(), oldL.begin(), oldL.end());
|
||||||
}
|
}
|
||||||
for (auto newL : newSegs) {
|
for (auto newL : newSegs) {
|
||||||
gjout.print(newL, {{"ver", "new"}});
|
gjout.print(newL, util::json::Dict{{"ver", "new"}});
|
||||||
newLCut.insert(newLCut.end(), newL.begin(), newL.end());
|
newLCut.insert(newLCut.end(), newL.begin(), newL.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
#ifndef PFAEDLE_NETGRAPH_EDGEPL_H_
|
#ifndef PFAEDLE_NETGRAPH_EDGEPL_H_
|
||||||
#define PFAEDLE_NETGRAPH_EDGEPL_H_
|
#define PFAEDLE_NETGRAPH_EDGEPL_H_
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "ad/cppgtfs/gtfs/Feed.h"
|
#include "ad/cppgtfs/gtfs/Feed.h"
|
||||||
#include "util/String.h"
|
#include "util/String.h"
|
||||||
#include "util/geo/GeoGraph.h"
|
#include "util/geo/GeoGraph.h"
|
||||||
|
@ -33,12 +33,14 @@ class EdgePL : public GeoEdgePL<float> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const util::geo::FLine* getGeom() const { return &_l; }
|
const util::geo::FLine* getGeom() const { return &_l; }
|
||||||
void getAttrs(std::map<std::string, std::string>* obj) const {
|
util::json::Dict getAttrs() const {
|
||||||
(*obj)["num_trips"] = std::to_string(_trips.size());
|
util::json::Dict obj;
|
||||||
(*obj)["route_short_names"] =
|
obj["num_trips"] = static_cast<int>(_trips.size());
|
||||||
util::implode(_routeShortNames.begin(), _routeShortNames.end(), ", ");
|
obj["route_short_names"] = util::json::Array(
|
||||||
(*obj)["trip_short_names"] =
|
_routeShortNames.begin(), _routeShortNames.end());
|
||||||
util::implode(_tripShortNames.begin(), _tripShortNames.end(), ", ");
|
obj["trip_short_names"] = util::json::Array(_tripShortNames.begin(),
|
||||||
|
_tripShortNames.end());
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -25,8 +25,8 @@ class NodePL : public GeoNodePL<float> {
|
||||||
NodePL(const util::geo::FPoint& geom) { _geom = geom; } // NOLINT
|
NodePL(const util::geo::FPoint& geom) { _geom = geom; } // NOLINT
|
||||||
|
|
||||||
const util::geo::FPoint* getGeom() const { return &_geom; }
|
const util::geo::FPoint* getGeom() const { return &_geom; }
|
||||||
void getAttrs(std::map<std::string, std::string>* attrs) const {
|
util::json::Dict getAttrs() const {
|
||||||
UNUSED(attrs);
|
return util::json::Dict();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -190,7 +190,7 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
||||||
deleteOrphEdgs(g);
|
deleteOrphEdgs(g);
|
||||||
|
|
||||||
LOG(VDEBUG) << "Collapsing edges...";
|
LOG(VDEBUG) << "Collapsing edges...";
|
||||||
collapseEdges(g);
|
// collapseEdges(g);
|
||||||
|
|
||||||
LOG(VDEBUG) << "Deleting orphan nodes...";
|
LOG(VDEBUG) << "Deleting orphan nodes...";
|
||||||
deleteOrphNds(g);
|
deleteOrphNds(g);
|
||||||
|
@ -212,8 +212,14 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
||||||
LOG(VDEBUG) << "Write dummy node self-edges...";
|
LOG(VDEBUG) << "Write dummy node self-edges...";
|
||||||
writeSelfEdgs(g);
|
writeSelfEdgs(g);
|
||||||
|
|
||||||
LOG(DEBUG) << "Graph has " << g->getNds()->size() << " nodes and " << comps
|
size_t numEdges = 0;
|
||||||
<< " connected component(s)";
|
|
||||||
|
for (auto* n : *g->getNds()) {
|
||||||
|
numEdges += n->getAdjListOut().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "Graph has " << g->getNds()->size() << " nodes, " << numEdges
|
||||||
|
<< " edges and " << comps << " connected component(s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
|
@ -367,8 +373,7 @@ void OsmBuilder::readWriteWays(xml::File* i, util::xml::XmlWriter* o,
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
NodePL OsmBuilder::plFromGtfs(const Stop* s,
|
NodePL OsmBuilder::plFromGtfs(const Stop* s, const OsmReadOpts& ops) const {
|
||||||
const OsmReadOpts& ops) const {
|
|
||||||
NodePL ret(util::geo::latLngToWebMerc<float>(s->getLat(), s->getLng()),
|
NodePL ret(util::geo::latLngToWebMerc<float>(s->getLat(), s->getLng()),
|
||||||
StatInfo(ops.statNormzer(s->getName()),
|
StatInfo(ops.statNormzer(s->getName()),
|
||||||
ops.trackNormzer(s->getPlatformCode()), false));
|
ops.trackNormzer(s->getPlatformCode()), false));
|
||||||
|
@ -1671,7 +1676,6 @@ uint32_t OsmBuilder::writeComps(Graph* g) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// the last comp was not used
|
// the last comp was not used
|
||||||
delete comp;
|
delete comp;
|
||||||
|
|
||||||
|
|
|
@ -76,24 +76,27 @@ void EdgePL::setCost(const router::EdgeCost& c) { _cost = c; }
|
||||||
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
void EdgePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
util::json::Dict EdgePL::getAttrs() const {
|
||||||
(*obj)["cost"] = std::to_string(_cost.getValue());
|
util::json::Dict obj;
|
||||||
(*obj)["from_edge"] = util::toString(_startE);
|
obj["cost"] = std::to_string(_cost.getValue());
|
||||||
(*obj)["to_edge"] = util::toString(_endE);
|
obj["from_edge"] = util::toString(_startE);
|
||||||
(*obj)["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
obj["to_edge"] = util::toString(_endE);
|
||||||
(*obj)["cost_m_lvl0"] = std::to_string(_cost.meterDist);
|
obj["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
||||||
(*obj)["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
obj["cost_m_lvl0"] = std::to_string(_cost.meterDist);
|
||||||
(*obj)["cost_m_lvl2"] = std::to_string(_cost.meterDistLvl2);
|
obj["cost_m_lvl1"] = std::to_string(_cost.meterDistLvl1);
|
||||||
(*obj)["cost_m_lvl3"] = std::to_string(_cost.meterDistLvl3);
|
obj["cost_m_lvl2"] = std::to_string(_cost.meterDistLvl2);
|
||||||
(*obj)["cost_m_lvl4"] = std::to_string(_cost.meterDistLvl4);
|
obj["cost_m_lvl3"] = std::to_string(_cost.meterDistLvl3);
|
||||||
(*obj)["cost_m_lvl5"] = std::to_string(_cost.meterDistLvl5);
|
obj["cost_m_lvl4"] = std::to_string(_cost.meterDistLvl4);
|
||||||
(*obj)["cost_m_lvl6"] = std::to_string(_cost.meterDistLvl6);
|
obj["cost_m_lvl5"] = std::to_string(_cost.meterDistLvl5);
|
||||||
(*obj)["cost_m_lvl7"] = std::to_string(_cost.meterDistLvl7);
|
obj["cost_m_lvl6"] = std::to_string(_cost.meterDistLvl6);
|
||||||
(*obj)["cost_fullturn"] = std::to_string(_cost.fullTurns);
|
obj["cost_m_lvl7"] = std::to_string(_cost.meterDistLvl7);
|
||||||
(*obj)["cost_st_passthru"] = std::to_string(_cost.passThruStations);
|
obj["cost_fullturn"] = std::to_string(_cost.fullTurns);
|
||||||
(*obj)["cost_m_oneway"] = std::to_string(_cost.oneWayMeters);
|
obj["cost_st_passthru"] = std::to_string(_cost.passThruStations);
|
||||||
(*obj)["cost_m_lineunmatch"] = std::to_string(_cost.lineUnmatchedMeters);
|
obj["cost_m_oneway"] = std::to_string(_cost.oneWayMeters);
|
||||||
(*obj)["cost_reach_node_pen"] = std::to_string(_cost.reachPen);
|
obj["cost_m_lineunmatch"] = std::to_string(_cost.lineUnmatchedMeters);
|
||||||
(*obj)["cost_oneway_event"] = std::to_string(_cost.oneWayEdges);
|
obj["cost_reach_node_pen"] = std::to_string(_cost.reachPen);
|
||||||
(*obj)["dummy"] = _edges.size() ? "no" : "yes";
|
obj["cost_oneway_event"] = std::to_string(_cost.oneWayEdges);
|
||||||
|
obj["dummy"] = _edges.size() ? "no" : "yes";
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class EdgePL : public GeoEdgePL<float> {
|
||||||
public:
|
public:
|
||||||
EdgePL() : _cost(), _start(0), _end(0), _startE(0), _endE(0) {}
|
EdgePL() : _cost(), _start(0), _end(0), _startE(0), _endE(0) {}
|
||||||
const util::geo::FLine* getGeom() const;
|
const util::geo::FLine* getGeom() const;
|
||||||
void getAttrs(std::map<std::string, std::string>* attrs) const;
|
util::json::Dict getAttrs() const;
|
||||||
router::EdgeList* getEdges();
|
router::EdgeList* getEdges();
|
||||||
const router::EdgeList& getEdges() const;
|
const router::EdgeList& getEdges() const;
|
||||||
void setStartNode(const trgraph::Node* s);
|
void setStartNode(const trgraph::Node* s);
|
||||||
|
|
|
@ -23,8 +23,9 @@ class NodePL : public GeoNodePL<float> {
|
||||||
const util::geo::FPoint* getGeom() const {
|
const util::geo::FPoint* getGeom() const {
|
||||||
return !_n ? 0 : _n->pl().getGeom();
|
return !_n ? 0 : _n->pl().getGeom();
|
||||||
}
|
}
|
||||||
void getAttrs(std::map<std::string, std::string>* attrs) const {
|
util::json::Dict getAttrs() const {
|
||||||
if (_n) _n->pl().getAttrs(attrs);
|
if (_n) return _n->pl().getAttrs();
|
||||||
|
return util::json::Dict();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -108,11 +108,12 @@ const util::geo::FLine* EdgePL::getGeom() const { return _l; }
|
||||||
util::geo::FLine* EdgePL::getGeom() { return _l; }
|
util::geo::FLine* EdgePL::getGeom() { return _l; }
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
void EdgePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
util::json::Dict EdgePL::getAttrs() const {
|
||||||
(*obj)["m_length"] = std::to_string(_length);
|
util::json::Dict obj;
|
||||||
(*obj)["oneway"] = std::to_string(static_cast<int>(_oneWay));
|
obj["m_length"] = std::to_string(_length);
|
||||||
(*obj)["level"] = std::to_string(_lvl);
|
obj["oneway"] = std::to_string(static_cast<int>(_oneWay));
|
||||||
(*obj)["restriction"] = isRestricted() ? "yes" : "no";
|
obj["level"] = std::to_string(_lvl);
|
||||||
|
obj["restriction"] = isRestricted() ? "yes" : "no";
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
bool first = false;
|
bool first = false;
|
||||||
|
@ -127,7 +128,8 @@ void EdgePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
||||||
first = true;
|
first = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*obj)["lines"] = ss.str();
|
obj["lines"] = ss.str();
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
|
|
|
@ -57,7 +57,7 @@ class EdgePL : public GeoEdgePL<float> {
|
||||||
void addPoint(const util::geo::FPoint& p);
|
void addPoint(const util::geo::FPoint& p);
|
||||||
|
|
||||||
// Fill obj with k/v pairs describing the parameters of this payload.
|
// Fill obj with k/v pairs describing the parameters of this payload.
|
||||||
void getAttrs(std::map<std::string, std::string>* obj) const;
|
util::json::Dict getAttrs() const;
|
||||||
|
|
||||||
// Return the length in meters stored for this edge payload
|
// Return the length in meters stored for this edge payload
|
||||||
double getLength() const;
|
double getLength() const;
|
||||||
|
|
|
@ -114,18 +114,19 @@ const util::geo::FPoint* NodePL::getGeom() const { return &_geom; }
|
||||||
void NodePL::setGeom(const util::geo::FPoint& geom) { _geom = geom; }
|
void NodePL::setGeom(const util::geo::FPoint& geom) { _geom = geom; }
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
void NodePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
util::json::Dict NodePL::getAttrs() const {
|
||||||
(*obj)["component"] = std::to_string(reinterpret_cast<size_t>(_component));
|
util::json::Dict obj;
|
||||||
|
obj["component"] = std::to_string(reinterpret_cast<size_t>(_component));
|
||||||
#ifdef PFAEDLE_DBG
|
#ifdef PFAEDLE_DBG
|
||||||
(*obj)["dijkstra_vis"] = _vis ? "yes" : "no";
|
obj["dijkstra_vis"] = _vis ? "yes" : "no";
|
||||||
#endif
|
#endif
|
||||||
if (getSI()) {
|
if (getSI()) {
|
||||||
(*obj)["station_info_ptr"] = util::toString(_si);
|
obj["station_info_ptr"] = util::toString(_si);
|
||||||
(*obj)["station_name"] = _si->getName();
|
obj["station_name"] = _si->getName();
|
||||||
(*obj)["station_alt_names"] = util::implode(_si->getAltNames(), ",");
|
obj["station_alt_names"] = util::implode(_si->getAltNames(), ",");
|
||||||
(*obj)["from_osm"] = _si->isFromOsm() ? "yes" : "no";
|
obj["from_osm"] = _si->isFromOsm() ? "yes" : "no";
|
||||||
(*obj)["station_platform"] = _si->getTrack();
|
obj["station_platform"] = _si->getTrack();
|
||||||
(*obj)["station_group"] =
|
obj["station_group"] =
|
||||||
std::to_string(reinterpret_cast<size_t>(_si->getGroup()));
|
std::to_string(reinterpret_cast<size_t>(_si->getGroup()));
|
||||||
|
|
||||||
std::stringstream gtfsIds;
|
std::stringstream gtfsIds;
|
||||||
|
@ -135,8 +136,9 @@ void NodePL::getAttrs(std::map<std::string, std::string>* obj) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(*obj)["station_group_stops"] = gtfsIds.str();
|
obj["station_group_stops"] = gtfsIds.str();
|
||||||
}
|
}
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
|
|
|
@ -37,7 +37,7 @@ class NodePL : public GeoNodePL<float> {
|
||||||
void setGeom(const util::geo::FPoint& geom);
|
void setGeom(const util::geo::FPoint& geom);
|
||||||
|
|
||||||
// Fill obj with k/v pairs describing the parameters of this payload.
|
// Fill obj with k/v pairs describing the parameters of this payload.
|
||||||
void getAttrs(std::map<std::string, std::string>* attrs) const;
|
util::json::Dict getAttrs() const;
|
||||||
|
|
||||||
// Set the station info for this node
|
// Set the station info for this node
|
||||||
void setSI(const StatInfo& si);
|
void setSI(const StatInfo& si);
|
||||||
|
|
|
@ -77,6 +77,8 @@ class RotatedBox {
|
||||||
const Point<T>& getCenter() const { return _center; }
|
const Point<T>& getCenter() const { return _center; }
|
||||||
Point<T>& getCenter() { return _center; }
|
Point<T>& getCenter() { return _center; }
|
||||||
|
|
||||||
|
void setDegree(double deg) { _deg = deg; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Box<T> _box;
|
Box<T> _box;
|
||||||
double _deg;
|
double _deg;
|
||||||
|
|
|
@ -219,15 +219,15 @@ inline Box<T> minbox() {
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline RotatedBox<T> shrink(const RotatedBox<T>& b, double d) {
|
inline RotatedBox<T> shrink(const RotatedBox<T>& b, double d) {
|
||||||
double xd = b.b.getUpperRight().getX() - b.b.getLowerLeft().getX();
|
double xd = b.getBox().getUpperRight().getX() - b.getBox().getLowerLeft().getX();
|
||||||
double yd = b.b.getUpperRight().getY() - b.b.getLowerLeft().getY();
|
double yd = b.getBox().getUpperRight().getY() - b.getBox().getLowerLeft().getY();
|
||||||
|
|
||||||
if (xd <= 2 * d) d = xd / 2 - 1;
|
if (xd <= 2 * d) d = xd / 2 - 1;
|
||||||
if (yd <= 2 * d) d = yd / 2 - 1;
|
if (yd <= 2 * d) d = yd / 2 - 1;
|
||||||
|
|
||||||
Box<T> r(
|
Box<T> r(
|
||||||
Point<T>(b.b.getLowerLeft().getX() + d, b.b.getLowerLeft().getY() + d),
|
Point<T>(b.getBox().getLowerLeft().getX() + d, b.getBox().getLowerLeft().getY() + d),
|
||||||
Point<T>(b.b.getUpperRight().getX() - d, b.b.getUpperRight().getY() - d));
|
Point<T>(b.getBox().getUpperRight().getX() - d, b.getBox().getUpperRight().getY() - d));
|
||||||
|
|
||||||
return RotatedBox<T>(r, b.getDegree(), b.getCenter());
|
return RotatedBox<T>(r, b.getDegree(), b.getCenter());
|
||||||
}
|
}
|
||||||
|
@ -1137,8 +1137,8 @@ inline Polygon<T> convexHull(const RotatedBox<T>& b) {
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline size_t convexHullImpl(const Line<T>& a, size_t p1, size_t p2,
|
inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
|
||||||
Line<double>* h, uint8_t d) {
|
Line<T>* h, uint8_t d) {
|
||||||
// quickhull by Barber, Dobkin & Huhdanpaa
|
// quickhull by Barber, Dobkin & Huhdanpaa
|
||||||
Point<T> pa;
|
Point<T> pa;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -1162,7 +1162,7 @@ inline size_t convexHullImpl(const Line<T>& a, size_t p1, size_t p2,
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Polygon<T> convexHull(const Line<T>& l) {
|
inline Polygon<T> convexHull(const MultiPoint<T>& l) {
|
||||||
if (l.size() == 2) return convexHull(LineSegment<T>(l[0], l[1]));
|
if (l.size() == 2) return convexHull(LineSegment<T>(l[0], l[1]));
|
||||||
if (l.size() == 1) return convexHull(l[0]);
|
if (l.size() == 1) return convexHull(l[0]);
|
||||||
|
|
||||||
|
@ -1185,6 +1185,14 @@ inline Polygon<T> convexHull(const Polygon<T>& p) {
|
||||||
return convexHull(p.getOuter());
|
return convexHull(p.getOuter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _____________________________________________________________________________
|
||||||
|
template <typename T>
|
||||||
|
inline Polygon<T> convexHull(const MultiLine<T>& ls) {
|
||||||
|
MultiPoint<T> mp;
|
||||||
|
for (const auto& l : ls) mp.insert(mp.end(), l.begin(), l.end());
|
||||||
|
return convexHull(mp);
|
||||||
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Box<T> extendBox(const Line<T>& l, Box<T> b) {
|
inline Box<T> extendBox(const Line<T>& l, Box<T> b) {
|
||||||
|
@ -1200,6 +1208,12 @@ inline Box<T> extendBox(const LineSegment<T>& ls, Box<T> b) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _____________________________________________________________________________
|
||||||
|
template <typename T>
|
||||||
|
inline Box<T> extendBox(const Polygon<T>& ls, Box<T> b) {
|
||||||
|
return extendBox(ls.getOuter(), b);
|
||||||
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <template <typename> class Geometry, typename T>
|
template <template <typename> class Geometry, typename T>
|
||||||
inline Box<T> extendBox(const std::vector<Geometry<T>>& multigeom, Box<T> b) {
|
inline Box<T> extendBox(const std::vector<Geometry<T>>& multigeom, Box<T> b) {
|
||||||
|
@ -1263,7 +1277,7 @@ inline double commonArea(const Box<T>& ba, const Box<T>& bb) {
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <template <typename> class Geometry, typename T>
|
template <template <typename> class Geometry, typename T>
|
||||||
inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) {
|
inline RotatedBox<T> getFullEnvelope(std::vector<Geometry<T>> pol) {
|
||||||
Point<T> center = centroid(pol);
|
Point<T> center = centroid(pol);
|
||||||
Box<T> tmpBox = getBoundingBox(pol);
|
Box<T> tmpBox = getBoundingBox(pol);
|
||||||
double rotateDeg = 0;
|
double rotateDeg = 0;
|
||||||
|
@ -1287,6 +1301,14 @@ inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) {
|
||||||
return RotatedBox<T>(tmpBox, rotateDeg, center);
|
return RotatedBox<T>(tmpBox, rotateDeg, center);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _____________________________________________________________________________
|
||||||
|
template <template <typename> class Geometry, typename T>
|
||||||
|
inline RotatedBox<T> getFullEnvelope(const Geometry<T> pol) {
|
||||||
|
std::vector<Geometry<T>> mult;
|
||||||
|
mult.push_back(pol);
|
||||||
|
return getFullEnvelope(mult);
|
||||||
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline RotatedBox<T> getOrientedEnvelopeAvg(MultiLine<T> ml) {
|
inline RotatedBox<T> getOrientedEnvelopeAvg(MultiLine<T> ml) {
|
||||||
|
@ -1298,18 +1320,18 @@ inline RotatedBox<T> getOrientedEnvelopeAvg(MultiLine<T> ml) {
|
||||||
ml = rotate(ml, -rbox.getDegree() - 45, center);
|
ml = rotate(ml, -rbox.getDegree() - 45, center);
|
||||||
|
|
||||||
double bestDeg = -45;
|
double bestDeg = -45;
|
||||||
double score = parallelity(rbox.b, ml);
|
double score = parallelity(rbox.getBox(), ml);
|
||||||
|
|
||||||
for (double i = -45; i <= 45; i += .5) {
|
for (double i = -45; i <= 45; i += .5) {
|
||||||
ml = rotate(ml, -.5, center);
|
ml = rotate(ml, -.5, center);
|
||||||
double p = parallelity(rbox.b, ml);
|
double p = parallelity(rbox.getBox(), ml);
|
||||||
if (parallelity(rbox.b, ml) > score) {
|
if (parallelity(rbox.getBox(), ml) > score) {
|
||||||
bestDeg = i;
|
bestDeg = i;
|
||||||
score = p;
|
score = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rbox.rotateDeg += bestDeg;
|
rbox.setDegree(rbox.getDegree() + bestDeg);
|
||||||
|
|
||||||
// move the box along 45deg angles from its origin until it fits the ml
|
// move the box along 45deg angles from its origin until it fits the ml
|
||||||
// = until the intersection of its hull and the box is largest
|
// = until the intersection of its hull and the box is largest
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "util/geo/Geo.h"
|
#include "util/geo/Geo.h"
|
||||||
|
#include "util/json/Writer.h"
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
namespace geograph {
|
namespace geograph {
|
||||||
|
@ -15,14 +16,14 @@ template<typename T>
|
||||||
class GeoEdgePL {
|
class GeoEdgePL {
|
||||||
public:
|
public:
|
||||||
virtual const util::geo::Line<T>* getGeom() const = 0;
|
virtual const util::geo::Line<T>* getGeom() const = 0;
|
||||||
virtual void getAttrs(std::map<std::string, std::string>* m) const = 0;
|
virtual json::Dict getAttrs() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class GeoNodePL {
|
class GeoNodePL {
|
||||||
public:
|
public:
|
||||||
virtual const util::geo::Point<T>* getGeom() const = 0;
|
virtual const util::geo::Point<T>* getGeom() const = 0;
|
||||||
virtual void getAttrs(std::map<std::string, std::string>* m) const = 0;
|
virtual json::Dict getAttrs() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geograph
|
} // namespace geograph
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <iomanip>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Geo.h"
|
#include "Geo.h"
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
// Chair of Algorithms and Data Structures.
|
// Chair of Algorithms and Data Structures.
|
||||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||||
|
|
||||||
using util::geo::output::Attrs;
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Line<T> GeoGraphJsonOutput::createLine(const util::geo::Point<T>& a,
|
Line<T> GeoGraphJsonOutput::createLine(const util::geo::Point<T>& a,
|
||||||
|
@ -24,11 +22,13 @@ void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
|
||||||
for (util::graph::Node<N, E>* n : outG.getNds()) {
|
for (util::graph::Node<N, E>* n : outG.getNds()) {
|
||||||
if (!n->pl().getGeom()) continue;
|
if (!n->pl().getGeom()) continue;
|
||||||
|
|
||||||
Attrs props = {{"id", toString(n)},
|
json::Dict props{{"id", toString(n)},
|
||||||
{"deg", toString(n->getInDeg() + n->getOutDeg())},
|
{"deg", toString(n->getInDeg() + n->getOutDeg())},
|
||||||
{"deg_out", toString(n->getOutDeg())},
|
{"deg_out", toString(n->getOutDeg())},
|
||||||
{"deg_in", toString(n->getInDeg())}};
|
{"deg_in", toString(n->getInDeg())}};
|
||||||
n->pl().getAttrs(&props);
|
|
||||||
|
auto addProps = n->pl().getAttrs();
|
||||||
|
props.insert(addProps.begin(), addProps.end());
|
||||||
|
|
||||||
_out.print(*n->pl().getGeom(), props);
|
_out.print(*n->pl().getGeom(), props);
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,12 @@ void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
|
||||||
for (graph::Edge<N, E>* e : n->getAdjListOut()) {
|
for (graph::Edge<N, E>* e : n->getAdjListOut()) {
|
||||||
// to avoid double output for undirected graphs
|
// to avoid double output for undirected graphs
|
||||||
if (e->getFrom() != n) continue;
|
if (e->getFrom() != n) continue;
|
||||||
Attrs props{{"from", toString(e->getFrom())},
|
json::Dict props{{"from", toString(e->getFrom())},
|
||||||
{"to", toString(e->getTo())},
|
{"to", toString(e->getTo())},
|
||||||
{"id", toString(e)}};
|
{"id", toString(e)}};
|
||||||
|
|
||||||
e->pl().getAttrs(&props);
|
auto addProps = e->pl().getAttrs();
|
||||||
|
props.insert(addProps.begin(), addProps.end());
|
||||||
|
|
||||||
if (!e->pl().getGeom() || !e->pl().getGeom()->size()) {
|
if (!e->pl().getGeom() || !e->pl().getGeom()->size()) {
|
||||||
if (e->getFrom()->pl().getGeom()) {
|
if (e->getFrom()->pl().getGeom()) {
|
||||||
|
|
|
@ -10,26 +10,24 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "util/String.h"
|
#include "util/String.h"
|
||||||
#include "util/geo/Geo.h"
|
#include "util/geo/Geo.h"
|
||||||
#include "util/json/JsonWriter.h"
|
#include "util/json/Writer.h"
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
namespace geo {
|
namespace geo {
|
||||||
namespace output {
|
namespace output {
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> Attrs;
|
|
||||||
|
|
||||||
class GeoJsonOutput {
|
class GeoJsonOutput {
|
||||||
public:
|
public:
|
||||||
GeoJsonOutput(std::ostream& str);
|
GeoJsonOutput(std::ostream& str);
|
||||||
~GeoJsonOutput();
|
~GeoJsonOutput();
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void print(const Point<T>& p, Attrs attrs);
|
void print(const Point<T>& p, json::Val attrs);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void print(const Line<T>& l, Attrs attrs);
|
void print(const Line<T>& l, json::Val attrs);
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
json::JsonWriter _wr;
|
json::Writer _wr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "util/geo/output/GeoJsonOutput.tpp"
|
#include "util/geo/output/GeoJsonOutput.tpp"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void GeoJsonOutput::print(const Point<T>& p, Attrs attrs) {
|
void GeoJsonOutput::print(const Point<T>& p, json::Val attrs) {
|
||||||
_wr.obj();
|
_wr.obj();
|
||||||
_wr.keyVal("type", "Feature");
|
_wr.keyVal("type", "Feature");
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ void GeoJsonOutput::print(const Point<T>& p, Attrs attrs) {
|
||||||
_wr.close();
|
_wr.close();
|
||||||
_wr.close();
|
_wr.close();
|
||||||
_wr.key("properties");
|
_wr.key("properties");
|
||||||
_wr.obj(attrs);
|
_wr.val(attrs);
|
||||||
_wr.close();
|
_wr.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
// _____________________________________________________________________________
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void GeoJsonOutput::print(const Line<T>& line, Attrs attrs) {
|
void GeoJsonOutput::print(const Line<T>& line, json::Val attrs) {
|
||||||
if (!line.size()) return;
|
if (!line.size()) return;
|
||||||
_wr.obj();
|
_wr.obj();
|
||||||
_wr.keyVal("type", "Feature");
|
_wr.keyVal("type", "Feature");
|
||||||
|
@ -37,12 +37,12 @@ void GeoJsonOutput::print(const Line<T>& line, Attrs attrs) {
|
||||||
for (auto p : line) {
|
for (auto p : line) {
|
||||||
_wr.arr();
|
_wr.arr();
|
||||||
_wr.val(p.getX());
|
_wr.val(p.getX());
|
||||||
_wr.val(p.template getY());
|
_wr.val(p.getY());
|
||||||
_wr.close();
|
_wr.close();
|
||||||
}
|
}
|
||||||
_wr.close();
|
_wr.close();
|
||||||
_wr.close();
|
_wr.close();
|
||||||
_wr.key("properties");
|
_wr.key("properties");
|
||||||
_wr.obj(attrs);
|
_wr.val(attrs);
|
||||||
_wr.close();
|
_wr.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
// Copyright 2018, University of Freiburg,
|
|
||||||
// Chair of Algorithms and Data Structures.
|
|
||||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include "JsonWriter.h"
|
|
||||||
#include "util/String.h"
|
|
||||||
using namespace util;
|
|
||||||
using namespace json;
|
|
||||||
|
|
||||||
using std::ostream;
|
|
||||||
using std::string;
|
|
||||||
using std::map;
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
JsonWriter::JsonWriter(std::ostream* out)
|
|
||||||
: _out(out), _pretty(false), _indent(2) {
|
|
||||||
*_out << std::setprecision(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
JsonWriter::JsonWriter(std::ostream* out, size_t prec)
|
|
||||||
: _out(out), _pretty(false), _indent(2) {
|
|
||||||
*_out << std::setprecision(prec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
JsonWriter::JsonWriter(std::ostream* out, size_t prec, bool pret)
|
|
||||||
: _out(out), _pretty(pret), _indent(2) {
|
|
||||||
*_out << std::setprecision(prec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
JsonWriter::JsonWriter(std::ostream* out, size_t prec, bool pret, size_t indent)
|
|
||||||
: _out(out), _pretty(pret), _indent(indent) {
|
|
||||||
*_out << std::setprecision(prec);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::obj() {
|
|
||||||
if (!_stack.empty() && _stack.top().type == OBJ)
|
|
||||||
throw JsonWriterException("Object not allowed as key");
|
|
||||||
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
|
|
||||||
if (!_stack.empty() && _stack.top().type == ARR) valCheck();
|
|
||||||
if (_stack.size() && _stack.top().type == ARR) prettor();
|
|
||||||
(*_out) << "{";
|
|
||||||
_stack.push({OBJ, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::obj(const std::map<std::string, std::string> kvs) {
|
|
||||||
obj();
|
|
||||||
for (const auto& kv : kvs) {
|
|
||||||
key(kv.first);
|
|
||||||
val(kv.second);
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::key(const std::string& k) {
|
|
||||||
if (_stack.empty() || _stack.top().type != OBJ)
|
|
||||||
throw JsonWriterException("Keys only allowed in objects.");
|
|
||||||
if (!_stack.top().empty) (*_out) << "," << (_pretty ? " " : "");
|
|
||||||
_stack.top().empty = 0;
|
|
||||||
prettor();
|
|
||||||
(*_out) << "\"" << k << "\""
|
|
||||||
<< ":" << (_pretty ? " " : "");
|
|
||||||
_stack.push({KEY, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::keyVal(const std::string& k, const std::string& v) {
|
|
||||||
key(k);
|
|
||||||
val(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::valCheck() {
|
|
||||||
if (_stack.empty() || (_stack.top().type != KEY && _stack.top().type != ARR))
|
|
||||||
throw JsonWriterException("Value not allowed here.");
|
|
||||||
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
|
|
||||||
if (!_stack.empty() && _stack.top().type == ARR) {
|
|
||||||
if (!_stack.top().empty) (*_out) << "," << (_pretty ? " " : "");
|
|
||||||
_stack.top().empty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::val(const std::string& v) {
|
|
||||||
valCheck();
|
|
||||||
(*_out) << "\"" << util::jsonStringEscape(v) << "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::val(int v) {
|
|
||||||
valCheck();
|
|
||||||
(*_out) << v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::val(double v) {
|
|
||||||
valCheck();
|
|
||||||
(*_out) << v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::arr() {
|
|
||||||
if (!_stack.empty() && _stack.top().type == OBJ)
|
|
||||||
throw JsonWriterException("Array not allowed as key");
|
|
||||||
if (!_stack.empty() && _stack.top().type == KEY) _stack.pop();
|
|
||||||
if (!_stack.empty() && _stack.top().type == ARR) valCheck();
|
|
||||||
(*_out) << "[";
|
|
||||||
_stack.push({ARR, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::prettor() {
|
|
||||||
if (_pretty) {
|
|
||||||
(*_out) << "\n";
|
|
||||||
for (size_t i = 0; i < _indent * _stack.size(); i++) (*_out) << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::closeAll() {
|
|
||||||
while (!_stack.empty()) close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// _____________________________________________________________________________
|
|
||||||
void JsonWriter::close() {
|
|
||||||
if (_stack.empty()) return;
|
|
||||||
switch (_stack.top().type) {
|
|
||||||
case OBJ:
|
|
||||||
_stack.pop();
|
|
||||||
prettor();
|
|
||||||
(*_out) << "}";
|
|
||||||
break;
|
|
||||||
case ARR:
|
|
||||||
_stack.pop();
|
|
||||||
(*_out) << "]";
|
|
||||||
break;
|
|
||||||
case KEY:
|
|
||||||
throw JsonWriterException("Missing value.");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
// Copyright 2018, University of Freiburg,
|
|
||||||
// Chair of Algorithms and Data Structures.
|
|
||||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
|
||||||
|
|
||||||
#ifndef UTIL_JSON_JSONWRITER_H_
|
|
||||||
#define UTIL_JSON_JSONWRITER_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <ostream>
|
|
||||||
#include <stack>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
namespace json {
|
|
||||||
|
|
||||||
class JsonWriterException : public std::exception {
|
|
||||||
public:
|
|
||||||
JsonWriterException(std::string msg) : _msg(msg) {}
|
|
||||||
~JsonWriterException() throw() {}
|
|
||||||
|
|
||||||
virtual const char* what() const throw() { return _msg.c_str(); };
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string _msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
// simple JSON writer class without much overhead
|
|
||||||
class JsonWriter {
|
|
||||||
public:
|
|
||||||
explicit JsonWriter(std::ostream* out);
|
|
||||||
JsonWriter(std::ostream* out, size_t prec);
|
|
||||||
JsonWriter(std::ostream* out, size_t prec, bool pretty);
|
|
||||||
JsonWriter(std::ostream* out, size_t prec, bool pretty, size_t indent);
|
|
||||||
~JsonWriter(){};
|
|
||||||
|
|
||||||
void obj();
|
|
||||||
void obj(const std::map<std::string, std::string> kvs);
|
|
||||||
void arr();
|
|
||||||
void key(const std::string& k);
|
|
||||||
void val(const std::string& v);
|
|
||||||
void val(int v);
|
|
||||||
void val(double v);
|
|
||||||
void keyVal(const std::string& k, const std::string& v);
|
|
||||||
|
|
||||||
void close();
|
|
||||||
void closeAll();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ostream* _out;
|
|
||||||
|
|
||||||
enum JSON_NODE_T { OBJ, ARR, KEY };
|
|
||||||
|
|
||||||
struct JsonNode {
|
|
||||||
JSON_NODE_T type;
|
|
||||||
bool empty;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::stack<JsonNode> _stack;
|
|
||||||
|
|
||||||
bool _pretty;
|
|
||||||
size_t _indent;
|
|
||||||
|
|
||||||
void valCheck();
|
|
||||||
void prettor();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace json
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
#endif // UTIL_JSON_JSONWRITER_H_
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "util/Nullable.h"
|
#include "util/Nullable.h"
|
||||||
#include "util/String.h"
|
#include "util/String.h"
|
||||||
#include "util/geo/Geo.h"
|
#include "util/geo/Geo.h"
|
||||||
|
#include "util/json/Writer.h"
|
||||||
#include "util/graph/DirGraph.h"
|
#include "util/graph/DirGraph.h"
|
||||||
#include "util/graph/UndirGraph.h"
|
#include "util/graph/UndirGraph.h"
|
||||||
#include "util/graph/Dijkstra.h"
|
#include "util/graph/Dijkstra.h"
|
||||||
|
@ -36,6 +37,56 @@ CASE("atof") {
|
||||||
// TODO: more test cases
|
// TODO: more test cases
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
// ___________________________________________________________________________
|
||||||
|
{
|
||||||
|
CASE("json") {
|
||||||
|
std::stringstream ss;
|
||||||
|
util::json::Writer wr(&ss, 2, false);
|
||||||
|
|
||||||
|
util::json::Val a("bla");
|
||||||
|
util::json::Val b(1);
|
||||||
|
util::json::Val c(1.0);
|
||||||
|
util::json::Val d("a");
|
||||||
|
util::json::Val e({"a", "b", "c"});
|
||||||
|
|
||||||
|
util::json::Val f({1, json::Array{2, 3, 4}, 3});
|
||||||
|
|
||||||
|
ss = std::stringstream();
|
||||||
|
wr = util::json::Writer(&ss, 2, false);
|
||||||
|
util::json::Val i({1, json::Array{2, json::Null(), 4}, true});
|
||||||
|
wr.val(i);
|
||||||
|
wr.closeAll();
|
||||||
|
EXPECT(ss.str() == "[1,[2,null,4],true]");
|
||||||
|
|
||||||
|
ss = std::stringstream();
|
||||||
|
wr = util::json::Writer(&ss, 2, false);
|
||||||
|
i = util::json::Val({1, json::Array{2, json::Null(), 4}, false});
|
||||||
|
wr.val(i);
|
||||||
|
wr.closeAll();
|
||||||
|
EXPECT(ss.str() == "[1,[2,null,4],false]");
|
||||||
|
|
||||||
|
ss = std::stringstream();
|
||||||
|
wr = util::json::Writer(&ss, 2, false);
|
||||||
|
i = util::json::Val({1, json::Array{2, json::Null(), 4}, false});
|
||||||
|
wr.val(i);
|
||||||
|
wr.closeAll();
|
||||||
|
EXPECT(ss.str() == "[1,[2,null,4],false]");
|
||||||
|
|
||||||
|
ss = std::stringstream();
|
||||||
|
wr = util::json::Writer(&ss, 2, false);
|
||||||
|
i = util::json::Val({1, json::Array{2.13, "", 4}, 0});
|
||||||
|
wr.val(i);
|
||||||
|
wr.closeAll();
|
||||||
|
EXPECT(ss.str() == "[1,[2.13,\"\",4],0]");
|
||||||
|
|
||||||
|
ss = std::stringstream();
|
||||||
|
wr = util::json::Writer(&ss, 2, false);
|
||||||
|
i = util::json::Val({1, json::Array{2.13, json::Dict{{"a", 1}, {"B", 2.123}}, 4}, 0});
|
||||||
|
wr.val(i);
|
||||||
|
wr.closeAll();
|
||||||
|
EXPECT((ss.str() == "[1,[2.13,{\"a\":1,\"B\":2.12},4],0]" || ss.str() == "[1,[2.13,{\"B\":2.12,\"a\":1},4],0]"));
|
||||||
|
}},
|
||||||
|
|
||||||
// ___________________________________________________________________________
|
// ___________________________________________________________________________
|
||||||
{
|
{
|
||||||
CASE("dirgraph") {
|
CASE("dirgraph") {
|
||||||
|
|
Loading…
Reference in a new issue