FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

treeLeaf.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025 
00026 \*---------------------------------------------------------------------------*/
00027 
00028 #include "treeLeaf.H"
00029 #include "treeNode.H"
00030 #include "treeBoundBox.H"
00031 #include "octree.H"
00032 #include <OpenFOAM/HashSet.H>
00033 
00034 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00035 
00036 template <class Type>
00037 void Foam::treeLeaf<Type>::space(Ostream& os, const label n)
00038 {
00039     for (label i=0; i<n; i++)
00040     {
00041         os<< ' ';
00042     }
00043 }
00044 
00045 
00046 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00047 
00048 // Construct with given size
00049 template <class Type>
00050 Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const label size)
00051 :
00052     treeElem<Type>(bb), size_(0), indices_(size)
00053 {}
00054 
00055 
00056 // Construct from list
00057 template <class Type>
00058 Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const labelList& indices)
00059 :
00060     treeElem<Type>(bb), size_(indices.size()), indices_(indices)
00061 {
00062 }
00063 
00064 
00065 // Construct from Istream
00066 template <class Type>
00067 Foam::treeLeaf<Type>::treeLeaf(Istream& is)
00068 {
00069     is >> *this;
00070 }
00071 
00072 
00073 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00074 
00075 template <class Type>
00076 Foam::treeLeaf<Type>::~treeLeaf()
00077 {}
00078 
00079 
00080 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00081 
00082 // Take cells at this level and distribute them to lower levels
00083 template <class Type>
00084 Foam::treeLeaf<Type>* Foam::treeLeaf<Type>::redistribute
00085 (
00086     const label level,
00087     octree<Type>& top,
00088     const Type& shapes
00089 )
00090 {
00091     if (debug & 1)
00092     {
00093         space(Pout, level);
00094         Pout<< "treeLeaf::redistribute with bb:" << this->bb() << endl;
00095     }
00096 
00097     if (size_ <= top.maxLeafRatio())
00098     {
00099         // leaf small enough
00100         if (debug & 1)
00101         {
00102             space(Pout, level);
00103             Pout<< "end of treeLeaf::redistribute : small enough" << endl;
00104         }
00105         return this;
00106     }
00107     else
00108     {
00109         // create treeNode for this level
00110         treeNode<Type>* treeNodePtr = new treeNode<Type>(this->bb());
00111 
00112         top.setNodes(top.nNodes() + 1);
00113 
00114         treeNodePtr->distribute
00115         (
00116             level,
00117             top,
00118             shapes,
00119             indices_
00120         );
00121 
00122         if (debug & 1)
00123         {
00124             space(Pout, level);
00125             Pout<< "end of treeLeaf::redistribute : done creating node"
00126                 << this->bb() << endl;
00127         }
00128 
00129         // return pointer to let level above know.
00130         return reinterpret_cast<treeLeaf<Type>*>(treeNodePtr);
00131     }
00132 }
00133 
00134 
00135 // Set type of subnodes. Since contains elements return mixed type always.
00136 template <class Type>
00137 Foam::label Foam::treeLeaf<Type>::setSubNodeType
00138 (
00139     const label level,
00140     octree<Type>& top,
00141     const Type& shapes
00142 ) const
00143 {
00144     if (size() == 0)
00145     {
00146         FatalErrorIn
00147         (
00148             "treeLeaf<Type>::setSubNodeType(const label, octree<Type>&, "
00149             "const Type&)"
00150         )   << "empty leaf. bb:" << this->bb()
00151             << abort(FatalError);
00152     }
00153     return octree<Type>::MIXED;
00154 }
00155 
00156 
00157 template <class Type>
00158 Foam::label Foam::treeLeaf<Type>::getSampleType
00159 (
00160     const label level,
00161     const octree<Type>& top,
00162     const Type& shapes,
00163     const point& sample
00164 ) const
00165 {
00166     return shapes.getSampleType(top, sample);
00167 }
00168 
00169 
00170 template <class Type>
00171 Foam::label Foam::treeLeaf<Type>::find
00172 (
00173     const Type& shapes,
00174     const point& sample
00175 ) const
00176 {
00177     forAll(indices_, i)
00178     {
00179         if (shapes.contains(indices_[i], sample))
00180         {
00181             return indices_[i];
00182         }
00183     }
00184 
00185     return -1;
00186 }
00187 
00188 
00189 template <class Type>
00190 bool Foam::treeLeaf<Type>::findTightest
00191 (
00192     const Type& shapes,
00193     const point& sample,
00194     treeBoundBox& tightest
00195 ) const
00196 {
00197     bool changed = false;
00198 
00199     forAll(indices_, i)
00200     {
00201         changed |= shapes.findTightest
00202         (
00203             indices_[i],
00204             sample,
00205             tightest
00206         );
00207     }
00208 
00209     return changed;
00210 }
00211 
00212 
00213 template <class Type>
00214 bool Foam::treeLeaf<Type>::findNearest
00215 (
00216     const Type& shapes,
00217     const point& sample,
00218     treeBoundBox& tightest,
00219     label& tightestI,
00220     scalar& tightestDist
00221 ) const
00222 {
00223     bool changed = false;
00224 
00225     forAll(indices_, i)
00226     {
00227         if (shapes.overlaps(indices_[i], tightest))
00228         {
00229             if (debug & 8)
00230             {
00231                 //space(Pout, level);
00232                 Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
00233                     << "  shape:" << indices_[i] << " overlaps:" << tightest
00234                     << endl;
00235             }
00236             point nearest;
00237             scalar thisDist = shapes.calcNearest(indices_[i], sample, nearest);
00238 
00239             if (thisDist < tightestDist)
00240             {
00241                 // Construct new tightest Bb
00242                 point dist(thisDist, thisDist, thisDist);
00243 
00244                 tightest.min() = sample - dist;
00245                 tightest.max() = sample + dist;
00246 
00247                 // Update other return values
00248                 tightestI = indices_[i];
00249 
00250                 tightestDist = thisDist;
00251 
00252                 changed = true;
00253 
00254                 if (debug & 8)
00255                 {
00256                     //space(Pout, level);
00257                     Pout<< "treeLeaf<Type>::findNearest : Found nearer : shape:"
00258                         << tightestI << "  distance:" << tightestDist
00259                         << " to sample:" << sample << endl;
00260                 }
00261             }
00262         }
00263     }
00264 
00265     if (changed)
00266     {
00267         if (debug & 8)
00268         {
00269             //space(Pout, level);
00270             Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
00271                 << "  new nearer:" << tightestDist
00272                 << endl;
00273         }
00274     }
00275     return changed;
00276 }
00277 
00278 
00279 template <class Type>
00280 bool Foam::treeLeaf<Type>::findNearest
00281 (
00282     const Type& shapes,
00283     const linePointRef& ln,
00284     treeBoundBox& tightest,
00285     label& tightestI,
00286     point& linePoint,   // nearest point on line
00287     point& shapePoint   // nearest point on shape
00288 ) const
00289 {
00290     // Initial smallest distance
00291     scalar tightestDist = mag(linePoint - shapePoint);
00292 
00293     bool changed = false;
00294 
00295     forAll(indices_, i)
00296     {
00297         if (shapes.overlaps(indices_[i], tightest))
00298         {
00299             // Calculate nearest point on line and on shape.
00300             point linePt, shapePt;
00301             scalar thisDist = shapes.calcNearest
00302             (
00303                 indices_[i],
00304                 ln,
00305                 linePt,
00306                 shapePt
00307             );
00308 
00309             if (thisDist < tightestDist)
00310             {
00311                 // Found nearer. Use.
00312                 tightestDist = thisDist;
00313                 tightestI = indices_[i];
00314                 linePoint = linePt;
00315                 shapePoint = shapePt;
00316                 // Construct new tightest Bb. Nearest point can never be further
00317                 // away than bounding box of line + margin equal to the distance
00318                 vector span(thisDist, thisDist, thisDist);
00319 
00320                 tightest.min() = min(ln.start(), ln.end()) - span;
00321                 tightest.max() = max(ln.start(), ln.end()) + span;
00322 
00323                 changed = true;
00324             }
00325         }
00326     }
00327 
00328     return changed;
00329 }
00330 
00331 
00332 template <class Type>
00333 bool Foam::treeLeaf<Type>::findBox
00334 (
00335     const Type& shapes,
00336     const boundBox& box,
00337     labelHashSet& elements
00338 ) const
00339 {
00340     bool changed = false;
00341 
00342     forAll(indices_, i)
00343     {
00344         if (shapes.overlaps(indices_[i], box))
00345         {
00346             elements.insert(indices_[i]);
00347 
00348             changed = true;
00349         }
00350     }
00351 
00352     return changed;
00353 }
00354 
00355 
00356 template <class Type>
00357 void Foam::treeLeaf<Type>::printLeaf
00358 (
00359     Ostream& os,
00360     const label level
00361 ) const
00362 {
00363     space(os, level);
00364 
00365     os  << "leaf:" << this->bb()
00366         << "   number of entries:" << indices().size() << endl;
00367 
00368     space(os, level);
00369 
00370     os << indices() << endl;
00371 }
00372 
00373 
00374 // Dump cube coordinates in OBJ format
00375 template <class Type>
00376 void Foam::treeLeaf<Type>::writeOBJ
00377 (
00378     Ostream& os,
00379     const label level,
00380     label& vertNo
00381 ) const
00382 {
00383     point min = this->bb().min();
00384     point max = this->bb().max();
00385 
00386     os << "v " << min.x() << " " << min.y() << " " << min.z() << endl;
00387     os << "v " << max.x() << " " << min.y() << " " << min.z() << endl;
00388     os << "v " << max.x() << " " << max.y() << " " << min.z() << endl;
00389     os << "v " << min.x() << " " << max.y() << " " << min.z() << endl;
00390 
00391     os << "v " << min.x() << " " << min.y() << " " << max.z() << endl;
00392     os << "v " << max.x() << " " << min.y() << " " << max.z() << endl;
00393     os << "v " << max.x() << " " << max.y() << " " << max.z() << endl;
00394     os << "v " << min.x() << " " << max.y() << " " << max.z() << endl;
00395 
00396     os << "l " << vertNo   << " " << vertNo+1 << endl;
00397     os << "l " << vertNo+1 << " " << vertNo+2 << endl;
00398     os << "l " << vertNo+2 << " " << vertNo+3 << endl;
00399     os << "l " << vertNo+3 << " " << vertNo   << endl;
00400 
00401     os << "l " << vertNo+4 << " " << vertNo+5 << endl;
00402     os << "l " << vertNo+5 << " " << vertNo+6 << endl;
00403     os << "l " << vertNo+6 << " " << vertNo+7 << endl;
00404     os << "l " << vertNo+7 << " " << vertNo   << endl;
00405 
00406     os << "l " << vertNo   << " " << vertNo+4 << endl;
00407     os << "l " << vertNo+1 << " " << vertNo+5 << endl;
00408     os << "l " << vertNo+2 << " " << vertNo+6 << endl;
00409     os << "l " << vertNo+3 << " " << vertNo+7 << endl;
00410 
00411     vertNo += 8;
00412 }
00413 
00414 
00415 template <class Type>
00416 Foam::label Foam::treeLeaf<Type>::countLeaf
00417 (
00418     Ostream& os,
00419     const label level
00420 ) const
00421 {
00422     label nItems = size();
00423 
00424     space(os, level);
00425 
00426     os << "leaf:" << this->bb() << " has size:" << nItems << endl;
00427 
00428     return nItems;
00429 }
00430 
00431 
00432 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
00433 
00434 template <class Type>
00435 Foam::Istream& Foam::operator>> (Istream& is, treeLeaf<Type>& leaf)
00436 {
00437     is >> leaf.bb() >> leaf.indices_;
00438 
00439     // Was written trimmed
00440     leaf.size_ = leaf.indices_.size();
00441     return is;
00442 }
00443 
00444 
00445 template <class Type>
00446 Foam::Ostream& Foam::operator<< (Ostream& os, const treeLeaf<Type>& leaf)
00447 {
00448     os << leaf.bb();
00449 
00450     if (leaf.indices().size() == leaf.size())
00451     {
00452         os << leaf.indices();
00453     }
00454     else
00455     {
00456         // Storage not trimmed
00457         os << token::SPACE << leaf.size() << token::SPACE << token::BEGIN_LIST;
00458         for (label i = 0; i < leaf.size(); i++)
00459         {
00460             os << token::SPACE << leaf.indices()[i];
00461         }
00462         os << token::END_LIST;
00463     }
00464     return os;
00465 }
00466 
00467 
00468 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines