-
Paul Heinzlreiter authored39822222
Box.cpp 6.38 KiB
#include <iostream>
#include <cmath>
#include <cfloat>
#include "Box.hpp"
namespace nbody {
using namespace std;
Box::Box() {
for (int i = 0; i < 3; i++) {
this->min[i] = FLT_MAX;
this->max[i] = -FLT_MAX;
}
}
Box::~Box() {
}
//min/max getter/setters
double Box::getMin(int index) {
return this->min[index];
}
double Box::getMax(int index) {
return this->max[index];
}
void Box::setMin(int index, double value) {
this->min[index] = value;
}
void Box::setMax(int index, double value) {
this->max[index] = value;
}
void Box::extendForBodies(vector<Body> bodies) {
if (bodies.empty()) return;
for (vector<Body>::iterator it = bodies.begin(); it != bodies.end(); it++) {
for (int i = 0; i < 3; i++) {
if (it->position[i] < this->min[i]) {
this->min[i] = it->position[i];
}
if (it->position[i] > this->max[i]) {
this->max[i] = it->position[i];
}
}
}
}
void Box::extendToCube() {
int longestSide = -1;
double sidelength = 0.0;
for (int i = 0; i < 3; i++) {
if (this->max[i] - this->min[i] >= sidelength) {
longestSide = i;
sidelength = this->max[i] - this->min[i];
}
}
if (longestSide == -1) {
return;
}
for (int i = 0; i < 3; i++) {
if (i != longestSide) {
double extend = (sidelength - (this->max[i] - this->min[i])) / 2.0;
this->min[i] -= extend;
this->max[i] += extend;
}
}
}
vector<Body> Box::copyBodies(vector<Body> bodies) {
vector<Body> result;
for (vector<Body>::iterator it = bodies.begin(); it != bodies.end(); it++) {
if (it->position[0] >= this->min[0] && it->position[0] <= this->max[0] &&
it->position[1] >= this->min[1] && it->position[1] <= this->max[1] &&
it->position[2] >= this->min[2] && it->position[2] <= this->max[2]) {
result.push_back(*it);
}
}
return result;
}
vector<Body> Box::extractBodies(vector<Body>& bodies) {
vector<Body> result;
vector<Body>::iterator it = bodies.begin();
while (it != bodies.end()) {
if (it->position[0] >= this->min[0] && it->position[0] <= this->max[0] &&
it->position[1] >= this->min[1] && it->position[1] <= this->max[1] &&
it->position[2] >= this->min[2] && it->position[2] <= this->max[2]) {
result.push_back(*it);
it = bodies.erase(it);
} else {
it++;
}
}
return result;
}
bool Box::isContained(Body body) {
for (int i = 0; i < 3; i++) {
if (body.position[i] < this->min[i] || body.position[i] > this->max[i]) {
return false;
}
}
return true;
}
//TODO: check semantics
bool Box::isContained(Box box) {
for (int i = 0; i < 3; i++) {
if (box.min[i] < this->min[i] || box.max[i] > this->max[i]) {
return false;
}
}
return true;
}
double Box::volume() {
double result = 1.0;
for (int i = 0; i < 3; i++) {
result *= this->max[i] - this->min[i];
}
return result;
}
bool Box::overlapsSphere(double* sphereCenter, double sphereRadius) {
double dmin = 0.0;
for (int i = 0; i < 3; i++) {
if (sphereCenter[i] < this->min[i]) {
double dist = sphereCenter[i] - this->min[i];
dmin += dist * dist;
} else if (sphereCenter[i] > this->max[i]) {
double dist = sphereCenter[i] - this->max[i];
dmin += dist * dist;
}
}
return dmin <= sphereRadius * sphereRadius;
}
double Box::maxSidelength() {
double max = 0.0;
for (int i = 0; i < 3; i++) {
if (this->max[i] - this->min[i] > max) {
max = this->max[i] - this->min[i];
}
}
return max;
}
double Box::distanceToPosition(double* position) {
int inside = 0;
double nextPosition[3] = {position[0], position[1], position[2]};
for (int i = 0; i < 3; i++) {
if (nextPosition[i] < this->min[i]) {
nextPosition[i] = this->min[i];
} else if (nextPosition[i] > this->max[i]) {
nextPosition[i] = this->max[i];
} else {
inside++;
}
}
if (inside == 3) {
return 0.0;
} else {
double dist = 0.0;
for (int i = 0; i < 3; i++) {
dist += (nextPosition[i] - position[i]) * (nextPosition[i] - position[i]);
}
return sqrt(dist);
}
}
double Box::distanceToBox(Box box) {
double length = 0.0;
for (int i = 0; i < 3; i++) {
double elem;
if (box.min[i] < this->min[i] && box.max[i] < this->min[i]) {
elem = this->min[i] - box.max[i];
} else if (box.min[i] > this->max[i] && box.max[i] > this->max[i]) {
elem = box.min[i] - this->max[i];
} else {
elem = 0.0;
}
length += elem * elem;
}
return sqrt(length);
}
vector<Box> Box::octreeSplit() {
vector<Box> result;
for (unsigned int i = 0; i < 8; i++) {
Box current = *this;
for (unsigned int j = 0; j < 3; j++) {
double middle = current.getMin(j) + (current.getMax(j) - current.getMin(j)) / 2.0;
if (i & (1 << j)) {
current.setMin(j, middle);
} else {
current.setMax(j, middle);
}
}
result.push_back(current);
}
return result;
}
vector<Box> Box::splitLongestSide() {
vector<Box> result;
int longestIndex = -1;
double longestSide = -1.0;
for (int i = 0; i < 3; i++) {
if (this->max[i] - this->min[i] > longestSide) {
longestSide = this->max[i] - this->min[i];
longestIndex = i;
}
}
double middle = this->min[longestIndex] + (this->max[longestIndex] - this->min[longestIndex]) / 2.0;
result.push_back(*this);
result.back().max[longestIndex] = middle;
result.push_back(*this);
result.back().min[longestIndex] = middle;
return result;
}
bool Box::isCorrect() {
for (int i = 0; i < 3; i++) {
if (this->max[i] < this->min[i]) {
cout << "inverted bb" << endl;
return false;
}
}
return true;
}
void Box::print() {
cout << " min ";
for (int i = 0; i < 3; i++) {
cout << this->min[i] << " ";
}
cout << " max ";
for (int i = 0; i < 3; i++) {
cout << this->max[i] << " ";
}
cout << endl;
}
bool Box::contained(double* position) {
for (int i = 0; i < 3; i++) {
if (position[i] < this->min[i] || position[i] > this->max[i]) {
return false;
}
}
return true;
}
void Box::extend(Box extender) {
for (int i = 0; i < 3; i++) {
if (this->min[i] > extender.min[i]) {
this->min[i] = extender.min[i];
}
if (this->max[i] < extender.max[i]) {
this->max[i] = extender.max[i];
}
}
}
void Box::extend(Body extender) {
for (int i = 0; i < 3; i++) {
if (this->min[i] > extender.position[i]) {
this->min[i] = extender.position[i];
}
if (this->max[i] < extender.position[i]) {
this->max[i] = extender.position[i];
}
}
}
}