2019-01-24 14:38:18 +00:00
|
|
|
|
// This source code is property of the Computer Graphics and Visualization
|
|
|
|
|
// chair of the TU Dresden. Do not distribute!
|
2018-09-06 12:35:43 +00:00
|
|
|
|
// Copyright (C) CGV TU Dresden - All Rights Reserved
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <queue>
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
#include <util/OpenMeshUtils.h>
|
|
|
|
|
#include "Box.h"
|
|
|
|
|
#include "Triangle.h"
|
|
|
|
|
#include "LineSegment.h"
|
|
|
|
|
#include "Point.h"
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Axis aligned bounding volume hierachy data structure.
|
|
|
|
|
*/
|
|
|
|
|
template <typename Primitive>
|
|
|
|
|
class AABBTree
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
public:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
typedef std::vector<Primitive> primitive_list;
|
|
|
|
|
//iterator type pointing inside the primitive list
|
|
|
|
|
typedef typename primitive_list::iterator PrimitiveIterator;
|
|
|
|
|
//const iterator type pointing inside the primitive list
|
|
|
|
|
typedef typename primitive_list::const_iterator const_primitive_iterator;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//abstract base class defining the common interface of all aabb tree node
|
|
|
|
|
class AABBNode
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
protected:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//storage of bounding box assosiated with aabb_node
|
|
|
|
|
Box bounds;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AABBNode()
|
|
|
|
|
{
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode(const Box &b) : bounds(b)
|
|
|
|
|
{
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//returns the bounding box of the node
|
|
|
|
|
Box GetBounds() const
|
|
|
|
|
{
|
|
|
|
|
return bounds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int NumPrimitives() const = 0;
|
|
|
|
|
|
|
|
|
|
//this method must be implemented to return true for a leaf node and false for a non_lef node
|
|
|
|
|
virtual bool IsLeaf() const = 0;
|
|
|
|
|
//virtual destructor
|
|
|
|
|
virtual ~AABBNode() {}
|
|
|
|
|
};
|
|
|
|
|
///a class representing a leaf node of an aabb tree (non split node)
|
2019-01-24 14:38:18 +00:00
|
|
|
|
class AABBLeafNode : public AABBNode
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//internal storage to the range (begin and end pointer) of the primitives associated with the current leaf node
|
|
|
|
|
PrimitiveIterator primitivesBegin, primitivesEnd;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
//construct a leaf node from
|
|
|
|
|
AABBLeafNode(const PrimitiveIterator &primitivesBegin,
|
|
|
|
|
const PrimitiveIterator &primitivesEnd,
|
|
|
|
|
const Box &b) : primitivesBegin(primitivesBegin), primitivesEnd(primitivesEnd), AABBNode(b)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//return always true because its a leaf node
|
|
|
|
|
bool IsLeaf() const
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//returns the number primitives assosiated with the current leaf
|
|
|
|
|
int NumPrimitives() const
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
return (int)(primitivesEnd - primitivesBegin);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const_primitive_iterator begin() const
|
|
|
|
|
{
|
|
|
|
|
return primitivesBegin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const_primitive_iterator end() const
|
|
|
|
|
{
|
|
|
|
|
return primitivesEnd;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///a class representing a split node of an aabb tree (non leaf node)
|
2019-01-24 14:38:18 +00:00
|
|
|
|
class AABBSplitNode : public AABBNode
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
//child pointers
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *children[2];
|
|
|
|
|
|
|
|
|
|
public:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//default constructor
|
|
|
|
|
AABBSplitNode()
|
|
|
|
|
{
|
|
|
|
|
children[0] = children[1] = nullptr;
|
|
|
|
|
}
|
|
|
|
|
//construct a split node from given Left and right child pointers and given bounding box b of the node
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBSplitNode(AABBNode *left_child, AABBNode *right_child, const Box &b) : AABBNode(b)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
children[0] = left_child;
|
|
|
|
|
children[1] = right_child;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//destructor of node, recursively deleted whole subtree
|
|
|
|
|
~AABBSplitNode()
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (Left() != nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
delete Left();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (Right() != nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
delete Right();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//returns always false because its a split node
|
|
|
|
|
bool IsLeaf() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//returns a pointer to the left child node
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *Left()
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return children[0];
|
|
|
|
|
}
|
|
|
|
|
//returns a pointer to the right child node
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *Right()
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return children[1];
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//returns a const pointer to the left child node
|
|
|
|
|
const AABBNode *Left() const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return children[0];
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//returns a const pointer to the right child node
|
|
|
|
|
const AABBNode *Right() const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return children[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//counts the number of primitives of the subtree
|
|
|
|
|
int NumPrimitives() const
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
return Left()->NumPrimitives() + Right()->NumPrimitives();
|
|
|
|
|
}
|
2018-09-06 12:35:43 +00:00
|
|
|
|
};
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
private:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//search entry used internally for nearest and k nearest primitive queries
|
|
|
|
|
struct SearchEntry
|
|
|
|
|
{
|
|
|
|
|
//squared distance to node from query point
|
|
|
|
|
float sqrDistance;
|
|
|
|
|
//node
|
2019-01-24 14:38:18 +00:00
|
|
|
|
const AABBNode *node;
|
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//constructor
|
2019-01-24 14:38:18 +00:00
|
|
|
|
SearchEntry(float sqrDistance, const AABBNode *node)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
: sqrDistance(sqrDistance), node(node)
|
2019-01-24 14:38:18 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//search entry a < b means a.sqr_distance > b. sqr_distance
|
|
|
|
|
bool operator<(const SearchEntry &e) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return sqrDistance > e.sqrDistance;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//result entry for nearest and k nearest primitive queries
|
|
|
|
|
struct ResultEntry
|
|
|
|
|
{
|
|
|
|
|
//squared distance from query point to primitive
|
|
|
|
|
float sqrDistance;
|
|
|
|
|
//pointer to primitive
|
2019-01-24 14:38:18 +00:00
|
|
|
|
const Primitive *prim;
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//default constructor
|
|
|
|
|
ResultEntry()
|
|
|
|
|
: sqrDistance(std::numeric_limits<float>::infinity()), prim(nullptr)
|
2019-01-24 14:38:18 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//constructor
|
2019-01-24 14:38:18 +00:00
|
|
|
|
ResultEntry(float sqrDistance, const Primitive *p)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
: sqrDistance(sqrDistance), prim(p)
|
2019-01-24 14:38:18 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
//result_entry are sorted by their sqr_distance using this less than operator
|
|
|
|
|
bool operator<(const ResultEntry &e) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return sqrDistance < e.sqrDistance;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//list of all primitives in the tree
|
|
|
|
|
primitive_list primitives;
|
|
|
|
|
//maximum allowed tree depth to stop tree construction
|
|
|
|
|
int maxDepth;
|
|
|
|
|
//minimal number of primitives to stop tree construction
|
|
|
|
|
int minSize;
|
|
|
|
|
//pointer to the root node of the tree
|
|
|
|
|
AABBNode *root;
|
|
|
|
|
//a flag indicating if the tree is constructed
|
|
|
|
|
bool completed;
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
public:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//returns a pointer to the root node of the tree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *Root()
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
assert(IsCompleted());
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//returns a const pointer to the root node of the tree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
const AABBNode *Root() const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
assert(IsCompleted());
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//constructor of aabb tree
|
|
|
|
|
//default maximal tree depth is 20
|
|
|
|
|
//default minimal size of a node not to be further subdivided in the cnstruction process is two
|
|
|
|
|
AABBTree(int maxDepth = 20, int minSize = 2) : maxDepth(maxDepth), minSize(minSize), root(nullptr), completed(false)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//copy constructor
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBTree(const AABBTree &other)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
primitives = other.primitives;
|
|
|
|
|
maxDepth = other.maxDepth;
|
|
|
|
|
minSize = other.minSize;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
root = CopyTree(other.primitives, other.root);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
completed = other.completed;
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//move constructor
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBTree(AABBTree &&other) : root(nullptr), completed(false)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
*this = std::move(other);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//copy assignment operator
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBTree &operator=(const AABBTree &other)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (this != &other)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (root != nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
delete root;
|
|
|
|
|
primitives = other.primitives;
|
|
|
|
|
maxDepth = other.maxDepth;
|
|
|
|
|
minSize = other.minSize;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
root = CopyTree(other.primitives, other.root);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
completed = other.completed;
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//move assign operator
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBTree &operator=(AABBTree &&other)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (this != &other)
|
|
|
|
|
{
|
|
|
|
|
std::swap(primitives, other.primitives);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
std::swap(maxDepth, other.maxDepth);
|
|
|
|
|
std::swap(minSize, other.minSize);
|
2019-01-24 14:38:18 +00:00
|
|
|
|
std::swap(root, other.root);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
std::swap(completed, other.completed);
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//remove all primitives from tree
|
|
|
|
|
void Clear()
|
|
|
|
|
{
|
|
|
|
|
primitives.clear();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (root != nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
delete root;
|
|
|
|
|
root = nullptr;
|
|
|
|
|
}
|
|
|
|
|
completed = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//returns true if tree is empty
|
|
|
|
|
bool Empty() const
|
|
|
|
|
{
|
|
|
|
|
return primitives.Empty();
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
//insert a primitive into internal primitive list
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//this method do not construct the tree!
|
|
|
|
|
//call the method Complete, after insertion of all primitives
|
2019-01-24 14:38:18 +00:00
|
|
|
|
void Insert(const Primitive &p)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
primitives.push_back(p);
|
2019-01-24 14:38:18 +00:00
|
|
|
|
completed = false;
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
//construct the tree from all prior inserted primitives
|
2018-09-06 12:35:43 +00:00
|
|
|
|
void Complete()
|
|
|
|
|
{
|
|
|
|
|
//if tree already constructed -> delete tree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (root != nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
delete root;
|
|
|
|
|
//compute bounding box over all primitives using helper function
|
2019-01-24 14:38:18 +00:00
|
|
|
|
Box bounds = ComputeBounds(primitives.begin(), primitives.end());
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//initial call to the recursive tree construction method over the whole range of primitives
|
2019-01-24 14:38:18 +00:00
|
|
|
|
root = Build(primitives.begin(), primitives.end(), bounds, 0);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//set completed flag to true
|
2019-01-24 14:38:18 +00:00
|
|
|
|
completed = true;
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//returns true if the tree can be used for queries
|
|
|
|
|
//if the tree is not completed call the method complete()
|
|
|
|
|
bool IsCompleted() const
|
|
|
|
|
{
|
|
|
|
|
return completed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//closest primitive computation via linear search
|
2019-01-24 14:38:18 +00:00
|
|
|
|
ResultEntry ClosestPrimitiveLinearSearch(const Eigen::Vector3f &q) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
ResultEntry best;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
auto pend = primitives.end();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
for (auto pit = primitives.begin(); pit != pend; ++pit)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
float dist = pit->SqrDistance(q);
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (dist < best.sqrDistance)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
best.sqrDistance = dist;
|
|
|
|
|
best.prim = &(*pit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return best;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-25 08:14:17 +00:00
|
|
|
|
ResultEntry ClosestPrimitiveAABBSearch(const Eigen::Vector3f &q) const{
|
|
|
|
|
AABBNode* node = root;
|
|
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
|
// TODO: dynamic cast to check for leaf- or split-node
|
|
|
|
|
// if split node: check BB of childs
|
|
|
|
|
// -> node = child with shorter distance
|
|
|
|
|
// if leaf node: iterate through primitives
|
|
|
|
|
|
|
|
|
|
if (node->IsLeaf()) {
|
|
|
|
|
AABBLeafNode* leaf_node = dynamic_cast<AABBLeafNode*>(node);
|
|
|
|
|
|
|
|
|
|
if (leaf_node != nullptr) {
|
|
|
|
|
ResultEntry best;
|
|
|
|
|
|
|
|
|
|
for (auto pit = leaf_node->begin(); pit != leaf_node->end(); ++pit)
|
|
|
|
|
{
|
|
|
|
|
float dist = pit->SqrDistance(q);
|
|
|
|
|
if (dist < best.sqrDistance)
|
|
|
|
|
{
|
|
|
|
|
best.sqrDistance = dist;
|
|
|
|
|
best.prim = &(*pit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return best;
|
|
|
|
|
} else {
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
AABBSplitNode* split_node = dynamic_cast<AABBSplitNode*>(node);
|
|
|
|
|
|
|
|
|
|
if (split_node != nullptr) {
|
|
|
|
|
AABBNode* left_child = split_node->Left();
|
|
|
|
|
AABBNode* right_child = split_node->Right();
|
|
|
|
|
|
|
|
|
|
float left_distance = left_child->GetBounds().SqrDistance(q);
|
|
|
|
|
float right_distance = right_child->GetBounds().SqrDistance(q);
|
|
|
|
|
|
|
|
|
|
if (left_distance < right_distance) {
|
|
|
|
|
node = left_child;
|
|
|
|
|
} else {
|
|
|
|
|
node = right_child;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//computes the k nearest neighbor primitives via linear search
|
2019-01-24 14:38:18 +00:00
|
|
|
|
std::vector<ResultEntry> ClosestKPrimitivesLinearSearch(size_t k, const Eigen::Vector3f &q) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
std::priority_queue<ResultEntry> k_best;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
Primitive best_p;
|
|
|
|
|
auto pend = primitives.end();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
for (auto pit = primitives.begin(); pit != pend; ++pit)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
float dist = pit->SqrDistance(q);
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (k_best.size() < k)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
k_best.push(ResultEntry(dist, *pit));
|
2018-10-19 12:40:51 +00:00
|
|
|
|
continue;
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (k_best.top().SqrDistance > dist)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
k_best.pop();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
k_best.push(ResultEntry(dist, *pit));
|
|
|
|
|
}
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
std::vector<ResultEntry> result(k_best.size());
|
|
|
|
|
auto rend = result.end();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
for (auto rit = result.begin(); rit != rend; ++rit)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
*rit = k_best.top();
|
|
|
|
|
k_best.pop();
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
//closest k primitive computation
|
|
|
|
|
std::vector<ResultEntry> ClosestKPrimitives(size_t k, const Eigen::Vector3f &q) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
//student begin
|
2019-01-24 14:38:18 +00:00
|
|
|
|
return ClosestKPrimitivesLinearSearch(k, q);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//student end
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//returns the closest primitive and its squared distance to the point q
|
2019-01-24 14:38:18 +00:00
|
|
|
|
ResultEntry ClosestPrimitive(const Eigen::Vector3f &q) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
assert(IsCompleted());
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (root == nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
return ResultEntry();
|
2019-01-24 22:55:44 +00:00
|
|
|
|
|
2019-01-25 08:14:17 +00:00
|
|
|
|
return ClosestPrimitiveAABBSearch(q);
|
2019-01-24 22:55:44 +00:00
|
|
|
|
|
2019-01-25 08:02:56 +00:00
|
|
|
|
//return ClosestPrimitiveLinearSearch(q);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//return the closest point position on the closest primitive in the tree with respect to the query point q
|
2019-01-24 14:38:18 +00:00
|
|
|
|
Eigen::Vector3f ClosestPoint(const Eigen::Vector3f &p) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
ResultEntry r = ClosestPrimitive(p);
|
2019-01-24 14:38:18 +00:00
|
|
|
|
return r.prim->ClosestPoint(p);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//return the squared distance between point p and the nearest primitive in the tree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
float SqrDistance(const Eigen::Vector3f &p) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
ResultEntry r = ClosestPrimitive(p);
|
|
|
|
|
return r.SqrDistance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//return the euclidean distance between point p and the nearest primitive in the tree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
float Distance(const Eigen::Vector3f &p) const
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
return sqrt(SqrDistance(p));
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
protected:
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//helper function to copy a subtree
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *CopyTree(const primitive_list &other_primitives, AABBNode *node)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (node == nullptr)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
return nullptr;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (node->IsLeaf())
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBLeafNode *leaf = (AABBLeafNode *)node;
|
|
|
|
|
return new AABBLeafNode(primitives.begin() + (leaf->primitives.begin() - other_primitives.begin()),
|
|
|
|
|
primitives.begin() + (leaf->primitives.end() - other_primitives.begin()));
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBSplitNode *split = (AABBSplitNode *)node;
|
|
|
|
|
return new AABBSplitNode(CopyTree(other_primitives, split->Left()),
|
|
|
|
|
CopyTree(other_primitives, split->Right()));
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//helper function to compute an axis aligned bounding box over the range of primitives [begin,end)
|
|
|
|
|
Box ComputeBounds(const_primitive_iterator begin,
|
2019-01-24 14:38:18 +00:00
|
|
|
|
const_primitive_iterator end)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
Box bounds;
|
2019-01-24 14:38:18 +00:00
|
|
|
|
for (auto pit = begin; pit != end; ++pit)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
bounds.Insert(pit->ComputeBounds());
|
|
|
|
|
return bounds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//recursive tree construction initially called from method complete()
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//build an aabb (sub)-tree over the range of primitives [begin,end),
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//the current bounding box is given by bounds and the current tree depth is given by the parameter depth
|
|
|
|
|
//if depth >= max_depth or the number of primitives (end-begin) <= min_size a leaf node is constructed
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//otherwise split node is created
|
|
|
|
|
// to create a split node the range of primitives [begin,end) must be splitted and reordered into two
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//sub ranges [begin,mid) and [mid,end),
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//therefore sort the range of primitives [begin,end) along the largest bounding box extent by its reference
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//point returned by the method ReferencePoint()
|
2019-01-24 14:38:18 +00:00
|
|
|
|
//then choose the median element as mid
|
2018-09-06 12:35:43 +00:00
|
|
|
|
// the STL routine std::nth_element would be very useful here , you only have to provide a ordering predicate
|
|
|
|
|
//compute the boundg boxed of the two resulting sub ranges and recursivly call build on the two subranges
|
|
|
|
|
//the resulting subtree are used as children of the resulting split node.
|
2019-01-24 14:38:18 +00:00
|
|
|
|
AABBNode *Build(PrimitiveIterator begin, PrimitiveIterator end, Box &bounds, int depth)
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
|
|
|
|
if (depth >= maxDepth || end - begin <= minSize)
|
|
|
|
|
{
|
|
|
|
|
return new AABBLeafNode(begin, end, bounds);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Eigen::Vector3f e = bounds.Extents();
|
2019-01-24 14:38:18 +00:00
|
|
|
|
|
2018-09-06 12:35:43 +00:00
|
|
|
|
int axis = 0;
|
|
|
|
|
float max_extent = e[0];
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (max_extent < e[1])
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
axis = 1;
|
|
|
|
|
max_extent = e[1];
|
|
|
|
|
}
|
2019-01-24 14:38:18 +00:00
|
|
|
|
if (max_extent < e[2])
|
2018-09-06 12:35:43 +00:00
|
|
|
|
{
|
|
|
|
|
axis = 2;
|
|
|
|
|
max_extent = e[2];
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
PrimitiveIterator mid = begin + (end - begin) / 2;
|
|
|
|
|
std::nth_element(begin, mid, end, [&axis](const Primitive &a, const Primitive &b) { return a.ReferencePoint()[axis] < b.ReferencePoint()[axis]; });
|
2018-09-06 12:35:43 +00:00
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
Box lbounds = ComputeBounds(begin, mid);
|
|
|
|
|
Box rbounds = ComputeBounds(mid, end);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
|
2019-01-24 14:38:18 +00:00
|
|
|
|
return new AABBSplitNode(Build(begin, mid, lbounds, depth + 1), Build(mid, end, rbounds, depth + 1), bounds);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//helper function to construct an aabb tree data structure from the triangle faces of the halfedge mesh m
|
2019-01-24 14:38:18 +00:00
|
|
|
|
void BuildAABBTreeFromTriangles(const HEMesh &m, AABBTree<Triangle> &tree);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//helper function to construct an aabb tree data structure from the vertices of the halfedge mesh m
|
2019-01-24 14:38:18 +00:00
|
|
|
|
void BuildAABBTreeFromVertices(const HEMesh &m, AABBTree<Point> &tree);
|
2018-09-06 12:35:43 +00:00
|
|
|
|
//helper function to construct an aabb tree data structure from the edges of the halfedge mesh m
|
2019-01-24 14:38:18 +00:00
|
|
|
|
void BuildAABBTreeFromEdges(const HEMesh &m, AABBTree<LineSegment> &tree);
|