minor changes to comply gcc compiler

This commit is contained in:
Paolo Cignoni 2006-10-16 16:10:22 +00:00
parent 947b27d691
commit 5e4f12f28a
3 changed files with 244 additions and 222 deletions

View File

@ -34,6 +34,7 @@
#include <vcg/space/index/octree_template.h> #include <vcg/space/index/octree_template.h>
#include <vcg/space/box3.h> #include <vcg/space/box3.h>
#include <wrap/callback.h> #include <wrap/callback.h>
#include <wrap/gl/space.h>
namespace vcg namespace vcg
{ {
@ -104,13 +105,32 @@ namespace vcg
template < class OBJECT_TYPE, class SCALAR_TYPE> template < class OBJECT_TYPE, class SCALAR_TYPE>
class Octree : public vcg::OctreeTemplate< Voxel, SCALAR_TYPE >, public vcg::SpatialIndex< OBJECT_TYPE, SCALAR_TYPE > class Octree : public vcg::OctreeTemplate< Voxel, SCALAR_TYPE >, public vcg::SpatialIndex< OBJECT_TYPE, SCALAR_TYPE >
{ {
public: protected:
struct Neighbour;
public:
typedef SCALAR_TYPE ScalarType; typedef SCALAR_TYPE ScalarType;
typedef OBJECT_TYPE ObjectType; typedef OBJECT_TYPE ObjectType;
typedef typename Octree::Leaf * LeafPointer; typedef typename Octree::Leaf * LeafPointer;
typedef typename Octree::InnerNode * InnerNodePointer; typedef typename Octree::InnerNode * InnerNodePointer;
typedef typename ReferenceType<OBJECT_TYPE>::Type * ObjectPointer; typedef typename ReferenceType<OBJECT_TYPE>::Type * ObjectPointer;
typedef vcg::Voxel VoxelType;
typedef VoxelType * VoxelPointer;
typedef vcg::OctreeTemplate< VoxelType, SCALAR_TYPE > TemplatedOctree;
typedef typename TemplatedOctree::ZOrderType ZOrderType;
typedef typename TemplatedOctree::BoundingBoxType BoundingBoxType;
typedef typename TemplatedOctree::CenterType CenterType;
typedef typename TemplatedOctree::CoordinateType CoordType;
typedef typename TemplatedOctree::NodeType NodeType;
typedef typename TemplatedOctree::NodePointer NodePointer;
typedef typename TemplatedOctree::NodeIndex NodeIndex;
typedef typename std::vector< Neighbour >::iterator NeighbourIterator;
/*! /*!
* Structure which holds the rendering settings * Structure which holds the rendering settings
*/ */
@ -130,10 +150,6 @@ namespace vcg
vcg::Color4b color; vcg::Color4b color;
}; };
protected: protected:
/*********************************************** /***********************************************
* INNER DATA STRUCTURES AND PREDICATES * * INNER DATA STRUCTURES AND PREDICATES *
@ -148,11 +164,11 @@ namespace vcg
ObjectPlaceholder() { z_order = object_index = -1, leaf_pointer = NULL;} ObjectPlaceholder() { z_order = object_index = -1, leaf_pointer = NULL;}
ObjectPlaceholder(ZOrderType z_order, void* leaf_pointer, unsigned int object_index) ObjectPlaceholder(ZOrderType zOrder, void* leafPointer, unsigned int objectIndex)
{ {
this->z_order = z_order; z_order = zOrder;
this->leaf_pointer = leaf_pointer; leaf_pointer = leafPointer;
this->object_index = object_index; object_index = objectIndex;
} }
ZOrderType z_order; ZOrderType z_order;
@ -201,6 +217,11 @@ namespace vcg
this->point = point; this->point = point;
this->distance = distance; this->distance = distance;
} }
inline bool operator<(const Neighbour &n)
{
return distance<n.distance;
}
ObjectPointer object; ObjectPointer object;
@ -208,13 +229,13 @@ namespace vcg
ScalarType distance; ScalarType distance;
}; };
/* // /*
* The operator used for sorting the items in neighbors based on the distances // * The operator used for sorting the items in neighbors based on the distances
*/ // */
struct DistanceCompare // struct DistanceCompare
{ // {
inline bool operator()( const Neighbour &p1, const Neighbour &p2) const { return p1.distance<p2.distance; } // inline bool operator()( const Neighbour &p1, const Neighbour &p2) const { return p1.distance<p2.distance; }
}; //end of DistanceCompare // }; //end of DistanceCompare
@ -222,18 +243,18 @@ public:
~Octree() ~Octree()
{ {
delete []marks; delete []marks;
int node_count = NodeCount(); int node_count = TemplatedOctree::NodeCount();
for (int i=0; i<node_count; i++) for (int i=0; i<node_count; i++)
delete nodes[i]; delete TemplatedOctree::nodes[i];
nodes.clear(); TemplatedOctree::nodes.clear();
} }
/*! /*!
* Populate the octree * Populate the octree
*/ */
template <class OBJECT_ITERATOR/*, class BOUNDING_BOX_FUNCTOR*/> template < class OBJECT_ITERATOR >
void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj /*, const BoundingBoxType &bounding_box*/ /*, const BOUNDING_BOX_FUNCTOR &bb_functor*/ /*, vcg::CallBackPos *callback=NULL*/) void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj /*, vcg::CallBackPos *callback=NULL*/)
{ {
// Compute the bounding-box enclosing the whole dataset // Compute the bounding-box enclosing the whole dataset
typedef Dereferencer<typename ReferenceType<typename OBJECT_ITERATOR::value_type>::Type > DereferencerType; typedef Dereferencer<typename ReferenceType<typename OBJECT_ITERATOR::value_type>::Type > DereferencerType;
@ -253,7 +274,7 @@ public:
ScalarType longest_side = vcg::math::Max( resulting_bb.DimX(), vcg::math::Max(resulting_bb.DimY(), resulting_bb.DimZ()) )/2.0f; ScalarType longest_side = vcg::math::Max( resulting_bb.DimX(), vcg::math::Max(resulting_bb.DimY(), resulting_bb.DimZ()) )/2.0f;
resulting_bb.Set(center); resulting_bb.Set(center);
resulting_bb.Offset(longest_side); resulting_bb.Offset(longest_side);
boundingBox = resulting_bb; TemplatedOctree::boundingBox = resulting_bb;
// Try to find a reasonable octree depth // Try to find a reasonable octree depth
int dataset_dimension = std::distance(bObj, eObj); int dataset_dimension = std::distance(bObj, eObj);
@ -268,16 +289,16 @@ public:
depth++; depth++;
} }
while (primitives_per_voxel>25 && depth<15); while (primitives_per_voxel>25 && depth<15);
Initialize(++depth); TemplatedOctree::Initialize(++depth);
// Sort the dataset (using the lebesgue space filling curve...) // Sort the dataset (using the lebesgue space filling curve...)
std::string message("Indexing dataset..."); std::string message("Indexing dataset...");
Octree::NodePointer *route = new Octree::NodePointer[depth+1]; NodePointer *route = new NodePointer[depth+1];
OBJECT_ITERATOR iObj = bObj; OBJECT_ITERATOR iObj = bObj;
//if (callback!=NULL) callback(int((i+1)*100/dataset_dimension), message.c_str()); //if (callback!=NULL) callback(int((i+1)*100/dataset_dimension), message.c_str());
std::vector< ObjectPlaceholder< Octree::Node > > placeholders/*(dataset_dimension)*/; std::vector< ObjectPlaceholder< NodeType > > placeholders/*(dataset_dimension)*/;
vcg::Box3<ScalarType> object_bb; vcg::Box3<ScalarType> object_bb;
vcg::Point3<ScalarType> hit_leaf; vcg::Point3<ScalarType> hit_leaf;
for (int i=0; i<dataset_dimension; i++, iObj++) for (int i=0; i<dataset_dimension; i++, iObj++)
@ -288,20 +309,20 @@ public:
while (object_bb.IsIn(hit_leaf)) while (object_bb.IsIn(hit_leaf))
{ {
int placeholder_index = placeholders.size(); int placeholder_index = placeholders.size();
placeholders.push_back( ObjectPlaceholder< Octree::Node >() ); placeholders.push_back( ObjectPlaceholder< NodeType >() );
placeholders[placeholder_index].z_order = BuildRoute(hit_leaf, route); placeholders[placeholder_index].z_order = BuildRoute(hit_leaf, route);
placeholders[placeholder_index].leaf_pointer = route[depth]; placeholders[placeholder_index].leaf_pointer = route[depth];
placeholders[placeholder_index].object_index = i; placeholders[placeholder_index].object_index = i;
hit_leaf.X() += leafDimension.X(); hit_leaf.X() += TemplatedOctree::leafDimension.X();
if (hit_leaf.X()>object_bb.max.X()) if (hit_leaf.X()>object_bb.max.X())
{ {
hit_leaf.X() = object_bb.min.X(); hit_leaf.X() = object_bb.min.X();
hit_leaf.Z()+= leafDimension.Z(); hit_leaf.Z()+= TemplatedOctree::leafDimension.Z();
if (hit_leaf.Z()>object_bb.max.Z()) if (hit_leaf.Z()>object_bb.max.Z())
{ {
hit_leaf.Z() = object_bb.min.Z(); hit_leaf.Z() = object_bb.min.Z();
hit_leaf.Y()+= leafDimension.Y(); hit_leaf.Y()+= TemplatedOctree::leafDimension.Y();
} }
} }
} }
@ -315,8 +336,8 @@ public:
marks = new unsigned char[placeholder_count]; marks = new unsigned char[placeholder_count];
memset(&marks[0], 0, sizeof(unsigned char)*placeholder_count); memset(&marks[0], 0, sizeof(unsigned char)*placeholder_count);
std::sort(placeholders.begin(), placeholders.end(), ObjectSorter< Octree::Node >()); std::sort(placeholders.begin(), placeholders.end(), ObjectSorter< NodeType >());
std::vector< Octree::Node* > filled_leaves(placeholder_count); std::vector< NodePointer > filled_leaves(placeholder_count);
sorted_dataset.resize( placeholder_count ); sorted_dataset.resize( placeholder_count );
for (int i=0; i<placeholder_count; i++) for (int i=0; i<placeholder_count; i++)
{ {
@ -337,13 +358,13 @@ public:
do end++; do end++;
while (end<placeholder_count && initial_leaf==filled_leaves[end]); while (end<placeholder_count && initial_leaf==filled_leaves[end]);
VoxelType *voxel = Voxel(initial_leaf); VoxelType *voxel = TemplatedOctree::Voxel(initial_leaf);
voxel->SetRange(begin, end); voxel->SetRange(begin, end);
} }
// The octree is built, the dataset is sorted but only the leaves are indexed: // The octree is built, the dataset is sorted but only the leaves are indexed:
// we propaget the indexing information bottom-up to the root // we propaget the indexing information bottom-up to the root
IndexInnerNodes( Root() ); IndexInnerNodes( TemplatedOctree::Root() );
} //end of Set } //end of Set
/*! /*!
@ -370,7 +391,7 @@ public:
unsigned int object_count; unsigned int object_count;
int leaves_count; int leaves_count;
ScalarType k_distance = leafDiagonal; ScalarType k_distance = TemplatedOctree::leafDiagonal;
IncrementMark(); IncrementMark();
@ -379,14 +400,14 @@ public:
leaves.clear(); leaves.clear();
object_count = 0; object_count = 0;
query_bb.Offset(k_distance); query_bb.Offset(k_distance);
sphere_radius += vcg::math::Max<ScalarType>(leafDiagonal, k_distance); sphere_radius += vcg::math::Max<ScalarType>(TemplatedOctree::leafDiagonal, k_distance);
ContainedLeaves(query_bb, leaves, Root(), boundingBox); ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox);
leaves_count = int(leaves.size()); leaves_count = int(leaves.size());
object_count = 0; object_count = 0;
for (int i=0; i<leaves_count; i++) for (int i=0; i<leaves_count; i++)
object_count += Voxel( leaves[i] )->count; object_count += TemplatedOctree::Voxel( leaves[i] )->count;
} }
while (object_count==0 && sphere_radius<max_distance); while (object_count==0 && sphere_radius<max_distance);
@ -426,9 +447,9 @@ public:
} // end of for (int i=0; i<leavesCount; i++) } // end of for (int i=0; i<leavesCount; i++)
object_count = int(neighbors.size()); object_count = int(neighbors.size());
std::vector< Neighbour >::iterator first = neighbors.begin(); typename std::vector< Neighbour >::iterator first = neighbors.begin();
std::vector< Neighbour >::iterator last = neighbors.end(); typename std::vector< Neighbour >::iterator last = neighbors.end();
std::partial_sort(first, first+object_count, last, DistanceCompare()); std::partial_sort< Neighbour >(first, first+object_count, last/*, DistanceCompare()*/);
distance = neighbors[0].distance; distance = neighbors[0].distance;
point = neighbors[0].point; point = neighbors[0].point;
return neighbors[0].object; return neighbors[0].object;
@ -442,14 +463,14 @@ public:
( (
OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor,
OBJECT_MARKER & /*marker*/, OBJECT_MARKER & /*marker*/,
const unsigned int k, unsigned int k,
const CoordType & query_point, const CoordType & query_point,
const ScalarType & max_distance, const ScalarType & max_distance,
OBJECT_POINTER_CONTAINER & objects, OBJECT_POINTER_CONTAINER & objects,
DISTANCE_CONTAINER & distances, DISTANCE_CONTAINER & distances,
POINT_CONTAINER & points, POINT_CONTAINER & points,
bool sort_per_distance = false, bool sort_per_distance = true,
bool allow_zero_distance = false bool allow_zero_distance = true
) )
{ {
BoundingBoxType query_bb; BoundingBoxType query_bb;
@ -462,7 +483,7 @@ public:
unsigned int object_count; unsigned int object_count;
int leaves_count; int leaves_count;
float k_distance = leafDiagonal; float k_distance = TemplatedOctree::leafDiagonal;
do do
{ {
IncrementMark(); IncrementMark();
@ -472,14 +493,14 @@ public:
leaves.clear(); leaves.clear();
object_count = 0; object_count = 0;
query_bb.Offset(k_distance); query_bb.Offset(k_distance);
sphere_radius += vcg::math::Max<float>(leafDiagonal, k_distance); sphere_radius += vcg::math::Max<float>(TemplatedOctree::leafDiagonal, k_distance);
ContainedLeaves(query_bb, leaves, Root(), boundingBox); ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox);
leaves_count = int(leaves.size()); leaves_count = int(leaves.size());
object_count = 0; object_count = 0;
for (int i=0; i<leaves_count; i++) for (int i=0; i<leaves_count; i++)
object_count += Voxel( leaves[i] )->count; object_count += TemplatedOctree::Voxel( leaves[i] )->count;
} }
while (object_count<k && sphere_radius<max_distance); // TODO check the termination condintion while (object_count<k && sphere_radius<max_distance); // TODO check the termination condintion
@ -529,11 +550,11 @@ public:
else else
object_count=int(neighbors.size()); object_count=int(neighbors.size());
std::vector< Neighbour >::iterator first = neighbors.begin(); NeighbourIterator first = neighbors.begin();
std::vector< Neighbour >::iterator last = neighbors.end(); NeighbourIterator last = neighbors.end();
if (sort_per_distance) std::partial_sort(first, first+object_count, last, DistanceCompare()); if (sort_per_distance) std::partial_sort< NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ );
else std::nth_element (first, first+object_count, last, DistanceCompare()); else std::nth_element < NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ );
k_distance = neighbors[object_count-1].distance; k_distance = neighbors[object_count-1].distance;
} }
while (k_distance>sphere_radius && sphere_radius<max_distance); while (k_distance>sphere_radius && sphere_radius<max_distance);
@ -563,19 +584,19 @@ public:
BoundingBoxType query_bb(sphere_center, sphere_radius); BoundingBoxType query_bb(sphere_center, sphere_radius);
// If that bounding-box don't collide with the octree bounding-box, simply return 0 // If that bounding-box don't collide with the octree bounding-box, simply return 0
if (!boundingBox.Collide(query_bb)) if (!TemplatedOctree::boundingBox.Collide(query_bb))
return 0; return 0;
std::vector< NodePointer > leaves; std::vector< NodePointer > leaves;
std::vector< Neighbour > neighbors; std::vector< Neighbour > neighbors;
unsigned int object_count = 0; unsigned int object_count = 0;
float k_distance = leafDiagonal; //float k_distance = TemplatedOctree::leafDiagonal;
IncrementMark(); IncrementMark();
ContainedLeaves(query_bb, leaves, Root(), boundingBox); ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox);
int leaves_countleaves_count = int(leaves.size()); int leaves_count = int(leaves.size());
if (leaves_count==0) if (leaves_count==0)
return 0; return 0;
@ -597,20 +618,20 @@ public:
continue; continue;
distance = sphere_radius; distance = sphere_radius;
if (!distance_functor(*ref->pObject, query_point, distance, closest_point)) if (!distance_functor(*ref->pObject, sphere_center, distance, closest_point))
continue; continue;
object_count++; object_count++;
Mark(ref); Mark(ref);
if ((distance!=0.0f || allow_zero_distance) && distance<max_distance) if ((distance!=0.0f || allow_zero_distance) && distance<sphere_radius)
neighbors.push_back( Neighbour(ref->pObject, closest_point, distance) ); neighbors.push_back( Neighbour(ref->pObject, closest_point, distance) );
} //end of for ( ; begin<end; begin++) } //end of for ( ; begin<end; begin++)
} // end of for (int i=0; i<leavesCount; i++) } // end of for (int i=0; i<leavesCount; i++)
std::vector< Neighbour >::iterator first = neighbors.begin(); NeighbourIterator first = neighbors.begin();
std::vector< Neighbour >::iterator last = neighbors.end(); NeighbourIterator last = neighbors.end();
if (sort_per_distance) std::partial_sort(first, first+object_count, last, DistanceCompare()); if (sort_per_distance) std::partial_sort< NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ );
else std::nth_element (first, first+object_count, last, DistanceCompare()); else std::nth_element < NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ );
return CopyQueryResults<OBJECT_POINTER_CONTAINER, DISTANCE_CONTAINER, POINT_CONTAINER>(neighbors, object_count, objects, distances, points); return CopyQueryResults<OBJECT_POINTER_CONTAINER, DISTANCE_CONTAINER, POINT_CONTAINER>(neighbors, object_count, objects, distances, points);
};//end of GetInSphere };//end of GetInSphere
@ -638,7 +659,7 @@ public:
unsigned int object_count; unsigned int object_count;
int leaves_count; int leaves_count;
ContainedLeaves(query_bounding_box, leaves, Root(), boundingBox); ContainedLeaves(query_bounding_box, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox);
leaves_count = int(leaves.size()); leaves_count = int(leaves.size());
if (leaves_count==0) if (leaves_count==0)
{ {
@ -684,7 +705,7 @@ public:
{ {
for (int s=0; s<8; s++) for (int s=0; s<8; s++)
if ((son=Son(n, s))!=0) if ((son=Son(n, s))!=0)
DrawOctree(SubBox(boundingBox, s), son); DrawOctree(TemplatedOctree::SubBox(boundingBox, s), son);
} }
else else
{ {
@ -692,7 +713,7 @@ public:
if (level<rendering_settings.maxVisibleDepth) if (level<rendering_settings.maxVisibleDepth)
for (int s=0; s<8; s++) for (int s=0; s<8; s++)
if ((son=Son(n, s))!=0) if ((son=Son(n, s))!=0)
DrawOctree(SubBox(boundingBox, s), son); DrawOctree(TemplatedOctree::SubBox(boundingBox, s), son);
} }
}; };
@ -755,10 +776,10 @@ public:
{ {
do do
{ {
query_bb.Offset(leafDiagonal); query_bb.Offset(TemplatedOctree::leafDiagonal);
sphere_radius += leafDiagonal; sphere_radius += TemplatedOctree::leafDiagonal;
} }
while ( !boundingBox.Collide(query_bb) || sphere_radius>max_distance); // TODO check the termination condintion while ( !TemplatedOctree::boundingBox.Collide(query_bb) || sphere_radius>max_distance); // TODO check the termination condintion
} }
return (sphere_radius<=max_distance); return (sphere_radius<=max_distance);
}; };
@ -784,9 +805,9 @@ public:
objects.resize(object_count); objects.resize(object_count);
} }
POINT_CONTAINER::iterator iPoint = points.begin(); typename POINT_CONTAINER::iterator iPoint = points.begin();
DISTANCE_CONTAINER::iterator iDistance = distances.begin(); typename DISTANCE_CONTAINER::iterator iDistance = distances.begin();
OBJECT_POINTER_CONTAINER::iterator iObject = objects.begin(); typename OBJECT_POINTER_CONTAINER::iterator iObject = objects.begin();
for (unsigned int n=0; n<object_count; n++, iPoint++, iDistance++, iObject++) for (unsigned int n=0; n<object_count; n++, iPoint++, iDistance++, iObject++)
{ {
(*iPoint) = neighbors[n].point; (*iPoint) = neighbors[n].point;
@ -803,24 +824,22 @@ public:
{ {
assert(n!=NULL); assert(n!=NULL);
VoxelPointer current_voxel = Voxel(n); VoxelPointer current_voxel = TemplatedOctree::Voxel(n);
VoxelPointer son_voxel; VoxelPointer son_voxel;
for (int s=0; s<8; s++) for (int s=0; s<8; s++)
{ {
NodePointer son_index = Son(n, s); NodePointer son_index = Son(n, s);
if (son_index!=NULL) if (son_index!=NULL)
{ {
if (Level(son_index)!=maximumDepth) if (Level(son_index)!=TemplatedOctree::maximumDepth)
IndexInnerNodes(son_index); IndexInnerNodes(son_index);
son_voxel = Voxel(son_index); son_voxel = TemplatedOctree::Voxel(son_index);
current_voxel->AddRange( son_voxel ); current_voxel->AddRange( son_voxel );
} }
} }
}; // end of IndexInnerNodes }; // end of IndexInnerNodes
}; };
} //end of namespace vcg } //end of namespace vcg
#endif //VCG_SPACE_INDEX_OCTREE_H #endif //VCG_SPACE_INDEX_OCTREE_H

