/*---------------------------------------------------------------------------*\ ========= | \\ / 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 void Foam::treeLeaf::space(Ostream& os, const label n) { for (label i=0; i Foam::treeLeaf::treeLeaf(const treeBoundBox& bb, const label size) : treeElem(bb), size_(0), indices_(size) {} // Construct from list template Foam::treeLeaf::treeLeaf(const treeBoundBox& bb, const labelList& indices) : treeElem(bb), size_(indices.size()), indices_(indices) { } // Construct from Istream template Foam::treeLeaf::treeLeaf(Istream& is) { is >> *this; } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // template Foam::treeLeaf::~treeLeaf() {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // Take cells at this level and distribute them to lower levels template Foam::treeLeaf* Foam::treeLeaf::redistribute ( const label level, octree& 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* treeNodePtr = new treeNode(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*>(treeNodePtr); } } // Set type of subnodes. Since contains elements return mixed type always. template Foam::label Foam::treeLeaf::setSubNodeType ( const label level, octree& top, const Type& shapes ) const { if (size() == 0) { FatalErrorIn ( "treeLeaf::setSubNodeType(const label, octree&, " "const Type&)" ) << "empty leaf. bb:" << this->bb() << abort(FatalError); } return octree::MIXED; } template Foam::label Foam::treeLeaf::getSampleType ( const label level, const octree& top, const Type& shapes, const point& sample ) const { return shapes.getSampleType(top, sample); } template Foam::label Foam::treeLeaf::find ( const Type& shapes, const point& sample ) const { forAll(indices_, i) { if (shapes.contains(indices_[i], sample)) { return indices_[i]; } } return -1; } template bool Foam::treeLeaf::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 bool Foam::treeLeaf::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::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::findNearest : Found nearer : shape:" << tightestI << " distance:" << tightestDist << " to sample:" << sample << endl; } } } } if (changed) { if (debug & 8) { //space(Pout, level); Pout<< "treeLeaf::findNearest : sample:" << sample << " new nearer:" << tightestDist << endl; } } return changed; } template bool Foam::treeLeaf::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 bool Foam::treeLeaf::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 void Foam::treeLeaf::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 void Foam::treeLeaf::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 Foam::label Foam::treeLeaf::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 Foam::Istream& Foam::operator>> (Istream& is, treeLeaf& leaf) { is >> leaf.bb() >> leaf.indices_; // Was written trimmed leaf.size_ = leaf.indices_.size(); return is; } template Foam::Ostream& Foam::operator<< (Ostream& os, const treeLeaf& 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; } // ************************************************************************* //