diff --git a/vcg/space/index/octree.h b/vcg/space/index/octree.h index 5a2862e0..1e587dda 100644 --- a/vcg/space/index/octree.h +++ b/vcg/space/index/octree.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace vcg { @@ -104,13 +105,32 @@ namespace vcg template < class OBJECT_TYPE, class 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 OBJECT_TYPE ObjectType; typedef typename Octree::Leaf * LeafPointer; typedef typename Octree::InnerNode * InnerNodePointer; typedef typename ReferenceType::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 */ @@ -130,10 +150,6 @@ namespace vcg vcg::Color4b color; }; - - - - protected: /*********************************************** * INNER DATA STRUCTURES AND PREDICATES * @@ -148,11 +164,11 @@ namespace vcg 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; - this->leaf_pointer = leaf_pointer; - this->object_index = object_index; + z_order = zOrder; + leaf_pointer = leafPointer; + object_index = objectIndex; } ZOrderType z_order; @@ -201,6 +217,11 @@ namespace vcg this->point = point; this->distance = distance; } + + inline bool operator<(const Neighbour &n) + { + return distance - void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj /*, const BoundingBoxType &bounding_box*/ /*, const BOUNDING_BOX_FUNCTOR &bb_functor*/ /*, vcg::CallBackPos *callback=NULL*/) + template < class OBJECT_ITERATOR > + void Set(const OBJECT_ITERATOR & bObj, const OBJECT_ITERATOR & eObj /*, vcg::CallBackPos *callback=NULL*/) { // Compute the bounding-box enclosing the whole dataset typedef Dereferencer::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; resulting_bb.Set(center); resulting_bb.Offset(longest_side); - boundingBox = resulting_bb; + TemplatedOctree::boundingBox = resulting_bb; // Try to find a reasonable octree depth int dataset_dimension = std::distance(bObj, eObj); @@ -268,16 +289,16 @@ public: depth++; } while (primitives_per_voxel>25 && depth<15); - Initialize(++depth); + TemplatedOctree::Initialize(++depth); // Sort the dataset (using the lebesgue space filling curve...) std::string message("Indexing dataset..."); - Octree::NodePointer *route = new Octree::NodePointer[depth+1]; + NodePointer *route = new NodePointer[depth+1]; OBJECT_ITERATOR iObj = bObj; //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 object_bb; vcg::Point3 hit_leaf; for (int i=0; i() ); + placeholders.push_back( ObjectPlaceholder< NodeType >() ); placeholders[placeholder_index].z_order = BuildRoute(hit_leaf, route); placeholders[placeholder_index].leaf_pointer = route[depth]; 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()) { 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()) { 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]; memset(&marks[0], 0, sizeof(unsigned char)*placeholder_count); - std::sort(placeholders.begin(), placeholders.end(), ObjectSorter< Octree::Node >()); - std::vector< Octree::Node* > filled_leaves(placeholder_count); + std::sort(placeholders.begin(), placeholders.end(), ObjectSorter< NodeType >()); + std::vector< NodePointer > filled_leaves(placeholder_count); sorted_dataset.resize( placeholder_count ); for (int i=0; iSetRange(begin, end); } // The octree is built, the dataset is sorted but only the leaves are indexed: // we propaget the indexing information bottom-up to the root - IndexInnerNodes( Root() ); + IndexInnerNodes( TemplatedOctree::Root() ); } //end of Set /*! @@ -370,7 +391,7 @@ public: unsigned int object_count; int leaves_count; - ScalarType k_distance = leafDiagonal; + ScalarType k_distance = TemplatedOctree::leafDiagonal; IncrementMark(); @@ -379,14 +400,14 @@ public: leaves.clear(); object_count = 0; query_bb.Offset(k_distance); - sphere_radius += vcg::math::Max(leafDiagonal, k_distance); + sphere_radius += vcg::math::Max(TemplatedOctree::leafDiagonal, k_distance); - ContainedLeaves(query_bb, leaves, Root(), boundingBox); + ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox); leaves_count = int(leaves.size()); object_count = 0; for (int i=0; icount; + object_count += TemplatedOctree::Voxel( leaves[i] )->count; } while (object_count==0 && sphere_radius::iterator first = neighbors.begin(); - std::vector< Neighbour >::iterator last = neighbors.end(); - std::partial_sort(first, first+object_count, last, DistanceCompare()); + typename std::vector< Neighbour >::iterator first = neighbors.begin(); + typename std::vector< Neighbour >::iterator last = neighbors.end(); + std::partial_sort< Neighbour >(first, first+object_count, last/*, DistanceCompare()*/); distance = neighbors[0].distance; point = neighbors[0].point; return neighbors[0].object; @@ -442,14 +463,14 @@ public: ( OBJECT_POINT_DISTANCE_FUNCTOR & distance_functor, OBJECT_MARKER & /*marker*/, - const unsigned int k, + unsigned int k, const CoordType & query_point, const ScalarType & max_distance, OBJECT_POINTER_CONTAINER & objects, DISTANCE_CONTAINER & distances, POINT_CONTAINER & points, - bool sort_per_distance = false, - bool allow_zero_distance = false + bool sort_per_distance = true, + bool allow_zero_distance = true ) { BoundingBoxType query_bb; @@ -462,7 +483,7 @@ public: unsigned int object_count; int leaves_count; - float k_distance = leafDiagonal; + float k_distance = TemplatedOctree::leafDiagonal; do { IncrementMark(); @@ -472,14 +493,14 @@ public: leaves.clear(); object_count = 0; query_bb.Offset(k_distance); - sphere_radius += vcg::math::Max(leafDiagonal, k_distance); + sphere_radius += vcg::math::Max(TemplatedOctree::leafDiagonal, k_distance); - ContainedLeaves(query_bb, leaves, Root(), boundingBox); + ContainedLeaves(query_bb, leaves, TemplatedOctree::Root(), TemplatedOctree::boundingBox); leaves_count = int(leaves.size()); object_count = 0; for (int i=0; icount; + object_count += TemplatedOctree::Voxel( leaves[i] )->count; } while (object_count::iterator first = neighbors.begin(); - std::vector< Neighbour >::iterator last = neighbors.end(); + NeighbourIterator first = neighbors.begin(); + NeighbourIterator last = neighbors.end(); - if (sort_per_distance) std::partial_sort(first, first+object_count, last, DistanceCompare()); - else std::nth_element (first, first+object_count, last, DistanceCompare()); + if (sort_per_distance) std::partial_sort< NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ ); + else std::nth_element < NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ ); k_distance = neighbors[object_count-1].distance; } while (k_distance>sphere_radius && sphere_radius leaves; std::vector< Neighbour > neighbors; unsigned int object_count = 0; - float k_distance = leafDiagonal; + //float k_distance = TemplatedOctree::leafDiagonal; 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) return 0; @@ -597,20 +618,20 @@ public: continue; distance = sphere_radius; - if (!distance_functor(*ref->pObject, query_point, distance, closest_point)) + if (!distance_functor(*ref->pObject, sphere_center, distance, closest_point)) continue; object_count++; Mark(ref); - if ((distance!=0.0f || allow_zero_distance) && distancepObject, closest_point, distance) ); } //end of for ( ; begin::iterator first = neighbors.begin(); - std::vector< Neighbour >::iterator last = neighbors.end(); - if (sort_per_distance) std::partial_sort(first, first+object_count, last, DistanceCompare()); - else std::nth_element (first, first+object_count, last, DistanceCompare()); + NeighbourIterator first = neighbors.begin(); + NeighbourIterator last = neighbors.end(); + if (sort_per_distance) std::partial_sort< NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ ); + else std::nth_element < NeighbourIterator >(first, first+object_count, last /*, DistanceCompare()*/ ); return CopyQueryResults(neighbors, object_count, objects, distances, points); };//end of GetInSphere @@ -638,7 +659,7 @@ public: unsigned int object_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()); if (leaves_count==0) { @@ -684,7 +705,7 @@ public: { for (int s=0; s<8; s++) if ((son=Son(n, s))!=0) - DrawOctree(SubBox(boundingBox, s), son); + DrawOctree(TemplatedOctree::SubBox(boundingBox, s), son); } else { @@ -692,7 +713,7 @@ public: if (levelmax_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); }; @@ -784,9 +805,9 @@ public: objects.resize(object_count); } - POINT_CONTAINER::iterator iPoint = points.begin(); - DISTANCE_CONTAINER::iterator iDistance = distances.begin(); - OBJECT_POINTER_CONTAINER::iterator iObject = objects.begin(); + typename POINT_CONTAINER::iterator iPoint = points.begin(); + typename DISTANCE_CONTAINER::iterator iDistance = distances.begin(); + typename OBJECT_POINTER_CONTAINER::iterator iObject = objects.begin(); for (unsigned int n=0; nAddRange( son_voxel ); } } }; // end of IndexInnerNodes }; - - } //end of namespace vcg #endif //VCG_SPACE_INDEX_OCTREE_H diff --git a/vcg/space/index/octree_template.h b/vcg/space/index/octree_template.h index 19250166..48150e23 100644 --- a/vcg/space/index/octree_template.h +++ b/vcg/space/index/octree_template.h @@ -8,7 +8,7 @@ * \ * * 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 * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -58,13 +58,14 @@ public: // Octree Type Definitions typedef unsigned long long ZOrderType; typedef SCALAR_TYPE ScalarType; - typedef typename VOXEL_TYPE VoxelType; - typedef typename VOXEL_TYPE *VoxelPointer; - typedef vcg::Point3i CenterType; + typedef VOXEL_TYPE VoxelType; + typedef VoxelType * VoxelPointer; + typedef vcg::Point3i CenterType; static const ScalarType EXPANSION_FACTOR; + typedef Node NodeType; typedef int NodeIndex; - typedef Node *NodePointer; - typedef vcg::Box3 BoundingBoxType; + typedef NodeType * NodePointer; + typedef vcg::Box3 BoundingBoxType; typedef vcg::Point3 CoordinateType; 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 root has position (lsz/2,lsz/2,lsz/2) - CenterType center; - char level; + CenterType center; + char level; NodePointer parent; VoxelType voxel; }; /* - * Inner struct: Node + * Inner struct: Node */ struct InnerNode : public 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*)); } @@ -136,7 +137,8 @@ protected: inline NodePointer &Son(int /*sonIndex*/) { assert(false); - return parent; + NodePointer p = NULL; + return p; } inline bool IsLeaf() @@ -152,12 +154,12 @@ public: this->maximumDepth = maximumDepth; size = 1<< maximumDepth; // e.g. 1*2^maxDepth lSize = 1<<(maximumDepth+1); // e.g. 1*2^(maxDepth+1) - + InnerNode *root = new InnerNode(NULL,0); nodes.clear(); nodes.push_back( root ); root->center = CenterType(size, size, size); - + ScalarType szf = (ScalarType) size; leafDimension = boundingBox.Dim(); leafDimension /= szf; @@ -166,7 +168,7 @@ public: // Return the octree bounding-box inline BoundingBoxType BoundingBox() { return boundingBox; } - + // Return the Voxel of the n-th node inline VoxelPointer Voxel(const NodePointer n) { return &(n->voxel); } @@ -188,20 +190,20 @@ public: // Return the index of the current node in its father int WhatSon(NodePointer n) const { - if(n==Root()) + if(n==Root()) assert(false); - + NodePointer parent = Parent(n); for(int i=0;i<8;++i) - if(parent->Son(i)==n) + if(parent->Son(i)==n) return i; - + 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;} - + /*! * 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 @@ -210,12 +212,12 @@ public: { assert(0<=n && nlevel + 1; + int shift = maximumDepth - Level(n) + 1; CoordinateType ocCenter = CenterInOctreeCoordinates(n); - CoordinateType nodeSize = boundingBox.Dim()/float(1<>shift))); - wcCenter.Y() = boundingBox.min.Y() + (nodeSize.Y()*(0.5f+(ocCenter.Y()>>shift))); - wcCenter.Z() = boundingBox.min.Z() + (nodeSize.Z()*(0.5f+(ocCenter.Z()>>shift))); + CoordinateType nodeSize = boundingBox.Dim()/float(1<>shift))); + wc_Center.Y() = boundingBox.min.Y() + (nodeSize.Y()*(0.5f+(ocCenter.Y()>>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. @@ -238,30 +240,30 @@ public: a) a leaf at the deepest level 2 has position (.5,.5) 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 other approach is to use position as a bit string - codifying the tree path, but in this case you have to - supply also the level (e.g. the string lenght) + The other approach is to use position as a bit string + codifying the tree path, but in this case you have to + 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) | ~~~ | | 0~~ | 1~~ | | 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 - if your octree represent a space [minv,maxv] and you want - to find the octree cell containing a point p in [minv,maxv] + if your octree represent a space [minv,maxv] and you want + 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. For example, consider an octree of depth 3, representing a range [0..100) sz=8 (each cell contains form 0 to 12.5 - the point + the point 5 -> 0.4 -> path is 000 - 45 -> 3.6 -> path is 011 - 50 -> 4.0 -> path is 100 + 45 -> 3.6 -> path is 011 + 50 -> 4.0 -> path is 100 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) @@ -321,21 +323,21 @@ public: 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; else bs.max.Z()=((bs.min.Z()=lbb.min.Z())+lbb.max.Z())/2.0f; - + return bs; } // 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 ¢er, int i) { BoundingBoxType bs; - if (i&1) + if (i&1) { bs.min[0]=center[0]; bs.max[0]=lbb.max[0]; } - else + else { bs.min[0]=lbb.min[0]; bs.max[0]=center[0]; @@ -345,17 +347,17 @@ public: bs.min[1]=center[1]; bs.max[1]=lbb.max[1]; } - else + else { bs.max[1]=center[1]; bs.min[1]=lbb.min[1]; } - if (i&4) + if (i&4) { bs.min[2]=center[2]; bs.max[2]=lbb.max[2]; } - else + else { bs.max[2]=center[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. * Return the pointer to the new node */ @@ -375,11 +377,11 @@ public: //int index = NodeCount(); char level = Level(parent)+1; - + Node *node = (levelcenter); int displacement = 1<<(maximumDepth-level); node->center.X() = parentCenter->X() + ((i&1)? displacement : -displacement); @@ -395,24 +397,24 @@ public: NodePointer AddNode(CenterType path) { //the input coordinates must be in the range 0..2^maxdepth - assert(path[0]>=0 && path[0]=0 && path[1]=0 && path[0]=0 && path[1]=0 && path[2]= rootLevel) { int nextSon=0; - if((path[0]>>shiftLevel)%2) nextSon +=1; - if((path[1]>>shiftLevel)%2) nextSon +=2; - if((path[2]>>shiftLevel)%2) nextSon +=4; - NodePointer nextNode = Son(curNode, nextSon); - if(nextNode!=NULL) // nessun nodo può aver Root() per figlio + if((path[0]>>shiftLevel)%2) nextSon +=1; + if((path[1]>>shiftLevel)%2) nextSon +=2; + if((path[2]>>shiftLevel)%2) nextSon +=4; + NodePointer nextNode = Son(curNode, nextSon); + if(nextNode!=NULL) // nessun nodo può aver Root() per figlio curNode = nextNode; - else + else { NodePointer newNode = NewNode(curNode, nextSon); 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. * 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 - CenterType Interize(const CoordinateType &pf) const + CenterType Interize(const CoordinateType &pf) const { CenterType pi; @@ -440,29 +442,29 @@ public: 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.Z() = int((pf.Z() - boundingBox.min.Z()) * size / (boundingBox.max.Z() - boundingBox.min.Z())); - + return pi; } - // Inverse function of Interize; + // Inverse function of Interize; // 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; - assert(pi.X()>=0 && pi.X()=0 && pi.Y()=0 && pi.Z()=0 && pi.X()=0 && pi.Y()=0 && pi.Z()=0 && path[0]=0 && path[1]=0 && path[2]=0 && path[0]=0 && path[1]=0 && path[2]>shift)%2) son +=1; - if((path[1]>>shift)%2) son +=2; - if((path[2]>>shift)%2) son +=4; + if((path[0]>>shift)%2) son +=1; + if((path[1]>>shift)%2) son +=2; + if((path[2]>>shift)%2) son +=4; NodePointer nextNode = Son(curNode, son); - if(nextNode!=NULL) - CurNode=nextNode; - else + if(nextNode!=NULL) + curNode=nextNode; + else break; --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; CenterType GetPath(NodePointer n) const { - if(n==Root()) + if(n==Root()) return CenterType(0,0,0); - + CenterType path(0,0,0); int shift, mask, son; @@ -538,13 +540,13 @@ public: if(son&2) path[1] |= mask; if(son&4) path[2] |= mask; n = Parent(n); // nodes[n].parent - } + } return path; } - // Dato un punto 3D nello spazio restituisce un array contenente - // i puntatori ai nodi che lo contengono, dalla radice fino alle foglie. - // I nodi mancanti dalla radice fino a profondità maxDepth vengono aggiunti. + // Dato un punto 3D nello spazio restituisce un array contenente + // i puntatori ai nodi che lo contengono, dalla radice fino alle foglie. + // I nodi mancanti dalla radice fino a profondità maxDepth vengono aggiunti. // In posizione i ci sarà il nodo di livello i. // Restituisce lo z-order del punto p ZOrderType BuildRoute(const CoordinateType &p, NodePointer *&route) @@ -560,9 +562,9 @@ public: while(shift >= 0) { int son = 0; - if((path[0]>>shift)%2) son +=1; - if((path[1]>>shift)%2) son +=2; - if((path[2]>>shift)%2) son +=4; + if((path[0]>>shift)%2) son +=1; + if((path[1]>>shift)%2) son +=2; + if((path[2]>>shift)%2) son +=4; NodePointer nextNode = Son(curNode, son); if(nextNode!=NULL) @@ -570,7 +572,7 @@ public: route[maximumDepth-shift] = nextNode; curNode = nextNode; } - else + else { NodePointer newNode = NewNode(curNode, son); route[maximumDepth-shift] = newNode; @@ -594,43 +596,43 @@ public: assert( boundingBox.min.Y()<=p.Y() && p.Y()<=boundingBox.max.Y() ); 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)); - int shift = maxDepth-1; + int shift = maximumDepth-1; NodePointer finalLevel = Root(); NodePointer curNode = Root(); - + while(shift >= finalLevel) { int son=0; - if((path[0]>>shift)%2) son +=1; - if((path[1]>>shift)%2) son +=2; - if((path[2]>>shift)%2) son +=4; - NodePointer nextNode = Son(curNode, son); - if(nextNode!=NULL) + if((path[0]>>shift)%2) son +=1; + if((path[1]>>shift)%2) son +=2; + if((path[2]>>shift)%2) son +=4; + NodePointer nextNode = Son(curNode, son); + if(nextNode!=NULL) { - route[maxDepth-shift] = nextNode; + route[maximumDepth-shift] = nextNode; curNode = nextNode; } - else + else return false; - + --shift; } return true; }; //end of GetReoute - // Data una bounding-box bb_query, calcola l'insieme dei nodi di - // profondità depth il cui bounding-box ha intersezione non nulla con - // bb (la bounding-box dell'octree); i puntatori a tali nodi sono + // Data una bounding-box bb_query, calcola l'insieme dei nodi di + // profondità depth il cui bounding-box ha intersezione non nulla con + // bb (la bounding-box dell'octree); i puntatori a tali nodi sono // inseriti progressivamente in contained_nodes. // The vector nodes must be cleared before calling this method. void ContainedNodes ( BoundingBoxType &query, std::vector< NodePointer > &nodes, - int depth, + int depth, NodePointer n, BoundingBoxType &nodeBB) { @@ -655,13 +657,13 @@ public: } } }; //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 // sono inseriti all'interno di leaves. void ContainedLeaves( - BoundingBoxType &query, + BoundingBoxType &query, std::vector< NodePointer > &leaves, NodePointer node, BoundingBoxType &nodeBB @@ -687,7 +689,7 @@ public: } }; //end of ContainedLeaves - + /* * Octree Data Members */ @@ -702,11 +704,11 @@ public: int maximumDepth; // The dimension of a leaf - CoordinateType leafDimension; + CoordinateType leafDimension; // The diagonal of a leaf ScalarType leafDiagonal; - + // The Octree nodes std::vector< Node* > nodes; diff --git a/vcg/space/normal_extrapolation.h b/vcg/space/normal_extrapolation.h index c4607135..6f7ab173 100644 --- a/vcg/space/normal_extrapolation.h +++ b/vcg/space/normal_extrapolation.h @@ -47,23 +47,19 @@ namespace vcg class NormalExtrapolation { public: - typedef typename VERTEX_CONTAINER::value_type VertexType; - typedef typename VertexType *VertexPointer; - typedef typename VERTEX_CONTAINER::iterator VertexIterator; - typedef typename VertexType::CoordType CoordType; - typedef typename VertexType::NormalType NormalType; - typedef typename VertexType::ScalarType ScalarType; - typedef typename vcg::Box3< ScalarType > BoundingBoxType; - typedef typename vcg::Matrix33 MatrixType; + typedef typename VERTEX_CONTAINER::value_type VertexType; + typedef VertexType * VertexPointer; + typedef typename VERTEX_CONTAINER::iterator VertexIterator; + typedef typename VertexType::CoordType CoordType; + typedef typename VertexType::NormalType NormalType; + typedef typename VertexType::ScalarType ScalarType; + typedef typename vcg::Box3< ScalarType > BoundingBoxType; + typedef typename vcg::Matrix33 MatrixType; enum NormalOrientation {IsCorrect=0, MustBeFlipped=1}; - - public: - /*! - */ - static void ExtrapolateNormlas(const VertexIterator &begin, const VertexIterator &end, int k, const int root_index=-1, NormalOrientation orientation=IsCorrect, CallBackPos *callback=NULL) - { - /************************************************* + + private: + /************************************************* * Inner class definitions **************************************************/ // Dummy class: no object marker is needed @@ -139,9 +135,14 @@ namespace vcg std::vector< MSTNode* > sons; }; - /************************************************* - * The Algorithm - **************************************************/ + typedef std::vector< Plane > PlaneContainer; + 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; for (VertexIterator iter=begin; iter!=end; iter++) dataset_bb.Add(iter->P()); @@ -156,7 +157,7 @@ namespace vcg sprintf(message, "Locating tangent planes..."); std::vector< Plane > tangent_planes(vertex_count); 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< 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); - octree_for_planes.GetKClosest, std::vector, std::vector > - (VertPointDistanceFunctor(), DummyObjectMarker(), k, iter->P(), max_distance, nearest_vertices, distances, nearest_points); + octree_for_planes.GetKClosest(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 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. dataset_bb.SetNull(); - std::vector< Plane >::iterator ePlane = tangent_planes.end(); - for (std::vector< Plane >::iterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) + PlaneIterator ePlane = tangent_planes.end(); + for (PlaneIterator iPlane=tangent_planes.begin(); iPlane!=ePlane; iPlane++) dataset_bb.Add(iPlane->center); max_distance = dataset_bb.Diag(); vcg::Octree< Plane, ScalarType > octree_for_plane; - octree_for_plane.Set< std::vector::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< std::vector< RiemannianEdge > > riemannian_graph(vertex_count); //it's probably that we are wasting the last position... progress = 0; 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); - octree_for_plane.GetKClosest< PlanePointDistanceFunctor, DummyObjectMarker, std::vector< Plane* >, std::vector< ScalarType >, std::vector< CoordType > > - (PlanePointDistanceFunctor(), DummyObjectMarker(), k, iPlane->center, max_distance, nearest_planes, distances, nearest_points, true, false); + unsigned int kk = k; + octree_for_plane.GetKClosest + (PlanePointDistanceFunctor(), DummyObjectMarker(), kk, iPlane->center, max_distance, nearest_planes, distances, nearest_points, true, false); for (int n=0; nindexindex) @@ -225,8 +226,8 @@ namespace vcg // Step 3: compute the minimum spanning tree (MST) over the Riemannian graph (we use the Kruskal algorithm) std::vector< MSTEdge > E; - std::vector< std::vector< RiemannianEdge > >::iterator iRiemannian = riemannian_graph.begin(); - std::vector< RiemannianEdge >::iterator iRiemannianEdge, eRiemannianEdge; + typename std::vector< std::vector< RiemannianEdge > >::iterator iRiemannian = riemannian_graph.begin(); + typename std::vector< RiemannianEdge >::iterator iRiemannianEdge, eRiemannianEdge; for (int i=0; ibegin(), eRiemannianEdge=iRiemannian->end(); iRiemannianEdge!=eRiemannianEdge; iRiemannianEdge++) E.push_back(MSTEdge(&tangent_planes[i], iRiemannianEdge->plane, iRiemannianEdge->weight)); @@ -234,11 +235,11 @@ namespace vcg std::sort( E.begin(), E.end() ); vcg::DisjointSet 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 ); - std::vector< MSTEdge >::iterator iMSTEdge = E.begin(); - std::vector< MSTEdge >::iterator eMSTEdge = E.end(); + typename std::vector< MSTEdge >::iterator iMSTEdge = E.begin(); + typename std::vector< MSTEdge >::iterator eMSTEdge = E.end(); std::vector< MSTEdge > unoriented_tree; Plane *u, *v; for ( ; iMSTEdge!=eMSTEdge; iMSTEdge++) @@ -268,8 +269,8 @@ namespace vcg VertexIterator iCurrentVertex, iSonVertex; std::vector< MSTNode > MST(vertex_count); - std::vector< Plane >::iterator iFirstPlane = tangent_planes.begin(); - std::vector< Plane >::iterator iCurrentPlane, iSonPlane; + typename std::vector< Plane >::iterator iFirstPlane = tangent_planes.begin(); + typename std::vector< Plane >::iterator iCurrentPlane, iSonPlane; MSTNode *mst_root; int r_index = (root_index!=-1)? root_index : rand()*vertex_count/RAND_MAX;