diff --git a/src/util/geo/Box.h b/src/util/geo/Box.h index 3c41e80..dfaae15 100644 --- a/src/util/geo/Box.h +++ b/src/util/geo/Box.h @@ -43,8 +43,8 @@ class RotatedBox { public: RotatedBox() : _box() {} RotatedBox(const Box& box) : _box(box), _deg(0), _center() {} - RotatedBox(const Point& ll, const Point& ur) : _box(ll, ur), _deg(0), _center() {} - + RotatedBox(const Point& ll, const Point& ur) + : _box(ll, ur), _deg(0), _center() {} private: Box _box; diff --git a/src/util/geo/Geo.h b/src/util/geo/Geo.h index 4787c90..b176592 100644 --- a/src/util/geo/Geo.h +++ b/src/util/geo/Geo.h @@ -1,6 +1,7 @@ // Copyright 2016, University of Freiburg, // Chair of Algorithms and Data Structures. // Authors: Patrick Brosi + #ifndef UTIL_GEO_GEO_H_ #define UTIL_GEO_GEO_H_ @@ -45,52 +46,12 @@ typedef Polygon FPolygon; typedef Polygon IPolygon; const static double EPSILON = 0.0000001; - -// _____________________________________________________________________________ -// template -// inline Line rotate(const Line& geo, double deg, const Point& center) -// { -// Line ret; - -// bgeo::strategy::transform::translate_transformer translate( -// -center.getX(), -center.getY()); -// bgeo::strategy::transform::rotate_transformer rotate( -// deg); -// bgeo::strategy::transform::translate_transformer translateBack( -// center.getX(), center.getY()); - -// bgeo::strategy::transform::ublas_transformer translateRotate( -// prod(rotate.matrix(), translate.matrix())); -// bgeo::strategy::transform::ublas_transformer all( -// prod(translateBack.matrix(), translateRotate.matrix())); - -// bgeo::transform(geo, ret, all); - -// return ret; -// } +const static double RAD = 0.017453292519943295; // PI/180 // _____________________________________________________________________________ // template // inline MultiLine rotate(const MultiLine& geo, double deg, -// const Point& center) { -// MultiLine ret; - -// bgeo::strategy::transform::translate_transformer translate( -// -center.getX(), -center.getY()); -// bgeo::strategy::transform::rotate_transformer rotate( -// deg); -// bgeo::strategy::transform::translate_transformer translateBack( -// center.getX(), center.getY()); - -// bgeo::strategy::transform::ublas_transformer translateRotate( -// prod(rotate.matrix(), translate.matrix())); -// bgeo::strategy::transform::ublas_transformer all( -// prod(translateBack.matrix(), translateRotate.matrix())); - -// bgeo::transform(geo, ret, all); - -// return ret; -// } +// const Point& center) {} // _____________________________________________________________________________ template @@ -101,6 +62,42 @@ inline Box pad(const Box& box, double padding) { box.getUpperRight().getY() + padding)); } +// _____________________________________________________________________________ +template +inline Point centroid(const Point p) { + return p; +} + +// _____________________________________________________________________________ +template +inline Point centroid(const LineSegment ls) { + return Point((ls.first.getX() + ls.second.getX()) / T(2), + (ls.first.getY() + ls.second.getY()) / T(2)); +} + +// _____________________________________________________________________________ +template +inline Point centroid(const Line ls) { + double x = 0, y = 0; + for (const auto& p : ls) { + x += p.getX(); + y += p.getY(); + } + return Point(x / T(ls.size()), y / T(ls.size())); +} + +// _____________________________________________________________________________ +template +inline Point centroid(const Polygon ls) { + return centroid(ls.getOuter()); +} + +// _____________________________________________________________________________ +template +inline Point centroid(const Box box) { + return centroid(LineSegment(box.getLowerLeft(), box.getUpperRight())); +} + // _____________________________________________________________________________ template inline Point rotate(const Point& p, double deg) { @@ -108,12 +105,47 @@ inline Point rotate(const Point& p, double deg) { } // _____________________________________________________________________________ -// template -// inline Line rotate(const Line& geo, double deg) { -// Point center; -// bgeo::centroid(geo, center); -// return rotate(geo, deg, center); -// } +template +inline Point rotate(Point p, double deg, const Point& c) { + deg *= -RAD; + double si = sin(deg); + double co = cos(deg); + p = p - c; + + return Point(p.getX() * co - p.getY() * si, + p.getX() * si + p.getY() * co) + + c; +} + +// _____________________________________________________________________________ +template +inline LineSegment rotate(LineSegment geo, double deg, + const Point& c) { + geo.first = rotate(geo.first, deg, c); + geo.second = rotate(geo.second, deg, c); + return geo; +} + +// _____________________________________________________________________________ +template +inline LineSegment rotate(LineSegment geo, double deg) { + return (geo, deg, centroid(geo)); +} + +// _____________________________________________________________________________ +template +inline Line rotate(Line geo, double deg, const Point& c) { + for (size_t i = 0; i < geo.size(); i++) geo[i] = rotate(geo[i], deg, c); + return geo; +} + +// _____________________________________________________________________________ +template +inline Polygon rotate(Polygon geo, double deg, const Point& c) { + for (size_t i = 0; i < geo.getOuter().size(); i++) + geo.getOuter()[i] = rotate(geo.getOuter()[i], deg, c); + return geo; +} // _____________________________________________________________________________ // template diff --git a/src/util/geo/Point.h b/src/util/geo/Point.h index 942a361..df2b9aa 100644 --- a/src/util/geo/Point.h +++ b/src/util/geo/Point.h @@ -23,6 +23,10 @@ class Point { return Point(_x + p.getX(), _y + p.getY()); } + Point operator-(const Point& p) const { + return Point(_x - p.getX(), _y - p.getY()); + } + bool operator==(const Point& p) const { return p.getX() == _x && p.getY() == _y; } diff --git a/src/util/geo/Polygon.h b/src/util/geo/Polygon.h index 1cef21f..3b1adac 100644 --- a/src/util/geo/Polygon.h +++ b/src/util/geo/Polygon.h @@ -6,8 +6,9 @@ #define UTIL_GEO_POLYGON_H_ #include -#include "./Point.h" +#include "./Box.h" #include "./Line.h" +#include "./Point.h" namespace util { namespace geo { @@ -18,15 +19,19 @@ class Polygon { Polygon() {} Polygon(const Line& l) : _outer(l) {} + Polygon(const Box& b) + : _outer({b.getLowerLeft(), + Point(b.getUpperRight().getX(), b.getLowerLeft().getY()), + b.getUpperRight(), + Point(b.getLowerLeft().getX(), b.getUpperRight().getY())}) {} const std::vector>& getOuter() const { return _outer; } - std::vector>& getOuter() {return _outer; } + std::vector>& getOuter() { return _outer; } private: std::vector> _outer; }; - } // namespace geo } // namespace util diff --git a/src/util/tests/TestMain.cpp b/src/util/tests/TestMain.cpp index 053f20f..cd43ed3 100644 --- a/src/util/tests/TestMain.cpp +++ b/src/util/tests/TestMain.cpp @@ -959,12 +959,26 @@ CASE("geometry") { EXPECT(geo::contains(Line{Point(4, 2), Point(5, 1)}, poly)); Box polybox(Point(1, 1), Point(6, 4)); + EXPECT(geo::centroid(polybox).getX() == approx(3.5)); + EXPECT(geo::centroid(polybox).getY() == approx(2.5)); EXPECT(geo::contains(poly, polybox)); EXPECT(!geo::contains(polybox, poly)); Box polybox2(Point(4, 1), Point(5, 2)); EXPECT(geo::contains(polybox2, poly)); EXPECT(geo::contains(poly, getBoundingBox(poly))); + Point rotP(2, 2); + EXPECT(geo::dist(geo::rotate(rotP, 180, Point(1, 1)), Point(0, 0)) == approx(0)); + EXPECT(geo::dist(geo::rotate(rotP, 360, Point(1, 1)), rotP) == approx(0)); + + Line rotLine({{1, 1}, {3, 3}}); + EXPECT(geo::rotate(rotLine, 90, Point(2, 2))[0].getX() == approx(1)); + EXPECT(geo::rotate(rotLine, 90, Point(2, 2))[0].getY() == approx(3)); + EXPECT(geo::rotate(rotLine, 90, Point(2, 2))[1].getX() == approx(3)); + EXPECT(geo::rotate(rotLine, 90, Point(2, 2))[1].getY() == approx(1)); + + EXPECT(geo::dist(geo::centroid(rotP), rotP) == approx(0)); + EXPECT(geo::dist(geo::centroid(rotLine), rotP) == approx(0)); } };