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
@ -179,7 +179,7 @@ void Foam::dynamicIndexedOctree<Type>::divide
|
||||
|
||||
|
||||
template<class Type>
|
||||
typename Foam::dynamicIndexedOctree<Type>::node
|
||||
Foam::dynamicIndexedOctreeBase::node
|
||||
Foam::dynamicIndexedOctree<Type>::divide
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
@ -295,9 +295,9 @@ void Foam::dynamicIndexedOctree<Type>::recursiveSubDivision
|
||||
|
||||
// Recursively divide the contents until maxLevels_ is
|
||||
// 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))
|
||||
{
|
||||
@ -335,7 +335,7 @@ Foam::volumeType Foam::dynamicIndexedOctree<Type>::calcVolumeType
|
||||
|
||||
volumeType myType = volumeType::UNKNOWN;
|
||||
|
||||
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
|
||||
for (direction octant = 0; octant < node::nChildren; ++octant)
|
||||
{
|
||||
volumeType subType;
|
||||
|
||||
@ -1027,7 +1027,7 @@ bool Foam::dynamicIndexedOctree<Type>::walkToParent
|
||||
// Find octant nodeI is in.
|
||||
parentOctant = 255;
|
||||
|
||||
for (direction i = 0; i < parentNode.subNodes_.size(); i++)
|
||||
for (direction i = 0; i < node::nChildren; ++i)
|
||||
{
|
||||
labelBits index = parentNode.subNodes_[i];
|
||||
|
||||
@ -1794,7 +1794,7 @@ void Foam::dynamicIndexedOctree<Type>::findBox
|
||||
const node& nod = nodes_[nodeI];
|
||||
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];
|
||||
|
||||
@ -1842,7 +1842,7 @@ void Foam::dynamicIndexedOctree<Type>::findSphere
|
||||
const node& nod = nodes_[nodeI];
|
||||
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];
|
||||
|
||||
@ -1910,7 +1910,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
||||
{
|
||||
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];
|
||||
const treeBoundBox subBb2
|
||||
@ -1938,7 +1938,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
||||
else if (tree2.isContent(index2))
|
||||
{
|
||||
// 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];
|
||||
const treeBoundBox subBb1
|
||||
@ -1978,7 +1978,7 @@ void Foam::dynamicIndexedOctree<Type>::findNear
|
||||
|
||||
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];
|
||||
const treeBoundBox subBb2
|
||||
@ -2067,7 +2067,7 @@ Foam::label Foam::dynamicIndexedOctree<Type>::countElements
|
||||
|
||||
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]);
|
||||
}
|
||||
@ -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>
|
||||
void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
||||
(
|
||||
@ -2092,11 +2129,6 @@ void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
||||
const direction octant
|
||||
) const
|
||||
{
|
||||
OFstream str
|
||||
(
|
||||
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
||||
);
|
||||
|
||||
labelBits index = nodes_[nodeI].subNodes_[octant];
|
||||
|
||||
treeBoundBox subBb;
|
||||
@ -2110,24 +2142,28 @@ void Foam::dynamicIndexedOctree<Type>::writeOBJ
|
||||
subBb = nodes_[nodeI].bb_.subBbox(octant);
|
||||
}
|
||||
|
||||
OFstream os
|
||||
(
|
||||
"node" + Foam::name(nodeI) + "_octant" + Foam::name(octant) + ".obj"
|
||||
);
|
||||
|
||||
Pout<< "dumpContentNode : writing node:" << nodeI << " octant:" << octant
|
||||
<< " to " << str.name() << endl;
|
||||
<< " to " << os.name() << endl;
|
||||
|
||||
// Dump bounding box
|
||||
pointField bbPoints(subBb.points());
|
||||
bool writeLinesOnly(false);
|
||||
label vertIndex(0);
|
||||
indexedOctreeBase::writeOBJ(os, subBb, vertIndex, writeLinesOnly);
|
||||
}
|
||||
|
||||
forAll(bbPoints, i)
|
||||
|
||||
template<class Type>
|
||||
void Foam::dynamicIndexedOctree<Type>::writeOBJ(Ostream& os) const
|
||||
{
|
||||
if (!nodes_.empty())
|
||||
{
|
||||
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;
|
||||
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()
|
||||
<< " nodes_:" << nodes_.size()
|
||||
<< " nodeTypes_:" << nodeTypes_.size()
|
||||
@ -2552,9 +2588,9 @@ bool Foam::dynamicIndexedOctree<Type>::insertIndex
|
||||
{
|
||||
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))
|
||||
{
|
||||
@ -2642,9 +2678,9 @@ Foam::label Foam::dynamicIndexedOctree<Type>::removeIndex
|
||||
{
|
||||
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))
|
||||
{
|
||||
@ -2731,7 +2767,7 @@ void Foam::dynamicIndexedOctree<Type>::print
|
||||
<< "parent:" << nod.parent_ << 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));
|
||||
|
||||
@ -2798,7 +2834,7 @@ void Foam::dynamicIndexedOctree<Type>::writeTreeInfo() const
|
||||
nEntries += contents_[i]->size();
|
||||
}
|
||||
|
||||
Pout<< "indexedOctree<Type>::indexedOctree"
|
||||
Pout<< "indexedOctree::indexedOctree"
|
||||
<< " : finished construction of tree of:" << shapes().typeName
|
||||
<< nl
|
||||
<< " bounding box: " << this->bb() << nl
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -38,14 +39,8 @@ SourceFiles
|
||||
#ifndef Foam_dynamicIndexedOctree_H
|
||||
#define Foam_dynamicIndexedOctree_H
|
||||
|
||||
#include "treeBoundBox.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "FixedList.H"
|
||||
#include "Ostream.H"
|
||||
#include "HashSet.H"
|
||||
#include "labelBits.H"
|
||||
#include "PackedList.H"
|
||||
#include "volumeType.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -55,22 +50,36 @@ namespace Foam
|
||||
typedef DynamicList<autoPtr<DynamicList<label>>> contentListList;
|
||||
|
||||
// Forward Declarations
|
||||
template<class Type> class dynamicIndexedOctree;
|
||||
|
||||
template<class Type> Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const dynamicIndexedOctree<Type>&
|
||||
);
|
||||
|
||||
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>
|
||||
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
|
||||
|
||||
//- Relative perturbation tolerance. Determines when point is
|
||||
@ -137,7 +100,7 @@ private:
|
||||
static scalar perturbTol_;
|
||||
|
||||
|
||||
// Private data
|
||||
// Private Data
|
||||
|
||||
//- Underlying shapes for geometric queries.
|
||||
const Type shapes_;
|
||||
@ -361,42 +324,24 @@ private:
|
||||
);
|
||||
|
||||
|
||||
// Other
|
||||
// Other
|
||||
|
||||
//- Count number of elements on this and sublevels
|
||||
label countElements(const labelBits index) const;
|
||||
//- Count number of elements on this and sublevels
|
||||
label countElements(const labelBits index) const;
|
||||
|
||||
//- Dump node+octant to an obj file
|
||||
void writeOBJ(const label nodeI, const direction octant) const;
|
||||
//- Write node treeBoundBoxes in OBJ format
|
||||
void writeOBJ
|
||||
(
|
||||
const label nodeI,
|
||||
Ostream& os,
|
||||
label& vertIndex,
|
||||
const bool leavesOnly,
|
||||
const bool writeLinesOnly = false
|
||||
) const;
|
||||
|
||||
//- From index into contents_ to subNodes_ entry
|
||||
static labelBits contentPlusOctant
|
||||
(
|
||||
const label i,
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(-i - 1, octant);
|
||||
}
|
||||
//- Dump node+octant to an obj file
|
||||
void writeOBJ(const label nodeI, const direction octant) const;
|
||||
|
||||
//- 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:
|
||||
|
||||
@ -426,79 +371,36 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
// Access
|
||||
|
||||
//- Reference to shape
|
||||
const Type& shapes() const
|
||||
//- Reference to shape
|
||||
const Type& shapes() const noexcept { return shapes_; }
|
||||
|
||||
//- List of all nodes
|
||||
const List<node>& nodes() const noexcept { return nodes_; }
|
||||
|
||||
//- List of all contents
|
||||
//- (referenced by those nodes that are contents)
|
||||
const contentListList& contents() const
|
||||
{
|
||||
return contents_;
|
||||
}
|
||||
|
||||
//- Per node, per octant whether is fully inside/outside/mixed.
|
||||
PackedList<2>& nodeTypes() const noexcept
|
||||
{
|
||||
return nodeTypes_;
|
||||
}
|
||||
|
||||
//- Top bounding box
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
if (nodes_.empty())
|
||||
{
|
||||
return shapes_;
|
||||
}
|
||||
|
||||
//- List of all nodes
|
||||
const List<node>& nodes() const
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
//- List of all contents (referenced by those nodes that are
|
||||
// contents)
|
||||
const contentListList& contents() const
|
||||
{
|
||||
return contents_;
|
||||
}
|
||||
|
||||
//- Top bounding box
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
if (nodes_.empty())
|
||||
{
|
||||
return treeBoundBox::null();
|
||||
}
|
||||
return nodes_[0].bb_;
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
return treeBoundBox::null();
|
||||
}
|
||||
return nodes_[0].bb_;
|
||||
}
|
||||
|
||||
|
||||
// Queries
|
||||
@ -629,20 +531,23 @@ public:
|
||||
label removeIndex(const label nodIndex, const label index);
|
||||
|
||||
|
||||
// Write
|
||||
// Write
|
||||
|
||||
//- Print tree. Either print all indices (printContent = true) or
|
||||
// just size of contents nodes.
|
||||
void print
|
||||
(
|
||||
prefixOSstream&,
|
||||
const bool printContents,
|
||||
const label
|
||||
) const;
|
||||
//- Write all tree boxes as OBJ format
|
||||
void writeOBJ(Ostream& os) const;
|
||||
|
||||
bool write(Ostream& os) const;
|
||||
//- Print tree. Either print all indices (printContent = true) or
|
||||
// just size of contents nodes.
|
||||
void print
|
||||
(
|
||||
prefixOSstream&,
|
||||
const bool printContents,
|
||||
const label
|
||||
) const;
|
||||
|
||||
void writeTreeInfo() const;
|
||||
bool write(Ostream& os) const;
|
||||
|
||||
void writeTreeInfo() const;
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
@ -31,7 +31,7 @@ License
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(dynamicIndexedOctreeName, 0);
|
||||
defineTypeNameAndDebug(dynamicIndexedOctreeBase, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user