#include <cfloat> #include <cstdlib> #include <cmath> #include <iostream> #include "Node.hpp" namespace nbody { using namespace std; Node::Node(Tree* tree) { for (int i = 0; i < 3; i++) { this->bb.setMin(i, 1.0); this->bb.setMax(i, -1.0); } this->afterSubtree = NULL; this->prev = this; this->next = this; this->leaf = true; this->tree = tree; this->prevSibling = NULL; this->nextSibling = NULL; this->parent = NULL; } Node::~Node() { } Box Node::getBB() { return this->bb; } bool Node::isSplitable() { if (this->bodies.size() < 2) { return false; } if (this->bb.volume() <= FLT_EPSILON) { return false; } return true; } void Node::extendBBforBodies() { this->bb.extendForBodies(this->bodies); } void Node::extendBBtoCube() { this->bb.extendToCube(); } vector<Body> Node::getBodies() { return this->bodies; } void Node::insertBefore(Node* node) { node->next = this; node->prev = this->prev; this->prev->next = node; this->prev = node; } void Node::insertAfter(Node* node) { this->next->insertBefore(node); } void Node::unlink() { this->next->prev = this->prev; this->prev->next = this->next; this->next = this; this->prev = this; } bool Node::isCorrect() { if (this->afterSubtree == NULL) { cout << "after subtree null" << endl; return false; } if (!this->bb.isCorrect()) { cout << "bb wrong" << endl; return false; } for (int i = 0; i < 3; i++) { if (this->bb.getMin(i) > this->bb.getMax(i)) { cout << "bb " << i << " min " << this->bb.getMin(i) << " " << this->bb.getMax(i) << endl; return false; } } for (vector<Body>::iterator it = this->bodies.begin(); it != this->bodies.end(); it++) { if (!this->bb.isContained(*it)) { cout << "bb out of bounds" << endl; return false; } } if (!this->leaf) { Node* current = this->next; int children = 0; while (current != NULL && current != this->afterSubtree) { current = current->afterSubtree; children++; } if (current == NULL) { cout << "afterSubtree null" << endl; return false; } if (children != this->tree->numberOfChildren()) { cout << "wrong number of children " << children << endl; return false; } current = this->next; for (int i = 0; i < this->tree->numberOfChildren(); i++) { current = current->afterSubtree; } if (current != this->afterSubtree) { cout << "last sibling afterSubtree inconsistent" << endl; return false; } } if (!this->leaf && this->bodies.size() > 0) { cout << "non-empty inner node" << endl; return false; } return true; } void Node::update() { double position[3] = {0.0, 0.0, 0.0}; double mass = 0.0; if (this->leaf) { for (vector<Body>::iterator it = this->bodies.begin(); it != this->bodies.end(); it++) { mass += it->mass; for (int i = 0; i < 3; i++) { position[i] += it->position[i] * it->mass; } } } else { for (Node* node = this->next; node != this->tree->nodes && node != NULL; node = node->afterSubtree) { mass += node->representative.mass; } } for (int i = 0; i < 3; i++) { this->representative.position[i] = position[i] / mass; } this->representative.mass = mass; } double Node::getL() { return this->bb.maxSidelength(); } void Node::print() { this->bb.print(); for (vector<Body>::iterator it = this->bodies.begin(); it != this->bodies.end(); it++) { cout << " "; it->print(); } } bool Node::sufficientForBody(Body body) { double distance = 0.0; for (int i = 0; i < 3; i++) { distance += (this->representative.position[i] - body.position[i]) * (this->representative.position[i] - body.position[i]); } return sqrt(distance) > this->getL(); } }