2014-01-06 17:29:10 +00:00
|
|
|
#include "BoundingBox.hpp"
|
|
|
|
#include <algorithm>
|
2017-09-12 14:48:44 +00:00
|
|
|
#include <assert.h>
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
|
|
template <class PointClass>
|
2014-01-09 18:56:12 +00:00
|
|
|
BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &points)
|
2014-01-06 17:29:10 +00:00
|
|
|
{
|
2017-10-25 10:53:31 +00:00
|
|
|
if (points.empty())
|
|
|
|
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
|
2014-01-07 11:48:09 +00:00
|
|
|
typename std::vector<PointClass>::const_iterator it = points.begin();
|
|
|
|
this->min.x = this->max.x = it->x;
|
|
|
|
this->min.y = this->max.y = it->y;
|
|
|
|
for (++it; it != points.end(); ++it) {
|
2014-01-06 17:29:10 +00:00
|
|
|
this->min.x = std::min(it->x, this->min.x);
|
|
|
|
this->min.y = std::min(it->y, this->min.y);
|
|
|
|
this->max.x = std::max(it->x, this->max.x);
|
|
|
|
this->max.y = std::max(it->y, this->max.y);
|
|
|
|
}
|
2014-09-21 08:51:36 +00:00
|
|
|
this->defined = true;
|
2014-01-06 17:29:10 +00:00
|
|
|
}
|
2014-01-09 18:56:12 +00:00
|
|
|
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
|
2014-06-16 13:18:39 +00:00
|
|
|
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
template <class PointClass>
|
2014-01-09 18:56:12 +00:00
|
|
|
BoundingBox3Base<PointClass>::BoundingBox3Base(const std::vector<PointClass> &points)
|
2014-01-06 17:29:10 +00:00
|
|
|
: BoundingBoxBase<PointClass>(points)
|
|
|
|
{
|
2017-10-25 10:53:31 +00:00
|
|
|
if (points.empty())
|
|
|
|
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
|
2014-01-07 11:48:09 +00:00
|
|
|
typename std::vector<PointClass>::const_iterator it = points.begin();
|
|
|
|
this->min.z = this->max.z = it->z;
|
|
|
|
for (++it; it != points.end(); ++it) {
|
2014-01-06 17:29:10 +00:00
|
|
|
this->min.z = std::min(it->z, this->min.z);
|
|
|
|
this->max.z = std::max(it->z, this->max.z);
|
|
|
|
}
|
|
|
|
}
|
2014-01-09 18:56:12 +00:00
|
|
|
template BoundingBox3Base<Pointf3>::BoundingBox3Base(const std::vector<Pointf3> &points);
|
|
|
|
|
|
|
|
BoundingBox::BoundingBox(const Lines &lines)
|
|
|
|
{
|
|
|
|
Points points;
|
2017-10-25 10:53:31 +00:00
|
|
|
points.reserve(lines.size());
|
|
|
|
for (const Line &line : lines) {
|
|
|
|
points.emplace_back(line.a);
|
|
|
|
points.emplace_back(line.b);
|
2014-01-09 18:56:12 +00:00
|
|
|
}
|
|
|
|
*this = BoundingBox(points);
|
|
|
|
}
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
BoundingBox::polygon(Polygon* polygon) const
|
|
|
|
{
|
|
|
|
polygon->points.clear();
|
|
|
|
polygon->points.resize(4);
|
|
|
|
polygon->points[0].x = this->min.x;
|
|
|
|
polygon->points[0].y = this->min.y;
|
|
|
|
polygon->points[1].x = this->max.x;
|
|
|
|
polygon->points[1].y = this->min.y;
|
|
|
|
polygon->points[2].x = this->max.x;
|
|
|
|
polygon->points[2].y = this->max.y;
|
|
|
|
polygon->points[3].x = this->min.x;
|
|
|
|
polygon->points[3].y = this->max.y;
|
|
|
|
}
|
|
|
|
|
2014-05-13 18:06:01 +00:00
|
|
|
Polygon
|
|
|
|
BoundingBox::polygon() const
|
|
|
|
{
|
|
|
|
Polygon p;
|
|
|
|
this->polygon(&p);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2016-09-13 11:30:00 +00:00
|
|
|
BoundingBox BoundingBox::rotated(double angle) const
|
|
|
|
{
|
|
|
|
BoundingBox out;
|
|
|
|
out.merge(this->min.rotated(angle));
|
|
|
|
out.merge(this->max.rotated(angle));
|
|
|
|
out.merge(Point(this->min.x, this->max.y).rotated(angle));
|
|
|
|
out.merge(Point(this->max.x, this->min.y).rotated(angle));
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
BoundingBox BoundingBox::rotated(double angle, const Point ¢er) const
|
|
|
|
{
|
|
|
|
BoundingBox out;
|
|
|
|
out.merge(this->min.rotated(angle, center));
|
|
|
|
out.merge(this->max.rotated(angle, center));
|
|
|
|
out.merge(Point(this->min.x, this->max.y).rotated(angle, center));
|
|
|
|
out.merge(Point(this->max.x, this->min.y).rotated(angle, center));
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2014-01-06 17:29:10 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBoxBase<PointClass>::scale(double factor)
|
|
|
|
{
|
|
|
|
this->min.scale(factor);
|
|
|
|
this->max.scale(factor);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template void BoundingBoxBase<Point>::scale(double factor);
|
2014-06-16 13:18:39 +00:00
|
|
|
template void BoundingBoxBase<Pointf>::scale(double factor);
|
2014-01-07 11:48:09 +00:00
|
|
|
template void BoundingBoxBase<Pointf3>::scale(double factor);
|
|
|
|
|
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBoxBase<PointClass>::merge(const PointClass &point)
|
|
|
|
{
|
2014-09-21 08:51:36 +00:00
|
|
|
if (this->defined) {
|
|
|
|
this->min.x = std::min(point.x, this->min.x);
|
|
|
|
this->min.y = std::min(point.y, this->min.y);
|
|
|
|
this->max.x = std::max(point.x, this->max.x);
|
|
|
|
this->max.y = std::max(point.y, this->max.y);
|
|
|
|
} else {
|
|
|
|
this->min = this->max = point;
|
|
|
|
this->defined = true;
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
}
|
|
|
|
template void BoundingBoxBase<Point>::merge(const Point &point);
|
2014-06-16 13:18:39 +00:00
|
|
|
template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
|
2014-01-06 17:29:10 +00:00
|
|
|
|
2014-11-15 21:41:22 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBoxBase<PointClass>::merge(const std::vector<PointClass> &points)
|
|
|
|
{
|
|
|
|
this->merge(BoundingBoxBase(points));
|
|
|
|
}
|
|
|
|
template void BoundingBoxBase<Point>::merge(const Points &points);
|
|
|
|
template void BoundingBoxBase<Pointf>::merge(const Pointfs &points);
|
|
|
|
|
2014-01-06 17:29:10 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
|
|
|
{
|
2017-09-12 14:48:44 +00:00
|
|
|
assert(bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y);
|
2017-09-12 13:55:38 +00:00
|
|
|
if (bb.defined) {
|
|
|
|
if (this->defined) {
|
|
|
|
this->min.x = std::min(bb.min.x, this->min.x);
|
|
|
|
this->min.y = std::min(bb.min.y, this->min.y);
|
|
|
|
this->max.x = std::max(bb.max.x, this->max.x);
|
|
|
|
this->max.y = std::max(bb.max.y, this->max.y);
|
|
|
|
} else {
|
|
|
|
this->min = bb.min;
|
|
|
|
this->max = bb.max;
|
|
|
|
this->defined = true;
|
|
|
|
}
|
2014-09-21 08:51:36 +00:00
|
|
|
}
|
2014-01-06 17:29:10 +00:00
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
2014-06-16 13:18:39 +00:00
|
|
|
template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
|
2014-01-07 11:48:09 +00:00
|
|
|
|
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
|
|
|
{
|
2014-09-21 08:51:36 +00:00
|
|
|
if (this->defined) {
|
|
|
|
this->min.z = std::min(point.z, this->min.z);
|
|
|
|
this->max.z = std::max(point.z, this->max.z);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
BoundingBoxBase<PointClass>::merge(point);
|
|
|
|
}
|
|
|
|
template void BoundingBox3Base<Pointf3>::merge(const Pointf3 &point);
|
2014-01-06 17:29:10 +00:00
|
|
|
|
2014-11-15 21:41:22 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBox3Base<PointClass>::merge(const std::vector<PointClass> &points)
|
|
|
|
{
|
|
|
|
this->merge(BoundingBox3Base(points));
|
|
|
|
}
|
|
|
|
template void BoundingBox3Base<Pointf3>::merge(const Pointf3s &points);
|
|
|
|
|
2014-01-06 17:29:10 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
|
|
|
|
{
|
2017-09-12 14:48:44 +00:00
|
|
|
assert(bb.defined || bb.min.x >= bb.max.x || bb.min.y >= bb.max.y || bb.min.z >= bb.max.z);
|
2017-09-12 13:55:38 +00:00
|
|
|
if (bb.defined) {
|
|
|
|
if (this->defined) {
|
|
|
|
this->min.z = std::min(bb.min.z, this->min.z);
|
|
|
|
this->max.z = std::max(bb.max.z, this->max.z);
|
|
|
|
}
|
|
|
|
BoundingBoxBase<PointClass>::merge(bb);
|
2014-09-21 08:51:36 +00:00
|
|
|
}
|
2014-01-06 17:29:10 +00:00
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb);
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
template <class PointClass> PointClass
|
2014-01-07 11:48:09 +00:00
|
|
|
BoundingBoxBase<PointClass>::size() const
|
2014-01-06 17:29:10 +00:00
|
|
|
{
|
|
|
|
return PointClass(this->max.x - this->min.x, this->max.y - this->min.y);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template Point BoundingBoxBase<Point>::size() const;
|
2014-06-16 13:18:39 +00:00
|
|
|
template Pointf BoundingBoxBase<Pointf>::size() const;
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
template <class PointClass> PointClass
|
|
|
|
BoundingBox3Base<PointClass>::size() const
|
|
|
|
{
|
|
|
|
return PointClass(this->max.x - this->min.x, this->max.y - this->min.y, this->max.z - this->min.z);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template Pointf3 BoundingBox3Base<Pointf3>::size() const;
|
2014-01-06 17:29:10 +00:00
|
|
|
|
2017-10-25 10:53:31 +00:00
|
|
|
template <class PointClass> double BoundingBoxBase<PointClass>::radius() const
|
2016-09-13 11:30:00 +00:00
|
|
|
{
|
2017-10-25 10:53:31 +00:00
|
|
|
assert(this->defined);
|
2016-09-13 11:30:00 +00:00
|
|
|
double x = this->max.x - this->min.x;
|
|
|
|
double y = this->max.y - this->min.y;
|
|
|
|
return 0.5 * sqrt(x*x+y*y);
|
|
|
|
}
|
|
|
|
template double BoundingBoxBase<Point>::radius() const;
|
|
|
|
template double BoundingBoxBase<Pointf>::radius() const;
|
|
|
|
|
2017-10-25 10:53:31 +00:00
|
|
|
template <class PointClass> double BoundingBox3Base<PointClass>::radius() const
|
2016-09-13 11:30:00 +00:00
|
|
|
{
|
|
|
|
double x = this->max.x - this->min.x;
|
|
|
|
double y = this->max.y - this->min.y;
|
|
|
|
double z = this->max.z - this->min.z;
|
|
|
|
return 0.5 * sqrt(x*x+y*y+z*z);
|
|
|
|
}
|
|
|
|
template double BoundingBox3Base<Pointf3>::radius() const;
|
|
|
|
|
2014-07-24 16:32:07 +00:00
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBoxBase<PointClass>::offset(coordf_t delta)
|
|
|
|
{
|
|
|
|
this->min.translate(-delta, -delta);
|
|
|
|
this->max.translate(delta, delta);
|
|
|
|
}
|
|
|
|
template void BoundingBoxBase<Point>::offset(coordf_t delta);
|
|
|
|
template void BoundingBoxBase<Pointf>::offset(coordf_t delta);
|
|
|
|
|
|
|
|
template <class PointClass> void
|
|
|
|
BoundingBox3Base<PointClass>::offset(coordf_t delta)
|
|
|
|
{
|
|
|
|
this->min.translate(-delta, -delta, -delta);
|
|
|
|
this->max.translate(delta, delta, delta);
|
|
|
|
}
|
|
|
|
template void BoundingBox3Base<Pointf3>::offset(coordf_t delta);
|
|
|
|
|
2014-01-06 17:29:10 +00:00
|
|
|
template <class PointClass> PointClass
|
2014-01-07 11:48:09 +00:00
|
|
|
BoundingBoxBase<PointClass>::center() const
|
2014-01-06 17:29:10 +00:00
|
|
|
{
|
|
|
|
return PointClass(
|
2014-01-07 11:48:09 +00:00
|
|
|
(this->max.x + this->min.x)/2,
|
|
|
|
(this->max.y + this->min.y)/2
|
2014-01-06 17:29:10 +00:00
|
|
|
);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template Point BoundingBoxBase<Point>::center() const;
|
2014-06-16 13:18:39 +00:00
|
|
|
template Pointf BoundingBoxBase<Pointf>::center() const;
|
2014-01-06 17:29:10 +00:00
|
|
|
|
|
|
|
template <class PointClass> PointClass
|
|
|
|
BoundingBox3Base<PointClass>::center() const
|
|
|
|
{
|
|
|
|
return PointClass(
|
2014-01-07 11:48:09 +00:00
|
|
|
(this->max.x + this->min.x)/2,
|
|
|
|
(this->max.y + this->min.y)/2,
|
|
|
|
(this->max.z + this->min.z)/2
|
2014-01-06 17:29:10 +00:00
|
|
|
);
|
|
|
|
}
|
2014-01-07 11:48:09 +00:00
|
|
|
template Pointf3 BoundingBox3Base<Pointf3>::center() const;
|
2014-01-06 17:29:10 +00:00
|
|
|
|
2016-11-29 18:25:10 +00:00
|
|
|
// Align a coordinate to a grid. The coordinate may be negative,
|
|
|
|
// the aligned value will never be bigger than the original one.
|
|
|
|
static inline coord_t _align_to_grid(const coord_t coord, const coord_t spacing) {
|
|
|
|
// Current C++ standard defines the result of integer division to be rounded to zero,
|
|
|
|
// for both positive and negative numbers. Here we want to round down for negative
|
|
|
|
// numbers as well.
|
|
|
|
coord_t aligned = (coord < 0) ?
|
|
|
|
((coord - spacing + 1) / spacing) * spacing :
|
|
|
|
(coord / spacing) * spacing;
|
|
|
|
assert(aligned <= coord);
|
|
|
|
return aligned;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BoundingBox::align_to_grid(const coord_t cell_size)
|
|
|
|
{
|
|
|
|
if (this->defined) {
|
|
|
|
min.x = _align_to_grid(min.x, cell_size);
|
|
|
|
min.y = _align_to_grid(min.y, cell_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 17:29:10 +00:00
|
|
|
}
|