定义AABBRect类,通常用于表示其他几何对象的AABB外接矩形,用于相交的快速判断。
下面给出AABBRect的声明。
class AABBRect : public Geometry
{
private:
std::vector<Point> _points;
public:
AABBRect();
AABBRect(const double x0, const double y0, const double x1, const double y1);
AABBRect(const Point &point0, const Point &point1);
AABBRect(const AABBRect &rect);
const Type type() const override;
const double left() const;
const double top() const;
const double right() const;
const double bottom() const;
void set_left(const double value);
void set_top(const double value);
void set_right(const double value);
void set_bottom(const double value);
AABBRect &operator=(const AABBRect &reac);
const bool empty() const override;
const double length() const override;
void clear() override;
AABBRect *clone() const override;
const double area() const;
const double width() const;
const double height() const;
void set_width(const double value);
void set_height(const double value);
void transform(const double a, const double b, const double c, const double d, const double e, const double f) override;
void transform(const double mat[6]) override;
void translate(const double tx, const double ty) override;
void rotate(const double x, const double y, const double rad) override; // 弧度制
void scale(const double x, const double y, const double k) override;
Polygon convex_hull() const override;
AABBRect bounding_rect() const override;
Polygon mini_bounding_rect() const override;
std::vector<Point>::const_iterator begin() const;
std::vector<Point>::const_iterator cbegin() const;
std::vector<Point>::const_iterator end() const;
std::vector<Point>::const_iterator cend() const;
std::vector<Point>::const_reverse_iterator rbegin() const;
std::vector<Point>::const_reverse_iterator crbegin() const;
std::vector<Point>::const_reverse_iterator rend() const;
std::vector<Point>::const_reverse_iterator crend() const;
std::vector<Point>::const_iterator find(const Point &point) const;
AABBRect operator+(const Point &point) const;
AABBRect operator-(const Point &point) const;
void operator+=(const Point &point);
void operator-=(const Point &point);
const Point center() const;
const Point &operator[](const size_t index) const;
};
下面给出AABBRect的实现。
AABBRect::AABBRect()
{
_points.assign({Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0)});
}
AABBRect::AABBRect(const double x0, const double y0, const double x1, const double y1)
{
if (x0 < x1)
{
if (y0 > y1)
{
_points.assign({Point(x0, y0), Point(x1, y0), Point(x1, y1), Point(x0, y1), Point(x0, y0)});
}
else
{
_points.assign({Point(x0, y1), Point(x1, y1), Point(x1, y0), Point(x0, y0), Point(x0, y1)});
}
}
else
{
if (y0 > y1)
{
_points.assign({Point(x1, y0), Point(x0, y0), Point(x0, y1), Point(x1, y1), Point(x1, y0)});
}
else
{
_points.assign({Point(x1, y1), Point(x0, y1), Point(x0, y0), Point(x1, y0), Point(x1, y1)});
}
}
}
AABBRect::AABBRect(const Point &point0, const Point &point1)
{
const double x0 = point0.x, y0 = point0.y, x1 = point1.x, y1 = point1.y;
if (x0 < x1)
{
if (y0 > y1)
{
_points.assign({Point(x0, y0), Point(x1, y0), Point(x1, y1), Point(x0, y1), Point(x0, y0)});
}
else
{
_points.assign({Point(x0, y1), Point(x1, y1), Point(x1, y0), Point(x0, y0), Point(x0, y1)});
}
}
else
{
if (y0 > y1)
{
_points.assign({Point(x1, y0), Point(x0, y0), Point(x0, y1), Point(x1, y1), Point(x1, y0)});
}
else
{
_points.assign({Point(x1, y1), Point(x0, y1), Point(x0, y0), Point(x1, y0), Point(x1, y1)});
}
}
}
AABBRect::AABBRect(const AABBRect &rect)
:Geometry(rect)
,_points(rect._points)
{}
const Type AABBRect::type() const
{
return Type::AABBRECT;
}
const double AABBRect::left() const
{
return _points.front().x;
}
const double AABBRect::top() const
{
return _points.front().y;
}
const double AABBRect::right() const
{
return _points[2].x;
}
const double AABBRect::bottom() const
{
return _points[2].y;
}
void AABBRect::set_left(const double value)
{
_points.front().x = value;
_points[3].x = value;
_points.back().x = value;
}
void AABBRect::set_top(const double value)
{
_points.front().y = value;
_points[1].y = value;
_points.back().y = value;
}
void AABBRect::set_right(const double value)
{
_points[1].x = value;
_points[2].x = value;
}
void AABBRect::set_bottom(const double value)
{
_points[2].y = value;
_points[3].y = value;
}
AABBRect &AABBRect::operator=(const AABBRect &rect)
{
if (this != &rect)
{
Geometry::operator=(rect);
_points = rect._points;
}
return *this;
}
const bool AABBRect::empty() const
{
return _points.empty();
}
const double AABBRect::length() const
{
double reuslt = 0;
for (size_t i = 1, count = _points.size(); i < count; ++i)
{
reuslt += Geo::distance(_points[i], _points[i-1]);
}
return reuslt;
}
void AABBRect::clear()
{
_points.clear();
}
AABBRect *AABBRect::clone() const
{
return new AABBRect(*this);
}
const double AABBRect::area() const
{
if (empty())
{
return 0;
}
else
{
return distance(_points[0], _points[1]) * distance(_points[1], _points[2]);
}
}
const double AABBRect::width() const
{
if (!_points.empty())
{
return Geo::distance(_points.front(), _points[1]);
}
else
{
return -1;
}
}
const double AABBRect::height() const
{
if (!_points.empty())
{
return Geo::distance(_points[1], _points[2]);
}
else
{
return -1;
}
}
void AABBRect::set_width(const double value)
{
const double d = (value - width()) / 2;
_points[0].x = _points[3].x = _points[4].x = _points[0].x - d;
_points[1].x = _points[2].x = _points[1].x + d;
}
void AABBRect::set_height(const double value)
{
const double d = (value - height()) / 2;
_points[0].y = _points[1].y = _points[4].y = _points[0].y + d;
_points[2].x = _points[3].x = _points[2].x + d;
}
void AABBRect::transform(const double a, const double b, const double c, const double d, const double e, const double f)
{
std::for_each(_points.begin(), _points.end(), [=](Point &point){point.transform(a,b,c,d,e,f);});
if (_points[0].x > _points[1].x)
{
std::swap(_points[0], _points[1]);
std::swap(_points[2], _points[3]);
}
if (_points[0].y < _points[2].y)
{
std::swap(_points[0], _points[3]);
std::swap(_points[1], _points[2]);
}
_points[4] = _points[0];
}
void AABBRect::transform(const double mat[6])
{
std::for_each(_points.begin(), _points.end(), [=](Point &point){point.transform(mat);});
if (_points[0].x > _points[1].x)
{
std::swap(_points[0], _points[1]);
std::swap(_points[2], _points[3]);
}
if (_points[0].y < _points[2].y)
{
std::swap(_points[0], _points[3]);
std::swap(_points[1], _points[2]);
}
_points[4] = _points[0];
}
void AABBRect::translate(const double tx, const double ty)
{
std::for_each(_points.begin(), _points.end(), [=](Point &point){point.translate(tx, ty);});
}
void AABBRect::rotate(const double x, const double y, const double rad)
{
std::for_each(_points.begin(), _points.end(), [=](Point &point){point.rotate(x, y, rad);});
}
void AABBRect::scale(const double x, const double y, const double k)
{
std::for_each(_points.begin(), _points.end(), [=](Point &point){point.scale(x, y, k);});
}
Polygon AABBRect::convex_hull() const
{
return Polygon(_points.cbegin(), _points.cend());
}
AABBRect AABBRect::bounding_rect() const
{
if (_points.empty())
{
return AABBRect();
}
double x0 = DBL_MAX, y0 = DBL_MAX, x1 = (-FLT_MAX), y1 = (-FLT_MAX);
for (const Point &point : _points)
{
x0 = std::min(x0, point.x);
y0 = std::min(y0, point.y);
x1 = std::max(x1, point.x);
y1 = std::max(y1, point.y);
}
return AABBRect(x0, y0, x1, y1);
}
Polygon AABBRect::mini_bounding_rect() const
{
return *this;
}
std::vector<Point>::const_iterator AABBRect::begin() const
{
return _points.cbegin();
}
std::vector<Point>::const_iterator AABBRect::cbegin() const
{
return _points.cbegin();
}
std::vector<Point>::const_iterator AABBRect::end() const
{
return _points.cend();
}
std::vector<Point>::const_iterator AABBRect::cend() const
{
return _points.cend();
}
std::vector<Point>::const_reverse_iterator AABBRect::rbegin() const
{
return _points.crbegin();
}
std::vector<Point>::const_reverse_iterator AABBRect::crbegin() const
{
return _points.crbegin();
}
std::vector<Point>::const_reverse_iterator AABBRect::rend() const
{
return _points.crend();
}
std::vector<Point>::const_reverse_iterator AABBRect::crend() const
{
return _points.crend();
}
std::vector<Point>::const_iterator AABBRect::find(const Point &point) const
{
return std::find(_points.cbegin(), _points.cend(), point);
}
AABBRect AABBRect::operator+(const Point &point) const
{
return AABBRect(_points[0].x + point.x, _points[0].y + point.y,
_points[2].x + point.x, _points[2].y + point.y);
}
AABBRect AABBRect::operator-(const Point &point) const
{
return AABBRect(_points[0].x - point.x, _points[0].y - point.y,
_points[2].x - point.x, _points[2].y - point.y);
}
void AABBRect::operator+=(const Point &point)
{
for (Point &p : _points)
{
p += point;
}
}
void AABBRect::operator-=(const Point &point)
{
for (Point &p : _points)
{
p -= point;
}
}
const Point AABBRect::center() const
{
return (_points[0] + _points[2]) / 2;
}
const Point &AABBRect::operator[](const size_t index) const
{
assert(!_points.empty() && index <= 4);
return _points[index];
}