Files
secondo/Algebras/FixedMRegion/fmr/BoundingBox.cpp

153 lines
3.8 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
* File: BoundingBox.cpp
* Author: Florian Heinz <fh@sysv.de>
*
* Created on October 10, 2016, 3:08 PM
//paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}]
//[TOC] [\tableofcontents]
[1] Implementation of the class ~BoundingBox~
[TOC]
1 Overview
This class represents the bounding box of an object. Several functions to
update and modify the bounding box as well as some tests (point inside, segment
intersects) are implemented.
*/
#include "fmr_BoundingBox.h"
using namespace fmr;
/*
2 ~update~ with point
Update the bounding box to contain the given point ~p~
*/
void BoundingBox::update (Point p) {
if (!lowerLeft.valid()) {
lowerLeft = p;
} else {
if (lowerLeft.x > p.x)
lowerLeft.x = p.x;
if (lowerLeft.y > p.y)
lowerLeft.y = p.y;
}
if (!upperRight.valid()) {
upperRight = p;
} else {
if (upperRight.x < p.x)
upperRight.x = p.x;
if (upperRight.y < p.y)
upperRight.y = p.y;
}
}
/*
3 ~update~ with boundingbox
Update the bounding box to contain the given boundingbox ~bb~
*/
void BoundingBox::update (BoundingBox bb) {
update(bb.lowerLeft);
update(bb.upperRight);
}
/*
4 ~rotate~
Rotate the bounding box around ~center~ by ~angle~ and update this bounding box
to contain the rotated bounding box.
*/
void BoundingBox::rotate (Point center, double angle) {
Point p1 = lowerLeft.rotate(center, angle);
Point p2 = Point(lowerLeft.x, upperRight.y).rotate(center, angle);
Point p3 = Point(upperRight.x, lowerLeft.y).rotate(center, angle);
Point p4 = upperRight.rotate(center, angle);
invalidate();
update(p1);
update(p2);
update(p3);
update(p4);
}
/*
5 ~inside~
Tests, if a given Point ~p~ is inside the bounding box.
*/
bool BoundingBox::inside (Point p) {
return valid() &&
lowerLeft.x <= p.x && lowerLeft.y <= p.y &&
upperRight.x >= p.x && upperRight.y >= p.y;
}
/*
6 ~intersects~
Tests, if a line segment ~seg~ intersects with this bounding box.
*/
bool BoundingBox::intersects (Seg& seg) {
bool intersects = false;
if (seg.f.x == seg.i.x) { // Line is parallel to y-axis
double x = seg.i.x;
double y1 = std::min(seg.i.y, seg.f.y);
double y2 = std::max(seg.i.y, seg.f.y);
intersects = ((lowerLeft.x <= x && x <= upperRight.x) &&
((lowerLeft.y <= y1 && y1 <= upperRight.y) ||
(lowerLeft.y <= y2 && y2 <= upperRight.y) ||
(y1 < lowerLeft.y && y2 > upperRight.y)));
} else {
// Initialize values m and c, so that the segment is
// on the line y = m*x + c
double m = (seg.f.y - seg.i.y) / (seg.f.x - seg.i.x);
double c = seg.i.y - m * seg.i.x;
double y1, y2;
if (m > 0) { // Ensure that y1 < y2
y1 = m*lowerLeft.x + c;
y2 = m*upperRight.x + c;
} else {
y1 = m*upperRight.x + c;
y2 = m*lowerLeft.x + c;
}
intersects = ((lowerLeft.y <= y1 && y1 <= upperRight.y) ||
(lowerLeft.y <= y2 && y2 <= upperRight.y) ||
(y1 < lowerLeft.y && upperRight.y < y2));
}
if (!intersects) {
// Test, if the segment is completely inside the bounding box
if (lowerLeft.x <= seg.i.x && seg.i.x <= upperRight.x &&
lowerLeft.y <= seg.i.y && seg.i.y <= upperRight.y)
intersects = true;
}
return intersects;
}
/*
7 ~toString~
Returns a string representation of this bounding box.
*/
std::string BoundingBox::ToString() {
std::stringstream ss;
ss << "BB (" << lowerLeft.ToString() << " " << upperRight.ToString() << ")";
return ss.str();
}