This commit is contained in:
Patrick Brosi 2018-07-10 17:04:59 +02:00
parent 73eb2c16da
commit cf79e67631
5 changed files with 424 additions and 280 deletions

39
src/util/geo/Box.h Normal file
View file

@ -0,0 +1,39 @@
// Copyright 2016, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Patrick Brosi <brosi@informatik.uni-freiburg.de>
#ifndef UTIL_GEO_BOX_H_
#define UTIL_GEO_BOX_H_
#include "./Point.h"
namespace util {
namespace geon {
template <typename T>
class Box {
public:
// maximum inverse box as default value of box
Box() : _ll(std::numeric_limits<T>::max), _ur(std::numeric_limits<T>::min) {}
Box(const Point<T>& ll, const Point<T>& ur) : _ll(ll), _ur(ur) {}
const Point<T>& getLowerLeft() const { return _ll; }
const Point<T>& getUpperRight() const { return _ur; }
void setLowerLeft(const Point<T>& ll) { _ll = ll; }
void setUpperRight(const Point<T>& ur) { _ur = ur; }
bool operator==(const Box<T>& b) const {
return getLowerLeft() == b.getLowerLeft() &&
getUpperRight == b.getUpperRight();
}
bool operator!=(const Box<T>& p) const { return !(*this == p); }
private:
Point<T> _ll, _ur;
};
} // namespace geon
} // namespace util
#endif // UTIL_GEO_BOX_H_

View file

