This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/geo/BBox2.h
2018-10-25 11:50:12 +02:00

197 lines
4.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © 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 <vector>
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<Line2> lines() const {
return std::vector<Line2>(
{
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