Merge branch 'upstream/OpenFOAM' into master
[freefoam.git] / src / meshTools / octree / treeLeaf.C
blob3220ac85e25d62eac859536ff1ac9d158bc6093b
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 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 <OpenFOAM/HashSet.H>
35 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
37 template <class Type>
38 void Foam::treeLeaf<Type>::space(Ostream& os, const label n)
40     for (label i=0; i<n; i++)
41     {
42         os<< ' ';
43     }
47 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
49 // Construct with given size
50 template <class Type>
51 Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const label size)
53     treeElem<Type>(bb), size_(0), indices_(size)
57 // Construct from list
58 template <class Type>
59 Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const labelList& indices)
61     treeElem<Type>(bb), size_(indices.size()), indices_(indices)
66 // Construct from Istream
67 template <class Type>
68 Foam::treeLeaf<Type>::treeLeaf(Istream& is)
70     is >> *this;
74 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
76 template <class Type>
77 Foam::treeLeaf<Type>::~treeLeaf()
81 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
83 // Take cells at this level and distribute them to lower levels
84 template <class Type>
85 Foam::treeLeaf<Type>* Foam::treeLeaf<Type>::redistribute
87     const label level,
88     octree<Type>& top,
89     const Type& shapes
92     if (debug & 1)
93     {
94         space(Pout, level);
95         Pout<< "treeLeaf::redistribute with bb:" << this->bb() << endl;
96     }
98     if (size_ <= top.maxLeafRatio())
99     {
100         // leaf small enough
101         if (debug & 1)
102         {
103             space(Pout, level);
104             Pout<< "end of treeLeaf::redistribute : small enough" << endl;
105         }
106         return this;
107     }
108     else
109     {
110         // create treeNode for this level
111         treeNode<Type>* treeNodePtr = new treeNode<Type>(this->bb());
113         top.setNodes(top.nNodes() + 1);
115         treeNodePtr->distribute
116         (
117             level,
118             top,
119             shapes,
120             indices_
121         );
123         if (debug & 1)
124         {
125             space(Pout, level);
126             Pout<< "end of treeLeaf::redistribute : done creating node"
127                 << this->bb() << endl;
128         }
130         // return pointer to let level above know.
131         return reinterpret_cast<treeLeaf<Type>*>(treeNodePtr);
132     }
136 // Set type of subnodes. Since contains elements return mixed type always.
137 template <class Type>
138 Foam::label Foam::treeLeaf<Type>::setSubNodeType
140     const label level,
141     octree<Type>& top,
142     const Type& shapes
143 ) const
145     if (size() == 0)
146     {
147         FatalErrorIn
148         (
149             "treeLeaf<Type>::setSubNodeType(const label, octree<Type>&, "
150             "const Type&)"
151         )   << "empty leaf. bb:" << this->bb()
152             << abort(FatalError);
153     }
154     return octree<Type>::MIXED;
158 template <class Type>
159 Foam::label Foam::treeLeaf<Type>::getSampleType
161     const label level,
162     const octree<Type>& top,
163     const Type& shapes,
164     const point& sample
165 ) const
167     return shapes.getSampleType(top, sample);
171 template <class Type>
172 Foam::label Foam::treeLeaf<Type>::find
174     const Type& shapes,
175     const point& sample
176 ) const
178     forAll(indices_, i)
179     {
180         if (shapes.contains(indices_[i], sample))
181         {
182             return indices_[i];
183         }
184     }
186     return -1;
190 template <class Type>
191 bool Foam::treeLeaf<Type>::findTightest
193     const Type& shapes,
194     const point& sample,
195     treeBoundBox& tightest
196 ) const
198     bool changed = false;
200     forAll(indices_, i)
201     {
202         changed |= shapes.findTightest
203         (
204             indices_[i],
205             sample,
206             tightest
207         );
208     }
210     return changed;
214 template <class Type>
215 bool Foam::treeLeaf<Type>::findNearest
217     const Type& shapes,
218     const point& sample,
219     treeBoundBox& tightest,
220     label& tightestI,
221     scalar& tightestDist
222 ) const
224     bool changed = false;
226     forAll(indices_, i)
227     {
228         if (shapes.overlaps(indices_[i], tightest))
229         {
230             if (debug & 8)
231             {
232                 //space(Pout, level);
233                 Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
234                     << "  shape:" << indices_[i] << " overlaps:" << tightest
235                     << endl;
236             }
237             point nearest;
238             scalar thisDist = shapes.calcNearest(indices_[i], sample, nearest);
240             if (thisDist < tightestDist)
241             {
242                 // Construct new tightest Bb
243                 point dist(thisDist, thisDist, thisDist);
245                 tightest.min() = sample - dist;
246                 tightest.max() = sample + dist;
248                 // Update other return values
249                 tightestI = indices_[i];
251                 tightestDist = thisDist;
253                 changed = true;
255                 if (debug & 8)
256                 {
257                     //space(Pout, level);
258                     Pout<< "treeLeaf<Type>::findNearest : Found nearer : shape:"
259                         << tightestI << "  distance:" << tightestDist
260                         << " to sample:" << sample << endl;
261                 }
262             }
263         }
264     }
266     if (changed)
267     {
268         if (debug & 8)
269         {
270             //space(Pout, level);
271             Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
272                 << "  new nearer:" << tightestDist
273                 << endl;
274         }
275     }
276     return changed;
280 template <class Type>
281 bool Foam::treeLeaf<Type>::findNearest
283     const Type& shapes,
284     const linePointRef& ln,
285     treeBoundBox& tightest,
286     label& tightestI,
287     point& linePoint,   // nearest point on line
288     point& shapePoint   // nearest point on shape
289 ) const
291     // Initial smallest distance
292     scalar tightestDist = mag(linePoint - shapePoint);
294     bool changed = false;
296     forAll(indices_, i)
297     {
298         if (shapes.overlaps(indices_[i], tightest))
299         {
300             // Calculate nearest point on line and on shape.
301             point linePt, shapePt;
302             scalar thisDist = shapes.calcNearest
303             (
304                 indices_[i],
305                 ln,
306                 linePt,
307                 shapePt
308             );
310             if (thisDist < tightestDist)
311             {
312                 // Found nearer. Use.
313                 tightestDist = thisDist;
314                 tightestI = indices_[i];
315                 linePoint = linePt;
316                 shapePoint = shapePt;
317                 // Construct new tightest Bb. Nearest point can never be further
318                 // away than bounding box of line + margin equal to the distance
319                 vector span(thisDist, thisDist, thisDist);
321                 tightest.min() = min(ln.start(), ln.end()) - span;
322                 tightest.max() = max(ln.start(), ln.end()) + span;
324                 changed = true;
325             }
326         }
327     }
329     return changed;
333 template <class Type>
334 bool Foam::treeLeaf<Type>::findBox
336     const Type& shapes,
337     const boundBox& box,
338     labelHashSet& elements
339 ) const
341     bool changed = false;
343     forAll(indices_, i)
344     {
345         if (shapes.overlaps(indices_[i], box))
346         {
347             elements.insert(indices_[i]);
349             changed = true;
350         }
351     }
353     return changed;
357 template <class Type>
358 void Foam::treeLeaf<Type>::printLeaf
360     Ostream& os,
361     const label level
362 ) const
364     space(os, level);
366     os  << "leaf:" << this->bb()
367         << "   number of entries:" << indices().size() << endl;
369     space(os, level);
371     os << indices() << endl;
375 // Dump cube coordinates in OBJ format
376 template <class Type>
377 void Foam::treeLeaf<Type>::writeOBJ
379     Ostream& os,
380     const label level,
381     label& vertNo
382 ) const
384     point min = this->bb().min();
385     point max = this->bb().max();
387     os << "v " << min.x() << " " << min.y() << " " << min.z() << endl;
388     os << "v " << max.x() << " " << min.y() << " " << min.z() << endl;
389     os << "v " << max.x() << " " << max.y() << " " << min.z() << endl;
390     os << "v " << min.x() << " " << max.y() << " " << min.z() << endl;
392     os << "v " << min.x() << " " << min.y() << " " << max.z() << endl;
393     os << "v " << max.x() << " " << min.y() << " " << max.z() << endl;
394     os << "v " << max.x() << " " << max.y() << " " << max.z() << endl;
395     os << "v " << min.x() << " " << max.y() << " " << max.z() << endl;
397     os << "l " << vertNo   << " " << vertNo+1 << endl;
398     os << "l " << vertNo+1 << " " << vertNo+2 << endl;
399     os << "l " << vertNo+2 << " " << vertNo+3 << endl;
400     os << "l " << vertNo+3 << " " << vertNo   << endl;
402     os << "l " << vertNo+4 << " " << vertNo+5 << endl;
403     os << "l " << vertNo+5 << " " << vertNo+6 << endl;
404     os << "l " << vertNo+6 << " " << vertNo+7 << endl;
405     os << "l " << vertNo+7 << " " << vertNo   << endl;
407     os << "l " << vertNo   << " " << vertNo+4 << endl;
408     os << "l " << vertNo+1 << " " << vertNo+5 << endl;
409     os << "l " << vertNo+2 << " " << vertNo+6 << endl;
410     os << "l " << vertNo+3 << " " << vertNo+7 << endl;
412     vertNo += 8;
416 template <class Type>
417 Foam::label Foam::treeLeaf<Type>::countLeaf
419     Ostream& os,
420     const label level
421 ) const
423     label nItems = size();
425     space(os, level);
427     os << "leaf:" << this->bb() << " has size:" << nItems << endl;
429     return nItems;
433 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
435 template <class Type>
436 Foam::Istream& Foam::operator>> (Istream& is, treeLeaf<Type>& leaf)
438     is >> leaf.bb() >> leaf.indices_;
440     // Was written trimmed
441     leaf.size_ = leaf.indices_.size();
442     return is;
446 template <class Type>
447 Foam::Ostream& Foam::operator<< (Ostream& os, const treeLeaf<Type>& leaf)
449     os << leaf.bb();
451     if (leaf.indices().size() == leaf.size())
452     {
453         os << leaf.indices();
454     }
455     else
456     {
457         // Storage not trimmed
458         os << token::SPACE << leaf.size() << token::SPACE << token::BEGIN_LIST;
459         for (label i = 0; i < leaf.size(); i++)
460         {
461             os << token::SPACE << leaf.indices()[i];
462         }
463         os << token::END_LIST;
464     }
465     return os;
469 // ************************ vim: set sw=4 sts=4 et: ************************ //