refactoring

This commit is contained in:
Patrick Brosi 2018-08-01 14:25:54 +02:00
parent 04e87c1d9c
commit 64b83f569c
24 changed files with 186 additions and 310 deletions

View file

@ -77,6 +77,8 @@ class RotatedBox {
const Point<T>& getCenter() const { return _center; }
Point<T>& getCenter() { return _center; }
void setDegree(double deg) { _deg = deg; }
private:
Box<T> _box;
double _deg;

View file

@ -219,15 +219,15 @@ inline Box<T> minbox() {
// _____________________________________________________________________________
template <typename T>
inline RotatedBox<T> shrink(const RotatedBox<T>& b, double d) {
double xd = b.b.getUpperRight().getX() - b.b.getLowerLeft().getX();
double yd = b.b.getUpperRight().getY() - b.b.getLowerLeft().getY();
double xd = b.getBox().getUpperRight().getX() - b.getBox().getLowerLeft().getX();
double yd = b.getBox().getUpperRight().getY() - b.getBox().getLowerLeft().getY();
if (xd <= 2 * d) d = xd / 2 - 1;
if (yd <= 2 * d) d = yd / 2 - 1;
Box<T> r(
Point<T>(b.b.getLowerLeft().getX() + d, b.b.getLowerLeft().getY() + d),
Point<T>(b.b.getUpperRight().getX() - d, b.b.getUpperRight().getY() - d));
Point<T>(b.getBox().getLowerLeft().getX() + d, b.getBox().getLowerLeft().getY() + d),
Point<T>(b.getBox().getUpperRight().getX() - d, b.getBox().getUpperRight().getY() - d));
return RotatedBox<T>(r, b.getDegree(), b.getCenter());
}
@ -1137,8 +1137,8 @@ inline Polygon<T> convexHull(const RotatedBox<T>& b) {
// _____________________________________________________________________________
template <typename T>
inline size_t convexHullImpl(const Line<T>& a, size_t p1, size_t p2,
Line<double>* h, uint8_t d) {
inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
Line<T>* h, uint8_t d) {
// quickhull by Barber, Dobkin & Huhdanpaa
Point<T> pa;
bool found = false;
@ -1162,7 +1162,7 @@ inline size_t convexHullImpl(const Line<T>& a, size_t p1, size_t p2,
// _____________________________________________________________________________
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() == 1) return convexHull(l[0]);
@ -1185,6 +1185,14 @@ inline Polygon<T> convexHull(const Polygon<T>& p) {
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>
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;
}
// _____________________________________________________________________________
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>
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>
inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) {
inline RotatedBox<T> getFullEnvelope(std::vector<Geometry<T>> pol) {
Point<T> center = centroid(pol);
Box<T> tmpBox = getBoundingBox(pol);
double rotateDeg = 0;
@ -1287,6 +1301,14 @@ inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) {
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>
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);
double bestDeg = -45;
double score = parallelity(rbox.b, ml);
double score = parallelity(rbox.getBox(), ml);
for (double i = -45; i <= 45; i += .5) {
ml = rotate(ml, -.5, center);
double p = parallelity(rbox.b, ml);
if (parallelity(rbox.b, ml) > score) {
double p = parallelity(rbox.getBox(), ml);
if (parallelity(rbox.getBox(), ml) > score) {
bestDeg = i;
score = p;
}
}
rbox.rotateDeg += bestDeg;
rbox.setDegree(rbox.getDegree() + bestDeg);
// 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

View file

@ -7,6 +7,7 @@
#include <map>
#include "util/geo/Geo.h"
#include "util/json/Writer.h"
namespace util {
namespace geograph {
@ -15,14 +16,14 @@ template<typename T>
class GeoEdgePL {
public:
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>
class GeoNodePL {
public:
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

View file

@ -7,6 +7,7 @@
#include <cfloat>
#include <ostream>
#include <iomanip>
#include <string>
#include <vector>
#include "Geo.h"

View file

@ -2,8 +2,6 @@
// Chair of Algorithms and Data Structures.
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
using util::geo::output::Attrs;
// _____________________________________________________________________________
template <typename T>
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()) {
if (!n->pl().getGeom()) continue;
Attrs props = {{"id", toString(n)},
json::Dict props{{"id", toString(n)},
{"deg", toString(n->getInDeg() + n->getOutDeg())},
{"deg_out", toString(n->getOutDeg())},
{"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);
}
@ -38,11 +38,12 @@ void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
for (graph::Edge<N, E>* e : n->getAdjListOut()) {
// to avoid double output for undirected graphs
if (e->getFrom() != n) continue;
Attrs props{{"from", toString(e->getFrom())},
json::Dict props{{"from", toString(e->getFrom())},
{"to", toString(e->getTo())},
{"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->getFrom()->pl().getGeom()) {

View file

@ -10,26 +10,24 @@
#include <map>
#include "util/String.h"
#include "util/geo/Geo.h"
#include "util/json/JsonWriter.h"
#include "util/json/Writer.h"
namespace util {
namespace geo {
namespace output {
typedef std::map<std::string, std::string> Attrs;
class GeoJsonOutput {
public:
GeoJsonOutput(std::ostream& str);
~GeoJsonOutput();
template <typename T>
void print(const Point<T>& p, Attrs attrs);
void print(const Point<T>& p, json::Val attrs);
template <typename T>
void print(const Line<T>& l, Attrs attrs);
void print(const Line<T>& l, json::Val attrs);
void flush();
private:
json::JsonWriter _wr;
json::Writer _wr;
};
#include "util/geo/output/GeoJsonOutput.tpp"

View file

@ -4,7 +4,7 @@
// _____________________________________________________________________________
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.keyVal("type", "Feature");
@ -18,13 +18,13 @@ void GeoJsonOutput::print(const Point<T>& p, Attrs attrs) {
_wr.close();
_wr.close();
_wr.key("properties");
_wr.obj(attrs);
_wr.val(attrs);
_wr.close();
}
// _____________________________________________________________________________
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;
_wr.obj();
_wr.keyVal("type", "Feature");
@ -37,12 +37,12 @@ void GeoJsonOutput::print(const Line<T>& line, Attrs attrs) {
for (auto p : line) {
_wr.arr();
_wr.val(p.getX());
_wr.val(p.template getY());
_wr.val(p.getY());
_wr.close();
}
_wr.close();
_wr.close();
_wr.key("properties");
_wr.obj(attrs);
_wr.val(attrs);
_wr.close();
}

View file

@ -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.");
}
}

View file

@ -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_

View file

@ -7,6 +7,7 @@
#include "util/Nullable.h"
#include "util/String.h"
#include "util/geo/Geo.h"
#include "util/json/Writer.h"
#include "util/graph/DirGraph.h"
#include "util/graph/UndirGraph.h"
#include "util/graph/Dijkstra.h"
@ -36,6 +37,56 @@ CASE("atof") {
// 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") {