mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: split off template-invariant part of indexedOctree node indexing
- code reduction, reinherit for dynamicIndexedOctree ENH: additional OBJ writing, statistics
This commit is contained in:
committed by
Andrew Heather
parent
e5006a62d7
commit
3384747f9b
@ -820,12 +820,14 @@ $(interpolationWeights)/linearInterpolationWeights/linearInterpolationWeights.C
|
|||||||
$(interpolationWeights)/splineInterpolationWeights/splineInterpolationWeights.C
|
$(interpolationWeights)/splineInterpolationWeights/splineInterpolationWeights.C
|
||||||
|
|
||||||
|
|
||||||
algorithms/indexedOctree/indexedOctreeName.C
|
algorithms/AABBTree/AABBTreeBase.C
|
||||||
|
|
||||||
|
algorithms/indexedOctree/indexedOctreeBase.C
|
||||||
algorithms/indexedOctree/treeDataCell.C
|
algorithms/indexedOctree/treeDataCell.C
|
||||||
algorithms/indexedOctree/treeDataEdge.C
|
algorithms/indexedOctree/treeDataEdge.C
|
||||||
algorithms/indexedOctree/treeDataPoint.C
|
algorithms/indexedOctree/treeDataPoint.C
|
||||||
|
|
||||||
algorithms/dynamicIndexedOctree/dynamicIndexedOctreeName.C
|
algorithms/dynamicIndexedOctree/dynamicIndexedOctreeBase.C
|
||||||
algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C
|
algorithms/dynamicIndexedOctree/dynamicTreeDataPoint.C
|
||||||
|
|
||||||
parallel/commSchedule/commSchedule.C
|
parallel/commSchedule/commSchedule.C
|
||||||
|
|||||||
@ -29,51 +29,8 @@ License
|
|||||||
#include "AABBTree.H"
|
#include "AABBTree.H"
|
||||||
#include "bitSet.H"
|
#include "bitSet.H"
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
Foam::scalar Foam::AABBTree<Type>::tolerance_ = 1e-4;
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
void Foam::AABBTree<Type>::writeOBJ
|
|
||||||
(
|
|
||||||
const bool writeLinesOnly,
|
|
||||||
const treeBoundBox& bb,
|
|
||||||
label& vertI,
|
|
||||||
Ostream& os
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const pointField pts(bb.points());
|
|
||||||
|
|
||||||
for (const point& p : pts)
|
|
||||||
{
|
|
||||||
os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeLinesOnly)
|
|
||||||
{
|
|
||||||
for (const edge& e : treeBoundBox::edges)
|
|
||||||
{
|
|
||||||
os << "l " << e[0] + vertI + 1 << ' ' << e[1] + vertI + 1 << nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (const face& f : treeBoundBox::faces)
|
|
||||||
{
|
|
||||||
os << 'f';
|
|
||||||
for (const label fpi : f)
|
|
||||||
{
|
|
||||||
os << ' ' << fpi + vertI + 1;
|
|
||||||
}
|
|
||||||
os << nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vertI += pts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::AABBTree<Type>::writeOBJ
|
void Foam::AABBTree<Type>::writeOBJ
|
||||||
(
|
(
|
||||||
@ -89,7 +46,7 @@ void Foam::AABBTree<Type>::writeOBJ
|
|||||||
{
|
{
|
||||||
if (!leavesOnly || nodeI < 0)
|
if (!leavesOnly || nodeI < 0)
|
||||||
{
|
{
|
||||||
writeOBJ(writeLinesOnly, bb, vertI, os);
|
AABBTreeBase::writeOBJ(os, bb, vertI, writeLinesOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recurse to find leaves
|
// recurse to find leaves
|
||||||
@ -126,9 +83,9 @@ void Foam::AABBTree<Type>::createBoxes
|
|||||||
(
|
(
|
||||||
const bool equalBinSize,
|
const bool equalBinSize,
|
||||||
const label level,
|
const label level,
|
||||||
const List<Type>& objects,
|
const UList<Type>& objects,
|
||||||
const pointField& points,
|
const pointField& points,
|
||||||
const DynamicList<label>& objectIDs,
|
const labelUList& objectIDs,
|
||||||
const treeBoundBox& bb,
|
const treeBoundBox& bb,
|
||||||
const label nodeI,
|
const label nodeI,
|
||||||
|
|
||||||
@ -153,7 +110,7 @@ void Foam::AABBTree<Type>::createBoxes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scalar divide;
|
scalar pivotValue;
|
||||||
|
|
||||||
if (equalBinSize)
|
if (equalBinSize)
|
||||||
{
|
{
|
||||||
@ -179,17 +136,17 @@ void Foam::AABBTree<Type>::createBoxes
|
|||||||
|
|
||||||
Foam::sort(component);
|
Foam::sort(component);
|
||||||
|
|
||||||
divide = component[component.size()/2];
|
pivotValue = component[component.size()/2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Geometric middle
|
// Geometric middle
|
||||||
divide = bb.min()[maxDir] + 0.5*maxSpan;
|
pivotValue = bb.min()[maxDir] + 0.5*maxSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scalar divMin = divide + tolerance_*maxSpan;
|
const scalar divMin = pivotValue + tolerance_*maxSpan;
|
||||||
scalar divMax = divide - tolerance_*maxSpan;
|
const scalar divMax = pivotValue - tolerance_*maxSpan;
|
||||||
|
|
||||||
|
|
||||||
// Assign the objects to min or max bin
|
// Assign the objects to min or max bin
|
||||||
@ -333,8 +290,8 @@ Foam::AABBTree<Type>::AABBTree
|
|||||||
const UList<Type>& objects,
|
const UList<Type>& objects,
|
||||||
const pointField& points,
|
const pointField& points,
|
||||||
const bool equalBinSize,
|
const bool equalBinSize,
|
||||||
const label maxLevel,
|
label maxLevel,
|
||||||
const label minLeafSize
|
label minLeafSize
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
maxLevel_(maxLevel),
|
maxLevel_(maxLevel),
|
||||||
@ -356,7 +313,7 @@ Foam::AABBTree<Type>::AABBTree
|
|||||||
treeBoundBox topBb(points);
|
treeBoundBox topBb(points);
|
||||||
topBb.inflate(0.01);
|
topBb.inflate(0.01);
|
||||||
|
|
||||||
DynamicList<label> objectIDs(identity(objects.size()));
|
labelList objectIDs(identity(objects.size()));
|
||||||
|
|
||||||
createBoxes
|
createBoxes
|
||||||
(
|
(
|
||||||
@ -438,16 +395,15 @@ Foam::AABBTree<Type>::AABBTree
|
|||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
const Foam::List<Foam::treeBoundBox>& Foam::AABBTree<Type>::boundBoxes() const
|
void Foam::AABBTree<Type>::writeOBJ(Ostream& os) const
|
||||||
{
|
{
|
||||||
return boundBoxes_;
|
label vertIndex(0);
|
||||||
|
|
||||||
|
for (const treeBoundBox& bb : boundBoxes_)
|
||||||
|
{
|
||||||
|
// writeLinesOnly=false
|
||||||
|
AABBTreeBase::writeOBJ(os, bb, vertIndex, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
const Foam::List<Foam::labelList>& Foam::AABBTree<Type>::addressing() const
|
|
||||||
{
|
|
||||||
return addressing_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -486,24 +442,7 @@ bool Foam::AABBTree<Type>::overlaps(const boundBox& bbIn) const
|
|||||||
template<class Type>
|
template<class Type>
|
||||||
Foam::Ostream& Foam::operator<<(Ostream& os, const AABBTree<Type>& tree)
|
Foam::Ostream& Foam::operator<<(Ostream& os, const AABBTree<Type>& tree)
|
||||||
{
|
{
|
||||||
if (os.format() == IOstreamOption::ASCII)
|
os << tree.boundBoxes_ << tree.addressing_;
|
||||||
{
|
|
||||||
os << tree.maxLevel_ << token::SPACE
|
|
||||||
<< tree.minLeafSize_ << token::SPACE
|
|
||||||
<< tree.boundBoxes_ << token::SPACE
|
|
||||||
<< tree.addressing_ << token::SPACE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
os.write
|
|
||||||
(
|
|
||||||
reinterpret_cast<const char*>(&tree.maxLevel_),
|
|
||||||
sizeof(tree.maxLevel_)
|
|
||||||
+ sizeof(tree.minLeafSize_)
|
|
||||||
);
|
|
||||||
os << tree.boundBoxes_
|
|
||||||
<< tree.addressing_;
|
|
||||||
}
|
|
||||||
|
|
||||||
os.check(FUNCTION_NAME);
|
os.check(FUNCTION_NAME);
|
||||||
return os;
|
return os;
|
||||||
@ -513,23 +452,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const AABBTree<Type>& tree)
|
|||||||
template<class Type>
|
template<class Type>
|
||||||
Foam::Istream& Foam::operator>>(Istream& is, AABBTree<Type>& tree)
|
Foam::Istream& Foam::operator>>(Istream& is, AABBTree<Type>& tree)
|
||||||
{
|
{
|
||||||
if (is.format() == IOstreamOption::ASCII)
|
is >> tree.boundBoxes_ >> tree.addressing_;
|
||||||
{
|
|
||||||
is >> tree.maxLevel_
|
|
||||||
>> tree.minLeafSize_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
is.beginRawRead();
|
|
||||||
|
|
||||||
readRawLabel(is, &tree.maxLevel_);
|
|
||||||
readRawLabel(is, &tree.minLeafSize_);
|
|
||||||
|
|
||||||
is.endRawRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
is >> tree.boundBoxes_
|
|
||||||
>> tree.addressing_;
|
|
||||||
|
|
||||||
is.check(FUNCTION_NAME);
|
is.check(FUNCTION_NAME);
|
||||||
return is;
|
return is;
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015 OpenFOAM Foundation
|
Copyright (C) 2015 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -36,11 +37,12 @@ Description
|
|||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
AABBTree.C
|
AABBTree.C
|
||||||
|
AABBTreeBase.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef AABBTree_H
|
#ifndef Foam_AABBTree_H
|
||||||
#define AABBTree_H
|
#define Foam_AABBTree_H
|
||||||
|
|
||||||
#include "labelList.H"
|
#include "labelList.H"
|
||||||
#include "labelPair.H"
|
#include "labelPair.H"
|
||||||
@ -54,10 +56,8 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
// Forward declaration of friend functions and operators
|
// Forward Declarations
|
||||||
|
template<class Type> class AABBTree;
|
||||||
template<class Type>
|
|
||||||
class AABBTree;
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Istream& operator>>(Istream&, AABBTree<Type>&);
|
Istream& operator>>(Istream&, AABBTree<Type>&);
|
||||||
@ -65,21 +65,56 @@ Istream& operator>>(Istream&, AABBTree<Type>&);
|
|||||||
template<class Type>
|
template<class Type>
|
||||||
Ostream& operator<<(Ostream&, const AABBTree<Type>&);
|
Ostream& operator<<(Ostream&, const AABBTree<Type>&);
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class AABBTreeBase Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//- Template invariant parts for AABBTree
|
||||||
|
class AABBTreeBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Static Data
|
||||||
|
|
||||||
|
//- Relative tolerance.
|
||||||
|
static scalar tolerance_;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
AABBTreeBase() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Output Helpers
|
||||||
|
|
||||||
|
//- Write treeBoundBox in OBJ format
|
||||||
|
static void writeOBJ
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const treeBoundBox& bb,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool writeLinesOnly = false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class AABBTree Declaration
|
Class AABBTree Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
class AABBTree
|
class AABBTree
|
||||||
|
:
|
||||||
|
public AABBTreeBase
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Tolerance
|
|
||||||
static scalar tolerance_;
|
|
||||||
|
|
||||||
//- Maximum tree level
|
//- Maximum tree level
|
||||||
label maxLevel_;
|
label maxLevel_;
|
||||||
|
|
||||||
@ -95,15 +130,6 @@ protected:
|
|||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Write OBJ file of bounding box
|
|
||||||
void writeOBJ
|
|
||||||
(
|
|
||||||
const bool writeLinesOnly,
|
|
||||||
const treeBoundBox& bb,
|
|
||||||
label& vertI,
|
|
||||||
Ostream& os
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Write OBJ for all bounding boxes
|
//- Write OBJ for all bounding boxes
|
||||||
void writeOBJ
|
void writeOBJ
|
||||||
(
|
(
|
||||||
@ -122,9 +148,9 @@ protected:
|
|||||||
(
|
(
|
||||||
const bool equalBinSize,
|
const bool equalBinSize,
|
||||||
const label level,
|
const label level,
|
||||||
const List<Type>& objects,
|
const UList<Type>& objects,
|
||||||
const pointField& points,
|
const pointField& points,
|
||||||
const DynamicList<label>& objectIDs,
|
const labelUList& objectIDs,
|
||||||
const treeBoundBox& bb,
|
const treeBoundBox& bb,
|
||||||
const label nodeI,
|
const label nodeI,
|
||||||
|
|
||||||
@ -138,7 +164,7 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Null constructor
|
//- Default construct
|
||||||
AABBTree();
|
AABBTree();
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
@ -148,8 +174,8 @@ public:
|
|||||||
const UList<Type>& objects,
|
const UList<Type>& objects,
|
||||||
const pointField& points,
|
const pointField& points,
|
||||||
const bool equalBinSize = true,
|
const bool equalBinSize = true,
|
||||||
const label maxLevel = 3,
|
label maxLevel = 3,
|
||||||
const label minBinSize = 100
|
label minBinSize = 100
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -158,10 +184,16 @@ public:
|
|||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Return the bounding boxes making up the tree
|
//- Return the bounding boxes making up the tree
|
||||||
const List<treeBoundBox>& boundBoxes() const;
|
const List<treeBoundBox>& boundBoxes() const noexcept
|
||||||
|
{
|
||||||
|
return boundBoxes_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Return the contents addressing
|
//- Return the contents addressing
|
||||||
const List<labelList>& addressing() const;
|
const List<labelList>& addressing() const noexcept
|
||||||
|
{
|
||||||
|
return addressing_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Evaluation
|
// Evaluation
|
||||||
@ -169,12 +201,17 @@ public:
|
|||||||
//- Determine whether a point is inside the bounding boxes
|
//- Determine whether a point is inside the bounding boxes
|
||||||
bool pointInside(const point& pt) const;
|
bool pointInside(const point& pt) const;
|
||||||
|
|
||||||
//- Determine whether a bounding box overlaps the tree bounding
|
//- Determine whether a bounding box overlaps the tree bounding boxes
|
||||||
//- boxes
|
|
||||||
bool overlaps(const boundBox& bbIn) const;
|
bool overlaps(const boundBox& bbIn) const;
|
||||||
|
|
||||||
|
|
||||||
// IOstream operators
|
// Write
|
||||||
|
|
||||||
|
//- Write all tree boxes (leaves) in OBJ format
|
||||||
|
void writeOBJ(Ostream& os) const;
|
||||||
|
|
||||||
|
|
||||||
|
// IOstream Operators
|
||||||
|
|
||||||
friend Istream& operator>> <Type>(Istream&, AABBTree&);
|
friend Istream& operator>> <Type>(Istream&, AABBTree&);
|
||||||
friend Ostream& operator<< <Type>(Ostream&, const AABBTree&);
|
friend Ostream& operator<< <Type>(Ostream&, const AABBTree&);
|
||||||
|
|||||||
81
src/OpenFOAM/algorithms/AABBTree/AABBTreeBase.C
Normal file
81
src/OpenFOAM/algorithms/AABBTree/AABBTreeBase.C
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM 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.
|
||||||
|
|
||||||
|
OpenFOAM 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
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "AABBTree.H"
|
||||||
|
#include "treeBoundBox.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::scalar Foam::AABBTreeBase::tolerance_ = 1e-4;
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::AABBTreeBase::writeOBJ
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const treeBoundBox& bb,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool writeLinesOnly
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Annotate with '#box' which can be grep'd for later
|
||||||
|
os << "#box" << nl;
|
||||||
|
|
||||||
|
pointField pts(bb.points());
|
||||||
|
|
||||||
|
for (const point& p : pts)
|
||||||
|
{
|
||||||
|
os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeLinesOnly)
|
||||||
|
{
|
||||||
|
for (const edge& e : treeBoundBox::edges)
|
||||||
|
{
|
||||||
|
os << "l " << e[0] + vertIndex + 1
|
||||||
|
<< ' ' << e[1] + vertIndex + 1 << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const face& f : treeBoundBox::faces)
|
||||||
|
{
|
||||||
|
os << 'f';
|
||||||
|
for (const label fpi : f)
|
||||||
|
{
|
||||||
|
os << ' ' << fpi + vertIndex + 1;
|
||||||
|
}
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vertIndex += pts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -179,7 +179,7 @@ void Foam::dynamicIndexedOctree<Type>::divide
|
|||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
typename Foam::dynamicIndexedOctree<Type>::node
|
Foam::dynamicIndexedOctreeBase::node
|
||||||
Foam::dynamicIndexedOctree<Type>::divide
|
Foam::dynamicIndexedOctree<Type>::divide
|
||||||
(
|
(
|
||||||
const treeBoundBox& bb,
|
const treeBoundBox& bb,
|
||||||
@ -295,9 +295,9 @@ void Foam::dynamicIndexedOctree<Type>::recursiveSubDivision
|
|||||||
|
|
||||||
// Recursively divide the contents until maxLevels_ is
|
// Recursively divide the contents until maxLevels_ is
|
||||||
// reached or the content sizes are less than minSize_
|
// reached or the content sizes are less than minSize_
|
||||||
for (direction subOct = 0; subOct < 8; subOct++)
|
for (direction subOct = 0; subOct < node::nChildren; ++subOct)
|
||||||
{
|
{
|
||||||
const labelBits& subNodeLabel = nod.subNodes_[subOct];
|
const labelBits subNodeLabel = nod.subNodes_[subOct];
|
||||||
|
|
||||||
if (isContent(subNodeLabel))
|
if (isContent(subNodeLabel))
|
||||||
{
|
{
|
||||||
@ -335,7 +335,7 @@ Foam::volumeType Foam::dynamicIndexedOctree<Type>::calcVolumeType
|
|||||||
|
|
||||||
volumeType myType = volumeType::UNKNOWN;
|
volumeType myType = volumeType::UNKNOWN;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
volumeType subType;
|
volumeType subType;
|
||||||
|
|
||||||
@ -1027,7 +1027,7 @@ bool Foam::dynamicIndexedOctree<Type>::walkToParent
|
|||||||
// Find octant nodeI is in.
|
// Find octant nodeI is in.
|
||||||
parentOctant = 255;
|
parentOctant = 255;
|
||||||
|
|
||||||
for (direction i = 0; i < parentNode.subNodes_.size(); i++)
|
for (direction i = 0; i < node::nChildren; ++i)
|
||||||
{
|
{
|
||||||
labelBits index = parentNode.subNodes_[i];
|
labelBits index = parentNode.subNodes_[i];
|
||||||
|
|
||||||
@ -1794,7 +1794,7 @@ void Foam::dynamicIndexedOctree<Type>::findBox
|
|||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
const treeBoundBox& nodeBb = nod.bb_;
|
const treeBoundBox& nodeBb = nod.bb_;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -1842,7 +1842,7 @@ void Foam::dynamicIndexedOctree<Type>::findSphere
|
|||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
const treeBoundBox& nodeBb = nod.bb_;
|
const treeBoundBox& nodeBb = nod.bb_;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -1910,7 +1910,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
|||||||
{
|
{
|
||||||
const node& nod2 = tree2.nodes()[tree2.getNode(index2)];
|
const node& nod2 = tree2.nodes()[tree2.getNode(index2)];
|
||||||
|
|
||||||
for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
|
for (direction i2 = 0; i2 < node::nChildren; ++i2)
|
||||||
{
|
{
|
||||||
labelBits subIndex2 = nod2.subNodes_[i2];
|
labelBits subIndex2 = nod2.subNodes_[i2];
|
||||||
const treeBoundBox subBb2
|
const treeBoundBox subBb2
|
||||||
@ -1938,7 +1938,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
|||||||
else if (tree2.isContent(index2))
|
else if (tree2.isContent(index2))
|
||||||
{
|
{
|
||||||
// index2 is leaf, index1 not yet.
|
// index2 is leaf, index1 not yet.
|
||||||
for (direction i1 = 0; i1 < nod1.subNodes_.size(); i1++)
|
for (direction i1 = 0; i1 < node::nChildren; ++i1)
|
||||||
{
|
{
|
||||||
labelBits subIndex1 = nod1.subNodes_[i1];
|
labelBits subIndex1 = nod1.subNodes_[i1];
|
||||||
const treeBoundBox subBb1
|
const treeBoundBox subBb1
|
||||||
@ -1978,7 +1978,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
|||||||
|
|
||||||
if (bb2.overlaps(searchBox))
|
if (bb2.overlaps(searchBox))
|
||||||
{
|
{
|
||||||
for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
|
for (direction i2 = 0; i2 < node::nChildren; ++i2)
|
||||||
{
|
{
|
||||||
labelBits subIndex2 = nod2.subNodes_[i2];
|
labelBits subIndex2 = nod2.subNodes_[i2];
|
||||||
const treeBoundBox subBb2
|
const treeBoundBox subBb2
|
||||||
@ -2067,7 +2067,7 @@ Foam::label Foam::dynamicIndexedOctree<Type>::countElements
|
|||||||
|
|
||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
nElems += countElements(nod.subNodes_[octant]);
|
nElems += countElements(nod.subNodes_[octant]);
|
||||||
}
|
}
|
||||||
@ -2085,6 +2085,43 @@ Foam::label Foam::dynamicIndexedOctree<Type>::countElements
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
||||||
|
(
|
||||||
|
const label nodeI,
|
||||||
|
Ostream& os,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool leavesOnly,
|
||||||
|
const bool writeLinesOnly
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const node& nod = nodes_[nodeI];
|
||||||
|
const treeBoundBox& bb = nod.bb_;
|
||||||
|
|
||||||
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
|
{
|
||||||
|
const treeBoundBox subBb(bb.subBbox(octant));
|
||||||
|
|
||||||
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
|
if (isNode(index))
|
||||||
|
{
|
||||||
|
label subNodeI = getNode(index);
|
||||||
|
|
||||||
|
writeOBJ(subNodeI, os, vertIndex, leavesOnly, writeLinesOnly);
|
||||||
|
}
|
||||||
|
else if (isContent(index))
|
||||||
|
{
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
|
}
|
||||||
|
else if (isEmpty(index) && !leavesOnly)
|
||||||
|
{
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
||||||
(
|
(
|
||||||
@ -2092,11 +2129,6 @@ void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
|||||||
const direction octant
|
const direction octant
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
OFstream str
|
|
||||||
(
|
|
||||||
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
|
||||||
);
|
|
||||||
|
|
||||||
labelBits index = nodes_[nodeI].subNodes_[octant];
|
labelBits index = nodes_[nodeI].subNodes_[octant];
|
||||||
|
|
||||||
treeBoundBox subBb;
|
treeBoundBox subBb;
|
||||||
@ -2110,24 +2142,28 @@ void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
|||||||
subBb = nodes_[nodeI].bb_.subBbox(octant);
|
subBb = nodes_[nodeI].bb_.subBbox(octant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OFstream os
|
||||||
|
(
|
||||||
|
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
||||||
|
);
|
||||||
|
|
||||||
Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
|
Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
|
||||||
<< " to " << str.name() << endl;
|
<< " to " << os.name() << endl;
|
||||||
|
|
||||||
// Dump bounding box
|
bool writeLinesOnly(false);
|
||||||
pointField bbPoints(subBb.points());
|
label vertIndex(0);
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
forAll(bbPoints, i)
|
|
||||||
{
|
|
||||||
const point& pt = bbPoints[i];
|
|
||||||
|
|
||||||
str<< "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(treeBoundBox::edges, i)
|
|
||||||
{
|
|
||||||
const edge& e = treeBoundBox::edges[i];
|
|
||||||
|
|
||||||
str<< "l " << e[0] + 1 << ' ' << e[1] + 1 << nl;
|
template<class Type>
|
||||||
|
void Foam::dynamicIndexedOctree<Type>::writeOBJ(Ostream& os) const
|
||||||
|
{
|
||||||
|
if (!nodes_.empty())
|
||||||
|
{
|
||||||
|
label vertIndex(0);
|
||||||
|
// leavesOnly=true, writeLinesOnly=false
|
||||||
|
writeOBJ(0, os, vertIndex, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2456,7 +2492,7 @@ Foam::volumeType Foam::dynamicIndexedOctree<Type>::getVolumeType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "dynamicIndexedOctree<Type>::getVolumeType : "
|
Pout<< "dynamicIndexedOctree::getVolumeType : "
|
||||||
<< " bb:" << bb()
|
<< " bb:" << bb()
|
||||||
<< " nodes_:" << nodes_.size()
|
<< " nodes_:" << nodes_.size()
|
||||||
<< " nodeTypes_:" << nodeTypes_.size()
|
<< " nodeTypes_:" << nodeTypes_.size()
|
||||||
@ -2552,9 +2588,9 @@ bool Foam::dynamicIndexedOctree<Type>::insertIndex
|
|||||||
{
|
{
|
||||||
bool shapeInserted = false;
|
bool shapeInserted = false;
|
||||||
|
|
||||||
for (direction octant = 0; octant < 8; octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
const labelBits& subNodeLabel = nodes_[nodIndex].subNodes_[octant];
|
const labelBits subNodeLabel = nodes_[nodIndex].subNodes_[octant];
|
||||||
|
|
||||||
if (isNode(subNodeLabel))
|
if (isNode(subNodeLabel))
|
||||||
{
|
{
|
||||||
@ -2642,9 +2678,9 @@ Foam::label Foam::dynamicIndexedOctree<Type>::removeIndex
|
|||||||
{
|
{
|
||||||
label totalContents = 0;
|
label totalContents = 0;
|
||||||
|
|
||||||
for (direction octant = 0; octant < 8; octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
const labelBits& subNodeLabel = nodes_[nodIndex].subNodes_[octant];
|
const labelBits subNodeLabel = nodes_[nodIndex].subNodes_[octant];
|
||||||
|
|
||||||
if (isNode(subNodeLabel))
|
if (isNode(subNodeLabel))
|
||||||
{
|
{
|
||||||
@ -2731,7 +2767,7 @@ void Foam::dynamicIndexedOctree<Type>::print
|
|||||||
<< "parent:" << nod.parent_ << nl
|
<< "parent:" << nod.parent_ << nl
|
||||||
<< "n:" << countElements(nodePlusOctant(nodeI, 0)) << nl;
|
<< "n:" << countElements(nodePlusOctant(nodeI, 0)) << nl;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
const treeBoundBox subBb(bb.subBbox(octant));
|
const treeBoundBox subBb(bb.subBbox(octant));
|
||||||
|
|
||||||
@ -2798,7 +2834,7 @@ void Foam::dynamicIndexedOctree<Type>::writeTreeInfo() const
|
|||||||
nEntries += contents_[i]->size();
|
nEntries += contents_[i]->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "indexedOctree<Type>::indexedOctree"
|
Pout<< "indexedOctree::indexedOctree"
|
||||||
<< " : finished construction of tree of:" << shapes().typeName
|
<< " : finished construction of tree of:" << shapes().typeName
|
||||||
<< nl
|
<< nl
|
||||||
<< " bounding box: " << this->bb() << nl
|
<< " bounding box: " << this->bb() << nl
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -38,14 +39,8 @@ SourceFiles
|
|||||||
#ifndef Foam_dynamicIndexedOctree_H
|
#ifndef Foam_dynamicIndexedOctree_H
|
||||||
#define Foam_dynamicIndexedOctree_H
|
#define Foam_dynamicIndexedOctree_H
|
||||||
|
|
||||||
#include "treeBoundBox.H"
|
#include "indexedOctree.H"
|
||||||
#include "pointIndexHit.H"
|
#include "DynamicList.H"
|
||||||
#include "FixedList.H"
|
|
||||||
#include "Ostream.H"
|
|
||||||
#include "HashSet.H"
|
|
||||||
#include "labelBits.H"
|
|
||||||
#include "PackedList.H"
|
|
||||||
#include "volumeType.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -55,22 +50,36 @@ namespace Foam
|
|||||||
typedef DynamicList<autoPtr<DynamicList<label>>> contentListList;
|
typedef DynamicList<autoPtr<DynamicList<label>>> contentListList;
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
template<class Type> class dynamicIndexedOctree;
|
|
||||||
|
|
||||||
template<class Type> Ostream& operator<<
|
|
||||||
(
|
|
||||||
Ostream&,
|
|
||||||
const dynamicIndexedOctree<Type>&
|
|
||||||
);
|
|
||||||
|
|
||||||
class Istream;
|
class Istream;
|
||||||
|
template<class Type> class dynamicIndexedOctree;
|
||||||
|
template<class Type>
|
||||||
|
Ostream& operator<<(Ostream&, const dynamicIndexedOctree<Type>&);
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class dynamicIndexedOctreeName Declaration
|
Class dynamicIndexedOctreeBase Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TemplateName(dynamicIndexedOctree);
|
//- Template invariant parts for dynamicIndexedOctree
|
||||||
|
// Same type of node bookkeeping as indexedOctree
|
||||||
|
class dynamicIndexedOctreeBase
|
||||||
|
:
|
||||||
|
public indexedOctreeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Document that we are using the same types of node
|
||||||
|
using node = indexedOctreeBase::node;
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
ClassName("dynamicIndexedOctree");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
dynamicIndexedOctreeBase() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -80,54 +89,8 @@ TemplateName(dynamicIndexedOctree);
|
|||||||
template<class Type>
|
template<class Type>
|
||||||
class dynamicIndexedOctree
|
class dynamicIndexedOctree
|
||||||
:
|
:
|
||||||
public dynamicIndexedOctreeName
|
public dynamicIndexedOctreeBase
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
// Data types
|
|
||||||
|
|
||||||
//- Tree node. Has up pointer and down pointers.
|
|
||||||
class node
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Bounding box of this node
|
|
||||||
treeBoundBox bb_;
|
|
||||||
|
|
||||||
//- Parent node (index into nodes_ of tree)
|
|
||||||
label parent_;
|
|
||||||
|
|
||||||
//- IDs of the 8 nodes on all sides of the mid point
|
|
||||||
FixedList<labelBits, 8> subNodes_;
|
|
||||||
|
|
||||||
friend Ostream& operator<< (Ostream& os, const node& n)
|
|
||||||
{
|
|
||||||
return os << n.bb_ << token::SPACE
|
|
||||||
<< n.parent_ << token::SPACE << n.subNodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Istream& operator>> (Istream& is, node& n)
|
|
||||||
{
|
|
||||||
return is >> n.bb_ >> n.parent_ >> n.subNodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(const node& a, const node& b)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
a.bb_ == b.bb_
|
|
||||||
&& a.parent_ == b.parent_
|
|
||||||
&& a.subNodes_ == b.subNodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(const node& a, const node& b)
|
|
||||||
{
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Static data
|
// Static data
|
||||||
|
|
||||||
//- Relative perturbation tolerance. Determines when point is
|
//- Relative perturbation tolerance. Determines when point is
|
||||||
@ -137,7 +100,7 @@ private:
|
|||||||
static scalar perturbTol_;
|
static scalar perturbTol_;
|
||||||
|
|
||||||
|
|
||||||
// Private data
|
// Private Data
|
||||||
|
|
||||||
//- Underlying shapes for geometric queries.
|
//- Underlying shapes for geometric queries.
|
||||||
const Type shapes_;
|
const Type shapes_;
|
||||||
@ -366,37 +329,19 @@ private:
|
|||||||
//- Count number of elements on this and sublevels
|
//- Count number of elements on this and sublevels
|
||||||
label countElements(const labelBits index) const;
|
label countElements(const labelBits index) const;
|
||||||
|
|
||||||
|
//- Write node treeBoundBoxes in OBJ format
|
||||||
|
void writeOBJ
|
||||||
|
(
|
||||||
|
const label nodeI,
|
||||||
|
Ostream& os,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool leavesOnly,
|
||||||
|
const bool writeLinesOnly = false
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Dump node+octant to an obj file
|
//- Dump node+octant to an obj file
|
||||||
void writeOBJ(const label nodeI, const direction octant) const;
|
void writeOBJ(const label nodeI, const direction octant) const;
|
||||||
|
|
||||||
//- From index into contents_ to subNodes_ entry
|
|
||||||
static labelBits contentPlusOctant
|
|
||||||
(
|
|
||||||
const label i,
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(-i - 1, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- From index into nodes_ to subNodes_ entry
|
|
||||||
static labelBits nodePlusOctant
|
|
||||||
(
|
|
||||||
const label i,
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(i + 1, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- From empty to subNodes_ entry
|
|
||||||
static labelBits emptyPlusOctant
|
|
||||||
(
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(0, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -429,24 +374,24 @@ public:
|
|||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Reference to shape
|
//- Reference to shape
|
||||||
const Type& shapes() const
|
const Type& shapes() const noexcept { return shapes_; }
|
||||||
{
|
|
||||||
return shapes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- List of all nodes
|
//- List of all nodes
|
||||||
const List<node>& nodes() const
|
const List<node>& nodes() const noexcept { return nodes_; }
|
||||||
{
|
|
||||||
return nodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- List of all contents (referenced by those nodes that are
|
//- List of all contents
|
||||||
// contents)
|
//- (referenced by those nodes that are contents)
|
||||||
const contentListList& contents() const
|
const contentListList& contents() const
|
||||||
{
|
{
|
||||||
return contents_;
|
return contents_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Per node, per octant whether is fully inside/outside/mixed.
|
||||||
|
PackedList<2>& nodeTypes() const noexcept
|
||||||
|
{
|
||||||
|
return nodeTypes_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Top bounding box
|
//- Top bounding box
|
||||||
const treeBoundBox& bb() const
|
const treeBoundBox& bb() const
|
||||||
{
|
{
|
||||||
@ -458,49 +403,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Conversions for entries in subNodes_.
|
|
||||||
|
|
||||||
static bool isContent(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isEmpty(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isNode(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static label getContent(const labelBits i)
|
|
||||||
{
|
|
||||||
if (!isContent(i))
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
return -i.val()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static label getNode(const labelBits i)
|
|
||||||
{
|
|
||||||
if (!isNode(i))
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
return i.val() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static direction getOctant(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.bits();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Queries
|
// Queries
|
||||||
|
|
||||||
//- Calculate nearest point on nearest shape.
|
//- Calculate nearest point on nearest shape.
|
||||||
@ -631,6 +533,9 @@ public:
|
|||||||
|
|
||||||
// Write
|
// Write
|
||||||
|
|
||||||
|
//- Write all tree boxes as OBJ format
|
||||||
|
void writeOBJ(Ostream& os) const;
|
||||||
|
|
||||||
//- Print tree. Either print all indices (printContent = true) or
|
//- Print tree. Either print all indices (printContent = true) or
|
||||||
// just size of contents nodes.
|
// just size of contents nodes.
|
||||||
void print
|
void print
|
||||||
|
|||||||
@ -31,7 +31,7 @@ License
|
|||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(dynamicIndexedOctreeName, 0);
|
defineTypeNameAndDebug(dynamicIndexedOctreeBase, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ void Foam::indexedOctree<Type>::divide
|
|||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
typename Foam::indexedOctree<Type>::node
|
Foam::indexedOctreeBase::node
|
||||||
Foam::indexedOctree<Type>::divide
|
Foam::indexedOctree<Type>::divide
|
||||||
(
|
(
|
||||||
const treeBoundBox& bb,
|
const treeBoundBox& bb,
|
||||||
@ -227,7 +227,7 @@ template<class Type>
|
|||||||
void Foam::indexedOctree<Type>::splitNodes
|
void Foam::indexedOctree<Type>::splitNodes
|
||||||
(
|
(
|
||||||
const label minSize,
|
const label minSize,
|
||||||
DynamicList<indexedOctree<Type>::node>& nodes,
|
DynamicList<indexedOctreeBase::node>& nodes,
|
||||||
DynamicList<labelList>& contents
|
DynamicList<labelList>& contents
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -238,12 +238,7 @@ void Foam::indexedOctree<Type>::splitNodes
|
|||||||
// moved so make sure not to keep any references!
|
// moved so make sure not to keep any references!
|
||||||
for (label nodeI = 0; nodeI < currentSize; nodeI++)
|
for (label nodeI = 0; nodeI < currentSize; nodeI++)
|
||||||
{
|
{
|
||||||
for
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
(
|
|
||||||
direction octant = 0;
|
|
||||||
octant < nodes[nodeI].subNodes_.size();
|
|
||||||
octant++
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
labelBits index = nodes[nodeI].subNodes_[octant];
|
labelBits index = nodes[nodeI].subNodes_[octant];
|
||||||
|
|
||||||
@ -294,7 +289,7 @@ Foam::label Foam::indexedOctree<Type>::compactContents
|
|||||||
|
|
||||||
if (level < compactLevel)
|
if (level < compactLevel)
|
||||||
{
|
{
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -316,7 +311,7 @@ Foam::label Foam::indexedOctree<Type>::compactContents
|
|||||||
else if (level == compactLevel)
|
else if (level == compactLevel)
|
||||||
{
|
{
|
||||||
// Compact all content on this level
|
// Compact all content on this level
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -356,7 +351,7 @@ Foam::volumeType Foam::indexedOctree<Type>::calcVolumeType
|
|||||||
|
|
||||||
volumeType myType = volumeType::UNKNOWN;
|
volumeType myType = volumeType::UNKNOWN;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
volumeType subType;
|
volumeType subType;
|
||||||
|
|
||||||
@ -1048,7 +1043,7 @@ bool Foam::indexedOctree<Type>::walkToParent
|
|||||||
// Find octant nodeI is in.
|
// Find octant nodeI is in.
|
||||||
parentOctant = 255;
|
parentOctant = 255;
|
||||||
|
|
||||||
for (direction i = 0; i < parentNode.subNodes_.size(); i++)
|
for (direction i = 0; i < node::nChildren; ++i)
|
||||||
{
|
{
|
||||||
labelBits index = parentNode.subNodes_[i];
|
labelBits index = parentNode.subNodes_[i];
|
||||||
|
|
||||||
@ -1827,7 +1822,7 @@ void Foam::indexedOctree<Type>::findBox
|
|||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
const treeBoundBox& nodeBb = nod.bb_;
|
const treeBoundBox& nodeBb = nod.bb_;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -1875,7 +1870,7 @@ void Foam::indexedOctree<Type>::findSphere
|
|||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
const treeBoundBox& nodeBb = nod.bb_;
|
const treeBoundBox& nodeBb = nod.bb_;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
labelBits index = nod.subNodes_[octant];
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
@ -1943,7 +1938,7 @@ void Foam::indexedOctree<Type>::findNear
|
|||||||
{
|
{
|
||||||
const node& nod2 = tree2.nodes()[tree2.getNode(index2)];
|
const node& nod2 = tree2.nodes()[tree2.getNode(index2)];
|
||||||
|
|
||||||
for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
|
for (direction i2 = 0; i2 < node::nChildren; ++i2)
|
||||||
{
|
{
|
||||||
labelBits subIndex2 = nod2.subNodes_[i2];
|
labelBits subIndex2 = nod2.subNodes_[i2];
|
||||||
const treeBoundBox subBb2
|
const treeBoundBox subBb2
|
||||||
@ -1971,7 +1966,7 @@ void Foam::indexedOctree<Type>::findNear
|
|||||||
else if (tree2.isContent(index2))
|
else if (tree2.isContent(index2))
|
||||||
{
|
{
|
||||||
// index2 is leaf, index1 not yet.
|
// index2 is leaf, index1 not yet.
|
||||||
for (direction i1 = 0; i1 < nod1.subNodes_.size(); i1++)
|
for (direction i1 = 0; i1 < node::nChildren; ++i1)
|
||||||
{
|
{
|
||||||
labelBits subIndex1 = nod1.subNodes_[i1];
|
labelBits subIndex1 = nod1.subNodes_[i1];
|
||||||
const treeBoundBox subBb1
|
const treeBoundBox subBb1
|
||||||
@ -2011,7 +2006,7 @@ void Foam::indexedOctree<Type>::findNear
|
|||||||
|
|
||||||
if (bb2.overlaps(searchBox))
|
if (bb2.overlaps(searchBox))
|
||||||
{
|
{
|
||||||
for (direction i2 = 0; i2 < nod2.subNodes_.size(); i2++)
|
for (direction i2 = 0; i2 < node::nChildren; ++i2)
|
||||||
{
|
{
|
||||||
labelBits subIndex2 = nod2.subNodes_[i2];
|
labelBits subIndex2 = nod2.subNodes_[i2];
|
||||||
const treeBoundBox subBb2
|
const treeBoundBox subBb2
|
||||||
@ -2100,7 +2095,7 @@ Foam::label Foam::indexedOctree<Type>::countElements
|
|||||||
|
|
||||||
const node& nod = nodes_[nodeI];
|
const node& nod = nodes_[nodeI];
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
nElems += countElements(nod.subNodes_[octant]);
|
nElems += countElements(nod.subNodes_[octant]);
|
||||||
}
|
}
|
||||||
@ -2118,6 +2113,43 @@ Foam::label Foam::indexedOctree<Type>::countElements
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::indexedOctree<Type>::writeOBJ
|
||||||
|
(
|
||||||
|
const label nodeI,
|
||||||
|
Ostream& os,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool leavesOnly,
|
||||||
|
const bool writeLinesOnly
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const node& nod = nodes_[nodeI];
|
||||||
|
const treeBoundBox& bb = nod.bb_;
|
||||||
|
|
||||||
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
|
{
|
||||||
|
const treeBoundBox subBb(bb.subBbox(octant));
|
||||||
|
|
||||||
|
labelBits index = nod.subNodes_[octant];
|
||||||
|
|
||||||
|
if (isNode(index))
|
||||||
|
{
|
||||||
|
label subNodeI = getNode(index);
|
||||||
|
|
||||||
|
writeOBJ(subNodeI, os, vertIndex, leavesOnly, writeLinesOnly);
|
||||||
|
}
|
||||||
|
else if (isContent(index))
|
||||||
|
{
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
|
}
|
||||||
|
else if (isEmpty(index) && !leavesOnly)
|
||||||
|
{
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void Foam::indexedOctree<Type>::writeOBJ
|
void Foam::indexedOctree<Type>::writeOBJ
|
||||||
(
|
(
|
||||||
@ -2125,11 +2157,6 @@ void Foam::indexedOctree<Type>::writeOBJ
|
|||||||
const direction octant
|
const direction octant
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
OFstream str
|
|
||||||
(
|
|
||||||
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
|
||||||
);
|
|
||||||
|
|
||||||
labelBits index = nodes_[nodeI].subNodes_[octant];
|
labelBits index = nodes_[nodeI].subNodes_[octant];
|
||||||
|
|
||||||
treeBoundBox subBb;
|
treeBoundBox subBb;
|
||||||
@ -2143,24 +2170,28 @@ void Foam::indexedOctree<Type>::writeOBJ
|
|||||||
subBb = nodes_[nodeI].bb_.subBbox(octant);
|
subBb = nodes_[nodeI].bb_.subBbox(octant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OFstream os
|
||||||
|
(
|
||||||
|
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
||||||
|
);
|
||||||
|
|
||||||
Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
|
Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
|
||||||
<< " to " << str.name() << endl;
|
<< " to " << os.name() << endl;
|
||||||
|
|
||||||
// Dump bounding box
|
bool writeLinesOnly(false);
|
||||||
pointField bbPoints(subBb.points());
|
label vertIndex(0);
|
||||||
|
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||||
forAll(bbPoints, i)
|
|
||||||
{
|
|
||||||
const point& pt = bbPoints[i];
|
|
||||||
|
|
||||||
str<< "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forAll(treeBoundBox::edges, i)
|
|
||||||
{
|
|
||||||
const edge& e = treeBoundBox::edges[i];
|
|
||||||
|
|
||||||
str<< "l " << e[0] + 1 << ' ' << e[1] + 1 << nl;
|
template<class Type>
|
||||||
|
void Foam::indexedOctree<Type>::writeOBJ(Ostream& os) const
|
||||||
|
{
|
||||||
|
if (!nodes_.empty())
|
||||||
|
{
|
||||||
|
label vertIndex(0);
|
||||||
|
// leavesOnly=true, writeLinesOnly=false
|
||||||
|
writeOBJ(0, os, vertIndex, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2210,7 +2241,7 @@ Foam::indexedOctree<Type>::indexedOctree
|
|||||||
int oldMemSize = 0;
|
int oldMemSize = 0;
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "indexedOctree<Type>::indexedOctree:" << nl
|
Pout<< "indexedOctree::indexedOctree:" << nl
|
||||||
<< " shapes:" << shapes.size() << nl
|
<< " shapes:" << shapes.size() << nl
|
||||||
<< " bb:" << bb << nl
|
<< " bb:" << bb << nl
|
||||||
<< endl;
|
<< endl;
|
||||||
@ -2241,24 +2272,28 @@ Foam::indexedOctree<Type>::indexedOctree
|
|||||||
{
|
{
|
||||||
// Count number of references into shapes (i.e. contents)
|
// Count number of references into shapes (i.e. contents)
|
||||||
label nEntries = 0;
|
label nEntries = 0;
|
||||||
|
label minEntries = shapes.size();
|
||||||
label maxEntries = 0;
|
label maxEntries = 0;
|
||||||
forAll(contents, i)
|
for (const auto& subContents : contents)
|
||||||
{
|
{
|
||||||
maxEntries = max(maxEntries, contents[i].size());
|
const label num = subContents.size();
|
||||||
nEntries += contents[i].size();
|
|
||||||
|
nEntries += num;
|
||||||
|
minEntries = min(minEntries, num);
|
||||||
|
maxEntries = max(maxEntries, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "indexedOctree<Type>::indexedOctree:" << nl
|
Pout<< "indexedOctree::indexedOctree:" << nl
|
||||||
<< " nLevels:" << nLevels << nl
|
<< " nLevels:" << nLevels << nl
|
||||||
<< " nEntries per treeLeaf:" << nEntries/contents.size()
|
<< " nEntries:" << nEntries << nl
|
||||||
<< nl
|
<< " - min per leaf: " << minEntries << nl
|
||||||
<< " nEntries per shape (duplicity):"
|
<< " - max per leaf: " << maxEntries << nl
|
||||||
<< nEntries/shapes.size()
|
<< " - avg per leaf: "
|
||||||
<< nl
|
<< scalar(nEntries)/contents.size() << nl
|
||||||
<< " max nEntries:" << maxEntries
|
<< " - per shape (duplicity): "
|
||||||
<< nl
|
<< scalar(nEntries)/shapes_.size() << nl
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2334,17 +2369,20 @@ Foam::indexedOctree<Type>::indexedOctree
|
|||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
label nEntries = 0;
|
label nEntries = 0;
|
||||||
|
label minEntries = shapes.size();
|
||||||
label maxEntries = 0;
|
label maxEntries = 0;
|
||||||
forAll(contents_, i)
|
for (const auto& subContents : contents_)
|
||||||
{
|
{
|
||||||
maxEntries = max(maxEntries, contents_[i].size());
|
const label num = subContents.size();
|
||||||
nEntries += contents_[i].size();
|
|
||||||
|
nEntries += num;
|
||||||
|
minEntries = min(minEntries, num);
|
||||||
|
maxEntries = max(maxEntries, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
label memSize = memInfo().size();
|
label memSize = memInfo().size();
|
||||||
|
|
||||||
|
Pout<< "indexedOctree::indexedOctree"
|
||||||
Pout<< "indexedOctree<Type>::indexedOctree"
|
|
||||||
<< " : finished construction of tree of:" << shapes.typeName
|
<< " : finished construction of tree of:" << shapes.typeName
|
||||||
<< nl
|
<< nl
|
||||||
<< " bb:" << this->bb() << nl
|
<< " bb:" << this->bb() << nl
|
||||||
@ -2352,13 +2390,13 @@ Foam::indexedOctree<Type>::indexedOctree
|
|||||||
<< " nLevels:" << nLevels << nl
|
<< " nLevels:" << nLevels << nl
|
||||||
<< " treeNodes:" << nodes_.size() << nl
|
<< " treeNodes:" << nodes_.size() << nl
|
||||||
<< " nEntries:" << nEntries << nl
|
<< " nEntries:" << nEntries << nl
|
||||||
<< " per treeLeaf:"
|
<< " - min per leaf:" << minEntries << nl
|
||||||
|
<< " - max per leaf:" << maxEntries << nl
|
||||||
|
<< " - avg per leaf:"
|
||||||
<< scalar(nEntries)/contents.size() << nl
|
<< scalar(nEntries)/contents.size() << nl
|
||||||
<< " per shape (duplicity):"
|
<< " - per shape (duplicity):"
|
||||||
<< scalar(nEntries)/shapes.size() << nl
|
<< scalar(nEntries)/shapes.size() << nl
|
||||||
<< " max nEntries:" << maxEntries
|
<< " total memory:" << memSize-oldMemSize << nl
|
||||||
<< nl
|
|
||||||
<< " total memory:" << memSize-oldMemSize
|
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2740,7 +2778,7 @@ Foam::volumeType Foam::indexedOctree<Type>::getVolumeType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pout<< "indexedOctree<Type>::getVolumeType : "
|
Pout<< "indexedOctree::getVolumeType : "
|
||||||
<< " bb:" << bb()
|
<< " bb:" << bb()
|
||||||
<< " nodes_:" << nodes_.size()
|
<< " nodes_:" << nodes_.size()
|
||||||
<< " nodeTypes_:" << nodeTypes_.size()
|
<< " nodeTypes_:" << nodeTypes_.size()
|
||||||
@ -2803,7 +2841,7 @@ void Foam::indexedOctree<Type>::print
|
|||||||
<< "parent:" << nod.parent_ << nl
|
<< "parent:" << nod.parent_ << nl
|
||||||
<< "n:" << countElements(nodePlusOctant(nodeI, 0)) << nl;
|
<< "n:" << countElements(nodePlusOctant(nodeI, 0)) << nl;
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||||
{
|
{
|
||||||
const treeBoundBox subBb(bb.subBbox(octant));
|
const treeBoundBox subBb(bb.subBbox(octant));
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -52,45 +53,61 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
|
class Istream;
|
||||||
template<class Type> class indexedOctree;
|
template<class Type> class indexedOctree;
|
||||||
template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
|
template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
|
||||||
class Istream;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class indexedOctreeName Declaration
|
Class indexedOctreeBase Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TemplateName(indexedOctree);
|
//- Template invariant parts for indexedOctree
|
||||||
|
// The internal node bookkeeping is encoded follows:
|
||||||
|
// - 0: empty
|
||||||
/*---------------------------------------------------------------------------*\
|
// - +ve: parent
|
||||||
Class indexedOctree Declaration
|
// - -ve: leaf
|
||||||
\*---------------------------------------------------------------------------*/
|
class indexedOctreeBase
|
||||||
|
|
||||||
template<class Type>
|
|
||||||
class indexedOctree
|
|
||||||
:
|
|
||||||
public indexedOctreeName
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Data types
|
// Public Data Types
|
||||||
|
|
||||||
//- Tree node. Has up pointer and down pointers.
|
//- Tree node. Has up pointer and down pointers.
|
||||||
class node
|
class node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//- Has exactly 8 sub-nodes (octants)
|
||||||
|
static constexpr direction nChildren = 8;
|
||||||
|
|
||||||
//- Bounding box of this node
|
//- Bounding box of this node
|
||||||
treeBoundBox bb_;
|
treeBoundBox bb_;
|
||||||
|
|
||||||
//- Parent node (index into nodes_ of tree)
|
//- Parent node (index into flat list addressing for tree)
|
||||||
label parent_;
|
label parent_ = -1;
|
||||||
|
|
||||||
//- IDs of the 8 nodes on all sides of the mid point
|
//- IDs of the 8 nodes on all sides of the mid point
|
||||||
FixedList<labelBits, 8> subNodes_;
|
FixedList<labelBits, 8> subNodes_;
|
||||||
|
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
|
||||||
|
friend bool operator==(const node& a, const node& b)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
a.parent_ == b.parent_
|
||||||
|
&& a.subNodes_ == b.subNodes_
|
||||||
|
&& a.bb_ == b.bb_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const node& a, const node& b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
friend Ostream& operator<< (Ostream& os, const node& n)
|
friend Ostream& operator<< (Ostream& os, const node& n)
|
||||||
{
|
{
|
||||||
return os << n.bb_ << token::SPACE
|
return os << n.bb_ << token::SPACE
|
||||||
@ -101,24 +118,124 @@ public:
|
|||||||
{
|
{
|
||||||
return is >> n.bb_ >> n.parent_ >> n.subNodes_;
|
return is >> n.bb_ >> n.parent_ >> n.subNodes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const node& a, const node& b)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
a.bb_ == b.bb_
|
|
||||||
&& a.parent_ == b.parent_
|
|
||||||
&& a.subNodes_ == b.subNodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(const node& a, const node& b)
|
|
||||||
{
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
// Static Functions
|
||||||
|
|
||||||
|
// Tests for node handling
|
||||||
|
// (0: empty, +ve: parent, -ve: leaf)
|
||||||
|
|
||||||
|
//- An empty node - no content
|
||||||
|
static bool isEmpty(labelBits i) noexcept
|
||||||
|
{
|
||||||
|
return (i.val() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Node with content (leaf)
|
||||||
|
static bool isContent(labelBits i) noexcept
|
||||||
|
{
|
||||||
|
return (i.val() < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- A parent node
|
||||||
|
static bool isNode(labelBits i) noexcept
|
||||||
|
{
|
||||||
|
return (i.val() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Decode/retrieve node addressing
|
||||||
|
|
||||||
|
//- Return real (dereferenced) index for a content node
|
||||||
|
static label getContent(labelBits i)
|
||||||
|
{
|
||||||
|
if (!isContent(i))
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
return (-i.val()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return real (dereferenced) index for a parent node
|
||||||
|
static label getNode(const labelBits i)
|
||||||
|
{
|
||||||
|
if (!isNode(i))
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
return (i.val()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return sub-node direction/octant
|
||||||
|
static direction getOctant(labelBits i) noexcept
|
||||||
|
{
|
||||||
|
return i.bits();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
// Encode node addressing
|
||||||
|
// (only used when building)
|
||||||
|
|
||||||
|
//- From empty to subNodes_ entry
|
||||||
|
static labelBits emptyPlusOctant(direction octant)
|
||||||
|
{
|
||||||
|
return labelBits(0, octant);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- From index into contents_ to subNodes_ entry
|
||||||
|
static labelBits contentPlusOctant(label i, direction octant)
|
||||||
|
{
|
||||||
|
return labelBits(-i-1, octant);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- From index into nodes_ to subNodes_ entry
|
||||||
|
static labelBits nodePlusOctant(label i, direction octant)
|
||||||
|
{
|
||||||
|
return labelBits(i+1, octant);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
ClassName("indexedOctree");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
indexedOctreeBase() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Output Helpers
|
||||||
|
|
||||||
|
//- Write treeBoundBox in OBJ format
|
||||||
|
static void writeOBJ
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const treeBoundBox& bb,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool writeLinesOnly = false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class indexedOctree Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
class indexedOctree
|
||||||
|
:
|
||||||
|
public indexedOctreeBase
|
||||||
|
{
|
||||||
// Static data
|
// Static data
|
||||||
|
|
||||||
//- Relative perturbation tolerance. Determines when point is
|
//- Relative perturbation tolerance. Determines when point is
|
||||||
@ -128,7 +245,7 @@ private:
|
|||||||
static scalar perturbTol_;
|
static scalar perturbTol_;
|
||||||
|
|
||||||
|
|
||||||
// Private data
|
// Private Data
|
||||||
|
|
||||||
//- Underlying shapes for geometric queries.
|
//- Underlying shapes for geometric queries.
|
||||||
const Type shapes_;
|
const Type shapes_;
|
||||||
@ -142,6 +259,7 @@ private:
|
|||||||
//- Per node per octant whether is fully inside/outside/mixed.
|
//- Per node per octant whether is fully inside/outside/mixed.
|
||||||
mutable PackedList<2> nodeTypes_;
|
mutable PackedList<2> nodeTypes_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Helper: does bb intersect a sphere around sample? Or is any
|
//- Helper: does bb intersect a sphere around sample? Or is any
|
||||||
@ -366,37 +484,19 @@ private:
|
|||||||
//- Count number of elements on this and sublevels
|
//- Count number of elements on this and sublevels
|
||||||
label countElements(const labelBits index) const;
|
label countElements(const labelBits index) const;
|
||||||
|
|
||||||
|
//- Write node treeBoundBoxes in OBJ format
|
||||||
|
void writeOBJ
|
||||||
|
(
|
||||||
|
const label nodeI,
|
||||||
|
Ostream& os,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool leavesOnly,
|
||||||
|
const bool writeLinesOnly = false
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Dump node+octant to an obj file
|
//- Dump node+octant to an obj file
|
||||||
void writeOBJ(const label nodeI, const direction octant) const;
|
void writeOBJ(const label nodeI, const direction octant) const;
|
||||||
|
|
||||||
//- From index into contents_ to subNodes_ entry
|
|
||||||
static labelBits contentPlusOctant
|
|
||||||
(
|
|
||||||
const label i,
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(-i - 1, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- From index into nodes_ to subNodes_ entry
|
|
||||||
static labelBits nodePlusOctant
|
|
||||||
(
|
|
||||||
const label i,
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(i + 1, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- From empty to subNodes_ entry
|
|
||||||
static labelBits emptyPlusOctant
|
|
||||||
(
|
|
||||||
const direction octant
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return labelBits(0, octant);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -437,29 +537,30 @@ public:
|
|||||||
return autoPtr<indexedOctree<Type>>::New(*this);
|
return autoPtr<indexedOctree<Type>>::New(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Reference to shape
|
//- Reference to shape
|
||||||
const Type& shapes() const
|
const Type& shapes() const noexcept { return shapes_; }
|
||||||
{
|
|
||||||
return shapes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- List of all nodes
|
//- List of all nodes
|
||||||
const List<node>& nodes() const
|
const List<node>& nodes() const noexcept { return nodes_; }
|
||||||
{
|
|
||||||
return nodes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- List of all contents (referenced by those nodes that are
|
//- List of all contents
|
||||||
// contents)
|
//- (referenced by those nodes that are contents)
|
||||||
const labelListList& contents() const
|
const List<labelList>& contents() const noexcept
|
||||||
{
|
{
|
||||||
return contents_;
|
return contents_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- Per node, per octant whether is fully inside/outside/mixed.
|
||||||
|
PackedList<2>& nodeTypes() const noexcept
|
||||||
|
{
|
||||||
|
return nodeTypes_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Top bounding box
|
//- Top bounding box
|
||||||
const treeBoundBox& bb() const
|
const treeBoundBox& bb() const
|
||||||
{
|
{
|
||||||
@ -470,55 +571,6 @@ public:
|
|||||||
return nodes_[0].bb_;
|
return nodes_[0].bb_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Per node, per octant whether is fully inside/outside/mixed.
|
|
||||||
PackedList<2>& nodeTypes() const
|
|
||||||
{
|
|
||||||
return nodeTypes_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Conversions for entries in subNodes_.
|
|
||||||
|
|
||||||
static bool isContent(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isEmpty(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isNode(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.val() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static label getContent(const labelBits i)
|
|
||||||
{
|
|
||||||
if (!isContent(i))
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
return -i.val()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static label getNode(const labelBits i)
|
|
||||||
{
|
|
||||||
if (!isNode(i))
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< abort(FatalError);
|
|
||||||
}
|
|
||||||
return i.val() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static direction getOctant(const labelBits i)
|
|
||||||
{
|
|
||||||
return i.bits();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Queries
|
// Queries
|
||||||
|
|
||||||
@ -672,6 +724,9 @@ public:
|
|||||||
|
|
||||||
// Write
|
// Write
|
||||||
|
|
||||||
|
//- Write (non-empty) tree boxes in OBJ format
|
||||||
|
void writeOBJ(Ostream& os) const;
|
||||||
|
|
||||||
//- Print tree. Either print all indices (printContent = true) or
|
//- Print tree. Either print all indices (printContent = true) or
|
||||||
// just size of contents nodes.
|
// just size of contents nodes.
|
||||||
void print
|
void print
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2012 OpenFOAM Foundation
|
Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -26,12 +27,58 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
|
#include "treeBoundBox.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(indexedOctreeName, 0);
|
defineTypeNameAndDebug(indexedOctreeBase, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::indexedOctreeBase::writeOBJ
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const treeBoundBox& bb,
|
||||||
|
label& vertIndex,
|
||||||
|
const bool writeLinesOnly
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Annotate with '#box' which can be grep'd for later
|
||||||
|
os << "#box" << nl;
|
||||||
|
|
||||||
|
pointField pts(bb.points());
|
||||||
|
|
||||||
|
for (const point& p : pts)
|
||||||
|
{
|
||||||
|
os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writeLinesOnly)
|
||||||
|
{
|
||||||
|
for (const edge& e : treeBoundBox::edges)
|
||||||
|
{
|
||||||
|
os << "l " << e[0] + vertIndex + 1
|
||||||
|
<< ' ' << e[1] + vertIndex + 1 << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const face& f : treeBoundBox::faces)
|
||||||
|
{
|
||||||
|
os << 'f';
|
||||||
|
for (const label fpi : f)
|
||||||
|
{
|
||||||
|
os << ' ' << fpi + vertIndex + 1;
|
||||||
|
}
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vertIndex += pts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1517,7 +1517,7 @@ void Foam::distributedTriSurfaceMesh::collectLeafMids
|
|||||||
DynamicField<point>& midPoints
|
DynamicField<point>& midPoints
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataTriSurface>::node& nod = tree().nodes()[nodeI];
|
const auto& nod = tree().nodes()[nodeI];
|
||||||
|
|
||||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
||||||
{
|
{
|
||||||
@ -1557,7 +1557,7 @@ Foam::volumeType Foam::distributedTriSurfaceMesh::calcVolumeType
|
|||||||
// Recurses to determine status of lowest level boxes. Level above is
|
// Recurses to determine status of lowest level boxes. Level above is
|
||||||
// combination of octants below.
|
// combination of octants below.
|
||||||
|
|
||||||
const indexedOctree<treeDataTriSurface>::node& nod = tree().nodes()[nodeI];
|
const auto& nod = tree().nodes()[nodeI];
|
||||||
|
|
||||||
volumeType myType = volumeType::UNKNOWN;
|
volumeType myType = volumeType::UNKNOWN;
|
||||||
|
|
||||||
@ -1619,7 +1619,7 @@ Foam::volumeType Foam::distributedTriSurfaceMesh::cachedVolumeType
|
|||||||
const point& sample
|
const point& sample
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataTriSurface>::node& nod = tree().nodes()[nodeI];
|
const auto& nod = tree().nodes()[nodeI];
|
||||||
|
|
||||||
direction octant = nod.bb_.subOctant(sample);
|
direction octant = nod.bb_.subOctant(sample);
|
||||||
|
|
||||||
@ -4141,10 +4141,9 @@ void Foam::distributedTriSurfaceMesh::getVolumeType
|
|||||||
{
|
{
|
||||||
// Get local tree
|
// Get local tree
|
||||||
const indexedOctree<treeDataTriSurface>& t = tree();
|
const indexedOctree<treeDataTriSurface>& t = tree();
|
||||||
|
const auto& nodes = t.nodes();
|
||||||
PackedList<2>& nt = t.nodeTypes();
|
PackedList<2>& nt = t.nodeTypes();
|
||||||
const List<indexedOctree<treeDataTriSurface>::node>& nodes =
|
nt.resize(nodes.size());
|
||||||
t.nodes();
|
|
||||||
nt.setSize(nodes.size());
|
|
||||||
nt = volumeType::UNKNOWN;
|
nt = volumeType::UNKNOWN;
|
||||||
|
|
||||||
// Collect midpoints
|
// Collect midpoints
|
||||||
|
|||||||
Reference in New Issue
Block a user