src/kdtree.cc
branchpyrit
changeset 78 9569e9f35374
parent 76 3b60fd0bea64
child 80 907929fa9b59
--- a/src/kdtree.cc	Tue Apr 22 13:33:12 2008 +0200
+++ b/src/kdtree.cc	Wed Apr 23 10:38:33 2008 +0200
@@ -26,9 +26,11 @@
 
 #include <algorithm>
 #include <stack>
+#include <string>
+#include <sstream>
 
-#include "common.h"
 #include "kdtree.h"
+#include "serialize.h"
 
 class ShapeBound
 {
@@ -265,7 +267,7 @@
 			}
 			else
 			{ /* (stack[entry].pb[axis] > splitVal) */
-				if (splitVal < stack[exit].pb[axis])
+				if (stack[exit].pb[axis] > splitVal)
 				{
 					/* case P1, P2, P3, and N5 */
 					node = node->getRightChild();
@@ -305,7 +307,7 @@
 		ShapeList::iterator shape;
 		for (shape = node->getShapes()->begin(); shape != node->getShapes()->end(); shape++)
 			if (*shape != origin_shape && (*shape)->intersect(ray, dist)
-			&& dist >= stack[entry].t)
+			&& dist >= stack[entry].t - Eps)
 			{
 				nearest_shape = *shape;
 				nearest_distance = dist;
@@ -326,27 +328,118 @@
 	return NULL;
 }
 
-// this should save whole kd-tree with triangles distributed into leaves
-void KdTree::save(ostream &str, KdNode *node)
+ostream & operator<<(ostream &st, KdNode &node)
+{
+	if (node.isLeaf())
+	{
+		st << "(l," << node.getShapes()->size();
+		ShapeList::iterator shape;
+		for (shape = node.getShapes()->begin(); shape != node.getShapes()->end(); shape++)
+			st << "," << shape_index[*shape];
+		st << ")";
+	}
+	else
+	{
+		st << "(s," << (char)('x'+node.getAxis()) << "," << node.getSplit() << ",";
+		st << *node.getLeftChild() << ",";
+		st << *node.getRightChild() << ")";
+	}
+	return st;
+}
+
+ostream & KdTree::dump(ostream &st)
 {
 	if (!built)
-		return;
-	if (node == NULL)
-		node = root;
-	if (node->isLeaf())
-		str << "(leaf: " << node->getShapes()->size() << " shapes)";
-	else
+		return Container::dump(st);
+
+	st << "(kdtree," << shapes.size();
+	ShapeList::iterator shape;
+	for (shape = shapes.begin(); shape != shapes.end(); shape++)
+	{
+		int idx;
+		if (!shape_index.get(*shape, idx))
+			st << "," << endl << **shape;
+	}
+	return st << "," << endl << *getRootNode() << ")";
+}
+
+void KdTree::recursive_load(istream &st, KdNode *node)
+{
+	string s;
+	istringstream is;
+
+	getline(st, s, ',');
+	trim(s);
+
+	if (s.compare("(s") == 0)
 	{
-		str << "(split " << (char)('x'+node->getAxis()) << " at " << node->getSplit() << "; L=";
-		save(str, node->getLeftChild());
-		str << "; R=";
-		save(str, node->getRightChild());
-		str << ";)";
+		// split
+		int axis;
+		Float split;
+
+		delete node->getShapes();
+		node->setChildren(new KdNode[2]);
+
+		getline(st, s, ',');
+		axis = s.c_str()[0]-'x';
+		node->setAxis(axis);
+
+		st >> split;
+		getline(st, s, ',');
+		node->setSplit(split);
+
+		recursive_load(st, node->getLeftChild());
+		getline(st, s, ',');
+		recursive_load(st, node->getRightChild());
+		getline(st, s, ')');
+	}
+
+	if (s.compare("(l") == 0)
+	{
+		// leaf
+		int count, idx;
+
+		node->setLeaf();
+
+		st >> count;
+		for (int i = 0; i < count; i++)
+		{
+			getline(st, s, ',');
+			st >> idx;
+			node->addShape(shapes[idx]);
+		}
+		getline(st, s, ')');
 	}
 }
 
-// load kd-tree from file/stream
-void KdTree::load(istream &str, KdNode *node)
+istream & KdTree::load(istream &st)
 {
+	string s;
+	istringstream is;
 
+	getline(st, s, ',');
+	if (s.compare("(kdtree") != 0)
+		return st;
+
+	shapes.clear();
+	if (root) delete root;
+	root = new KdNode();
+
+	getline(st, s, ',');
+	int shape_count;
+	is.str(s);
+	is >> shape_count;
+
+	Shape *shape;
+	for (int i = 0; i < shape_count; i++)
+	{
+		shape = loadShape(st);
+		Container::addShape(shape);
+		getline(st, s, ',');
+	}
+
+	recursive_load(st, root);
+
+	built = true;
+	return st;
 }