@ -8,6 +8,8 @@
#include <math.h> #include <math.h>
#include "util/Misc.h" #include "util/Misc.h"
#include "util/geo/Box.h"
#include "util/geo/Line.h"
#include "util/geo/Point.h" #include "util/geo/Point.h"
// ------------------- // -------------------
@ -23,13 +25,13 @@ typedef Point<double> DPoint;
typedef Point<float> FPoint; typedef Point<float> FPoint;
typedef Point<int> IPoint; typedef Point<int> IPoint;
// typedef Line<double> DLine; typedef Line<double> DLine;
// typedef Line<float> FLine; typedef Line<float> FLine;
// typedef Line<int> ILine; typedef Line<int> ILine;
// typedef Box<double> DBox; typedef Box<double> DBox;
// typedef Box<float> FBox; typedef Box<float> FBox;
// typedef Box<int> IBox; typedef Box<int> IBox;
// typedef Polygon<double> DPolygon; // typedef Polygon<double> DPolygon;
// typedef Polygon<float> FPolygon; // typedef Polygon<float> FPolygon;
@ -37,57 +39,58 @@ typedef Point<int> IPoint;
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline Line<T> rotate(const Line<T>& geo, double deg, const Point<T>& center) { // inline Line<T> rotate(const Line<T>& geo, double deg, const Point<T>& center)
// Line<T> ret; // {
// Line<T> ret;
// bgeo::strategy::transform::translate_transformer<T, 2, 2> translate( // bgeo::strategy::transform::translate_transformer<T, 2, 2> translate(
// -center.getX(), -center.getY()); // -center.getX(), -center.getY());
// bgeo::strategy::transform::rotate_transformer<bgeo::degree, T, 2, 2> rotate( // bgeo::strategy::transform::rotate_transformer<bgeo::degree, T, 2, 2> rotate(
// deg); // deg);
// bgeo::strategy::transform::translate_transformer<T, 2, 2> translateBack( // bgeo::strategy::transform::translate_transformer<T, 2, 2> translateBack(
// center.getX(), center.getY()); // center.getX(), center.getY());
// bgeo::strategy::transform::ublas_transformer<T, 2, 2> translateRotate( // bgeo::strategy::transform::ublas_transformer<T, 2, 2> translateRotate(
// prod(rotate.matrix(), translate.matrix())); // prod(rotate.matrix(), translate.matrix()));
// bgeo::strategy::transform::ublas_transformer<T, 2, 2> all( // bgeo::strategy::transform::ublas_transformer<T, 2, 2> all(
// prod(translateBack.matrix(), translateRotate.matrix())); // prod(translateBack.matrix(), translateRotate.matrix()));
// bgeo::transform(geo, ret, all); // bgeo::transform(geo, ret, all);
// return ret; // return ret;
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline MultiLine<T> rotate(const MultiLine<T>& geo, double deg, // inline MultiLine<T> rotate(const MultiLine<T>& geo, double deg,
// const Point<T>& center) { // const Point<T>& center) {
// MultiLine<T> ret; // MultiLine<T> ret;
// bgeo::strategy::transform::translate_transformer<T, 2, 2> translate( // bgeo::strategy::transform::translate_transformer<T, 2, 2> translate(
// -center.getX(), -center.getY()); // -center.getX(), -center.getY());
// bgeo::strategy::transform::rotate_transformer<bgeo::degree, T, 2, 2> rotate( // bgeo::strategy::transform::rotate_transformer<bgeo::degree, T, 2, 2> rotate(
// deg); // deg);
// bgeo::strategy::transform::translate_transformer<T, 2, 2> translateBack( // bgeo::strategy::transform::translate_transformer<T, 2, 2> translateBack(
// center.getX(), center.getY()); // center.getX(), center.getY());
// bgeo::strategy::transform::ublas_transformer<T, 2, 2> translateRotate( // bgeo::strategy::transform::ublas_transformer<T, 2, 2> translateRotate(
// prod(rotate.matrix(), translate.matrix())); // prod(rotate.matrix(), translate.matrix()));
// bgeo::strategy::transform::ublas_transformer<T, 2, 2> all( // bgeo::strategy::transform::ublas_transformer<T, 2, 2> all(
// prod(translateBack.matrix(), translateRotate.matrix())); // prod(translateBack.matrix(), translateRotate.matrix()));
// bgeo::transform(geo, ret, all); // bgeo::transform(geo, ret, all);
// return ret; // return ret;
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> template <typename T>
// inline Box<T> pad(const Box<T>& box, double padding) { inline Box<T> pad(const Box<T>& box, double padding) {
// return Box<T>(Point<T>(box.min_corner().getX() - padding, return Box<T>(Point<T>(box.getLowerLeft().getX() - padding,
// box.min_corner().getY() - padding), box.getLowerLeft().getY() - padding),
// Point<T>(box.max_corner().getX() + padding, Point<T>(box.getUpperRight().getX() + padding,
// box.max_corner().getY() + padding)); box.getUpperRight().getY() + padding));
// } }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
@ -98,17 +101,17 @@ inline Point<T> rotate(const Point<T>& p, double deg) {
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline Line<T> rotate(const Line<T>& geo, double deg) { // inline Line<T> rotate(const Line<T>& geo, double deg) {
// Point<T> center; // Point<T> center;
// bgeo::centroid(geo, center); // bgeo::centroid(geo, center);
// return rotate(geo, deg, center); // return rotate(geo, deg, center);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline MultiLine<T> rotate(const MultiLine<T>& geo, double deg) { // inline MultiLine<T> rotate(const MultiLine<T>& geo, double deg) {
// Point<T> center; // Point<T> center;
// bgeo::centroid(geo, center); // bgeo::centroid(geo, center);
// return rotate(geo, deg, center); // return rotate(geo, deg, center);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -121,110 +124,124 @@ inline Point<T> move(const Point<T>& geo, T x, T y) {
// template <typename T> // template <typename T>
// struct RotatedBox { // struct RotatedBox {
// RotatedBox(const Box<T>& b, double rot, const Point<T>& center) // RotatedBox(const Box<T>& b, double rot, const Point<T>& center)
// : b(b), rotateDeg(rot), center(center) {} // : b(b), rotateDeg(rot), center(center) {}
// RotatedBox(const Box<T>& b, double rot) : b(b), rotateDeg(rot) { // RotatedBox(const Box<T>& b, double rot) : b(b), rotateDeg(rot) {
// bgeo::centroid(b, center); // bgeo::centroid(b, center);
// } // }
// Box<T> b; // Box<T> b;
// double rotateDeg; // double rotateDeg;
// Point<T> center; // Point<T> center;
// Polygon<T> getPolygon() { // Polygon<T> getPolygon() {
// Polygon<T> hull; // Polygon<T> hull;
// bgeo::convex_hull(b, hull); // bgeo::convex_hull(b, hull);
// return rotate(hull, rotateDeg, center); // return rotate(hull, rotateDeg, center);
// } // }
// }; // };
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline Box<T> minbox() { inline Box<T> minbox() {
//return bgeo::make_inverse<Box<T>>(); return Box<T>();
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
// 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 = // double xd =
// b.b.max_corner().getX() - b.b.min_corner().getX(); // b.b.getUpperRight().getX() - b.b.getLowerLeft().getX();
// double yd = // double yd =
// b.b.max_corner().getY() - b.b.min_corner().getY(); // b.b.getUpperRight().getY() - b.b.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(Point<T>(b.b.min_corner().getX() + d, // Box<T> r(Point<T>(b.b.getLowerLeft().getX() + d,
// b.b.min_corner().getY() + d), // b.b.getLowerLeft().getY() + d),
// Point<T>(b.b.max_corner().getX() - d, // Point<T>(b.b.getUpperRight().getX() - d,
// b.b.max_corner().getY() - d)); // b.b.getUpperRight().getY() - d));
// return RotatedBox<T>(r, b.rotateDeg, b.center); // return RotatedBox<T>(r, b.rotateDeg, b.center);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
inline bool doubleEq(double a, double b) { return fabs(a - b) < 0.000001; } inline bool doubleEq(double a, double b) { return fabs(a - b) < 0.000001; }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename Geometry, typename Box> template <typename T>
// inline bool contains(const Geometry& geom, const Box& box) { inline bool contains(const Point<T>& p, const Box<T>& box) {
// return bgeo::within(geom, box); return p.getX() >= box.getLowerLeft().getX() &&
p.getX() <= box.getUpperRight().getX() &&
p.getY() >= box.getLowerLeft().getY() &&
p.getY() <= box.getUpperRight().getY();
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Line<T>& l, const Box<T>& box) {
for (const auto& p : l)
if (!contains(p, box)) return false;
return true;
}
// _____________________________________________________________________________
// template <typename T>
// inline bool contains(const Point<T>& p1, const Point<T>& q1, const Point<T>&
// p2,
// const Point<T>& q2) {
// Line<T> a, b;
// a.push_back(p1);
// a.push_back(q1);
// b.push_back(p2);
// b.push_back(q2);
// return bgeo::covered_by(a, b);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline bool contains(const Point<T>& p1, const Point<T>& q1, const Point<T>& p2, // inline bool contains(T p1x, T p1y, T q1x, T q1y, T p2x, T p2y, T q2x, T q2y)
// const Point<T>& q2) { // {
// Line<T> a, b; // Point<T> p1(p1x, p1y);
// a.push_back(p1); // Point<T> q1(q1x, q1y);
// a.push_back(q1); // Point<T> p2(p2x, p2y);
// b.push_back(p2); // Point<T> q2(q2x, q2y);
// b.push_back(q2);
// return bgeo::covered_by(a, b); // return contains(p1, q1, p2, q2);
// }
// _____________________________________________________________________________
// template <typename T>
// inline bool contains(T p1x, T p1y, T q1x, T q1y, T p2x, T p2y, T q2x, T q2y) {
// Point<T> p1(p1x, p1y);
// Point<T> q1(q1x, q1y);
// Point<T> p2(p2x, p2y);
// Point<T> q2(q2x, q2y);
// return contains(p1, q1, p2, q2);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline bool intersects(const Point<T>& p1, const Point<T>& q1, // inline bool intersects(const Point<T>& p1, const Point<T>& q1,
// const Point<T>& p2, const Point<T>& q2) { // const Point<T>& p2, const Point<T>& q2) {
/* /*
* checks whether two line segments intersect * checks whether two line segments intersect
*/ */
// Line<T> a, b; // Line<T> a, b;
// a.push_back(p1); // a.push_back(p1);
// a.push_back(q1); // a.push_back(q1);
// b.push_back(p2); // b.push_back(p2);
// b.push_back(q2); // b.push_back(q2);
// return !(contains(p1, q1, p2, q2) || contains(p2, q2, p1, q1)) && // return !(contains(p1, q1, p2, q2) || contains(p2, q2, p1, q1)) &&
// bgeo::intersects(a, b); // bgeo::intersects(a, b);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline bool intersects(T p1x, T p1y, T q1x, T q1y, T p2x, T p2y, T q2x, T q2y) { // inline bool intersects(T p1x, T p1y, T q1x, T q1y, T p2x, T p2y, T q2x, T
/* // q2y) {
/*
* checks whether two line segments intersect * checks whether two line segments intersect
*/ */
// Point<T> p1(p1x, p1y); // Point<T> p1(p1x, p1y);
// Point<T> q1(q1x, q1y); // Point<T> q1(q1x, q1y);
// Point<T> p2(p2x, p2y); // Point<T> p2(p2x, p2y);
// Point<T> q2(q2x, q2y); // Point<T> q2(q2x, q2y);
// return intersects(p1, q1, p2, q2); // return intersects(p1, q1, p2, q2);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -254,10 +271,8 @@ inline Point<T> intersection(const Point<T>& p1, const Point<T>& q1,
/* /*
* calculates the intersection between two line segments * calculates the intersection between two line segments
*/ */
return intersection(p1.getX(), p1.getY(), return intersection(p1.getX(), p1.getY(), q1.getX(), q1.getY(), p2.getX(),
q1.getX(), q1.getY(), p2.getY(), q2.getX(), q2.getY());
p2.getX(), p2.getY(),
q2.getX(), q2.getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -280,10 +295,8 @@ inline bool lineIntersects(const Point<T>& p1, const Point<T>& q1,
/* /*
* checks whether two lines intersect * checks whether two lines intersect
*/ */
return lineIntersects(p1.getX(), p1.getY(), return lineIntersects(p1.getX(), p1.getY(), q1.getX(), q1.getY(), p2.getX(),
q1.getX(), q1.getY(), p2.getY(), q2.getX(), q2.getY());
p2.getX(), p2.getY(),
q2.getX(), q2.getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -296,8 +309,7 @@ inline double angBetween(double p1x, double p1y, double q1x, double q1y) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline double angBetween(const Point<T>& p1, const Point<T>& q1) { inline double angBetween(const Point<T>& p1, const Point<T>& q1) {
return angBetween(p1.getX(), p1.getY(), return angBetween(p1.getX(), p1.getY(), q1.getX(), q1.getY());
q1.getX(), q1.getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -321,23 +333,36 @@ inline double innerProd(double x1, double y1, double x2, double y2, double x3,
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline double innerProd(const Point<T>& a, const Point<T>& b, const Point<T>& c) { inline double innerProd(const Point<T>& a, const Point<T>& b,
return innerProd(a.template getX(), a.template getY(), const Point<T>& c) {
b.template getX(), b.template getY(), return innerProd(a.template getX(), a.template getY(), b.template getX(),
c.template getX(), c.template getY()); b.template getY(), c.template getX(), c.template getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline double dist(const Point<T>& p1, const Point<T>& p2) { inline double dist(const Point<T>& p1, const Point<T>& p2) {
return 0; // TODo return sqrt((p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) +
(p1.getY() - p2.getY()) * (p1.getY() - p2.getY()));
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline std::string getWKT(const Point<T>* p) { inline std::string getWKT(const Point<T>& p) {
std::stringstream ss; std::stringstream ss;
// TODO ss << "POINT (" << p.getX() << " " << p.getY() << ")";
return ss.str();
}
// _____________________________________________________________________________
template <typename T>
inline std::string getWKT(const Line<T>& l) {
std::stringstream ss;
ss << "LINESTRING (";
for (size_t i = 0; i < l.size(); i++) {
if (i) ss << ", ";
ss << l[i].getX() << " " << l[i].getY();
}
return ss.str(); return ss.str();
} }
@ -347,12 +372,26 @@ inline double len(const Point<T>& g) {
return 0; return 0;
} }
// _____________________________________________________________________________
template <typename T>
inline double len(const Line<T>& g) {
double ret = 0;
for (size_t i = 1; i < g.size(); i++) ret += dist(g[i - 1], g[i]);
return ret;
}
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline Point<T> simplify(const Point<T>& g, double d) { inline Point<T> simplify(const Point<T>& g, double d) {
return g; return g;
} }
// _____________________________________________________________________________
template <typename T>
inline Line<T> simplify(const Line<T>& g, double d) {
return g;
}
// _____________________________________________________________________________ // _____________________________________________________________________________
inline double distToSegment(double lax, double lay, double lbx, double lby, inline double distToSegment(double lax, double lay, double lbx, double lby,
double px, double py) { double px, double py) {
@ -374,24 +413,17 @@ inline double distToSegment(double lax, double lay, double lbx, double lby,
template <typename T> template <typename T>
inline double distToSegment(const Point<T>& la, const Point<T>& lb, inline double distToSegment(const Point<T>& la, const Point<T>& lb,
const Point<T>& p) { const Point<T>& p) {
return distToSegment(la.getX(), la.getY(), return distToSegment(la.getX(), la.getY(), lb.getX(), lb.getY(), p.getX(),
lb.getX(), lb.getY(), p.getY());
p.getX(), p.getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline Point<T> projectOn(const Point<T>& a, const Point<T>& b, inline Point<T> projectOn(const Point<T>& a, const Point<T>& b,
const Point<T>& c) { const Point<T>& c) {
if (doubleEq(a.getX(), b.getX()) && if (doubleEq(a.getX(), b.getX()) && doubleEq(a.getY(), b.getY())) return a;
doubleEq(a.getY(), b.getY())) if (doubleEq(a.getX(), c.getX()) && doubleEq(a.getY(), c.getY())) return a;
return a; if (doubleEq(b.getX(), c.getX()) && doubleEq(b.getY(), c.getY())) return b;
if (doubleEq(a.getX(), c.getX()) &&
doubleEq(a.getY(), c.getY()))
return a;
if (doubleEq(b.getX(), c.getX()) &&
doubleEq(b.getY(), c.getY()))
return b;
double x, y; double x, y;
@ -400,13 +432,11 @@ inline Point<T> projectOn(const Point<T>& a, const Point<T>& b,
x = a.getX(); x = a.getX();
y = b.getY(); y = b.getY();
} else { } else {
double m = (double)(c.getY() - a.getY()) / double m = (double)(c.getY() - a.getY()) / (c.getX() - a.getX());
(c.getX() - a.getX());
double bb = (double)a.getY() - (m * a.getX()); double bb = (double)a.getY() - (m * a.getX());
x = (m * b.getY() + b.getX() - m * bb) / (m * m + 1); x = (m * b.getY() + b.getX() - m * bb) / (m * m + 1);
y = (m * m * b.getY() + m * b.getX() + bb) / y = (m * m * b.getY() + m * b.getX() + bb) / (m * m + 1);
(m * m + 1);
} }
Point<T> ret = Point<T>(x, y); Point<T> ret = Point<T>(x, y);
@ -424,18 +454,18 @@ template <typename T>
inline double parallelity(const Box<T>& box, const Line<T>& line) { inline double parallelity(const Box<T>& box, const Line<T>& line) {
double ret = M_PI; double ret = M_PI;
double a = angBetween(box.min_corner(), double a = angBetween(
Point<T>(box.min_corner().getX(), box.getLowerLeft(),
box.max_corner().getY())); Point<T>(box.getLowerLeft().getX(), box.getUpperRight().getY()));
double b = angBetween(box.min_corner(), double b = angBetween(
Point<T>(box.max_corner().getX(), box.getLowerLeft(),
box.min_corner().getY())); Point<T>(box.getUpperRight().getX(), box.getLowerLeft().getY()));
double c = angBetween(box.max_corner(), double c = angBetween(
Point<T>(box.min_corner().getX(), box.getUpperRight(),
box.max_corner().getY())); Point<T>(box.getLowerLeft().getX(), box.getUpperRight().getY()));
double d = angBetween(box.max_corner(), double d = angBetween(
Point<T>(box.max_corner().getX(), box.getUpperRight(),
box.min_corner().getY())); Point<T>(box.getUpperRight().getX(), box.getLowerLeft().getY()));
double e = angBetween(line.front(), line.back()); double e = angBetween(line.front(), line.back());
@ -454,159 +484,170 @@ inline double parallelity(const Box<T>& box, const Line<T>& line) {
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline double parallelity(const Box<T>& box, const MultiLine<T>& multiline) { // inline double parallelity(const Box<T>& box, const MultiLine<T>& multiline) {
// double ret = 0; // double ret = 0;
// for (const Line<T>& l : multiline) { // for (const Line<T>& l : multiline) {
// ret += parallelity(box, l); // ret += parallelity(box, l);
// } // }
// return ret / multiline.size(); // return ret / multiline.size();
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename GeomA, typename GeomB> // template <typename GeomA, typename GeomB>
// inline bool intersects(const GeomA& a, const GeomB& b) { // inline bool intersects(const GeomA& a, const GeomB& b) {
// return bgeo::intersects(a, b); // return bgeo::intersects(a, b);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T, template <typename> typename Geometry> // template <typename T, template <typename> typename Geometry>
// inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) { // inline RotatedBox<T> getOrientedEnvelope(Geometry<T> pol) {
// // TODO: implement this nicer, works for now, but inefficient // // TODO: implement this nicer, works for now, but inefficient
// // see // // see
// // https://geidav.wordpress.com/tag/gift-wrapping/#fn-1057-FreemanShapira1975 // // https://geidav.wordpress.com/tag/gift-wrapping/#fn-1057-FreemanShapira1975
// // for a nicer algorithm // // for a nicer algorithm
// Point<T> center; // Point<T> center;
// bgeo::centroid(pol, center); // bgeo::centroid(pol, center);
// Box<T> tmpBox = getBoundingBox(pol); // Box<T> tmpBox = getBoundingBox(pol);
// double rotateDeg = 0; // double rotateDeg = 0;
// // rotate in 5 deg steps // // rotate in 5 deg steps
// for (int i = 1; i < 360; i += 1) { // for (int i = 1; i < 360; i += 1) {
// pol = rotate(pol, 1, center); // pol = rotate(pol, 1, center);
// Box<T> e; // Box<T> e;
// bgeo::envelope(pol, e); // bgeo::envelope(pol, e);
// if (bgeo::area(tmpBox) > bgeo::area(e)) { // if (bgeo::area(tmpBox) > bgeo::area(e)) {
// tmpBox = e; // tmpBox = e;
// rotateDeg = i; // rotateDeg = i;
// } // }
// } // }
// return RotatedBox<T>(tmpBox, -rotateDeg, center); // return RotatedBox<T>(tmpBox, -rotateDeg, center);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
// inline Box<T> getBoundingBox(Point<T> pol) { inline Box<T> getBoundingBox(const Point<T>& p) {
// Box<T> tmpBox; return Box<T>(p, p);
// bgeo::envelope(pol, tmpBox); }
// return tmpBox;
// }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> template <typename T>
// inline Box<T> extendBox(const Box<T>& a, Box<T> b) { inline Box<T> getBoundingBox(const Line<T>& l) {
// bgeo::expand(b, a); Box<T> ret;
// return b; for (const auto& p : l) extendBox(p, ret);
// } return ret;
}
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename G, typename T> template <typename T>
inline Box<T> extendBox(G pol, Box<T> b) { inline Box<T> extendBox(const Box<T>& a, Box<T> b) {
Box<T> tmp; b = extendBox(a.getLowerLeft(), b);
bgeo::envelope(pol, tmp); b = extendBox(a.getUpperRight(), b);
bgeo::expand(b, tmp);
return b; return b;
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> template <typename T>
// inline double commonArea(const Box<T>& ba, const Box<T>& bb) { inline Box<T> extendBox(const Point<T>& p, Box<T> b) {
// T l = std::max(ba.min_corner().getX(), if (p.getX() < b.getLowerLeft().getX()) b.getLowerLeft().setX(p.getX());
// bb.min_corner().getX()); if (p.getY() < b.getLowerLeft().getY()) b.getLowerLeft().setY(p.getY());
// T r = std::min(ba.max_corner().getX(),
// bb.max_corner().getX());
// T b = std::max(ba.min_corner().getY(),
// bb.min_corner().getY());
// T t = std::min(ba.max_corner().getY(),
// bb.max_corner().getY());
// if (l > r || b > t) return 0; if (p.getX() > b.getUpperRight().getX()) b.getUpperRight().setX(p.getX());
if (p.getY() > b.getUpperRight().getY()) b.getUpperRight().setY(p.getY());
return b;
}
// return (r - l) * (t - b); // _____________________________________________________________________________
// } template <typename T>
inline Box<T> extendBox(const Line<T>& l, Box<T> b) {
for (const auto& p : l) b = extendBox(p, b);
return b;
}
// _____________________________________________________________________________
template <typename T>
inline double commonArea(const Box<T>& ba, const Box<T>& bb) {
T l = std::max(ba.getLowerLeft().getX(), bb.getLowerLeft().getX());
T r = std::min(ba.getUpperRight().getX(), bb.getUpperRight().getX());
T b = std::max(ba.getLowerLeft().getY(), bb.getLowerLeft().getY());
T t = std::min(ba.getUpperRight().getY(), bb.getUpperRight().getY());
if (l > r || b > t) return 0;
return (r - l) * (t - b);
}
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T, template <typename> typename Geometry> // template <typename T, template <typename> typename Geometry>
// inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) { // inline RotatedBox<T> getFullEnvelope(Geometry<T> pol) {
// Point<T> center; // Point<T> center;
// bgeo::centroid(pol, center); // bgeo::centroid(pol, center);
// Box<T> tmpBox; // Box<T> tmpBox;
// bgeo::envelope(pol, tmpBox); // bgeo::envelope(pol, tmpBox);
// double rotateDeg = 0; // double rotateDeg = 0;
// MultiPolygon<T> ml; // MultiPolygon<T> ml;
// // rotate in 5 deg steps // // rotate in 5 deg steps
// for (int i = 1; i < 360; i += 1) { // for (int i = 1; i < 360; i += 1) {
// pol = rotate(pol, 1, center); // pol = rotate(pol, 1, center);
// Polygon<T> hull; // Polygon<T> hull;
// bgeo::convex_hull(pol, hull); // bgeo::convex_hull(pol, hull);
// ml.push_back(hull); // ml.push_back(hull);
// Box<T> e; // Box<T> e;
// bgeo::envelope(pol, e); // bgeo::envelope(pol, e);
// if (bgeo::area(tmpBox) > bgeo::area(e)) { // if (bgeo::area(tmpBox) > bgeo::area(e)) {
// tmpBox = e; // tmpBox = e;
// rotateDeg = i; // rotateDeg = i;
// } // }
// } // }
// bgeo::envelope(ml, tmpBox); // bgeo::envelope(ml, tmpBox);
// return RotatedBox<T>(tmpBox, rotateDeg, center); // return RotatedBox<T>(tmpBox, rotateDeg, center);
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
// template <typename T> // template <typename T>
// inline RotatedBox<T> getOrientedEnvelopeAvg(MultiLine<T> ml) { // inline RotatedBox<T> getOrientedEnvelopeAvg(MultiLine<T> ml) {
// MultiLine<T> orig = ml; // MultiLine<T> orig = ml;
// // get oriented envelope for hull // // get oriented envelope for hull
// RotatedBox<T> rbox = getFullEnvelope<T>(ml); // RotatedBox<T> rbox = getFullEnvelope<T>(ml);
// Point<T> center; // Point<T> center;
// bgeo::centroid(rbox.b, center); // bgeo::centroid(rbox.b, center);
// ml = rotate(ml, -rbox.rotateDeg - 45, center); // ml = rotate(ml, -rbox.rotateDeg - 45, center);
// double bestDeg = -45; // double bestDeg = -45;
// double score = parallelity(rbox.b, ml); // double score = parallelity(rbox.b, 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.b, ml);
// if (parallelity(rbox.b, ml) > score) { // if (parallelity(rbox.b, ml) > score) {
// bestDeg = i; // bestDeg = i;
// score = p; // score = p;
// } // }
// } // }
// rbox.rotateDeg += bestDeg; // rbox.rotateDeg += 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
// Polygon<T> p = rbox.getPolygon(); // Polygon<T> p = rbox.getPolygon();
// p = rotate(p, -rbox.rotateDeg, rbox.center); // p = rotate(p, -rbox.rotateDeg, rbox.center);
// Polygon<T> hull; // Polygon<T> hull;
// bgeo::convex_hull(orig, hull); // bgeo::convex_hull(orig, hull);
// hull = rotate(hull, -rbox.rotateDeg, rbox.center); // hull = rotate(hull, -rbox.rotateDeg, rbox.center);
// Box<T> box; // Box<T> box;
// bgeo::envelope(hull, box); // bgeo::envelope(hull, box);
// rbox = RotatedBox<T>(box, rbox.rotateDeg, rbox.center); // rbox = RotatedBox<T>(box, rbox.rotateDeg, rbox.center);
// return rbox; // return rbox;
// } // }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -619,15 +660,13 @@ inline Line<T> densify(const Line<T>& l, double d) {
ret.push_back(l.front()); ret.push_back(l.front());
for (size_t i = 1; i < l.size(); i++) { for (size_t i = 1; i < l.size(); i++) {
double segd = dist(l[i-1], l[i]); double segd = dist(l[i - 1], l[i]);
double dx = double dx = (l[i].getX() - l[i - 1].getX()) / segd;
(l[i].getX() - l[i-1].getX()) / segd; double dy = (l[i].getY() - l[i - 1].getY()) / segd;
double dy =
(l[i].getY() - l[i-1].getY()) / segd;
double curd = d; double curd = d;
while (curd < segd) { while (curd < segd) {
ret.push_back(Point<T>(l[i-1].getX() + dx * curd, ret.push_back(
l[i-1].getY() + dy * curd)); Point<T>(l[i - 1].getX() + dx * curd, l[i - 1].getY() + dy * curd));
curd += d; curd += d;
} }
@ -683,29 +722,29 @@ inline double frechetDist(const Line<T>& a, const Line<T>& b, double d) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline double accFrechetDistC(const Line<T>& a, const Line<T>& b, double d) { inline double accFrechetDistC(const Line<T>& a, const Line<T>& b, double d) {
auto p = densify(a, d); auto p = densify(a, d);
auto q = densify(b, d); auto q = densify(b, d);
std::vector<std::vector<double>> ca(p.size(), std::vector<std::vector<double>> ca(p.size(),
std::vector<double>(q.size(), 0)); std::vector<double>(q.size(), 0));
for (size_t i = 0; i < p.size(); i++) ca[i][0] = std::numeric_limits<double>::infinity(); for (size_t i = 0; i < p.size(); i++)
for (size_t j = 0; j < q.size(); j++) ca[0][j] = std::numeric_limits<double>::infinity(); ca[i][0] = std::numeric_limits<double>::infinity();
for (size_t j = 0; j < q.size(); j++)
ca[0][j] = std::numeric_limits<double>::infinity();
ca[0][0] = 0; ca[0][0] = 0;
for (size_t i = 1; i < p.size(); i++) { for (size_t i = 1; i < p.size(); i++) {
for (size_t j = 1; j < q.size(); j++) { for (size_t j = 1; j < q.size(); j++) {
double d = util::geo::dist(p[i], q[j]) * util::geo::dist(p[i], p[i-1]); double d = util::geo::dist(p[i], q[j]) * util::geo::dist(p[i], p[i - 1]);
ca[i][j] = d + std::min(ca[i-1][j], std::min(ca[i][j-1], ca[i-1][j-1])); ca[i][j] =
d + std::min(ca[i - 1][j], std::min(ca[i][j - 1], ca[i - 1][j - 1]));
} }
} }
return ca[p.size() - 1][q.size() - 1]; return ca[p.size() - 1][q.size() - 1];
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline Point<T> latLngToWebMerc(double lat, double lng) { inline Point<T> latLngToWebMerc(double lat, double lng) {

21
src/util/geo/Line.h Normal file
View file

@ -0,0 +1,21 @@
// Copyright 2016, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Patrick Brosi <brosi@informatik.uni-freiburg.de>
#ifndef UTIL_GEO_LINE_H_
#define UTIL_GEO_LINE_H_
#include <vector>
#include "./Point.h"
namespace util {
namespace geon {
template<typename T>
using Line = std::vector<Point<T>>;
} // namespace geon
} // namespace util
#endif // UTIL_GEO_LINE_H_

View file

@ -5,9 +5,6 @@
#ifndef UTIL_GEO_POINT_H_ #ifndef UTIL_GEO_POINT_H_
#define UTIL_GEO_POINT_H_ #define UTIL_GEO_POINT_H_
#include <set>
#include <vector>
namespace util { namespace util {
namespace geon { namespace geon {
@ -21,9 +18,20 @@ class Point {
void setX(T x) { _x = x; } void setX(T x) { _x = x; }
void setY(T y) { _y = y; } void setY(T y) { _y = y; }
Point<T> operator+(const Point<T>& p) const {
return Point<T>(_x + p.getX(), _y + p.getY());
}
bool operator==(const Point<T>& p) const {
return p.getX() == _x && p.getY() == _y;
}
bool operator!=(const Point<T>& p) const {
return !(*this == p);
}
private: private:
T _x, _y; T _x, _y;
}; };
} // namespace geon } // namespace geon

View file

@ -846,6 +846,43 @@ CASE("nullable") {
// ___________________________________________________________________________ // ___________________________________________________________________________
CASE("geometry") { CASE("geometry") {
geon::Point<double> a(1, 2);
geon::Point<double> b(2, 3);
geon::Point<double> c(4, 5);
EXPECT(a.getX() == approx(1));
EXPECT(a.getY() == approx(2));
a.setX(3);
EXPECT(a.getX() == approx(3));
EXPECT(a.getY() == approx(2));
a.setY(4);
EXPECT(a.getX() == approx(3));
EXPECT(a.getY() == approx(4));
auto d = a + b;
EXPECT(d.getX() == approx(5));
EXPECT(d.getY() == approx(7));
a.setX(1);
a.setY(2);
EXPECT(geon::dist(a, a) == approx(0));
EXPECT(geon::dist(a, b) == approx(sqrt(2)));
d = d + d;
geon::Box<double> box(a, c);
EXPECT(geon::contains(a, box));
EXPECT(geon::contains(b, box));
EXPECT(geon::contains(c, box));
EXPECT(!geon::contains(d, box));
geon::Line<double> line{a, b, c};
EXPECT(geon::contains(line, box));
line.push_back(d);
EXPECT(!geon::contains(line, box));
} }
}; };