Minor improvements
-Added the possibility to create a balanced tree -Added methods to get the protected members -Bug fixed in the size of the stack used in the query methods
This commit is contained in:
parent
a42c279255
commit
0906212a1f
|
|
@ -112,10 +112,12 @@ namespace vcg {
|
||||||
// return the protected members which store the nodes and the points list
|
// return the protected members which store the nodes and the points list
|
||||||
inline const NodeList& _getNodes(void) { return mNodes; }
|
inline const NodeList& _getNodes(void) { return mNodes; }
|
||||||
inline const std::vector<VectorType>& _getPoints(void) { return mPoints; }
|
inline const std::vector<VectorType>& _getPoints(void) { return mPoints; }
|
||||||
|
inline unsigned int _getNumLevel(void) { return numLevel; }
|
||||||
|
inline const AxisAlignedBoxType& _getAABBox(void) { return mAABB; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
KdTree(const ConstDataWrapper<VectorType>& points, unsigned int nofPointsPerCell = 16, unsigned int maxDepth = 64);
|
KdTree(const ConstDataWrapper<VectorType>& points, unsigned int nofPointsPerCell = 16, unsigned int maxDepth = 64, bool balanced = false);
|
||||||
|
|
||||||
~KdTree();
|
~KdTree();
|
||||||
|
|
||||||
|
|
@ -140,7 +142,7 @@ namespace vcg {
|
||||||
// and returns the index of the first element of the second subset
|
// and returns the index of the first element of the second subset
|
||||||
unsigned int split(int start, int end, unsigned int dim, float splitValue);
|
unsigned int split(int start, int end, unsigned int dim, float splitValue);
|
||||||
|
|
||||||
int createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level, unsigned int targetCellsize, unsigned int targetMaxDepth);
|
int createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
@ -148,10 +150,15 @@ namespace vcg {
|
||||||
NodeList mNodes; //kd-tree nodes
|
NodeList mNodes; //kd-tree nodes
|
||||||
std::vector<VectorType> mPoints; //points read from the input DataWrapper
|
std::vector<VectorType> mPoints; //points read from the input DataWrapper
|
||||||
std::vector<unsigned int> mIndices; //points indices
|
std::vector<unsigned int> mIndices; //points indices
|
||||||
|
unsigned int targetCellSize; //min number of point in a leaf
|
||||||
|
unsigned int targetMaxDepth; //max tree depth
|
||||||
|
unsigned int numLevel; //actual tree depth
|
||||||
|
bool isBalanced; //true if the tree is balanced
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
KdTree<Scalar>::KdTree(const ConstDataWrapper<VectorType>& points, unsigned int nofPointsPerCell, unsigned int maxDepth)
|
KdTree<Scalar>::KdTree(const ConstDataWrapper<VectorType>& points, unsigned int nofPointsPerCell, unsigned int maxDepth, bool balanced)
|
||||||
: mPoints(points.size()), mIndices(points.size())
|
: mPoints(points.size()), mIndices(points.size())
|
||||||
{
|
{
|
||||||
// compute the AABB of the input
|
// compute the AABB of the input
|
||||||
|
|
@ -164,12 +171,14 @@ namespace vcg {
|
||||||
mAABB.Add(mPoints[i]);
|
mAABB.Add(mPoints[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNodes.reserve(4*mPoints.size()/nofPointsPerCell);
|
targetMaxDepth = maxDepth;
|
||||||
|
targetCellSize = nofPointsPerCell;
|
||||||
|
isBalanced = balanced;
|
||||||
|
//mNodes.reserve(4 * mPoints.size() / nofPointsPerCell);
|
||||||
//first node inserted (no leaf). The others are made by the createTree function (recursively)
|
//first node inserted (no leaf). The others are made by the createTree function (recursively)
|
||||||
mNodes.resize(1);
|
mNodes.resize(1);
|
||||||
mNodes.back().leaf = 0;
|
mNodes.back().leaf = 0;
|
||||||
/*int numLevel = */
|
numLevel = createTree(0, 0, mPoints.size(), 1);
|
||||||
createTree(0, 0, mPoints.size(), 1, nofPointsPerCell, maxDepth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
|
|
@ -200,7 +209,7 @@ namespace vcg {
|
||||||
mNeighborQueue.setMaxSize(k);
|
mNeighborQueue.setMaxSize(k);
|
||||||
mNeighborQueue.init();
|
mNeighborQueue.init();
|
||||||
|
|
||||||
QueryNode mNodeStack[64];
|
std::vector<QueryNode> mNodeStack(numLevel + 1);
|
||||||
mNodeStack[0].nodeId = 0;
|
mNodeStack[0].nodeId = 0;
|
||||||
mNodeStack[0].sq = 0.f;
|
mNodeStack[0].sq = 0.f;
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
|
|
@ -272,7 +281,7 @@ namespace vcg {
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
void KdTree<Scalar>::doQueryDist(const VectorType& queryPoint, float dist, std::vector<unsigned int>& points, std::vector<Scalar>& sqrareDists)
|
void KdTree<Scalar>::doQueryDist(const VectorType& queryPoint, float dist, std::vector<unsigned int>& points, std::vector<Scalar>& sqrareDists)
|
||||||
{
|
{
|
||||||
QueryNode mNodeStack[64];
|
std::vector<QueryNode> mNodeStack(numLevel + 1);
|
||||||
mNodeStack[0].nodeId = 0;
|
mNodeStack[0].nodeId = 0;
|
||||||
mNodeStack[0].sq = 0.f;
|
mNodeStack[0].sq = 0.f;
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
|
|
@ -335,7 +344,7 @@ namespace vcg {
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
void KdTree<Scalar>::doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist)
|
void KdTree<Scalar>::doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist)
|
||||||
{
|
{
|
||||||
QueryNode mNodeStack[64];
|
std::vector<QueryNode> mNodeStack(numLevel + 1);
|
||||||
mNodeStack[0].nodeId = 0;
|
mNodeStack[0].nodeId = 0;
|
||||||
mNodeStack[0].sq = 0.f;
|
mNodeStack[0].sq = 0.f;
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
|
|
@ -438,7 +447,7 @@ namespace vcg {
|
||||||
* is more expensive than the gain it provides and the memory consumption is x4 higher !
|
* is more expensive than the gain it provides and the memory consumption is x4 higher !
|
||||||
*/
|
*/
|
||||||
template<typename Scalar>
|
template<typename Scalar>
|
||||||
int KdTree<Scalar>::createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level, unsigned int targetCellSize, unsigned int targetMaxDepth)
|
int KdTree<Scalar>::createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level)
|
||||||
{
|
{
|
||||||
//select the first node
|
//select the first node
|
||||||
Node& node = mNodes[nodeId];
|
Node& node = mNodes[nodeId];
|
||||||
|
|
@ -460,22 +469,29 @@ namespace vcg {
|
||||||
dim = diag.Y() > diag.Z() ? 1 : 2;
|
dim = diag.Y() > diag.Z() ? 1 : 2;
|
||||||
|
|
||||||
node.dim = dim;
|
node.dim = dim;
|
||||||
//we divide the bounding box in 2 partitions, considering the average of the "dim" dimension
|
if (isBalanced) //we divide the points using the median value along the "dim" dimension
|
||||||
|
{
|
||||||
|
std::vector<Scalar> tempVector;
|
||||||
|
for (unsigned int i = start + 1; i < end; ++i)
|
||||||
|
tempVector.push_back(mPoints[i][dim]);
|
||||||
|
std::sort(tempVector.begin(), tempVector.end());
|
||||||
|
node.splitValue = (tempVector[tempVector.size() / 2.0] + tempVector[tempVector.size() / 2.0 + 1]) / 2.0;
|
||||||
|
}
|
||||||
|
else //we divide the bounding box in 2 partitions, considering the average of the "dim" dimension
|
||||||
node.splitValue = Scalar(0.5*(aabb.max[dim] + aabb.min[dim]));
|
node.splitValue = Scalar(0.5*(aabb.max[dim] + aabb.min[dim]));
|
||||||
|
|
||||||
//midId is the index of the first element in the second partition
|
//midId is the index of the first element in the second partition
|
||||||
unsigned int midId = split(start, end, dim, node.splitValue);
|
unsigned int midId = split(start, end, dim, node.splitValue);
|
||||||
|
|
||||||
|
|
||||||
node.firstChildId = mNodes.size();
|
node.firstChildId = mNodes.size();
|
||||||
mNodes.resize(mNodes.size() + 2);
|
mNodes.resize(mNodes.size() + 2);
|
||||||
|
bool flag = (midId == start) || (midId == end);
|
||||||
int leftLevel, rightLevel;
|
int leftLevel, rightLevel;
|
||||||
|
|
||||||
{
|
{
|
||||||
// left child
|
// left child
|
||||||
unsigned int childId = mNodes[nodeId].firstChildId;
|
unsigned int childId = mNodes[nodeId].firstChildId;
|
||||||
Node& child = mNodes[childId];
|
Node& child = mNodes[childId];
|
||||||
if (midId - start <= targetCellSize || level>=targetMaxDepth)
|
if (flag || (midId - start) <= targetCellSize || level >= targetMaxDepth)
|
||||||
{
|
{
|
||||||
child.leaf = 1;
|
child.leaf = 1;
|
||||||
child.start = start;
|
child.start = start;
|
||||||
|
|
@ -485,7 +501,7 @@ namespace vcg {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
child.leaf = 0;
|
child.leaf = 0;
|
||||||
leftLevel = createTree(childId, start, midId, level+1, targetCellSize, targetMaxDepth);
|
leftLevel = createTree(childId, start, midId, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -493,7 +509,7 @@ namespace vcg {
|
||||||
// right child
|
// right child
|
||||||
unsigned int childId = mNodes[nodeId].firstChildId + 1;
|
unsigned int childId = mNodes[nodeId].firstChildId + 1;
|
||||||
Node& child = mNodes[childId];
|
Node& child = mNodes[childId];
|
||||||
if (end - midId <= targetCellSize || level>=targetMaxDepth)
|
if (flag || (end - midId) <= targetCellSize || level >= targetMaxDepth)
|
||||||
{
|
{
|
||||||
child.leaf = 1;
|
child.leaf = 1;
|
||||||
child.start = midId;
|
child.start = midId;
|
||||||
|
|
@ -503,13 +519,14 @@ namespace vcg {
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
child.leaf = 0;
|
child.leaf = 0;
|
||||||
rightLevel = createTree(childId, midId, end, level+1, targetCellSize, targetMaxDepth);
|
rightLevel = createTree(childId, midId, end, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (leftLevel > rightLevel)
|
if (leftLevel > rightLevel)
|
||||||
return leftLevel;
|
return leftLevel;
|
||||||
return rightLevel;
|
return rightLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue