more work on util

This commit is contained in:
Patrick Brosi 2018-07-17 19:33:05 +02:00
parent 223ffa6f6b
commit 3af004e49b
4 changed files with 139 additions and 3 deletions

View file

@ -38,6 +38,20 @@ class Box {
Point<T> _ll, _ur;
};
template <typename T>
class RotatedBox {
public:
RotatedBox() : _box() {}
RotatedBox(const Box<T>& box) : _box(box), _deg(0), _center() {}
RotatedBox(const Point<T>& ll, const Point<T>& ur) : _box(ll, ur), _deg(0), _center() {}
private:
Box<T> _box;
double _deg;
Point<T> _center;
};
} // namespace geo
} // namespace util

View file

@ -7,6 +7,7 @@
#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
#include <sstream>
#include "util/Misc.h"
#include "util/geo/Box.h"
@ -215,6 +216,90 @@ inline bool contains(const Point<T>& p, const Line<T>& l) {
return false;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Point<T>& p, const Polygon<T>& poly) {
// see https://de.wikipedia.org/wiki/Punkt-in-Polygon-Test_nach_Jordan
int8_t c = -1;
for (size_t i = 1; i < poly.getOuter().size(); i++) {
c *= polyContCheck(p, poly.getOuter()[i - 1], poly.getOuter()[i]);
if (c == 0) return true;
}
c *= polyContCheck(p, poly.getOuter().back(), poly.getOuter()[0]);
return c >= 0;
}
// _____________________________________________________________________________
template <typename T>
inline int8_t polyContCheck(const Point<T>& a, Point<T> b, Point<T> c) {
if (a.getY() == b.getY() && a.getY() == c.getY())
return (!((b.getX() <= a.getX() && a.getX() <= c.getX()) ||
(c.getX() <= a.getX() && a.getX() <= b.getX())));
if (a.getY() == b.getY() && a.getX() == b.getX()) return 0;
if (b.getY() > c.getY()) {
Point<T> tmp = b;
b = c;
c = tmp;
}
if (a.getY() <= b.getY() || a.getY() > c.getY()) return 1;
double d = (b.getX() - a.getX()) * (c.getY() - a.getY()) -
(b.getY() - a.getY()) * (c.getX() - a.getX());
if (d > 0) return -1;
if (d < 0) return 1;
return 0;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Polygon<T>& polyC, const Polygon<T>& poly) {
for (const auto& p : polyC.getOuter()) {
if (!contains(p, poly)) return false;
}
return true;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Line<T>& l, const Polygon<T>& poly) {
for (const auto& p : l) {
if (!contains(p, poly)) return false;
}
return true;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Box<T>& b, const Polygon<T>& poly) {
return contains(b.getLowerLeft(), poly) &&
contains(b.getUpperRight(), poly) &&
contains(Point<T>(b.getUpperRight().getX(), b.getLowerLeft().getY()),
poly) &&
contains(Point<T>(b.getLowerLeft().getX(), b.getUpperRight().getY()),
poly);
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Polygon<T>& poly, const Box<T>& b) {
for (const auto& p : poly.getOuter()) {
if (!contains(p, b)) return false;
}
return true;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const Polygon<T>& poly, const Line<T>& l) {
for (const auto& p : poly.getOuter()) {
if (!contains(p, l)) return false;
}
return true;
}
// _____________________________________________________________________________
template <typename T>
inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) {
@ -439,8 +524,7 @@ inline double innerProd(double x1, double y1, double x2, double y2, double x3,
template <typename T>
inline double innerProd(const Point<T>& a, const Point<T>& b,
const Point<T>& c) {
return innerProd(a.template getX(), a.template getY(), b.template getX(),
b.template getY(), c.template getX(), c.template getY());
return innerProd(a.getX(), a.getY(), b.getX(), b.getY(), c.getX(), c.getY());
}
// _____________________________________________________________________________
@ -486,6 +570,12 @@ inline std::string getWKT(const Line<T>& l) {
return ss.str();
}
// _____________________________________________________________________________
template <typename T>
inline std::string getWKT(const LineSegment<T>& l) {
return getWKT(Line<T>{l.first, l.second});
}
// _____________________________________________________________________________
template <typename T>
inline std::string getWKT(const Box<T>& l) {
@ -744,6 +834,14 @@ inline Box<T> getBoundingBox(const Line<T>& l) {
return ret;
}
// _____________________________________________________________________________
template <typename T>
inline Box<T> getBoundingBox(const Polygon<T>& pol) {
Box<T> ret;
for (const auto& p : pol.getOuter()) ret = extendBox(p, ret);
return ret;
}
// _____________________________________________________________________________
template <typename T>
inline Box<T> getBoundingBox(const LineSegment<T>& ls) {

View file

@ -15,7 +15,8 @@ namespace geo {
template <typename T>
class Polygon {
public:
// maximum inverse box as default value of box
Polygon() {}
Polygon(const Line<T>& l) : _outer(l) {}
const std::vector<Point<T>>& getOuter() const { return _outer; }

View file

@ -942,6 +942,29 @@ CASE("geometry") {
EXPECT(geo::intersects(Box<double>(Point<double>(0, 0), Point<double>(3, 3)), boxa));
EXPECT(geo::intersects(Box<double>(Point<double>(1.5, 1.5), Point<double>(3, 3)), boxa));
EXPECT(geo::intersects(Box<double>(Point<double>(0, 0), Point<double>(1.5, 1.5)), boxa));
Polygon<double> poly({Point<double>(1, 1), Point<double>(3, 2), Point<double>(4, 3), Point<double>(6, 3), Point<double>(5, 1)});
EXPECT(geo::getWKT(poly) == "POLYGON ((1 1, 3 2, 4 3, 6 3, 5 1))");
EXPECT(geo::contains(Point<double>(4, 2), poly));
EXPECT(!geo::contains(Point<double>(3, 3), poly));
EXPECT(geo::contains(Point<double>(1, 1), poly));
EXPECT(geo::contains(Point<double>(3, 2), poly));
EXPECT(geo::contains(Point<double>(4, 3), poly));
EXPECT(geo::contains(Point<double>(6, 3), poly));
EXPECT(geo::contains(Point<double>(5, 1), poly));
EXPECT(geo::contains(Line<double>{Point<double>(6, 3), Point<double>(5, 1)}, poly));
EXPECT(!geo::contains(Line<double>{Point<double>(6, 3), Point<double>(50, 1)}, poly));
EXPECT(geo::contains(Line<double>{Point<double>(4, 2), Point<double>(4.5, 2)}, poly));
EXPECT(geo::contains(Line<double>{Point<double>(4, 2), Point<double>(5, 1)}, poly));
Box<double> polybox(Point<double>(1, 1), Point<double>(6, 4));
EXPECT(geo::contains(poly, polybox));
EXPECT(!geo::contains(polybox, poly));
Box<double> polybox2(Point<double>(4, 1), Point<double>(5, 2));
EXPECT(geo::contains(polybox2, poly));
EXPECT(geo::contains(poly, getBoundingBox(poly)));
}
};