Skip to content
Snippets Groups Projects
BarnesHutTree.cpp 3.17 KiB
Newer Older
#include "BarnesHutTree.hpp"
#include "Node.hpp"
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
#include <iostream>
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	using namespace std;

	BarnesHutTree::BarnesHutTree() {
	}

	BarnesHutTree::~BarnesHutTree() {
	vector<Box> BarnesHutTree::splitBB(Node* node) {
		return node->getBB().octreeSplit();
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
	int BarnesHutTree::numberOfChildren() {
		return 8;
	}

	void BarnesHutTree::build(vector<Body> bodies) {
		Node* current;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		if (bodies.empty()) return;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		//insert root node
		this->nodes->insertAfter(new Node(this));
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		current = this->nodes->next;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		//assign bodies to root node
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		current->bodies = bodies;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		//setup proper bounding box
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		current->extendBBforBodies();
		current->extendBBtoCube();
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		current->afterSubtree = current->next;

		//iterate over existing boxes and split if it contains too much bodies
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		while (current != this->nodes) {
			if (current->isSplitable()) {
				vector<Box> subboxes = this->splitBB(current);
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				current->leaf = false;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				Node* after = current->next;

				for (vector<Box>::iterator it = subboxes.begin(); it != subboxes.end(); it++) {
					Node* child = new Node(this);
					child->parent = current;
					child->bb = *it;
					child->bodies = it->copyBodies(current->bodies);
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
					child->nextSibling = NULL;
					child->prevSibling = NULL;
					after->insertBefore(child);
					if (it != subboxes.begin()) {
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
						child->prev->nextSibling = child;
						child->prevSibling = child->prev;
						child->prev->afterSubtree = child;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				}
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				after->prev->afterSubtree = current->afterSubtree;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				if (!current->leaf) {
					Node* child = current->next;
					for (int i = 0; i < 8; i++) {
						if (i == 0) {
							if (child->prevSibling != NULL || child->nextSibling == NULL) {
								cout << "WRONG BEG" << endl;
							}
						} else if (i == 7) {
							if (child->prevSibling == NULL || child->nextSibling != NULL) {
								cout << "WRONG END" << endl;
							}
						} else {
							if (child->prevSibling == NULL || child->nextSibling == NULL) {
								cout << "WRONG MID" << endl;
							}
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
						child = child->next;
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
				current->bodies.clear();
			}
			current = current->next;
		}
Paul Heinzlreiter's avatar
Paul Heinzlreiter committed
		//iterate for updating representatives
		current = this->nodes->prev;
		while (current != this->nodes) {
			current->representative.mass = 0.0;
			current->representative.position[0] = 0.0;
			current->representative.position[1] = 0.0;
			current->representative.position[2] = 0.0;
			if (current->leaf) {
				for (unsigned int i = 0; i < current->bodies.size(); i++) {
					current->representative.mass += current->bodies[i].mass;
					for (int j = 0; j < 3; j++) {
						current->representative.position[j] += current->bodies[i].position[j];
					}
				}
			} else {
				Node* child = current->next;

				do {
					current->representative.mass += child->representative.mass;
					for (int j = 0; j < 3; j++) {
						current->representative.position[j] += child->representative.position[j];
					}
					child = child->nextSibling;
				} while (child != NULL);
			}
			current->representative.mass /= current->bodies.size();
			for (int j = 0; j < 3; j++) {
				current->representative.position[j] /= current->bodies.size();
			}
			current = current->prev;
		}