Files
openfoam/src/meshTools/octree/treeLeaf.C
2009-08-18 10:43:51 +01:00

468 lines
11 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "treeLeaf.H"
#include "treeNode.H"
#include "treeBoundBox.H"
#include "octree.H"
#include "HashSet.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template <class Type>
void Foam::treeLeaf<Type>::space(Ostream& os, const label n)
{
for (label i=0; i<n; i++)
{
os<< ' ';
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct with given size
template <class Type>
Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const label size)
:
treeElem<Type>(bb), size_(0), indices_(size)
{}
// Construct from list
template <class Type>
Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const labelList& indices)
:
treeElem<Type>(bb), size_(indices.size()), indices_(indices)
{
}
// Construct from Istream
template <class Type>
Foam::treeLeaf<Type>::treeLeaf(Istream& is)
{
is >> *this;
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template <class Type>
Foam::treeLeaf<Type>::~treeLeaf()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Take cells at this level and distribute them to lower levels
template <class Type>
Foam::treeLeaf<Type>* Foam::treeLeaf<Type>::redistribute
(
const label level,
octree<Type>& top,
const Type& shapes
)
{
if (debug & 1)
{
space(Pout, level);
Pout<< "treeLeaf::redistribute with bb:" << this->bb() << endl;
}
if (size_ <= top.maxLeafRatio())
{
// leaf small enough
if (debug & 1)
{
space(Pout, level);
Pout<< "end of treeLeaf::redistribute : small enough" << endl;
}
return this;
}
else
{
// create treeNode for this level
treeNode<Type>* treeNodePtr = new treeNode<Type>(this->bb());
top.setNodes(top.nNodes() + 1);
treeNodePtr->distribute
(
level,
top,
shapes,
indices_
);
if (debug & 1)
{
space(Pout, level);
Pout<< "end of treeLeaf::redistribute : done creating node"
<< this->bb() << endl;
}
// return pointer to let level above know.
return reinterpret_cast<treeLeaf<Type>*>(treeNodePtr);
}
}
// Set type of subnodes. Since contains elements return mixed type always.
template <class Type>
Foam::label Foam::treeLeaf<Type>::setSubNodeType
(
const label level,
octree<Type>& top,
const Type& shapes
) const
{
if (size() == 0)
{
FatalErrorIn
(
"treeLeaf<Type>::setSubNodeType(const label, octree<Type>&, "
"const Type&)"
) << "empty leaf. bb:" << this->bb()
<< abort(FatalError);
}
return octree<Type>::MIXED;
}
template <class Type>
Foam::label Foam::treeLeaf<Type>::getSampleType
(
const label level,
const octree<Type>& top,
const Type& shapes,
const point& sample
) const
{
return shapes.getSampleType(top, sample);
}
template <class Type>
Foam::label Foam::treeLeaf<Type>::find
(
const Type& shapes,
const point& sample
) const
{
forAll(indices_, i)
{
if (shapes.contains(indices_[i], sample))
{
return indices_[i];
}
}
return -1;
}
template <class Type>
bool Foam::treeLeaf<Type>::findTightest
(
const Type& shapes,
const point& sample,
treeBoundBox& tightest
) const
{
bool changed = false;
forAll(indices_, i)
{
changed |= shapes.findTightest
(
indices_[i],
sample,
tightest
);
}
return changed;
}
template <class Type>
bool Foam::treeLeaf<Type>::findNearest
(
const Type& shapes,
const point& sample,
treeBoundBox& tightest,
label& tightestI,
scalar& tightestDist
) const
{
bool changed = false;
forAll(indices_, i)
{
if (shapes.overlaps(indices_[i], tightest))
{
if (debug & 8)
{
//space(Pout, level);
Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
<< " shape:" << indices_[i] << " overlaps:" << tightest
<< endl;
}
point nearest;
scalar thisDist = shapes.calcNearest(indices_[i], sample, nearest);
if (thisDist < tightestDist)
{
// Construct new tightest Bb
point dist(thisDist, thisDist, thisDist);
tightest.min() = sample - dist;
tightest.max() = sample + dist;
// Update other return values
tightestI = indices_[i];
tightestDist = thisDist;
changed = true;
if (debug & 8)
{
//space(Pout, level);
Pout<< "treeLeaf<Type>::findNearest : Found nearer : shape:"
<< tightestI << " distance:" << tightestDist
<< " to sample:" << sample << endl;
}
}
}
}
if (changed)
{
if (debug & 8)
{
//space(Pout, level);
Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
<< " new nearer:" << tightestDist
<< endl;
}
}
return changed;
}
template <class Type>
bool Foam::treeLeaf<Type>::findNearest
(
const Type& shapes,
const linePointRef& ln,
treeBoundBox& tightest,
label& tightestI,
point& linePoint, // nearest point on line
point& shapePoint // nearest point on shape
) const
{
// Initial smallest distance
scalar tightestDist = mag(linePoint - shapePoint);
bool changed = false;
forAll(indices_, i)
{
if (shapes.overlaps(indices_[i], tightest))
{
// Calculate nearest point on line and on shape.
point linePt, shapePt;
scalar thisDist = shapes.calcNearest
(
indices_[i],
ln,
linePt,
shapePt
);
if (thisDist < tightestDist)
{
// Found nearer. Use.
tightestDist = thisDist;
tightestI = indices_[i];
linePoint = linePt;
shapePoint = shapePt;
// Construct new tightest Bb. Nearest point can never be further
// away than bounding box of line + margin equal to the distance
vector span(thisDist, thisDist, thisDist);
tightest.min() = min(ln.start(), ln.end()) - span;
tightest.max() = max(ln.start(), ln.end()) + span;
changed = true;
}
}
}
return changed;
}
template <class Type>
bool Foam::treeLeaf<Type>::findBox
(
const Type& shapes,
const boundBox& box,
labelHashSet& elements
) const
{
bool changed = false;
forAll(indices_, i)
{
if (shapes.overlaps(indices_[i], box))
{
elements.insert(indices_[i]);
changed = true;
}
}
return changed;
}
template <class Type>
void Foam::treeLeaf<Type>::printLeaf
(
Ostream& os,
const label level
) const
{
space(os, level);
os << "leaf:" << this->bb()
<< " number of entries:" << indices().size() << endl;
space(os, level);
os << indices() << endl;
}
// Dump cube coordinates in OBJ format
template <class Type>
void Foam::treeLeaf<Type>::writeOBJ
(
Ostream& os,
const label level,
label& vertNo
) const
{
point min = this->bb().min();
point max = this->bb().max();
os << "v " << min.x() << " " << min.y() << " " << min.z() << endl;
os << "v " << max.x() << " " << min.y() << " " << min.z() << endl;
os << "v " << max.x() << " " << max.y() << " " << min.z() << endl;
os << "v " << min.x() << " " << max.y() << " " << min.z() << endl;
os << "v " << min.x() << " " << min.y() << " " << max.z() << endl;
os << "v " << max.x() << " " << min.y() << " " << max.z() << endl;
os << "v " << max.x() << " " << max.y() << " " << max.z() << endl;
os << "v " << min.x() << " " << max.y() << " " << max.z() << endl;
os << "l " << vertNo << " " << vertNo+1 << endl;
os << "l " << vertNo+1 << " " << vertNo+2 << endl;
os << "l " << vertNo+2 << " " << vertNo+3 << endl;
os << "l " << vertNo+3 << " " << vertNo << endl;
os << "l " << vertNo+4 << " " << vertNo+5 << endl;
os << "l " << vertNo+5 << " " << vertNo+6 << endl;
os << "l " << vertNo+6 << " " << vertNo+7 << endl;
os << "l " << vertNo+7 << " " << vertNo << endl;
os << "l " << vertNo << " " << vertNo+4 << endl;
os << "l " << vertNo+1 << " " << vertNo+5 << endl;
os << "l " << vertNo+2 << " " << vertNo+6 << endl;
os << "l " << vertNo+3 << " " << vertNo+7 << endl;
vertNo += 8;
}
template <class Type>
Foam::label Foam::treeLeaf<Type>::countLeaf
(
Ostream& os,
const label level
) const
{
label nItems = size();
space(os, level);
os << "leaf:" << this->bb() << " has size:" << nItems << endl;
return nItems;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
template <class Type>
Foam::Istream& Foam::operator>> (Istream& is, treeLeaf<Type>& leaf)
{
is >> leaf.bb() >> leaf.indices_;
// Was written trimmed
leaf.size_ = leaf.indices_.size();
return is;
}
template <class Type>
Foam::Ostream& Foam::operator<< (Ostream& os, const treeLeaf<Type>& leaf)
{
os << leaf.bb();
if (leaf.indices().size() == leaf.size())
{
os << leaf.indices();
}
else
{
// Storage not trimmed
os << token::SPACE << leaf.size() << token::SPACE << token::BEGIN_LIST;
for (label i = 0; i < leaf.size(); i++)
{
os << token::SPACE << leaf.indices()[i];
}
os << token::END_LIST;
}
return os;
}
// ************************************************************************* //