| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-04-16 22:40:48 +00:00
										 |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  |  * Bounding Box | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 13:39:04 +00:00
										 |  |  | /** \file gameengine/SceneGraph/SG_Tree.cpp
 | 
					
						
							|  |  |  |  *  \ingroup bgesg | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | #include <math.h>
 | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | #include "SG_BBox.h"
 | 
					
						
							|  |  |  | #include "SG_Tree.h"
 | 
					
						
							|  |  |  | #include "SG_Node.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree::SG_Tree() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree::SG_Tree(SG_Tree* left, SG_Tree* right) : | 
					
						
							|  |  |  | 		m_left(left), | 
					
						
							|  |  |  | 		m_right(right), | 
					
						
							|  |  |  | 		m_client_object(NULL) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	if (m_left) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_bbox = m_left->m_bbox; | 
					
						
							|  |  |  | 		m_left->m_parent = this; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (m_right) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_bbox += m_right->m_bbox; | 
					
						
							|  |  |  | 		m_right->m_parent = this; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-04-04 13:18:41 +00:00
										 |  |  | 	m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_radius = (m_bbox.m_max - m_bbox.m_min).length(); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | SG_Tree::SG_Tree(SG_Node* client) : | 
					
						
							|  |  |  | 		m_left(NULL), | 
					
						
							|  |  |  | 		m_right(NULL), | 
					
						
							|  |  |  | 		m_client_object(client) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_bbox = SG_BBox(client->BBox(), client->GetWorldTransform()); | 
					
						
							| 
									
										
										
										
											2007-04-04 13:18:41 +00:00
										 |  |  | 	m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_radius = (m_bbox.m_max - m_bbox.m_min).length(); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2004-05-17 23:56:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | SG_Tree::~SG_Tree()  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | MT_Scalar SG_Tree::volume() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_bbox.volume(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | void SG_Tree::dump() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (m_left) | 
					
						
							|  |  |  | 		m_left->dump(); | 
					
						
							|  |  |  | 	if (m_client_object) | 
					
						
							|  |  |  | 		std::cout << m_client_object << std::endl; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		std::cout << this << " "; | 
					
						
							|  |  |  | 	if (m_right) | 
					
						
							|  |  |  | 		m_right->dump(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree* SG_Tree::Left() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_left; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree* SG_Tree::Right() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_right; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Node* SG_Tree::Client() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_client_object; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree* SG_Tree::Find(SG_Node *node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (m_client_object == node) | 
					
						
							|  |  |  | 		return this; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2004-05-17 23:56:56 +00:00
										 |  |  | 	SG_Tree *left = m_left, *right = m_right; | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if (left && right) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (right->m_bbox.intersects(node->BBox())) | 
					
						
							|  |  |  | 			std::swap(left, right); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if (left) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SG_Tree* ret = left->Find(node); | 
					
						
							|  |  |  | 		if (ret) return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (right) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SG_Tree* ret = right->Find(node); | 
					
						
							|  |  |  | 		if (ret) return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SG_Tree::get(MT_Point3 *box) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	MT_Transform identity; | 
					
						
							|  |  |  | 	identity.setIdentity(); | 
					
						
							|  |  |  | 	m_bbox.get(box, identity); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool SG_Tree::inside(const MT_Point3 &point) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_bbox.inside(point); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const SG_BBox& SG_Tree::BBox() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_bbox; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | void SG_Tree::SetLeft(SG_Tree *left) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_left = left; | 
					
						
							|  |  |  | 	m_bbox += left->m_bbox; | 
					
						
							| 
									
										
										
										
											2007-04-04 13:18:41 +00:00
										 |  |  | 	m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_radius = (m_bbox.m_max - m_bbox.m_min).length(); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | void SG_Tree::SetRight(SG_Tree *right) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_right = right; | 
					
						
							|  |  |  | 	m_bbox += right->m_bbox; | 
					
						
							| 
									
										
										
										
											2007-04-04 13:18:41 +00:00
										 |  |  | 	m_center = (m_bbox.m_min + m_bbox.m_max)/2.0; | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	m_radius = (m_bbox.m_max - m_bbox.m_min).length(); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * A Half array is a square 2d array where cell(x, y) is undefined | 
					
						
							|  |  |  |  * if x < y. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename T> | 
					
						
							|  |  |  | class HalfArray | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::vector<std::vector<T> > m_array; | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 	HalfArray() {} | 
					
						
							|  |  |  | 	~HalfArray() {} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	void resize(unsigned int size) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_array.resize(size); | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( unsigned int i = 0; i < size; i++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			m_array[i].resize(size - i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	T& operator() (unsigned int x, unsigned int y) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		assert(x >= y); | 
					
						
							|  |  |  | 		return m_array[y][x - y]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	void erase_column (unsigned int x) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for (unsigned int y = 0; y <= x; y++) | 
					
						
							|  |  |  | 			m_array[y].erase(m_array[y].begin() + x - y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void delete_column (unsigned int x) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for (unsigned int y = 0; y < x; y++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			delete m_array[y][x - y]; | 
					
						
							|  |  |  | 			m_array[y].erase(m_array[y].begin() + x - y); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	void erase_row (unsigned int y) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_array.erase(m_array.begin() + y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | SG_TreeFactory::SG_TreeFactory() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_TreeFactory::~SG_TreeFactory() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | void SG_TreeFactory::Add(SG_Node* client) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (client) | 
					
						
							|  |  |  | 		m_objects.insert(new SG_Tree(client)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SG_TreeFactory::Add(SG_Tree* tree) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_objects.insert(tree); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree* SG_TreeFactory::MakeTreeDown(SG_BBox &bbox) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-09-20 00:55:32 +00:00
										 |  |  | 	if (m_objects.empty()) | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (m_objects.size() == 1) | 
					
						
							|  |  |  | 		return *m_objects.begin(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	TreeSet::iterator it = m_objects.begin(); | 
					
						
							|  |  |  | 	SG_Tree *root = *it; | 
					
						
							|  |  |  | 	if (m_objects.size() == 2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		root->SetRight(*(++it)); | 
					
						
							|  |  |  | 		return root; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if (m_objects.size() == 3) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		root->SetLeft(*(++it)); | 
					
						
							|  |  |  | 		root->SetRight(*(++it)); | 
					
						
							|  |  |  | 		return root; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (bbox.volume() < 1.0) | 
					
						
							|  |  |  | 		return MakeTreeUp(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	SG_TreeFactory lefttree; | 
					
						
							|  |  |  | 	SG_TreeFactory righttree; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	SG_BBox left, right; | 
					
						
							|  |  |  | 	int hasleft = 0, hasright = 0; | 
					
						
							|  |  |  | 	bbox.split(left, right); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (left.test(root->BBox()) == SG_BBox::INSIDE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		lefttree.Add(root); | 
					
						
							|  |  |  | 		root = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (root && right.test(root->BBox()) == SG_BBox::INSIDE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		righttree.Add(root); | 
					
						
							|  |  |  | 		root = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (++it; it != m_objects.end(); ++it) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		switch (left.test((*it)->BBox())) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case SG_BBox::INSIDE: | 
					
						
							|  |  |  | 				// Object is inside left tree;
 | 
					
						
							|  |  |  | 				lefttree.Add(*it); | 
					
						
							|  |  |  | 				hasleft++; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case SG_BBox::OUTSIDE: | 
					
						
							|  |  |  | 				righttree.Add(*it); | 
					
						
							|  |  |  | 				hasright++; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case SG_BBox::INTERSECT: | 
					
						
							|  |  |  | 				if (left.inside((*it)->Client()->GetWorldPosition())) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					lefttree.Add(*it); | 
					
						
							|  |  |  | 					hasleft++; | 
					
						
							| 
									
										
										
										
											2012-07-21 22:58:08 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 					righttree.Add(*it); | 
					
						
							|  |  |  | 					hasright++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	std::cout << "Left: " << hasleft << " Right: " << hasright << " Count: " << m_objects.size() << std::endl; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	SG_Tree *leftnode = NULL; | 
					
						
							|  |  |  | 	if (hasleft) | 
					
						
							|  |  |  | 		leftnode = lefttree.MakeTreeDown(left); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	SG_Tree *rightnode = NULL; | 
					
						
							|  |  |  | 	if (hasright) | 
					
						
							|  |  |  | 		rightnode = righttree.MakeTreeDown(right); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if (!root) | 
					
						
							|  |  |  | 		root = new SG_Tree(leftnode, rightnode); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (leftnode) | 
					
						
							|  |  |  | 			root->SetLeft(leftnode); | 
					
						
							|  |  |  | 		if (rightnode) | 
					
						
							|  |  |  | 			root->SetRight(rightnode); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return root; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | SG_Tree* SG_TreeFactory::MakeTree() | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (m_objects.size() < 8) | 
					
						
							|  |  |  | 		return MakeTreeUp(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	TreeSet::iterator it = m_objects.begin(); | 
					
						
							|  |  |  | 	SG_BBox bbox((*it)->BBox()); | 
					
						
							|  |  |  | 	for (++it; it != m_objects.end(); ++it) | 
					
						
							|  |  |  | 		bbox += (*it)->BBox(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return MakeTreeDown(bbox); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SG_Tree* SG_TreeFactory::MakeTreeUp() | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	unsigned int num_objects = m_objects.size(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (num_objects < 1) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if (num_objects < 2) | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 		return *m_objects.begin(); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	HalfArray<SG_Tree*> sizes; | 
					
						
							|  |  |  | 	sizes.resize(num_objects); | 
					
						
							| 
									
										
										
										
											2004-05-17 23:56:56 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	unsigned int x, y; | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 	TreeSet::iterator xit, yit; | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 	for ( y = 0, yit = m_objects.begin(); y < num_objects; y++, ++yit) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 		sizes(y, y) = *yit; | 
					
						
							|  |  |  | 		xit = yit; | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( x = y+1, ++xit; x < num_objects; x++, ++xit) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2004-05-21 09:21:15 +00:00
										 |  |  | 			sizes(x, y) = new SG_Tree(*xit, *yit); | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	while (num_objects > 2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* Find the pair of bboxes that produce the smallest combined bbox. */ | 
					
						
							| 
									
										
										
										
											2005-03-09 19:45:59 +00:00
										 |  |  | 		unsigned int minx = UINT_MAX, miny = UINT_MAX; | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		MT_Scalar min_volume = FLT_MAX; | 
					
						
							| 
									
										
										
										
											2005-03-09 19:45:59 +00:00
										 |  |  | 		SG_Tree *min = NULL; | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		//char temp[16];
 | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( y = 0; y < num_objects; y++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 			for ( x = y+1; x < num_objects; x++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				if (sizes(x, y)->volume() < min_volume) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					min = sizes(x, y); | 
					
						
							|  |  |  | 					minx = x; | 
					
						
							|  |  |  | 					miny = y; | 
					
						
							|  |  |  | 					min_volume = sizes(x, y)->volume(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* Remove other bboxes that contain the two bboxes */ | 
					
						
							|  |  |  | 		sizes.delete_column(miny); | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( x = miny + 1; x < num_objects; x++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (x == minx) | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			delete sizes(x, miny); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		sizes.erase_row(miny); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		num_objects--; | 
					
						
							|  |  |  | 		minx--; | 
					
						
							|  |  |  | 		sizes(minx, minx) = min; | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( x = minx + 1; x < num_objects; x++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			delete sizes(x, minx); | 
					
						
							|  |  |  | 			sizes(x, minx) = new SG_Tree(min, sizes(x, x)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		for ( y = 0; y < minx; y++) | 
					
						
							| 
									
										
										
										
											2004-05-16 12:54:44 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			delete sizes(minx, y); | 
					
						
							|  |  |  | 			sizes(minx, y) = new SG_Tree(sizes(y, y), min); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return sizes(1, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |