initial commit for version 1.5.x patch release
[OpenFOAM-1.5.x.git] / src / meshTools / octree / treeLeaf.C
blob5825f55c0c04d02f8af290c9e72cd91b49b6a2f6
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 Description
27 \*---------------------------------------------------------------------------*/
29 #include "treeLeaf.H"
30 #include "treeNode.H"
31 #include "treeBoundBox.H"
32 #include "octree.H"
33 #include "labelHashSet.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37 namespace Foam
40 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
42 template <class Type>
43 void treeLeaf<Type>::space(Ostream& os, const label n)
45     for(label i=0; i<n; i++)
46     {
47         os<< ' ';
48     }
52 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
54 // Construct with given size
55 template <class Type>
56 treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const label size)
58     treeElem<Type>(bb), size_(0), indices_(size)
62 // Construct from list
63 template <class Type>
64 treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const labelList& indices)
66     treeElem<Type>(bb), size_(indices.size()), indices_(indices)
71 // Construct from Istream
72 template <class Type>
73 treeLeaf<Type>::treeLeaf(Istream& is)
75     is >> *this;
79 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
81 template <class Type>
82 treeLeaf<Type>::~treeLeaf()
86 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
88 // Take cells at this level and distribute them to lower levels
89 template <class Type>
90 treeLeaf<Type>* treeLeaf<Type>::redistribute
92     const label level,
93     octree<Type>& top,
94     const Type& shapes
97     if (debug & 1)
98     {
99         space(Pout, level);
100         Pout<< "treeLeaf::redistribute with bb:" << this->bb() << endl;
101     }
103     if (size_ <= top.maxLeafRatio())
104     {
105         // leaf small enough
106         if (debug & 1)
107         {
108             space(Pout, level);
109             Pout<< "end of treeLeaf::redistribute : small enough" << endl;
110         }
111         return this;
112     }
113     else
114     {
115         // create treeNode for this level
116         treeNode<Type>* treeNodePtr = new treeNode<Type>(this->bb());
118         top.setNodes(top.nNodes() + 1);
120         treeNodePtr->distribute
121         (
122             level,
123             top,
124             shapes,
125             indices_
126         );
128         if (debug & 1)
129         {
130             space(Pout, level);
131             Pout<< "end of treeLeaf::redistribute : done creating node"
132                 << this->bb() << endl;
133         }
135         // return pointer to let level above know.
136         return reinterpret_cast<treeLeaf<Type>*>(treeNodePtr);
137     }
141 // Set type of subnodes. Since contains elements return mixed type always.
142 template <class Type>
143 Foam::label treeLeaf<Type>::setSubNodeType
145     const label level,
146     octree<Type>& top,
147     const Type& shapes
148 ) const
150     if (size() == 0)
151     {
152         FatalErrorIn
153         (
154             "treeLeaf<Type>::setSubNodeType(const label, octree<Type>&, "
155             "const Type&)"
156         )   << "empty leaf. bb:" << this->bb()
157             << abort(FatalError);                
158     }
159     return octree<Type>::MIXED;
163 template <class Type>
164 Foam::label treeLeaf<Type>::getSampleType
166     const label level,
167     const octree<Type>& top,
168     const Type& shapes,
169     const point& sample
170 ) const
172     return shapes.getSampleType(top, sample);
176 template <class Type>
177 label treeLeaf<Type>::find
179     const Type& shapes,
180     const point& sample
181 ) const
183     forAll(indices_, i)
184     {
185         if (shapes.contains(indices_[i], sample))
186         {
187             return indices_[i];
188         }
189     }
191     return -1;
195 template <class Type>
196 bool treeLeaf<Type>::findTightest
198     const Type& shapes,
199     const point& sample,
200     treeBoundBox& tightest
201 ) const
203     bool changed = false;
205     forAll(indices_, i)
206     {
207         changed |=
208             shapes.findTightest
209             (
210                 indices_[i],
211                 sample,
212                 tightest
213             );
214     }
216     return changed;
220 template <class Type>
221 bool treeLeaf<Type>::findNearest
223     const Type& shapes,
224     const point& sample,
225     treeBoundBox& tightest,
226     label& tightesti,
227     scalar& tightestDist
228 ) const
230     bool changed = false;
232     forAll(indices_, i)
233     {
234         if (shapes.overlaps(indices_[i], tightest))
235         {
236             if (debug & 8)
237             {
238                 //space(Pout, level);
239                 Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
240                     << "  shape:" << indices_[i] << " overlaps:" << tightest
241                     << endl;
242             }
243             point nearest;
244             scalar thisDist = shapes.calcNearest(indices_[i], sample, nearest);
246             if (thisDist < tightestDist)
247             {
248                 // Construct new tightest Bb
249                 point dist(thisDist, thisDist, thisDist);
251                 tightest.min() = sample - dist;
252                 tightest.max() = sample + dist;
254                 // Update other return values
255                 tightesti = indices_[i];
257                 tightestDist = thisDist;
259                 changed = true;
261                 if (debug & 8)
262                 {
263                     //space(Pout, level);
264                     Pout<< "treeLeaf<Type>::findNearest : Found nearer : shape:"
265                         << tightesti << "  distance:" << tightestDist
266                         << " to sample:" << sample << endl;
267                 }
268             }
269         }
270     }
272     if (changed)
273     {
274         if (debug & 8)
275         {
276             //space(Pout, level);
277             Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
278                 << "  new nearer:" << tightestDist
279                 << endl;
280         }
281     }
282     return changed;
286 template <class Type>
287 bool treeLeaf<Type>::findNearest
289     const Type& shapes,
290     const linePointRef& ln,
291     treeBoundBox& tightest,
292     label& tightesti,
293     point& linePoint,   // nearest point on line
294     point& shapePoint   // nearest point on shape
295 ) const
297     // Initial smallest distance
298     scalar tightestDist = mag(linePoint - shapePoint);
300     bool changed = false;
302     forAll(indices_, i)
303     {
304         if (shapes.overlaps(indices_[i], tightest))
305         {
306             // Calculate nearest point on line and on shape.
307             point linePt, shapePt;
308             scalar thisDist = shapes.calcNearest
309             (
310                 indices_[i],
311                 ln,
312                 linePt,
313                 shapePt
314             );
316             if (thisDist < tightestDist)
317             {
318                 // Found nearer. Use.
319                 tightestDist = thisDist;
320                 tightesti = indices_[i];
321                 linePoint = linePt;
322                 shapePoint = shapePt;
323                 // Construct new tightest Bb. Nearest point can never be further
324                 // away than bounding box of line + margin equal to the distance
325                 vector span(thisDist, thisDist, thisDist);
327                 tightest.min() = min(ln.start(), ln.end()) - span;
328                 tightest.max() = max(ln.start(), ln.end()) + span;
330                 changed = true;
331             }
332         }
333     }
335     return changed;
339 template <class Type>
340 bool treeLeaf<Type>::findBox
342     const Type& shapes,
343     const boundBox& box,
344     labelHashSet& elements
345 ) const
347     bool changed = false;
349     forAll(indices_, i)
350     {
351         if (shapes.overlaps(indices_[i], box))
352         {
353             elements.insert(indices_[i]);
355             changed = true;
356         }
357     }
359     return changed;
363 template <class Type>
364 void treeLeaf<Type>::printLeaf
366     Ostream& os,
367     const label level
368 ) const
370     space(os, level);
372     os  << "leaf:" << this->bb()
373         << "   number of entries:" << indices().size() << endl;
375     space(os, level);
377     os << indices() << endl;
381 // Dump cube coordinates in OBJ format
382 template <class Type>
383 void treeLeaf<Type>::writeOBJ
385     Ostream& os,
386     const label level,
387     label& vertNo
388 ) const
390     point min = this->bb().min();
391     point max = this->bb().max();
393     os << "v " << min.x() << " " << min.y() << " " << min.z() << endl;
394     os << "v " << max.x() << " " << min.y() << " " << min.z() << endl;
395     os << "v " << max.x() << " " << max.y() << " " << min.z() << endl;
396     os << "v " << min.x() << " " << max.y() << " " << min.z() << endl;
398     os << "v " << min.x() << " " << min.y() << " " << max.z() << endl;
399     os << "v " << max.x() << " " << min.y() << " " << max.z() << endl;
400     os << "v " << max.x() << " " << max.y() << " " << max.z() << endl;
401     os << "v " << min.x() << " " << max.y() << " " << max.z() << endl;
403     os << "l " << vertNo   << " " << vertNo+1 << endl;
404     os << "l " << vertNo+1 << " " << vertNo+2 << endl;
405     os << "l " << vertNo+2 << " " << vertNo+3 << endl;
406     os << "l " << vertNo+3 << " " << vertNo   << endl;
408     os << "l " << vertNo+4 << " " << vertNo+5 << endl;
409     os << "l " << vertNo+5 << " " << vertNo+6 << endl;
410     os << "l " << vertNo+6 << " " << vertNo+7 << endl;
411     os << "l " << vertNo+7 << " " << vertNo   << endl;
413     os << "l " << vertNo   << " " << vertNo+4 << endl;
414     os << "l " << vertNo+1 << " " << vertNo+5 << endl;
415     os << "l " << vertNo+2 << " " << vertNo+6 << endl;
416     os << "l " << vertNo+3 << " " << vertNo+7 << endl;
418     vertNo += 8;
422 template <class Type>
423 label treeLeaf<Type>::countLeaf
425     Ostream& os,
426     const label level
427 ) const
429     label nItems = size();
431     space(os, level);
433     os << "leaf:" << this->bb() << " has size:" << nItems << endl;
435     return nItems;
439 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
441 template <class Type>
442 Istream& operator>> (Istream& is, treeLeaf<Type>& leaf)
444     is >> leaf.bb() >> leaf.indices_;
446     // Was written trimmed
447     leaf.size_ = leaf.indices_.size();
448     return is;
452 template <class Type>
453 Ostream& operator<< (Ostream& os, const treeLeaf<Type>& leaf)
455     os << leaf.bb();
457     if (leaf.indices().size() == leaf.size())
458     {
459         os << leaf.indices();
460     }
461     else
462     {
463         // Storage not trimmed
464         os << token::SPACE << leaf.size() << token::SPACE << token::BEGIN_LIST;
465         for (label i = 0; i < leaf.size(); i++)
466         {
467             os << token::SPACE << leaf.indices()[i];
468         }
469         os << token::END_LIST;
470     }
471     return os;
476 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
478 } // End namespace Foam
480 // ************************************************************************* //