/* * © Copyright 2014 – Urheberrechtshinweis * Alle Rechte vorbehalten / All Rights Reserved * * Programmcode ist urheberrechtlich geschuetzt. * Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner. * Einige Aenderungen beigetragen von Toni Fetzer * Keine Verwendung ohne explizite Genehmigung. * (vgl. § 106 ff UrhG / § 97 UrhG) */ #ifndef GEO_BBOX2_H #define GEO_BBOX2_H #include "Point2.h" #include "Line2.h" #include class BBox2 { protected: static constexpr float MAX = +99999999; static constexpr float MIN = -99999999; /** minimum */ Point2 p1; /** maximum */ Point2 p2; public: /** empty ctor */ BBox2() : p1(MAX,MAX), p2(MIN,MIN) {;} /** ctor */ BBox2(const Point2& p1, const Point2& p2) : p1(p1), p2(p2) {;} /** ctor */ BBox2(const float x1, const float y1, const float x2, const float y2) : p1(x1,y1), p2(x2,y2) {;} /** adjust the bounding-box by adding this point */ void add(const Point2& p) { add(p.x, p.y); } /** adjust the bounding-box by adding this point */ void add(const float x, const float y) { if (x > p2.x) {p2.x = x;} if (y > p2.y) {p2.y = y;} if (x < p1.x) {p1.x = x;} if (y < p1.y) {p1.y = y;} } /** the area spanned by the bbox */ float getArea() const {return getSize().x * getSize().y;} /** returns true if the bbox is not yet configured */ bool isInvalid() const { return p1.x == MAX || p1.y == MAX || p2.x == MIN || p2.y == MIN; } /** get the bbox's minimum */ const Point2& getMin() const {return p1;} /** get the bbox's maximum */ const Point2& getMax() const {return p2;} /** get the bbox's size [max-min] */ const Point2 getSize() const {return p2-p1;} /** get the bbox's center point */ Point2 getCenter() const { return (p1+p2) / 2; } Point2 getCorner1() const {return Point2(p1.x, p1.y);} Point2 getCorner2() const {return Point2(p2.x, p1.y);} Point2 getCorner3() const {return Point2(p1.x, p2.y);} Point2 getCorner4() const {return Point2(p2.x, p2.y);} /** equal? */ bool operator == (const BBox2& o) const { return (p1.x == o.p1.x) && (p1.y == o.p1.y) && (p2.x == o.p2.x) && (p2.y == o.p2.y); } bool intersects(const BBox2& o) const { // TODO is this correct? if (o.p2.x < p1.x) {return false;} if (o.p1.x > p2.x) {return false;} if (o.p2.y < p1.y) {return false;} if (o.p1.y > p2.y) {return false;} return true; // return (p1.x <= o.p2.x) && // (p1.y <= o.p2.y) && // (p2.x >= o.p1.x) && // (p2.y >= o.p1.y); } BBox2 combine(const BBox2& o) { // TODO is this correct? const float x1 = std::min(p1.x, o.p1.x); const float x2 = std::max(p2.x, o.p2.x); const float y1 = std::min(p1.y, o.p1.y); const float y2 = std::max(p2.y, o.p2.y); return BBox2(x1,y1, x2,y2); } BBox2 intersection(const BBox2& o) const { // TODO is this correct? const float x1 = std::max(p1.x, o.p1.x); const float x2 = std::min(p2.x, o.p2.x); const float y1 = std::max(p1.y, o.p1.y); const float y2 = std::min(p2.y, o.p2.y); return BBox2(x1,y1, x2,y2); } /** does the BBox intersect with the given line? */ bool intersects (const Line2& l) const { const Line2 l1(p1.x, p1.y, p2.x, p1.y); // upper const Line2 l2(p1.x, p2.y, p2.x, p2.y); // lower const Line2 l3(p1.x, p1.y, p1.x, p2.y); // left const Line2 l4(p2.x, p1.y, p2.x, p2.y); // right return l.getSegmentIntersection(l1) || l.getSegmentIntersection(l2) || l.getSegmentIntersection(l3) || l.getSegmentIntersection(l4); } std::vector lines() const { return std::vector( { Line2(p1.x, p1.y, p2.x, p1.y), Line2(p1.x, p2.y, p2.x, p2.y), Line2(p1.x, p1.y, p1.x, p2.y), Line2(p2.x, p1.y, p2.x, p2.y) } ); } bool contains(const Point2& p) const { return contains(p.x, p.y); } bool contains(const float x, const float y) const { if (x < p1.x) {return false;} if (x > p2.x) {return false;} if (y < p1.y) {return false;} if (y > p2.y) {return false;} return true; } /** grow the bbox by the amount given for each dimension */ void grow(const Point2& p) { p1 -= p; // decrease minimum p2 += p; // increase maximum } /** grow the bbox by the amount given for each dimension */ void grow(const float val) { p1 -= Point2(val, val); // decrease minimum p2 += Point2(val, val); // increase maximum } /** grow the bbox by the amount given for each dimension */ void growRel(const float val) { const Point2 center = (p1+p2)/2; p1 += (p1-center)*val; // decrease minimum p2 += (p2-center)*val; // increase maximum } /** combine two bboxes */ static BBox2 join(const BBox2& bb1, const BBox2& bb2) { const Point2 min( std::min(bb1.p1.x, bb2.p1.x), std::min(bb1.p1.y, bb2.p1.y) ); const Point2 max( std::max(bb1.p2.x, bb2.p2.x), std::max(bb1.p2.y, bb2.p2.y) ); return BBox2(min, max); } }; #endif // GEO_BBOX2_H