mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Added ArrayWrapper and BoundingBoxTree to VizFwk
This commit is contained in:
parent
a9140ca894
commit
c608376c4e
@ -10,6 +10,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}")
|
||||
set(CEE_HEADER_FILES
|
||||
cvfArray.h
|
||||
cvfArray.inl
|
||||
cvfArrayWrapperConst.h
|
||||
cvfArrayWrapperToEdit.h
|
||||
cvfAssert.h
|
||||
cvfBase.h
|
||||
cvfBase64.h
|
||||
|
@ -229,6 +229,8 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cvfArray.h" />
|
||||
<ClInclude Include="cvfArrayWrapperConst.h" />
|
||||
<ClInclude Include="cvfArrayWrapperToEdit.h" />
|
||||
<ClInclude Include="cvfAssert.h" />
|
||||
<ClInclude Include="cvfBase.h" />
|
||||
<ClInclude Include="cvfBase64.h" />
|
||||
|
@ -42,6 +42,8 @@
|
||||
<ClInclude Include="cvfLogDestination.h" />
|
||||
<ClInclude Include="cvfLogDestinationConsole.h" />
|
||||
<ClInclude Include="cvfLogDestinationFile.h" />
|
||||
<ClInclude Include="cvfArrayWrapperConst.h" />
|
||||
<ClInclude Include="cvfArrayWrapperToEdit.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cvfArray.inl" />
|
||||
|
153
Fwk/VizFwk/LibCore/cvfArrayWrapperConst.h
Normal file
153
Fwk/VizFwk/LibCore/cvfArrayWrapperConst.h
Normal file
@ -0,0 +1,153 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \class cvf::ArrayWrapperConst
|
||||
/// \ingroup Core
|
||||
///
|
||||
/// A wrapper class for const access to make it possible to use different array types with
|
||||
/// different element types in the same algorithms.
|
||||
///
|
||||
/// The implementation has a specialization for bare pointer arrays.
|
||||
/// The reason for the bare pointer specialization is the [] access implementation
|
||||
/// which is different. (*array)[] vs array[]
|
||||
///
|
||||
/// The convenience functions wrapArrayConst() are available to simplify wrapping of your data making it
|
||||
/// possible to do:
|
||||
/// myFunction (wrapArrayConst(myNodeArray), wrapArrayConst(myIndexArray), ...);
|
||||
/// when calling a template function using ArrayWrapperConst's as input.
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template < typename ArrayType, typename ElmType >
|
||||
class ArrayWrapperConst
|
||||
{
|
||||
public:
|
||||
ArrayWrapperConst(const ArrayType* array, size_t size) : m_array(array), m_size(size) { }
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
inline const ElmType& operator[] (const size_t index) const { return (*m_array)[index]; }
|
||||
|
||||
private:
|
||||
const ArrayType * m_array;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Const bare-pointer array wrapper specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template < typename ElmType >
|
||||
class ArrayWrapperConst <const ElmType*, ElmType>
|
||||
{
|
||||
public:
|
||||
ArrayWrapperConst(const ElmType* array, size_t size) : m_array(array), m_size(size) { }
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
|
||||
inline const ElmType& operator[](const size_t index) const { return m_array[index]; }
|
||||
|
||||
private:
|
||||
const ElmType * m_array;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include <vector>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// const cvf::Array specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const cvf::Array<ElmType>, ElmType > wrapArrayConst(const cvf::Array<ElmType>* array )
|
||||
{
|
||||
const ArrayWrapperConst<const cvf::Array<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const cvf::Array<ElmType>, ElmType > wrapArrayConst( cvf::Array<ElmType>* array )
|
||||
{
|
||||
const ArrayWrapperConst<const cvf::Array<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// const std::vector specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const std::vector<ElmType>, ElmType > wrapArrayConst( const std::vector<ElmType>* array )
|
||||
{
|
||||
const ArrayWrapperConst< const std::vector<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const std::vector<ElmType>, ElmType > wrapArrayConst( std::vector<ElmType>* array )
|
||||
{
|
||||
const ArrayWrapperConst< const std::vector<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// const Bare-pointer specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const ElmType*, ElmType > wrapArrayConst( const ElmType* array, size_t size )
|
||||
{
|
||||
const ArrayWrapperConst<const ElmType*, ElmType> warr(array, size);
|
||||
return warr;
|
||||
}
|
||||
|
||||
|
||||
template <typename ElmType>
|
||||
inline const ArrayWrapperConst< const ElmType*, ElmType > wrapArrayConst( ElmType* array, size_t size )
|
||||
{
|
||||
const ArrayWrapperConst<const ElmType*, ElmType> warr(array, size);
|
||||
return warr;
|
||||
}
|
||||
|
||||
}
|
132
Fwk/VizFwk/LibCore/cvfArrayWrapperToEdit.h
Normal file
132
Fwk/VizFwk/LibCore/cvfArrayWrapperToEdit.h
Normal file
@ -0,0 +1,132 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \class cvf::ArrayWrapperToEdit
|
||||
/// \ingroup Core
|
||||
///
|
||||
/// A wrapper class to make it possible to use different array types with
|
||||
/// different element types in the same algorithms.
|
||||
///
|
||||
/// The implementation has a specialization for bare pointer arrays.
|
||||
/// The reason for the bare pointer specialization is the [] access implementation
|
||||
/// which is different. (*array)[] vs array[]
|
||||
///
|
||||
/// The convenience functions wrapArrayToEdit() are available to simplify wrapping of your data making it
|
||||
/// possible to do:
|
||||
/// myFunction (wrapArrayToEdit(myNodeArray), wrapArrayToEdit(myIndexArray), ...);
|
||||
/// when calling a template function using ArrayWrapperToEdit's as input.
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template < typename ArrayType, typename ElmType >
|
||||
class ArrayWrapperToEdit
|
||||
{
|
||||
public:
|
||||
ArrayWrapperToEdit(ArrayType* array, size_t size) : m_array(array), m_size(size) { }
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
|
||||
inline ElmType& operator[](const size_t index) { return (*m_array)[index]; }
|
||||
inline const ElmType& operator[](const size_t index) const { return (*m_array)[index]; }
|
||||
|
||||
private:
|
||||
ArrayType * m_array;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Bare-pointer array wrapper specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template < typename ElmType >
|
||||
class ArrayWrapperToEdit <ElmType*, ElmType>
|
||||
{
|
||||
public:
|
||||
ArrayWrapperToEdit(ElmType* array, size_t size) : m_array(array), m_size(size) { }
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
|
||||
inline ElmType& operator[](const size_t index) { return m_array[index]; }
|
||||
inline const ElmType& operator[](const size_t index) const { return m_array[index]; }
|
||||
|
||||
private:
|
||||
ElmType * m_array;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
|
||||
#include "cvfArray.h"
|
||||
#include <vector>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// cvf::Array specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
template <typename ElmType>
|
||||
inline ArrayWrapperToEdit< cvf::Array<ElmType>, ElmType > wrapArrayToEdit(cvf::Array<ElmType>* array )
|
||||
{
|
||||
ArrayWrapperToEdit<cvf::Array<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// std::vector specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename ElmType>
|
||||
inline ArrayWrapperToEdit< std::vector<ElmType>, ElmType > wrapArrayToEdit(std::vector<ElmType>* array )
|
||||
{
|
||||
ArrayWrapperToEdit<std::vector<ElmType>, ElmType> warr(array, array->size());
|
||||
return warr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Bare-pointer specialization
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename ElmType>
|
||||
inline ArrayWrapperToEdit< ElmType*, ElmType > wrapArrayToEdit(ElmType* array, size_t size )
|
||||
{
|
||||
ArrayWrapperToEdit<ElmType*, ElmType> warr(array, size);
|
||||
return warr;
|
||||
}
|
||||
|
||||
}
|
@ -13,6 +13,7 @@ include_directories(../LibCore)
|
||||
set(CEE_HEADER_FILES
|
||||
cvfArrowGenerator.h
|
||||
cvfBoundingBox.h
|
||||
cvfBoundingBoxTree.h
|
||||
cvfBoxGenerator.h
|
||||
cvfEdgeKey.h
|
||||
cvfFrustum.h
|
||||
@ -34,6 +35,7 @@ cvfVertexWelder.h
|
||||
set(CEE_SOURCE_FILES
|
||||
cvfArrowGenerator.cpp
|
||||
cvfBoundingBox.cpp
|
||||
cvfBoundingBoxTree.cpp
|
||||
cvfBoxGenerator.cpp
|
||||
cvfFrustum.cpp
|
||||
cvfEdgeKey.cpp
|
||||
|
@ -241,6 +241,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="cvfArrowGenerator.h" />
|
||||
<ClInclude Include="cvfBoundingBox.h" />
|
||||
<ClInclude Include="cvfBoundingBoxTree.h" />
|
||||
<ClInclude Include="cvfBoxGenerator.h" />
|
||||
<ClInclude Include="cvfEdgeKey.h" />
|
||||
<ClInclude Include="cvfFrustum.h" />
|
||||
@ -261,6 +262,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cvfArrowGenerator.cpp" />
|
||||
<ClCompile Include="cvfBoundingBox.cpp" />
|
||||
<ClCompile Include="cvfBoundingBoxTree.cpp" />
|
||||
<ClCompile Include="cvfBoxGenerator.cpp" />
|
||||
<ClCompile Include="cvfEdgeKey.cpp" />
|
||||
<ClCompile Include="cvfFrustum.cpp" />
|
||||
|
@ -19,6 +19,7 @@
|
||||
<ClInclude Include="cvfTriangleVertexSplitter.h" />
|
||||
<ClInclude Include="cvfVertexCompactor.h" />
|
||||
<ClInclude Include="cvfTriangleMeshEdgeExtractor.h" />
|
||||
<ClInclude Include="cvfBoundingBoxTree.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
@ -41,5 +42,6 @@
|
||||
<ClCompile Include="cvfTriangleVertexSplitter.cpp" />
|
||||
<ClCompile Include="cvfVertexCompactor.cpp" />
|
||||
<ClCompile Include="cvfTriangleMeshEdgeExtractor.cpp" />
|
||||
<ClCompile Include="cvfBoundingBoxTree.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
974
Fwk/VizFwk/LibGeometry/cvfBoundingBoxTree.cpp
Normal file
974
Fwk/VizFwk/LibGeometry/cvfBoundingBoxTree.cpp
Normal file
@ -0,0 +1,974 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBoundingBoxTree.h"
|
||||
|
||||
#include "cvfLibCore.h"
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfObject.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
|
||||
|
||||
namespace cvf {
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class cvf::BoundingBoxTree
|
||||
/// \ingroup Geometry
|
||||
///
|
||||
/// An axis-aligned bounding-box search tree
|
||||
///
|
||||
/// This class can be used to quickly do an approximate search for geometry using a bounding box.
|
||||
/// The geometry entities to search for must be enclosed in bounding boxes which are inserted
|
||||
/// together with an ID.
|
||||
///
|
||||
/// When intersecting, the ID's or the indexes of the intersected boundingboxes are returned,
|
||||
/// depending on whether explicit id's where supplied.
|
||||
//==================================================================================================
|
||||
|
||||
enum NodeType
|
||||
{
|
||||
AB_UNDEFINED,
|
||||
AB_LEAF,
|
||||
AB_INTERNAL,
|
||||
AB_LEAF_GROUP
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class AABBTreeNode
|
||||
{
|
||||
public:
|
||||
AABBTreeNode();
|
||||
virtual ~AABBTreeNode() {}
|
||||
|
||||
const cvf::BoundingBox& boundingBox() const;
|
||||
void setBoundingBox(const cvf::BoundingBox bb);
|
||||
|
||||
NodeType type() const;
|
||||
|
||||
protected:
|
||||
NodeType m_type;
|
||||
|
||||
private:
|
||||
cvf::BoundingBox m_boundingBox;
|
||||
};
|
||||
|
||||
|
||||
//=================================================================================================================================
|
||||
/// Internal node in the AABB tree. It have at least two child nodes, but can have many more (grand-children etc.). Both the Left
|
||||
/// and right tree node pointes must exist (or else it should be a leaf node).
|
||||
//=================================================================================================================================
|
||||
class AABBTreeNodeInternal : public AABBTreeNode
|
||||
{
|
||||
public:
|
||||
AABBTreeNodeInternal();
|
||||
AABBTreeNodeInternal(AABBTreeNode* left, AABBTreeNode* right);
|
||||
|
||||
void setLeft(AABBTreeNode* left);
|
||||
AABBTreeNode* left();
|
||||
const AABBTreeNode* left() const;
|
||||
|
||||
void setRight(AABBTreeNode* right);
|
||||
AABBTreeNode* right();
|
||||
const AABBTreeNode* right() const;
|
||||
|
||||
private:
|
||||
AABBTreeNode* m_pLeft; ///< Left child of this internal node in the binary AABB tree
|
||||
AABBTreeNode* m_pRight; ///< Right child of this internal node in the binary AABB tree
|
||||
};
|
||||
|
||||
|
||||
//=================================================================================================================================
|
||||
/// Standard leaf node in the AABB tree. The leaf node contains only an index, and the interpretation of this index is depending on
|
||||
/// the type of AABB tree using the node.
|
||||
//=================================================================================================================================
|
||||
class AABBTreeNodeLeaf : public AABBTreeNode
|
||||
{
|
||||
public:
|
||||
AABBTreeNodeLeaf(size_t index);
|
||||
|
||||
size_t index() const;
|
||||
|
||||
private:
|
||||
size_t m_index; ///< An index of the leaf node. The interpretation of this index is depending on which tree the node is in.
|
||||
};
|
||||
|
||||
|
||||
//=================================================================================================================================
|
||||
/// Group leaf node in the AABB tree. The leaf node contains an array with indices, and the interpretation of these are depending on
|
||||
/// the type of AABB tree using the node.
|
||||
//=================================================================================================================================
|
||||
class AABBTreeNodeLeafGroup : public AABBTreeNode
|
||||
{
|
||||
public:
|
||||
AABBTreeNodeLeafGroup();
|
||||
|
||||
size_t addIndex(size_t index);
|
||||
const std::vector<size_t>& indices() const;
|
||||
|
||||
void sort();
|
||||
|
||||
private:
|
||||
std::vector<size_t> m_indices; ///< The interpretation of these indices is depending on which tree the node is in.
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=================================================================================================================================
|
||||
//
|
||||
/// An axis oriented bounding box tree. This is an abstract base class for AABB trees used for searching and intersection testing.
|
||||
/// All classes deriving from this must implement the CreateLeaves() method. This method creates all the leaf nodes in the AABB
|
||||
/// tree and is called as a part of the BuildTree() process.
|
||||
///
|
||||
/// This base class handles the building of the tree with all the internal nodes. It also handles basic intersection and searching,
|
||||
/// but the IntersectLeafLeaf() and IntersectBoxLeaf() methods should be implemented in any tree classes used for intersection
|
||||
/// testing.
|
||||
///
|
||||
/// The Find() method only searches for matches in bounding boxes, and must be reimplemented in the decendant classes for
|
||||
/// accurate testing of leaf nodes when the leaf node properties are known.
|
||||
//=================================================================================================================================
|
||||
class AABBTree : public cvf::Object
|
||||
{
|
||||
public:
|
||||
AABBTree();
|
||||
virtual ~AABBTree();
|
||||
|
||||
|
||||
virtual void free();
|
||||
|
||||
bool buildTree();
|
||||
|
||||
size_t treeSize() const;
|
||||
size_t leavesCount() const;
|
||||
bool boundingBox(cvf::BoundingBox* pBox) const;
|
||||
|
||||
cvf::String treeInfo() const;
|
||||
|
||||
protected:
|
||||
virtual bool createLeaves() = 0;
|
||||
virtual size_t treeNodeSize(const AABBTreeNode* pNode) const;
|
||||
|
||||
virtual AABBTreeNodeLeafGroup* createGroupNode(size_t iStartIdx, size_t iEndIdx);
|
||||
|
||||
void freeThis();
|
||||
void deleteInternalNodes(AABBTreeNode* pNode);
|
||||
|
||||
size_t treeSize(const AABBTreeNode* pNode) const;
|
||||
size_t treeHeight(const AABBTreeNode* pNode, size_t iLevel, size_t* piMin, size_t* piMax) const;
|
||||
void leafBoundingBox(cvf::BoundingBox& pBox, size_t iStartIdx, size_t iEndIdx) const;
|
||||
bool buildTree(AABBTreeNodeInternal* pNode, size_t iFromIdx, size_t iToIdx);
|
||||
|
||||
// Queries
|
||||
bool intersect(const AABBTreeNode* pA, const AABBTreeNode* pB) const;
|
||||
|
||||
|
||||
protected:
|
||||
std::vector<AABBTreeNodeLeaf*> m_ppLeaves;
|
||||
size_t m_iNumLeaves;
|
||||
|
||||
AABBTreeNode* m_pRoot;
|
||||
|
||||
bool m_bUseGroupNodes;
|
||||
size_t m_iGroupLimit;
|
||||
};
|
||||
|
||||
class BoundingBoxTreeImpl : public AABBTree
|
||||
{
|
||||
BoundingBoxTreeImpl() {}
|
||||
|
||||
private:
|
||||
friend BoundingBoxTree;
|
||||
|
||||
bool createLeaves();
|
||||
void findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>& bbIds) const;
|
||||
|
||||
void findIntersections(const cvf::BoundingBox& bb, const AABBTreeNode* node, std::vector<size_t>& indices) const;
|
||||
|
||||
const std::vector<cvf::BoundingBox>* m_boundingBoxes;
|
||||
const std::vector<size_t>* m_optionalBoundingBoxIds;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace cvf {
|
||||
|
||||
using cvf::ref;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int largestComponent(const cvf::Vec3d v)
|
||||
{
|
||||
double maxLength = v.x();
|
||||
int idx = 0;
|
||||
|
||||
if (v.y() > maxLength)
|
||||
{
|
||||
maxLength = v.y();
|
||||
idx = 1;
|
||||
}
|
||||
|
||||
if (v.z() > maxLength)
|
||||
{
|
||||
maxLength = v.z();
|
||||
idx = 2;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
double largestComponent(const cvf::Vec3d v, cvf::uint* largestIndex)
|
||||
{
|
||||
double length = v.x();
|
||||
cvf::uint idx = 0;
|
||||
|
||||
if (v.y() > length)
|
||||
{
|
||||
length = v.y();
|
||||
idx = 1;
|
||||
}
|
||||
|
||||
if (v.z() > length)
|
||||
{
|
||||
length = v.z();
|
||||
idx = 2;
|
||||
}
|
||||
|
||||
if (largestIndex) *largestIndex = idx;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNode::AABBTreeNode()
|
||||
{
|
||||
m_type = AB_UNDEFINED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const cvf::BoundingBox& AABBTreeNode::boundingBox() const
|
||||
{
|
||||
return m_boundingBox;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
NodeType AABBTreeNode::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTreeNode::setBoundingBox(const cvf::BoundingBox bb)
|
||||
{
|
||||
m_boundingBox = bb;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNodeInternal::AABBTreeNodeInternal(AABBTreeNode* left, AABBTreeNode* right)
|
||||
{
|
||||
m_type = AB_INTERNAL;
|
||||
|
||||
CVF_ASSERT(left);
|
||||
CVF_ASSERT(right);
|
||||
|
||||
m_pLeft = left;
|
||||
m_pRight = right;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNodeInternal::AABBTreeNodeInternal()
|
||||
{
|
||||
m_type = AB_INTERNAL;
|
||||
|
||||
m_pLeft = NULL;
|
||||
m_pRight = NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const AABBTreeNode* AABBTreeNodeInternal::left() const
|
||||
{
|
||||
return m_pLeft;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNode* AABBTreeNodeInternal::left()
|
||||
{
|
||||
return m_pLeft;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const AABBTreeNode* AABBTreeNodeInternal::right() const
|
||||
{
|
||||
return m_pRight;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNode* AABBTreeNodeInternal::right()
|
||||
{
|
||||
return m_pRight;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTreeNodeInternal::setLeft(AABBTreeNode* left)
|
||||
{
|
||||
CVF_ASSERT(left);
|
||||
m_pLeft = left;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTreeNodeInternal::setRight(AABBTreeNode* right)
|
||||
{
|
||||
CVF_ASSERT(right);
|
||||
m_pRight = right;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNodeLeaf::AABBTreeNodeLeaf(size_t index)
|
||||
{
|
||||
m_type = AB_LEAF;
|
||||
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTreeNodeLeaf::index() const
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTreeNodeLeafGroup::addIndex(size_t index)
|
||||
{
|
||||
m_indices.push_back(index);
|
||||
|
||||
return m_indices.size() - 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<size_t>& AABBTreeNodeLeafGroup::indices() const
|
||||
{
|
||||
return m_indices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNodeLeafGroup::AABBTreeNodeLeafGroup()
|
||||
{
|
||||
m_type = AB_LEAF_GROUP;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTreeNodeLeafGroup::sort()
|
||||
{
|
||||
std::sort(m_indices.begin(), m_indices.end());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTree::AABBTree()
|
||||
{
|
||||
m_pRoot = NULL;
|
||||
m_iNumLeaves = 0;
|
||||
|
||||
m_bUseGroupNodes = false;
|
||||
m_iGroupLimit = 33;
|
||||
|
||||
// ResetStatistics();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTree::~AABBTree()
|
||||
{
|
||||
freeThis();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTree::free()
|
||||
{
|
||||
freeThis();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool AABBTree::buildTree()
|
||||
{
|
||||
|
||||
// Possibly delete the tree before building it
|
||||
freeThis();
|
||||
|
||||
// First, create all the leaves
|
||||
if (!createLeaves()) return false;
|
||||
|
||||
if (m_iNumLeaves == 0) return true;
|
||||
|
||||
// Then find the bounding box of all items in the tree
|
||||
cvf::BoundingBox box;
|
||||
leafBoundingBox(box, 0, m_iNumLeaves - 1);
|
||||
|
||||
// Create the root
|
||||
if (m_iNumLeaves == 1)
|
||||
{
|
||||
m_pRoot = m_ppLeaves[0];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
m_pRoot = new AABBTreeNodeInternal();
|
||||
m_pRoot->setBoundingBox(box);
|
||||
|
||||
bool bRes = buildTree((AABBTreeNodeInternal*)m_pRoot, 0, m_iNumLeaves - 1);
|
||||
|
||||
return bRes;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool AABBTree::buildTree(AABBTreeNodeInternal* pNode, size_t iFromIdx, size_t iToIdx)
|
||||
{
|
||||
if (!pNode->boundingBox().isValid()) return false;
|
||||
|
||||
int iLongestAxis = largestComponent(pNode->boundingBox().extent());
|
||||
|
||||
double splitValue = pNode->boundingBox().center()[iLongestAxis];
|
||||
size_t i = iFromIdx;
|
||||
size_t iMid = iToIdx;
|
||||
|
||||
//=================================================================================================================================
|
||||
//
|
||||
// Geometric split tree - best!
|
||||
//
|
||||
//=================================================================================================================================
|
||||
// Order the leaves according to the position of the center of each BB in comparison with longest axis of the BB
|
||||
while (i < iMid)
|
||||
{
|
||||
if (!(m_ppLeaves[i]->boundingBox().isValid()) || m_ppLeaves[i]->boundingBox().center()[iLongestAxis] < splitValue)
|
||||
{
|
||||
// Ok, move on
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap, and move iMid back
|
||||
AABBTreeNodeLeaf* pTemp = m_ppLeaves[i];
|
||||
m_ppLeaves[i] = m_ppLeaves[iMid];
|
||||
m_ppLeaves[iMid] = pTemp;
|
||||
|
||||
iMid--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((iMid == iFromIdx) || (iMid == iToIdx))
|
||||
{
|
||||
iMid = (iToIdx + iFromIdx)/2;
|
||||
}
|
||||
|
||||
// Create the left tree
|
||||
if (iMid > iFromIdx)
|
||||
{
|
||||
if (m_bUseGroupNodes && ((iMid - iFromIdx + 1) < m_iGroupLimit))
|
||||
{
|
||||
|
||||
pNode->setLeft(createGroupNode(iFromIdx, iMid));
|
||||
}
|
||||
else
|
||||
{
|
||||
cvf::BoundingBox box;
|
||||
leafBoundingBox(box, iFromIdx, iMid);
|
||||
|
||||
AABBTreeNodeInternal* newNode = new AABBTreeNodeInternal;
|
||||
newNode->setBoundingBox(box);
|
||||
pNode->setLeft(newNode);
|
||||
|
||||
if (!buildTree((AABBTreeNodeInternal*)pNode->left(), iFromIdx, iMid)) return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pNode->setLeft(m_ppLeaves[iFromIdx]);
|
||||
}
|
||||
|
||||
// Create the right tree
|
||||
if (iMid < (iToIdx - 1))
|
||||
{
|
||||
if (m_bUseGroupNodes && ((iToIdx - (iMid + 1) + 1) < m_iGroupLimit))
|
||||
{
|
||||
pNode->setRight(createGroupNode(iMid + 1, iToIdx));
|
||||
}
|
||||
else
|
||||
{
|
||||
cvf::BoundingBox box;
|
||||
leafBoundingBox(box, iMid + 1, iToIdx);
|
||||
|
||||
AABBTreeNodeInternal* newNode = new AABBTreeNodeInternal;
|
||||
newNode->setBoundingBox(box);
|
||||
pNode->setRight(newNode);
|
||||
|
||||
if (!buildTree((AABBTreeNodeInternal*)pNode->right(), iMid + 1, iToIdx)) return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pNode->setRight(m_ppLeaves[iToIdx]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTree::freeThis()
|
||||
{
|
||||
// Delete all the internal nodes
|
||||
if (m_pRoot)
|
||||
{
|
||||
// This also deletes m_pRoot if not a leaf. If it is a leaf, it is deleted below
|
||||
deleteInternalNodes(m_pRoot);
|
||||
|
||||
m_pRoot = NULL;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < m_iNumLeaves; i++)
|
||||
{
|
||||
// Might be NULL if group nodes are used
|
||||
if (m_ppLeaves[i])
|
||||
{
|
||||
delete(m_ppLeaves[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_ppLeaves.clear();
|
||||
|
||||
m_iNumLeaves = 0;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTree::deleteInternalNodes(AABBTreeNode* pNode)
|
||||
{
|
||||
CVF_ASSERT(pNode);
|
||||
|
||||
if (pNode->type() == AB_LEAF) return;
|
||||
|
||||
if (pNode->type() == AB_LEAF_GROUP)
|
||||
{
|
||||
delete(pNode);
|
||||
return;
|
||||
}
|
||||
|
||||
AABBTreeNodeInternal* pInt = (AABBTreeNodeInternal*)pNode;
|
||||
|
||||
deleteInternalNodes(pInt->left());
|
||||
deleteInternalNodes(pInt->right());
|
||||
|
||||
delete(pNode);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
AABBTreeNodeLeafGroup* AABBTree::createGroupNode(size_t iStartIdx, size_t iEndIdx)
|
||||
{
|
||||
size_t iNumItems = iEndIdx - iStartIdx + 1;
|
||||
CVF_ASSERT(iNumItems > 1);
|
||||
|
||||
AABBTreeNodeLeafGroup* pNode = new AABBTreeNodeLeafGroup;
|
||||
if (!pNode) return NULL;
|
||||
|
||||
cvf::BoundingBox bb;
|
||||
leafBoundingBox(bb, iStartIdx, iEndIdx);
|
||||
pNode->setBoundingBox(bb);
|
||||
|
||||
size_t i;
|
||||
for (i = iStartIdx; i <= iEndIdx; i++)
|
||||
{
|
||||
pNode->addIndex(m_ppLeaves[i]->index());
|
||||
|
||||
// Delete the original leaf
|
||||
delete(m_ppLeaves[i]);
|
||||
|
||||
m_ppLeaves[i] = NULL;
|
||||
}
|
||||
|
||||
// Sort the element indices (this is not really required)
|
||||
// This is done to give then same result as the old implementation that did just a linear search in cases where
|
||||
// the points are on the element surfaces and thus will give multiple hits.
|
||||
//
|
||||
// The performance hit of this seems very small.
|
||||
pNode->sort();
|
||||
|
||||
return pNode;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void AABBTree::leafBoundingBox(cvf::BoundingBox& bb, size_t iStartIdx, size_t iEndIdx) const
|
||||
{
|
||||
CVF_ASSERT(iStartIdx <= iEndIdx);
|
||||
|
||||
bb.reset();
|
||||
|
||||
size_t i;
|
||||
for (i = iStartIdx; i <= iEndIdx; i++)
|
||||
{
|
||||
CVF_ASSERT(m_ppLeaves[i]);
|
||||
bb.add(m_ppLeaves[i]->boundingBox());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTree::treeSize(const AABBTreeNode* pNode) const
|
||||
{
|
||||
CVF_ASSERT(pNode);
|
||||
|
||||
if (pNode->type() == AB_LEAF)
|
||||
{
|
||||
return treeNodeSize(pNode);
|
||||
}
|
||||
|
||||
if (pNode->type() == AB_LEAF_GROUP)
|
||||
{
|
||||
return treeNodeSize(pNode);
|
||||
}
|
||||
|
||||
const AABBTreeNodeInternal* pInt = (const AABBTreeNodeInternal*)pNode;
|
||||
|
||||
return treeNodeSize(pInt) + treeSize(pInt->left()) + treeSize(pInt->right());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTree::treeSize() const
|
||||
{
|
||||
if (m_pRoot) return treeSize(m_pRoot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTree::treeNodeSize(const AABBTreeNode* pNode) const
|
||||
{
|
||||
CVF_ASSERT(pNode);
|
||||
|
||||
if (pNode->type() == AB_INTERNAL) return sizeof(AABBTreeNodeInternal);
|
||||
if (pNode->type() == AB_LEAF) return sizeof(AABBTreeNodeLeaf);
|
||||
if (pNode->type() == AB_LEAF_GROUP)
|
||||
{
|
||||
const AABBTreeNodeLeafGroup* pLeafGroup = (const AABBTreeNodeLeafGroup*)pNode;
|
||||
|
||||
return static_cast<size_t>(sizeof(AABBTreeNodeLeafGroup) + static_cast<size_t>(pLeafGroup->indices().size()) * sizeof(cvf::uint));
|
||||
}
|
||||
|
||||
// Should not get here...
|
||||
CVF_ASSERT(0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTree::treeHeight(const AABBTreeNode* pNode, size_t iLevel, size_t* piMin, size_t* piMax) const
|
||||
{
|
||||
CVF_ASSERT(pNode);
|
||||
|
||||
if ((pNode->type() == AB_LEAF) || (pNode->type() == AB_LEAF_GROUP))
|
||||
{
|
||||
if (iLevel < *piMin) *piMin = iLevel;
|
||||
if (iLevel > *piMax) *piMax = iLevel;
|
||||
|
||||
return iLevel;
|
||||
}
|
||||
|
||||
const AABBTreeNodeInternal* pInt = (const AABBTreeNodeInternal*)pNode;
|
||||
|
||||
iLevel++;
|
||||
|
||||
return treeHeight(pInt->left(), iLevel, piMin, piMax) + treeHeight(pInt->right(), iLevel, piMin, piMax);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::String AABBTree::treeInfo() const
|
||||
{
|
||||
cvf::String sInfo;
|
||||
|
||||
sInfo = cvf::String("Tree size: %1 \n").arg(static_cast<int>(treeSize()));
|
||||
sInfo += cvf::String("Num leaves: %1 \n").arg(static_cast<int>(leavesCount()));
|
||||
|
||||
size_t iMin = cvf::UNDEFINED_UINT;
|
||||
size_t iMax = 0;
|
||||
size_t iSumHeight = treeHeight(m_pRoot, 1, &iMin, &iMax);
|
||||
size_t iAvgHeigth = 0;
|
||||
size_t iIdealHeigth = 0;
|
||||
|
||||
if (leavesCount() > 0 ) iAvgHeigth = iSumHeight/leavesCount();
|
||||
|
||||
//sInfo += VTString::MakeForm("Tree height: Min: %d - Max: %d - Avg: %d - Ideal: %d\n", iMin, iMax, iAvgHeigth, (VTint)ceil((log((VTfloat)GetNumLeaves())/log(2.0f))));
|
||||
iIdealHeigth = (cvf::uint)ceil((log((float)leavesCount())/log(2.0f)));
|
||||
//sInfo = cvf::String("Tree height: Min: %1 - Max: %2 - Avg: %3 - Ideal: %4\n").arg(iMin).arg(iMax).arg(iAvgHeigth).arg(iIdealHeigth);
|
||||
|
||||
cvf::BoundingBox bb;
|
||||
boundingBox(&bb);
|
||||
sInfo += bb.debugString();
|
||||
|
||||
return sInfo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool AABBTree::boundingBox(cvf::BoundingBox* pBox) const
|
||||
{
|
||||
CVF_ASSERT(pBox);
|
||||
|
||||
if (!m_pRoot) return false;
|
||||
|
||||
*pBox = m_pRoot->boundingBox();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t AABBTree::leavesCount() const
|
||||
{
|
||||
return m_iNumLeaves;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool AABBTree::intersect(const AABBTreeNode* pA, const AABBTreeNode* pB) const
|
||||
{
|
||||
return pA->boundingBox().intersects(pB->boundingBox());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Creates leafs for the supplied valid bounding boxes, keeping the original index
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool BoundingBoxTreeImpl::createLeaves()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < m_boundingBoxes->size(); i++)
|
||||
{
|
||||
if (!(*m_boundingBoxes)[i].isValid()) continue;
|
||||
size_t bbId = i;
|
||||
if (m_optionalBoundingBoxIds) bbId = (*m_optionalBoundingBoxIds)[i];
|
||||
|
||||
AABBTreeNodeLeaf* leaf = new AABBTreeNodeLeaf(bbId);
|
||||
|
||||
leaf->setBoundingBox((*m_boundingBoxes)[i]);
|
||||
|
||||
m_ppLeaves.push_back(leaf);
|
||||
}
|
||||
|
||||
m_iNumLeaves = m_ppLeaves.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Find all indices to all bounding boxes intersecting the given bounding box and add them to indices
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>& indices) const
|
||||
{
|
||||
if (bb.isValid())
|
||||
{
|
||||
findIntersections(bb, m_pRoot, indices);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBoxTreeImpl::findIntersections(const cvf::BoundingBox& bb, const AABBTreeNode* node, std::vector<size_t>& cvIndices) const
|
||||
{
|
||||
CVF_TIGHT_ASSERT(bb.isValid());
|
||||
|
||||
if (node && bb.intersects(node->boundingBox()))
|
||||
{
|
||||
if (node->type() == AB_LEAF)
|
||||
{
|
||||
const AABBTreeNodeLeaf* leaf = static_cast<const AABBTreeNodeLeaf*>(node);
|
||||
{
|
||||
cvIndices.push_back(leaf->index());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (node->type() == AB_INTERNAL)
|
||||
{
|
||||
const AABBTreeNodeInternal* internalNode = static_cast<const AABBTreeNodeInternal*>(node);
|
||||
|
||||
findIntersections(bb, internalNode->left(), cvIndices);
|
||||
findIntersections(bb, internalNode->right(), cvIndices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBoxTree::BoundingBoxTree()
|
||||
{
|
||||
m_implTree = new BoundingBoxTreeImpl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
BoundingBoxTree::~BoundingBoxTree()
|
||||
{
|
||||
delete m_implTree;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Build a tree representation of valid bounding boxes. Invalid bounding boxes are ignored
|
||||
/// The supplied ID array is the ID's returned in the intersection method.
|
||||
/// If the ID array is omitted, the index of the bounding boxes are returned.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBoxTree::buildTreeFromBoundingBoxes(const std::vector<cvf::BoundingBox>& boundingBoxes,
|
||||
const std::vector<size_t>* optionalBoundingBoxIds)
|
||||
{
|
||||
if (optionalBoundingBoxIds) CVF_ASSERT(boundingBoxes.size() == optionalBoundingBoxIds->size());
|
||||
|
||||
m_implTree->m_boundingBoxes = &boundingBoxes;
|
||||
m_implTree->m_optionalBoundingBoxIds = optionalBoundingBoxIds;
|
||||
|
||||
m_implTree->buildTree();
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Find all indices to all bounding boxes intersecting the given bounding box and add them to indices
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void BoundingBoxTree::findIntersections(const cvf::BoundingBox& bb, std::vector<size_t>* bbIdsOrIndices) const
|
||||
{
|
||||
CVF_ASSERT(bbIdsOrIndices);
|
||||
|
||||
m_implTree->findIntersections(bb, *bbIdsOrIndices);
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
|
69
Fwk/VizFwk/LibGeometry/cvfBoundingBoxTree.h
Normal file
69
Fwk/VizFwk/LibGeometry/cvfBoundingBoxTree.h
Normal file
@ -0,0 +1,69 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfObject.h"
|
||||
#include "cvfBoundingBox.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
class BoundingBoxTreeImpl;
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// An axis-aligned bounding-box search tree class
|
||||
//
|
||||
//==================================================================================================
|
||||
class BoundingBoxTree : public cvf::Object
|
||||
{
|
||||
public:
|
||||
BoundingBoxTree();
|
||||
~BoundingBoxTree();
|
||||
|
||||
void buildTreeFromBoundingBoxes(const std::vector<cvf::BoundingBox>& boundingBoxes,
|
||||
const std::vector<size_t>* optionalBoundingBoxIds);
|
||||
|
||||
void findIntersections(const cvf::BoundingBox& inputBB, std::vector<size_t>* bbIdsOrIndexesIntersected) const;
|
||||
|
||||
private:
|
||||
|
||||
BoundingBoxTreeImpl* m_implTree;
|
||||
};
|
||||
|
||||
} // Namespace cvf
|
||||
|
@ -13,6 +13,7 @@ set(CEE_LIBS LibCore)
|
||||
|
||||
set(CEE_SOURCE_FILES
|
||||
cvfArray-Test.cpp
|
||||
cvfArrayWrapper-Test.cpp
|
||||
cvfBase-Test.cpp
|
||||
cvfBase64-Test.cpp
|
||||
cvfCharArray-Test.cpp
|
||||
|
@ -250,6 +250,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\ThirdParty\gtest\gtest-all.cpp" />
|
||||
<ClCompile Include="cvfArray-Test.cpp" />
|
||||
<ClCompile Include="cvfArrayWrapper-Test.cpp" />
|
||||
<ClCompile Include="cvfBase-Test.cpp" />
|
||||
<ClCompile Include="cvfBase64-Test.cpp" />
|
||||
<ClCompile Include="cvfCharArray-Test.cpp" />
|
||||
|
@ -32,6 +32,7 @@
|
||||
<ClCompile Include="cvfLogger-Test.cpp" />
|
||||
<ClCompile Include="cvfLogEvent-Test.cpp" />
|
||||
<ClCompile Include="cvfCodeLocation-Test.cpp" />
|
||||
<ClCompile Include="cvfArrayWrapper-Test.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
187
Fwk/VizFwk/Tests/LibCore_UnitTests/cvfArrayWrapper-Test.cpp
Normal file
187
Fwk/VizFwk/Tests/LibCore_UnitTests/cvfArrayWrapper-Test.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
|
||||
#include "cvfBase.h"
|
||||
#include "cvfArray.h"
|
||||
#include "cvfArrayWrapperToEdit.h"
|
||||
#include "cvfArrayWrapperConst.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace cvf;
|
||||
|
||||
|
||||
|
||||
template <typename ArrayType, typename ElmType>
|
||||
void arrayWrapperConstTestFunction(const ArrayWrapperConst< ArrayType, ElmType> cinRefArray)
|
||||
{
|
||||
ElmType e;
|
||||
size_t size;
|
||||
|
||||
size = cinRefArray.size();
|
||||
e = cinRefArray[size-1];
|
||||
// cinRefArray[size-1] = e;
|
||||
{
|
||||
const ElmType& cre = cinRefArray[size-1];
|
||||
CVF_UNUSED(cre);
|
||||
|
||||
//ElmType& re = cinRefArray[size-1];
|
||||
//re = e;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArrayType, typename ElmType>
|
||||
void arrayWrapperConstRefTestFunction(const ArrayWrapperConst< ArrayType, ElmType>& cinRefArray)
|
||||
{
|
||||
ElmType e;
|
||||
size_t size;
|
||||
|
||||
size = cinRefArray.size();
|
||||
e = cinRefArray[size-1];
|
||||
// cinRefArray[size-1] = e;
|
||||
{
|
||||
const ElmType& cre = cinRefArray[size-1];
|
||||
CVF_UNUSED(cre);
|
||||
//ElmType& re = cinRefArray[size-1];
|
||||
//re = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename ArrayType, typename ElmType>
|
||||
void arrayWrapperTestFunction(ArrayWrapperToEdit< ArrayType, ElmType> cinRefArray)
|
||||
{
|
||||
ElmType e, e2;
|
||||
size_t size;
|
||||
|
||||
size = cinRefArray.size();
|
||||
e = cinRefArray[size-1];
|
||||
e2 = cinRefArray[0];
|
||||
cinRefArray[0] = e;
|
||||
{
|
||||
const ElmType& cre = cinRefArray[size-1];
|
||||
CVF_UNUSED(cre);
|
||||
ElmType& re = cinRefArray[size-1];
|
||||
re = e2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(ArrayWrapperTest, AllSpecializations)
|
||||
{
|
||||
std::vector<cvf::Vec3d> vec3dStdVector;
|
||||
vec3dStdVector.push_back(Vec3d::ZERO);
|
||||
vec3dStdVector.push_back(Vec3d(1,1,1));
|
||||
|
||||
const std::vector<cvf::Vec3d> &cvec3dStdVector = vec3dStdVector;
|
||||
|
||||
cvf::Vec3dArray vec3dCvfArray(vec3dStdVector);
|
||||
const cvf::Vec3dArray& cvec3dCvfArray = vec3dCvfArray;
|
||||
|
||||
cvf::Array<size_t> siztCvfArray(2);
|
||||
siztCvfArray[0] = 0;
|
||||
siztCvfArray[1] = 1;
|
||||
|
||||
cvf::Array<uint> uintCvfArray(2);
|
||||
uintCvfArray[0] = 0;
|
||||
uintCvfArray[1] = 1;
|
||||
const cvf::Array<uint>& cuintCvfArray = uintCvfArray;
|
||||
|
||||
size_t siztBarePtrArray[2] = {0, 1};
|
||||
|
||||
size_t* siztBarePtr = new size_t[2];
|
||||
siztBarePtr[0] = 0;
|
||||
siztBarePtr[1] = 1;
|
||||
|
||||
const size_t* csiztBarePtr = siztBarePtr;
|
||||
|
||||
cvf::uint* uintBarePtr = new cvf::uint[2];
|
||||
uintBarePtr[0] = 0;
|
||||
uintBarePtr[1] = 1;
|
||||
|
||||
double* doubleBarePtr = new double[2];
|
||||
doubleBarePtr[0] = 0;
|
||||
doubleBarePtr[1] = 1;
|
||||
const double* cdoubleBarePtr = doubleBarePtr;
|
||||
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&vec3dStdVector));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&cvec3dStdVector));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&vec3dCvfArray));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&cvec3dCvfArray));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&uintCvfArray));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(&cuintCvfArray));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(siztBarePtrArray, 2));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(siztBarePtr, 2));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(csiztBarePtr, 2));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(doubleBarePtr,2));
|
||||
arrayWrapperConstTestFunction(wrapArrayConst(cdoubleBarePtr, 2));
|
||||
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&vec3dStdVector));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&cvec3dStdVector));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&vec3dCvfArray));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&cvec3dCvfArray));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&uintCvfArray));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(&cuintCvfArray));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(siztBarePtrArray, 2));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(siztBarePtr, 2));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(csiztBarePtr, 2));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(doubleBarePtr,2));
|
||||
arrayWrapperConstRefTestFunction(wrapArrayConst(cdoubleBarePtr, 2));
|
||||
|
||||
arrayWrapperTestFunction(wrapArrayToEdit(&vec3dStdVector));
|
||||
//arrayWrapperTestFunction3(wrapArray(&cvec3dStdVector));
|
||||
EXPECT_EQ(Vec3d::ZERO, vec3dStdVector[1]);
|
||||
EXPECT_EQ(Vec3d(1,1,1), vec3dStdVector[0]);
|
||||
|
||||
arrayWrapperTestFunction(wrapArrayToEdit(&vec3dCvfArray));
|
||||
EXPECT_EQ(Vec3d::ZERO, vec3dCvfArray[1]);
|
||||
EXPECT_EQ(Vec3d(1,1,1), vec3dStdVector[0]);
|
||||
//arrayWrapperTestFunction3(wrapArray(&cvec3dCvfArray));
|
||||
arrayWrapperTestFunction(wrapArrayToEdit(&uintCvfArray));
|
||||
//arrayWrapperTestFunction3(wrapArray(&cuintCvfArray));
|
||||
arrayWrapperTestFunction(wrapArrayToEdit(siztBarePtrArray, 2));
|
||||
//arrayWrapperTestFunction3(wrapArray(csiztBarePtr, 2));
|
||||
arrayWrapperTestFunction(wrapArrayToEdit(doubleBarePtr,2));
|
||||
//arrayWrapperTestFunction3(wrapArray(cdoubleBarePtr, 2));
|
||||
EXPECT_EQ(0.0, doubleBarePtr[1]);
|
||||
EXPECT_EQ(1.0, doubleBarePtr[0]);
|
||||
}
|
@ -15,6 +15,7 @@ set(CEE_LIBS LibGeometry LibCore)
|
||||
set(CEE_SOURCE_FILES
|
||||
cvfArrowGenerator-Test.cpp
|
||||
cvfBoundingBox-Test.cpp
|
||||
cvfBoundingBoxTree-Test.cpp
|
||||
cvfBoxGenerator-Test.cpp
|
||||
cvfFrustum-Test.cpp
|
||||
cvfEdgeKey-Test.cpp
|
||||
|
@ -251,6 +251,7 @@
|
||||
<ClCompile Include="..\..\ThirdParty\gtest\gtest-all.cpp" />
|
||||
<ClCompile Include="cvfArrowGenerator-Test.cpp" />
|
||||
<ClCompile Include="cvfBoundingBox-Test.cpp" />
|
||||
<ClCompile Include="cvfBoundingBoxTree-Test.cpp" />
|
||||
<ClCompile Include="cvfBoxGenerator-Test.cpp" />
|
||||
<ClCompile Include="cvfEdgeKey-Test.cpp" />
|
||||
<ClCompile Include="cvfFrustum-Test.cpp" />
|
||||
|
@ -20,6 +20,7 @@
|
||||
<ClCompile Include="cvfTriangleVertexSplitter-Test.cpp" />
|
||||
<ClCompile Include="cvfVertexCompactor-Test.cpp" />
|
||||
<ClCompile Include="cvfTriangleMeshEdgeExtractor-Test.cpp" />
|
||||
<ClCompile Include="cvfBoundingBoxTree-Test.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -0,0 +1,105 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) Ceetron Solutions AS
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
|
||||
#include "cvfBoundingBoxTree.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace cvf;
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const std::vector<size_t>& array)
|
||||
{
|
||||
for (size_t i = 0; i < array.size(); ++i)
|
||||
{
|
||||
stream << array[i] << " ";
|
||||
}
|
||||
stream << std::endl;
|
||||
return stream;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST(BoundingBoxTree, Intersection)
|
||||
{
|
||||
BoundingBoxTree bbtree;
|
||||
|
||||
std::vector<cvf::BoundingBox> bbs;
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(0,0,0), Vec3d(1,1,1)));
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(1,0,0), Vec3d(2,1,1)));
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(2,0,0), Vec3d(3,1,1)));
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(3,0,0), Vec3d(4,1,1)));
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(4,0,0), Vec3d(5,1,1)));
|
||||
bbs.push_back(cvf::BoundingBox(Vec3d(0.5,0.5,0), Vec3d(5.5,1.5,1)));
|
||||
|
||||
|
||||
std::vector<size_t> ids;
|
||||
ids.push_back(10);
|
||||
ids.push_back(11);
|
||||
ids.push_back(12);
|
||||
ids.push_back(13);
|
||||
ids.push_back(14);
|
||||
ids.push_back(15);
|
||||
|
||||
bbtree.buildTreeFromBoundingBoxes(bbs, &ids);
|
||||
|
||||
{
|
||||
std::vector<size_t> intIds;
|
||||
bbtree.findIntersections(cvf::BoundingBox(Vec3d(0.25,0.25,0.25), Vec3d(4.5,0.4,0.4)), &intIds);
|
||||
size_t numBB = intIds.size();
|
||||
EXPECT_EQ(5, numBB);
|
||||
EXPECT_EQ(intIds[4], 13);
|
||||
//std::cout << intIds;
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<size_t> intIds;
|
||||
bbtree.findIntersections(cvf::BoundingBox(Vec3d(0.25,0.75,0.25), Vec3d(4.5,0.8,0.4)), &intIds);
|
||||
size_t numBB = intIds.size();
|
||||
EXPECT_EQ(6, numBB);
|
||||
EXPECT_EQ(intIds[5], 15);
|
||||
//std::cout << intIds;
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<size_t> intIds;
|
||||
bbtree.findIntersections(cvf::BoundingBox(Vec3d(2,0,0), Vec3d(3,1,1)), &intIds);
|
||||
size_t numBB = intIds.size();
|
||||
EXPECT_EQ(4, numBB);
|
||||
EXPECT_EQ(intIds[0], 11);
|
||||
//std::cout << intIds;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user