View File

@ -8,7 +8,7 @@
* \ * * \ *
* All rights reserved. * * All rights reserved. *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
@ -58,13 +58,14 @@ public:
// Octree Type Definitions // Octree Type Definitions
typedef unsigned long long ZOrderType; typedef unsigned long long ZOrderType;
typedef SCALAR_TYPE ScalarType; typedef SCALAR_TYPE ScalarType;
typedef typename VOXEL_TYPE VoxelType; typedef VOXEL_TYPE VoxelType;
typedef typename VOXEL_TYPE *VoxelPointer; typedef VoxelType * VoxelPointer;
typedef vcg::Point3i CenterType; typedef vcg::Point3i CenterType;
static const ScalarType EXPANSION_FACTOR; static const ScalarType EXPANSION_FACTOR;
typedef Node NodeType;
typedef int NodeIndex; typedef int NodeIndex;
typedef Node *NodePointer; typedef NodeType * NodePointer;
typedef vcg::Box3<ScalarType> BoundingBoxType; typedef vcg::Box3<ScalarType> BoundingBoxType;
typedef vcg::Point3<ScalarType> CoordinateType; typedef vcg::Point3<ScalarType> CoordinateType;
protected: protected:
@ -94,19 +95,19 @@ protected:
// The position of the center of the node in integer coords in the 0..2^(2*sz) -1 range // The position of the center of the node in integer coords in the 0..2^(2*sz) -1 range
// The root has position (lsz/2,lsz/2,lsz/2) // The root has position (lsz/2,lsz/2,lsz/2)
CenterType center; CenterType center;
char level; char level;
NodePointer parent; NodePointer parent;
VoxelType voxel; VoxelType voxel;
}; };
/* /*
* Inner struct: Node * Inner struct: Node
*/ */
struct InnerNode : public Node struct InnerNode : public Node
{ {
InnerNode() : Node() {}; InnerNode() : Node() {};
InnerNode(NodePointer parent, int level) : Node(parent, level) InnerNode(NodePointer parent, int level) : Node(parent, level)
{ {
memset(&sons[0], NULL, 8*sizeof(Node*)); memset(&sons[0], NULL, 8*sizeof(Node*));
} }
@ -136,7 +137,8 @@ protected:
inline NodePointer &Son(int /*sonIndex*/) inline NodePointer &Son(int /*sonIndex*/)
{ {
assert(false); assert(false);
return parent; NodePointer p = NULL;
return p;
} }
inline bool IsLeaf() inline bool IsLeaf()
@ -152,12 +154,12 @@ public:
this->maximumDepth = maximumDepth; this->maximumDepth = maximumDepth;
size = 1<< maximumDepth; // e.g. 1*2^maxDepth size = 1<< maximumDepth; // e.g. 1*2^maxDepth
lSize = 1<<(maximumDepth+1); // e.g. 1*2^(maxDepth+1) lSize = 1<<(maximumDepth+1); // e.g. 1*2^(maxDepth+1)
InnerNode *root = new InnerNode(NULL,0); InnerNode *root = new InnerNode(NULL,0);
nodes.clear(); nodes.clear();
nodes.push_back( root ); nodes.push_back( root );
root->center = CenterType(size, size, size); root->center = CenterType(size, size, size);
ScalarType szf = (ScalarType) size; ScalarType szf = (ScalarType) size;
leafDimension = boundingBox.Dim(); leafDimension = boundingBox.Dim();
leafDimension /= szf; leafDimension /= szf;
@ -166,7 +168,7 @@ public:
// Return the octree bounding-box // Return the octree bounding-box
inline BoundingBoxType BoundingBox() { return boundingBox; } inline BoundingBoxType BoundingBox() { return boundingBox; }
// Return the Voxel of the n-th node // Return the Voxel of the n-th node
inline VoxelPointer Voxel(const NodePointer n) { return &(n->voxel); } inline VoxelPointer Voxel(const NodePointer n) { return &(n->voxel); }
@ -188,20 +190,20 @@ public:
// Return the index of the current node in its father // Return the index of the current node in its father
int WhatSon(NodePointer n) const int WhatSon(NodePointer n) const
{ {
if(n==Root()) if(n==Root())
assert(false); assert(false);
NodePointer parent = Parent(n); NodePointer parent = Parent(n);
for(int i=0;i<8;++i) for(int i=0;i<8;++i)
if(parent->Son(i)==n) if(parent->Son(i)==n)
return i; return i;
return -1; return -1;
} }
// Return the center of the n-th node // Return the center of the n-th node
inline CenterType CenterInOctreeCoordinates(const NodePointer n) const { return n->center;} inline CenterType CenterInOctreeCoordinates(const NodePointer n) const { return n->center;}
/*! /*!
* Return the center of the n-th node expressed in world-coordinate * Return the center of the n-th node expressed in world-coordinate
* \param NodePointer the pointer to the node whose center in world coordinate has to be computed * \param NodePointer the pointer to the node whose center in world coordinate has to be computed
@ -210,12 +212,12 @@ public:
{ {
assert(0<=n && n<NodeCount()); assert(0<=n && n<NodeCount());
int shift = maximumDepth - n->level + 1; int shift = maximumDepth - Level(n) + 1;
CoordinateType ocCenter = CenterInOctreeCoordinates(n); CoordinateType ocCenter = CenterInOctreeCoordinates(n);
CoordinateType nodeSize = boundingBox.Dim()/float(1<<level); CoordinateType nodeSize = boundingBox.Dim()/float(1<<Level(n));
wcCenter.X() = boundingBox.min.X() + (nodeSize.X()*(0.5f+(ocCenter.X()>>shift))); wc_Center.X() = boundingBox.min.X() + (nodeSize.X()*(0.5f+(ocCenter.X()>>shift)));
wcCenter.Y() = boundingBox.min.Y() + (nodeSize.Y()*(0.5f+(ocCenter.Y()>>shift))); wc_Center.Y() = boundingBox.min.Y() + (nodeSize.Y()*(0.5f+(ocCenter.Y()>>shift)));
wcCenter.Z() = boundingBox.min.Z() + (nodeSize.Z()*(0.5f+(ocCenter.Z()>>shift))); wc_Center.Z() = boundingBox.min.Z() + (nodeSize.Z()*(0.5f+(ocCenter.Z()>>shift)));
}; };
// Given a node (even not leaf) it returns the center of the box it represent. // Given a node (even not leaf) it returns the center of the box it represent.
@ -238,30 +240,30 @@ public:
a) a leaf at the deepest level 2 has position (.5,.5) a) a leaf at the deepest level 2 has position (.5,.5)
b) a mid node (lev 1) has position (1,1) b) a mid node (lev 1) has position (1,1)
c) root has level 0 and position (sz/2,sz/2) = (2,2) c) root has level 0 and position (sz/2,sz/2) = (2,2)
The center of a node has integer coords in the 2^(MaxDepth+1) range. The center of a node has integer coords in the 2^(MaxDepth+1) range.
The other approach is to use position as a bit string The other approach is to use position as a bit string
codifying the tree path, but in this case you have to codifying the tree path, but in this case you have to
supply also the level (e.g. the string lenght) supply also the level (e.g. the string lenght)
you desire. The lower left corner node is always 0 ( (,) for the root (0,0) level 1, and (00,00) for level 2) you desire. The lower left corner node is always 0 ( (,) for the root (0,0) level 1, and (00,00) for level 2)
| ~~~ | | ~~~ |
| 0~~ | 1~~ | | 0~~ | 1~~ |
| 00~ | 01~ | 10~ | 11~ | | 00~ | 01~ | 10~ | 11~ |
|000|001|010|011|100|101|110|111| |000|001|010|011|100|101|110|111|
The interesting properties is that The interesting properties is that
if your octree represent a space [minv,maxv] and you want if your octree represent a space [minv,maxv] and you want
to find the octree cell containing a point p in [minv,maxv] to find the octree cell containing a point p in [minv,maxv]
you just have to convert p in the range [0,sz) truncate it to an integer and use it as a path. you just have to convert p in the range [0,sz) truncate it to an integer and use it as a path.
For example, consider an octree of depth 3, representing a range [0..100) For example, consider an octree of depth 3, representing a range [0..100)
sz=8 (each cell contains form 0 to 12.5 sz=8 (each cell contains form 0 to 12.5
the point the point
5 -> 0.4 -> path is 000 5 -> 0.4 -> path is 000
45 -> 3.6 -> path is 011 45 -> 3.6 -> path is 011
50 -> 4.0 -> path is 100 50 -> 4.0 -> path is 100
100 -> 8 -> ERROR the interval is right open!!! 100 -> 8 -> ERROR the interval is right open!!!
Note how each cell is meant to contains a right open interval (e.g. the first cell contains [0,12.5) and the second [12.5,25) and so on) Note how each cell is meant to contains a right open interval (e.g. the first cell contains [0,12.5) and the second [12.5,25) and so on)
@ -321,21 +323,21 @@ public:
else bs.max.Y()=((bs.min.Y()=lbb.min.Y())+lbb.max.Y())/2.0f; else bs.max.Y()=((bs.min.Y()=lbb.min.Y())+lbb.max.Y())/2.0f;
if (i&4) bs.min.Z()=(lbb.min.Z()+(bs.max.Z()=lbb.max.Z()))/2.0f; if (i&4) bs.min.Z()=(lbb.min.Z()+(bs.max.Z()=lbb.max.Z()))/2.0f;
else bs.max.Z()=((bs.min.Z()=lbb.min.Z())+lbb.max.Z())/2.0f; else bs.max.Z()=((bs.min.Z()=lbb.min.Z())+lbb.max.Z())/2.0f;
return bs; return bs;
} }
// Given the bounding-box and the center (both in world-coordinates) // Given the bounding-box and the center (both in world-coordinates)
// of a node, return the bounding-box (in world-coordinats) of the i-th son // of a node, return the bounding-box (in world-coordinats) of the i-th son
BoundingBoxType SubBoxAndCenterInWorldCoordinates(BoundingBoxType &lbb, CoordinateType &center, int i) BoundingBoxType SubBoxAndCenterInWorldCoordinates(BoundingBoxType &lbb, CoordinateType &center, int i)
{ {
BoundingBoxType bs; BoundingBoxType bs;
if (i&1) if (i&1)
{ {
bs.min[0]=center[0]; bs.min[0]=center[0];
bs.max[0]=lbb.max[0]; bs.max[0]=lbb.max[0];
} }
else else
{ {
bs.min[0]=lbb.min[0]; bs.min[0]=lbb.min[0];
bs.max[0]=center[0]; bs.max[0]=center[0];
@ -345,17 +347,17 @@ public:
bs.min[1]=center[1]; bs.min[1]=center[1];
bs.max[1]=lbb.max[1]; bs.max[1]=lbb.max[1];
} }
else else
{ {
bs.max[1]=center[1]; bs.max[1]=center[1];
bs.min[1]=lbb.min[1]; bs.min[1]=lbb.min[1];
} }
if (i&4) if (i&4)
{ {
bs.min[2]=center[2]; bs.min[2]=center[2];
bs.max[2]=lbb.max[2]; bs.max[2]=lbb.max[2];
} }
else else
{ {
bs.max[2]=center[2]; bs.max[2]=center[2];
bs.min[2]=lbb.min[2]; bs.min[2]=lbb.min[2];
@ -364,7 +366,7 @@ public:
}; };
/* /*
* Add a new Node to the octree. * Add a new Node to the octree.
* The created node is the i-th son of the node pointed to by parent. * The created node is the i-th son of the node pointed to by parent.
* Return the pointer to the new node * Return the pointer to the new node
*/ */
@ -375,11 +377,11 @@ public:
//int index = NodeCount(); //int index = NodeCount();
char level = Level(parent)+1; char level = Level(parent)+1;
Node *node = (level<maximumDepth)? (Node*) new InnerNode(parent, level) : (Node*) new Leaf(parent, level); Node *node = (level<maximumDepth)? (Node*) new InnerNode(parent, level) : (Node*) new Leaf(parent, level);
nodes.push_back( node ); nodes.push_back( node );
Son(parent, i) = node; Son(parent, i) = node;
CenterType *parentCenter = &(parent->center); CenterType *parentCenter = &(parent->center);
int displacement = 1<<(maximumDepth-level); int displacement = 1<<(maximumDepth-level);
node->center.X() = parentCenter->X() + ((i&1)? displacement : -displacement); node->center.X() = parentCenter->X() + ((i&1)? displacement : -displacement);
@ -395,24 +397,24 @@ public:
NodePointer AddNode(CenterType path) NodePointer AddNode(CenterType path)
{ {
//the input coordinates must be in the range 0..2^maxdepth //the input coordinates must be in the range 0..2^maxdepth
assert(path[0]>=0 && path[0]<size); assert(path[0]>=0 && path[0]<size);
assert(path[1]>=0 && path[1]<size); assert(path[1]>=0 && path[1]<size);
assert(path[2]>=0 && path[2]<size); assert(path[2]>=0 && path[2]<size);
NodePointer curNode = Root(); NodePointer curNode = Root();
int rootLevel = 0; int rootLevel = 0;
int shiftLevel = maximumDepth-1; int shiftLevel = maximumDepth-1;
while(shiftLevel >= rootLevel) while(shiftLevel >= rootLevel)
{ {
int nextSon=0; int nextSon=0;
if((path[0]>>shiftLevel)%2) nextSon +=1; if((path[0]>>shiftLevel)%2) nextSon +=1;
if((path[1]>>shiftLevel)%2) nextSon +=2; if((path[1]>>shiftLevel)%2) nextSon +=2;
if((path[2]>>shiftLevel)%2) nextSon +=4; if((path[2]>>shiftLevel)%2) nextSon +=4;
NodePointer nextNode = Son(curNode, nextSon); NodePointer nextNode = Son(curNode, nextSon);
if(nextNode!=NULL) // nessun nodo può aver Root() per figlio if(nextNode!=NULL) // nessun nodo può aver Root() per figlio
curNode = nextNode; curNode = nextNode;
else else
{ {
NodePointer newNode = NewNode(curNode, nextSon); NodePointer newNode = NewNode(curNode, nextSon);
assert(Son(curNode, nextSon)==newNode); // TODO delete an assignment assert(Son(curNode, nextSon)==newNode); // TODO delete an assignment
@ -427,9 +429,9 @@ public:
* Given a query point, compute the z_order of the leaf where this point would be contained. * Given a query point, compute the z_order of the leaf where this point would be contained.
* This leaf not necessarily must be exist! * This leaf not necessarily must be exist!
*/ */
// Convert the point p coordinates to the integer based representation // Convert the point p coordinates to the integer based representation
// in the range 0..size, where size is 2^maxdepth // in the range 0..size, where size is 2^maxdepth
CenterType Interize(const CoordinateType &pf) const CenterType Interize(const CoordinateType &pf) const
{ {
CenterType pi; CenterType pi;
@ -440,29 +442,29 @@ public:
pi.X() = int((pf.X() - boundingBox.min.X()) * size / (boundingBox.max.X() - boundingBox.min.X())); pi.X() = int((pf.X() - boundingBox.min.X()) * size / (boundingBox.max.X() - boundingBox.min.X()));
pi.Y() = int((pf.Y() - boundingBox.min.Y()) * size / (boundingBox.max.Y() - boundingBox.min.Y())); pi.Y() = int((pf.Y() - boundingBox.min.Y()) * size / (boundingBox.max.Y() - boundingBox.min.Y()));
pi.Z() = int((pf.Z() - boundingBox.min.Z()) * size / (boundingBox.max.Z() - boundingBox.min.Z())); pi.Z() = int((pf.Z() - boundingBox.min.Z()) * size / (boundingBox.max.Z() - boundingBox.min.Z()));
return pi; return pi;
} }
// Inverse function of Interize; // Inverse function of Interize;
// Return to the original coords space (not to the original values!!) // Return to the original coords space (not to the original values!!)
CoordinateType DeInterize(const CenterType &pi ) const CoordinateType DeInterize(const CenterType &pi ) const
{ {
CoordinateType pf; CoordinateType pf;
assert(pi.X()>=0 && pi.X()<size); assert(pi.X()>=0 && pi.X()<size);
assert(pi.Y()>=0 && pi.Y()<size); assert(pi.Y()>=0 && pi.Y()<size);
assert(pi.Z()>=0 && pi.Z()<size); assert(pi.Z()>=0 && pi.Z()<size);
pf.X() = pi.X() * (boundingBox.max.X() - boundingBox.min.X()) / size + boundingBox.min.X();
pf.Y() = pi.Y() * (boundingBox.max.Y() - boundingBox.min.Y()) / size + boundingBox.min.Y();
pf.Z() = pi.Z() * (boundingBox.max.Z() - boundingBox.min.Z()) / size + boundingBox.min.Z();
pf.X() = vi.X() * (boundingBox.max.X() - boundingBox.min.X()) / size + boundingBox.min.X();
pf.Y() = vi.Y() * (boundingBox.max.Y() - boundingBox.min.Y()) / size + boundingBox.min.Y();
pf.Z() = vi.Z() * (boundingBox.max.Z() - boundingBox.min.Z()) / size + boundingBox.min.Z();
return pf; return pf;
} }
// Compute the z-ordering integer value for a given node; // Compute the z-ordering integer value for a given node;
// this value can be used to compute a complete ordering of the nodes of a given level of the octree. // this value can be used to compute a complete ordering of the nodes of a given level of the octree.
// It assumes that the octree has a max depth of 10. // It assumes that the octree has a max depth of 10.
ZOrderType ZOrder(NodePointer n) const { return ZOrder(GetPath(n), Level(n)); } ZOrderType ZOrder(NodePointer n) const { return ZOrder(GetPath(n), Level(n)); }
ZOrderType ComputeZOrder(const CoordinateType &query) const { return ZOrder(CenterType::Construct(Interize(query)), maximumDepth); }; ZOrderType ComputeZOrder(const CoordinateType &query) const { return ZOrder(CenterType::Construct(Interize(query)), maximumDepth); };
@ -471,7 +473,7 @@ public:
{ {
ZOrderType finalPosition = 0; ZOrderType finalPosition = 0;
ZOrderType currentPosition; ZOrderType currentPosition;
for(int i=0; i<level; ++i) for(int i=0; i<level; ++i)
{ {
currentPosition = 0; currentPosition = 0;
@ -485,33 +487,33 @@ public:
return finalPosition; return finalPosition;
}; };
// Funzione principale di accesso secondo un path; // Funzione principale di accesso secondo un path;
// restituisce l'indice del voxel di profondita' massima // restituisce l'indice del voxel di profondita' massima
// che contiene il punto espresso in range 0..2^maxk // che contiene il punto espresso in range 0..2^maxk
NodePointer DeepestNode(CenterType path, int MaxLev) NodePointer DeepestNode(CenterType path, int MaxLev)
{ {
assert(path[0]>=0 && path[0]<sz); assert(path[0]>=0 && path[0]<size);
assert(path[1]>=0 && path[1]<sz); assert(path[1]>=0 && path[1]<size);
assert(path[2]>=0 && path[2]<sz); assert(path[2]>=0 && path[2]<size);
NodePointer curNode = Root(); NodePointer curNode = Root();
int shift = maximumDepth-1; int shift = maximumDepth-1;
while(shift && Level(curNode) < MaxLev) while(shift && Level(curNode) < MaxLev)
{ {
int son = 0; int son = 0;
if((path[0]>>shift)%2) son +=1; if((path[0]>>shift)%2) son +=1;
if((path[1]>>shift)%2) son +=2; if((path[1]>>shift)%2) son +=2;
if((path[2]>>shift)%2) son +=4; if((path[2]>>shift)%2) son +=4;
NodePointer nextNode = Son(curNode, son); NodePointer nextNode = Son(curNode, son);
if(nextNode!=NULL) if(nextNode!=NULL)
CurNode=nextNode; curNode=nextNode;
else else
break; break;
--shift; --shift;
} }
return CurNode; return curNode;
} }
@ -522,9 +524,9 @@ public:
// for the first level only one bit of each one of the three components are maninguful; // for the first level only one bit of each one of the three components are maninguful;
CenterType GetPath(NodePointer n) const CenterType GetPath(NodePointer n) const
{ {
if(n==Root()) if(n==Root())
return CenterType(0,0,0); return CenterType(0,0,0);
CenterType path(0,0,0); CenterType path(0,0,0);
int shift, mask, son; int shift, mask, son;
@ -538,13 +540,13 @@ public:
if(son&2) path[1] |= mask; if(son&2) path[1] |= mask;
if(son&4) path[2] |= mask; if(son&4) path[2] |= mask;
n = Parent(n); // nodes[n].parent n = Parent(n); // nodes[n].parent
} }
return path; return path;
} }
// Dato un punto 3D nello spazio restituisce un array contenente // Dato un punto 3D nello spazio restituisce un array contenente
// i puntatori ai nodi che lo contengono, dalla radice fino alle foglie. // i puntatori ai nodi che lo contengono, dalla radice fino alle foglie.
// I nodi mancanti dalla radice fino a profondità maxDepth vengono aggiunti. // I nodi mancanti dalla radice fino a profondità maxDepth vengono aggiunti.
// In posizione i ci sarà il nodo di livello i. // In posizione i ci sarà il nodo di livello i.
// Restituisce lo z-order del punto p // Restituisce lo z-order del punto p
ZOrderType BuildRoute(const CoordinateType &p, NodePointer *&route) ZOrderType BuildRoute(const CoordinateType &p, NodePointer *&route)
@ -560,9 +562,9 @@ public:
while(shift >= 0) while(shift >= 0)
{ {
int son = 0; int son = 0;
if((path[0]>>shift)%2) son +=1; if((path[0]>>shift)%2) son +=1;
if((path[1]>>shift)%2) son +=2; if((path[1]>>shift)%2) son +=2;
if((path[2]>>shift)%2) son +=4; if((path[2]>>shift)%2) son +=4;
NodePointer nextNode = Son(curNode, son); NodePointer nextNode = Son(curNode, son);
if(nextNode!=NULL) if(nextNode!=NULL)
@ -570,7 +572,7 @@ public:
route[maximumDepth-shift] = nextNode; route[maximumDepth-shift] = nextNode;
curNode = nextNode; curNode = nextNode;
} }
else else
{ {
NodePointer newNode = NewNode(curNode, son); NodePointer newNode = NewNode(curNode, son);
route[maximumDepth-shift] = newNode; route[maximumDepth-shift] = newNode;
@ -594,43 +596,43 @@ public:
assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() ); assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() );
assert( boundingBox.min.Z()<=p.Z() && p.Z()<=boundingBox.max.Z() ); assert( boundingBox.min.Z()<=p.Z() && p.Z()<=boundingBox.max.Z() );
memset(route, NULL, maxDepth*sizeof(NodePointer)); memset(route, NULL, maximumDepth*sizeof(NodePointer));
CenterType path = CenterType::Construct(Interize(p)); CenterType path = CenterType::Construct(Interize(p));
int shift = maxDepth-1; int shift = maximumDepth-1;
NodePointer finalLevel = Root(); NodePointer finalLevel = Root();
NodePointer curNode = Root(); NodePointer curNode = Root();
while(shift >= finalLevel) while(shift >= finalLevel)
{ {
int son=0; int son=0;
if((path[0]>>shift)%2) son +=1; if((path[0]>>shift)%2) son +=1;
if((path[1]>>shift)%2) son +=2; if((path[1]>>shift)%2) son +=2;
if((path[2]>>shift)%2) son +=4; if((path[2]>>shift)%2) son +=4;
NodePointer nextNode = Son(curNode, son); NodePointer nextNode = Son(curNode, son);
if(nextNode!=NULL) if(nextNode!=NULL)
{ {
route[maxDepth-shift] = nextNode; route[maximumDepth-shift] = nextNode;
curNode = nextNode; curNode = nextNode;
} }
else else
return false; return false;
--shift; --shift;
} }
return true; return true;
}; //end of GetReoute }; //end of GetReoute
// Data una bounding-box bb_query, calcola l'insieme dei nodi di // Data una bounding-box bb_query, calcola l'insieme dei nodi di
// profondità depth il cui bounding-box ha intersezione non nulla con // profondità depth il cui bounding-box ha intersezione non nulla con
// bb (la bounding-box dell'octree); i puntatori a tali nodi sono // bb (la bounding-box dell'octree); i puntatori a tali nodi sono
// inseriti progressivamente in contained_nodes. // inseriti progressivamente in contained_nodes.
// The vector nodes must be cleared before calling this method. // The vector nodes must be cleared before calling this method.
void ContainedNodes void ContainedNodes
( (
BoundingBoxType &query, BoundingBoxType &query,
std::vector< NodePointer > &nodes, std::vector< NodePointer > &nodes,
int depth, int depth,
NodePointer n, NodePointer n,
BoundingBoxType &nodeBB) BoundingBoxType &nodeBB)
{ {
@ -655,13 +657,13 @@ public:
} }
} }
}; //end of ContainedNodes }; //end of ContainedNodes
// Data una bounding-box bb, calcola l'insieme delle foglie il cui
// Data una bounding-box bb, calcola l'insieme delle foglie il cui
// bounding-box ha intersezione non nulla con bb; i loro indici // bounding-box ha intersezione non nulla con bb; i loro indici
// sono inseriti all'interno di leaves. // sono inseriti all'interno di leaves.
void ContainedLeaves( void ContainedLeaves(
BoundingBoxType &query, BoundingBoxType &query,
std::vector< NodePointer > &leaves, std::vector< NodePointer > &leaves,
NodePointer node, NodePointer node,
BoundingBoxType &nodeBB BoundingBoxType &nodeBB
@ -687,7 +689,7 @@ public:
} }
}; //end of ContainedLeaves }; //end of ContainedLeaves
/* /*
* Octree Data Members * Octree Data Members
*/ */
@ -702,11 +704,11 @@ public:
int maximumDepth; int maximumDepth;
// The dimension of a leaf // The dimension of a leaf
CoordinateType leafDimension; CoordinateType leafDimension;
// The diagonal of a leaf // The diagonal of a leaf
ScalarType leafDiagonal; ScalarType leafDiagonal;
// The Octree nodes // The Octree nodes
std::vector< Node* > nodes; std::vector< Node* > nodes;

View File

@ -47,23 +47,19 @@ namespace vcg
class NormalExtrapolation class NormalExtrapolation
{ {
public: public:
typedef typename VERTEX_CONTAINER::value_type VertexType; typedef typename VERTEX_CONTAINER::value_type VertexType;
typedef typename VertexType *VertexPointer; typedef VertexType * VertexPointer;
typedef typename VERTEX_CONTAINER::iterator VertexIterator; typedef typename VERTEX_CONTAINER::iterator VertexIterator;
typedef typename VertexType::CoordType CoordType; typedef typename VertexType::CoordType CoordType;
typedef typename VertexType::NormalType NormalType; typedef typename VertexType::NormalType NormalType;
typedef typename VertexType::ScalarType ScalarType; typedef typename VertexType::ScalarType ScalarType;
typedef typename vcg::Box3< ScalarType > BoundingBoxType; typedef typename vcg::Box3< ScalarType > BoundingBoxType;
typedef typename vcg::Matrix33<ScalarType> MatrixType; typedef typename vcg::Matrix33<ScalarType> MatrixType;
enum NormalOrientation {IsCorrect=0, MustBeFlipped=1}; enum NormalOrientation {IsCorrect=0, MustBeFlipped=1};
public: private:
/*! /*************************************************
*/
static void ExtrapolateNormlas(const VertexIterator &begin, const VertexIterator &end, int k, const int root_index=-1, NormalOrientation orientation=IsCorrect, CallBackPos *callback=NULL)
{
/*************************************************
* Inner class definitions * Inner class definitions
**************************************************/ **************************************************/
// Dummy class: no object marker is needed // Dummy class: no object marker is needed
@ -139,9 +135,14 @@ namespace vcg
std::vector< MSTNode* > sons; std::vector< MSTNode* > sons;
}; };
/************************************************* typedef std::vector< Plane > PlaneContainer;
* The Algorithm typedef typename PlaneContainer::iterator PlaneIterator;
**************************************************/
public:
/*!
*/
static void ExtrapolateNormals(const VertexIterator &begin, const VertexIterator &end, const unsigned int k, const int root_index=-1, NormalOrientation orientation=IsCorrect, CallBackPos *callback=NULL)
{
BoundingBoxType dataset_bb; BoundingBoxType dataset_bb;
for (VertexIterator iter=begin; iter!=end; iter++) for (VertexIterator iter=begin; iter!=end; iter++)
dataset_bb.Add(iter->P()); dataset_bb.Add(iter->P());
@ -156,7 +157,7 @@ namespace vcg
sprintf(message, "Locating tangent planes..."); sprintf(message, "Locating tangent planes...");
std::vector< Plane > tangent_planes(vertex_count); std::vector< Plane > tangent_planes(vertex_count);
vcg::Octree< VertexType, ScalarType > octree_for_planes; vcg::Octree< VertexType, ScalarType > octree_for_planes;
octree_for_planes.Set< VertexIterator >(begin, end); octree_for_planes.Set( begin, end );
std::vector< VertexPointer > nearest_vertices; std::vector< VertexPointer > nearest_vertices;
std::vector< CoordType > nearest_points; std::vector< CoordType > nearest_points;
@ -165,8 +166,7 @@ namespace vcg
{ {
if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message); if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message);
octree_for_planes.GetKClosest<VertPointDistanceFunctor, DummyObjectMarker, std::vector<VertexPointer>, std::vector<ScalarType>, std::vector<CoordType> > octree_for_planes.GetKClosest(VertPointDistanceFunctor(), DummyObjectMarker(), k, iter->P(), max_distance, nearest_vertices, distances, nearest_points);
(VertPointDistanceFunctor(), DummyObjectMarker(), k, iter->P(), max_distance, nearest_vertices, distances, nearest_points);
// for each vertex *iter, compute the centroid as avarege of the k-nearest vertices of *iter // for each vertex *iter, compute the centroid as avarege of the k-nearest vertices of *iter
Plane *plane = &tangent_planes[ std::distance(begin, iter) ]; Plane *plane = &tangent_planes[ std::distance(begin, iter) ];
@ -200,23 +200,24 @@ namespace vcg
// Step 2: build the Riemannian graph, i.e. the graph where each point is connected to the k-nearest neigbours. // Step 2: build the Riemannian graph, i.e. the graph where each point is connected to the k-nearest neigbours.
dataset_bb.SetNull(); dataset_bb.SetNull();
std::vector< Plane >::iterator ePlane = tangent_planes.end(); PlaneIterator ePlane = tangent_planes.end();
for (std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) for (PlaneIterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++)
dataset_bb.Add(iPlane->center); dataset_bb.Add(iPlane->center);
max_distance = dataset_bb.Diag(); max_distance = dataset_bb.Diag();
vcg::Octree< Plane, ScalarType > octree_for_plane; vcg::Octree< Plane, ScalarType > octree_for_plane;
octree_for_plane.Set< std::vector<Plane>::iterator >(tangent_planes.begin(), tangent_planes.end()); octree_for_plane.Set( tangent_planes.begin(), tangent_planes.end());
std::vector< Plane* > nearest_planes(distances.size()); std::vector< Plane* > nearest_planes(distances.size());
std::vector< std::vector< RiemannianEdge > > riemannian_graph(vertex_count); //it's probably that we are wasting the last position... std::vector< std::vector< RiemannianEdge > > riemannian_graph(vertex_count); //it's probably that we are wasting the last position...
progress = 0; progress = 0;
sprintf(message, "Building Riemannian graph..."); sprintf(message, "Building Riemannian graph...");
for (std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) for (PlaneIterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++)
{ {
if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message); if (callback!=NULL && (++progress%step)==0 && (percentage=int((progress*100)/vertex_count))<100) (callback)(percentage, message);
octree_for_plane.GetKClosest< PlanePointDistanceFunctor, DummyObjectMarker, std::vector< Plane* >, std::vector< ScalarType >, std::vector< CoordType > > unsigned int kk = k;
(PlanePointDistanceFunctor(), DummyObjectMarker(), k, iPlane->center, max_distance, nearest_planes, distances, nearest_points, true, false); octree_for_plane.GetKClosest
(PlanePointDistanceFunctor(), DummyObjectMarker(), kk, iPlane->center, max_distance, nearest_planes, distances, nearest_points, true, false);
for (int n=0; n<k; n++) for (int n=0; n<k; n++)
if (iPlane->index<nearest_planes[n]->index) if (iPlane->index<nearest_planes[n]->index)
@ -225,8 +226,8 @@ namespace vcg
// Step 3: compute the minimum spanning tree (MST) over the Riemannian graph (we use the Kruskal algorithm) // Step 3: compute the minimum spanning tree (MST) over the Riemannian graph (we use the Kruskal algorithm)
std::vector< MSTEdge > E; std::vector< MSTEdge > E;
std::vector< std::vector< RiemannianEdge > >::iterator iRiemannian = riemannian_graph.begin(); typename std::vector< std::vector< RiemannianEdge > >::iterator iRiemannian = riemannian_graph.begin();
std::vector< RiemannianEdge >::iterator iRiemannianEdge, eRiemannianEdge; typename std::vector< RiemannianEdge >::iterator iRiemannianEdge, eRiemannianEdge;
for (int i=0; i<vertex_count; i++, iRiemannian++) for (int i=0; i<vertex_count; i++, iRiemannian++)
for (iRiemannianEdge=iRiemannian->begin(), eRiemannianEdge=iRiemannian->end(); iRiemannianEdge!=eRiemannianEdge; iRiemannianEdge++) for (iRiemannianEdge=iRiemannian->begin(), eRiemannianEdge=iRiemannian->end(); iRiemannianEdge!=eRiemannianEdge; iRiemannianEdge++)
E.push_back(MSTEdge(&tangent_planes[i], iRiemannianEdge->plane, iRiemannianEdge->weight)); E.push_back(MSTEdge(&tangent_planes[i], iRiemannianEdge->plane, iRiemannianEdge->weight));
@ -234,11 +235,11 @@ namespace vcg
std::sort( E.begin(), E.end() ); std::sort( E.begin(), E.end() );
vcg::DisjointSet<Plane> set; vcg::DisjointSet<Plane> set;
for (std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) for (typename std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++)
set.MakeSet( &*iPlane ); set.MakeSet( &*iPlane );
std::vector< MSTEdge >::iterator iMSTEdge = E.begin(); typename std::vector< MSTEdge >::iterator iMSTEdge = E.begin();
std::vector< MSTEdge >::iterator eMSTEdge = E.end(); typename std::vector< MSTEdge >::iterator eMSTEdge = E.end();
std::vector< MSTEdge > unoriented_tree; std::vector< MSTEdge > unoriented_tree;
Plane *u, *v; Plane *u, *v;
for ( ; iMSTEdge!=eMSTEdge; iMSTEdge++) for ( ; iMSTEdge!=eMSTEdge; iMSTEdge++)
@ -268,8 +269,8 @@ namespace vcg
VertexIterator iCurrentVertex, iSonVertex; VertexIterator iCurrentVertex, iSonVertex;
std::vector< MSTNode > MST(vertex_count); std::vector< MSTNode > MST(vertex_count);
std::vector< Plane >::iterator iFirstPlane = tangent_planes.begin(); typename std::vector< Plane >::iterator iFirstPlane = tangent_planes.begin();
std::vector< Plane >::iterator iCurrentPlane, iSonPlane; typename std::vector< Plane >::iterator iCurrentPlane, iSonPlane;
MSTNode *mst_root; MSTNode *mst_root;
int r_index = (root_index!=-1)? root_index : rand()*vertex_count/RAND_MAX; int r_index = (root_index!=-1)? root_index : rand()*vertex_count/RAND_MAX;