FreeFOAM The Cross-Platform CFD Toolkit
treeLeaf.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "treeLeaf.H"
29 #include "treeNode.H"
30 #include "treeBoundBox.H"
31 #include "octree.H"
32 #include <OpenFOAM/HashSet.H>
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 template <class Type>
37 void Foam::treeLeaf<Type>::space(Ostream& os, const label n)
38 {
39  for (label i=0; i<n; i++)
40  {
41  os<< ' ';
42  }
43 }
44 
45 
46 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
47 
48 // Construct with given size
49 template <class Type>
50 Foam::treeLeaf<Type>::treeLeaf(const treeBoundBox& bb, const label size)
51 :
52  treeElem<Type>(bb), size_(0), indices_(size)
53 {}
54 
55 
56 // Construct from list
57 template <class Type>
59 :
60  treeElem<Type>(bb), size_(indices.size()), indices_(indices)
61 {
62 }
63 
64 
65 // Construct from Istream
66 template <class Type>
68 {
69  is >> *this;
70 }
71 
72 
73 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
74 
75 template <class Type>
77 {}
78 
79 
80 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
81 
82 // Take cells at this level and distribute them to lower levels
83 template <class Type>
85 (
86  const label level,
87  octree<Type>& top,
88  const Type& shapes
89 )
90 {
91  if (debug & 1)
92  {
93  space(Pout, level);
94  Pout<< "treeLeaf::redistribute with bb:" << this->bb() << endl;
95  }
96 
97  if (size_ <= top.maxLeafRatio())
98  {
99  // leaf small enough
100  if (debug & 1)
101  {
102  space(Pout, level);
103  Pout<< "end of treeLeaf::redistribute : small enough" << endl;
104  }
105  return this;
106  }
107  else
108  {
109  // create treeNode for this level
110  treeNode<Type>* treeNodePtr = new treeNode<Type>(this->bb());
111 
112  top.setNodes(top.nNodes() + 1);
113 
114  treeNodePtr->distribute
115  (
116  level,
117  top,
118  shapes,
119  indices_
120  );
121 
122  if (debug & 1)
123  {
124  space(Pout, level);
125  Pout<< "end of treeLeaf::redistribute : done creating node"
126  << this->bb() << endl;
127  }
128 
129  // return pointer to let level above know.
130  return reinterpret_cast<treeLeaf<Type>*>(treeNodePtr);
131  }
132 }
133 
134 
135 // Set type of subnodes. Since contains elements return mixed type always.
136 template <class Type>
138 (
139  const label level,
140  octree<Type>& top,
141  const Type& shapes
142 ) const
143 {
144  if (size() == 0)
145  {
147  (
148  "treeLeaf<Type>::setSubNodeType(const label, octree<Type>&, "
149  "const Type&)"
150  ) << "empty leaf. bb:" << this->bb()
151  << abort(FatalError);
152  }
153  return octree<Type>::MIXED;
154 }
155 
156 
157 template <class Type>
159 (
160  const label level,
161  const octree<Type>& top,
162  const Type& shapes,
163  const point& sample
164 ) const
165 {
166  return shapes.getSampleType(top, sample);
167 }
168 
169 
170 template <class Type>
171 Foam::label Foam::treeLeaf<Type>::find
172 (
173  const Type& shapes,
174  const point& sample
175 ) const
176 {
177  forAll(indices_, i)
178  {
179  if (shapes.contains(indices_[i], sample))
180  {
181  return indices_[i];
182  }
183  }
184 
185  return -1;
186 }
187 
188 
189 template <class Type>
191 (
192  const Type& shapes,
193  const point& sample,
194  treeBoundBox& tightest
195 ) const
196 {
197  bool changed = false;
198 
199  forAll(indices_, i)
200  {
201  changed |= shapes.findTightest
202  (
203  indices_[i],
204  sample,
205  tightest
206  );
207  }
208 
209  return changed;
210 }
211 
212 
213 template <class Type>
215 (
216  const Type& shapes,
217  const point& sample,
218  treeBoundBox& tightest,
219  label& tightestI,
220  scalar& tightestDist
221 ) const
222 {
223  bool changed = false;
224 
225  forAll(indices_, i)
226  {
227  if (shapes.overlaps(indices_[i], tightest))
228  {
229  if (debug & 8)
230  {
231  //space(Pout, level);
232  Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
233  << " shape:" << indices_[i] << " overlaps:" << tightest
234  << endl;
235  }
236  point nearest;
237  scalar thisDist = shapes.calcNearest(indices_[i], sample, nearest);
238 
239  if (thisDist < tightestDist)
240  {
241  // Construct new tightest Bb
242  point dist(thisDist, thisDist, thisDist);
243 
244  tightest.min() = sample - dist;
245  tightest.max() = sample + dist;
246 
247  // Update other return values
248  tightestI = indices_[i];
249 
250  tightestDist = thisDist;
251 
252  changed = true;
253 
254  if (debug & 8)
255  {
256  //space(Pout, level);
257  Pout<< "treeLeaf<Type>::findNearest : Found nearer : shape:"
258  << tightestI << " distance:" << tightestDist
259  << " to sample:" << sample << endl;
260  }
261  }
262  }
263  }
264 
265  if (changed)
266  {
267  if (debug & 8)
268  {
269  //space(Pout, level);
270  Pout<< "treeLeaf<Type>::findNearest : sample:" << sample
271  << " new nearer:" << tightestDist
272  << endl;
273  }
274  }
275  return changed;
276 }
277 
278 
279 template <class Type>
281 (
282  const Type& shapes,
283  const linePointRef& ln,
284  treeBoundBox& tightest,
285  label& tightestI,
286  point& linePoint, // nearest point on line
287  point& shapePoint // nearest point on shape
288 ) const
289 {
290  // Initial smallest distance
291  scalar tightestDist = mag(linePoint - shapePoint);
292 
293  bool changed = false;
294 
295  forAll(indices_, i)
296  {
297  if (shapes.overlaps(indices_[i], tightest))
298  {
299  // Calculate nearest point on line and on shape.
300  point linePt, shapePt;
301  scalar thisDist = shapes.calcNearest
302  (
303  indices_[i],
304  ln,
305  linePt,
306  shapePt
307  );
308 
309  if (thisDist < tightestDist)
310  {
311  // Found nearer. Use.
312  tightestDist = thisDist;
313  tightestI = indices_[i];
314  linePoint = linePt;
315  shapePoint = shapePt;
316  // Construct new tightest Bb. Nearest point can never be further
317  // away than bounding box of line + margin equal to the distance
318  vector span(thisDist, thisDist, thisDist);
319 
320  tightest.min() = min(ln.start(), ln.end()) - span;
321  tightest.max() = max(ln.start(), ln.end()) + span;
322 
323  changed = true;
324  }
325  }
326  }
327 
328  return changed;
329 }
330 
331 
332 template <class Type>
334 (
335  const Type& shapes,
336  const boundBox& box,
337  labelHashSet& elements
338 ) const
339 {
340  bool changed = false;
341 
342  forAll(indices_, i)
343  {
344  if (shapes.overlaps(indices_[i], box))
345  {
346  elements.insert(indices_[i]);
347 
348  changed = true;
349  }
350  }
351 
352  return changed;
353 }
354 
355 
356 template <class Type>
358 (
359  Ostream& os,
360  const label level
361 ) const
362 {
363  space(os, level);
364 
365  os << "leaf:" << this->bb()
366  << " number of entries:" << indices().size() << endl;
367 
368  space(os, level);
369 
370  os << indices() << endl;
371 }
372 
373 
374 // Dump cube coordinates in OBJ format
375 template <class Type>
377 (
378  Ostream& os,
379  const label level,
380  label& vertNo
381 ) const
382 {
383  point min = this->bb().min();
384  point max = this->bb().max();
385 
386  os << "v " << min.x() << " " << min.y() << " " << min.z() << endl;
387  os << "v " << max.x() << " " << min.y() << " " << min.z() << endl;
388  os << "v " << max.x() << " " << max.y() << " " << min.z() << endl;
389  os << "v " << min.x() << " " << max.y() << " " << min.z() << endl;
390 
391  os << "v " << min.x() << " " << min.y() << " " << max.z() << endl;
392  os << "v " << max.x() << " " << min.y() << " " << max.z() << endl;
393  os << "v " << max.x() << " " << max.y() << " " << max.z() << endl;
394  os << "v " << min.x() << " " << max.y() << " " << max.z() << endl;
395 
396  os << "l " << vertNo << " " << vertNo+1 << endl;
397  os << "l " << vertNo+1 << " " << vertNo+2 << endl;
398  os << "l " << vertNo+2 << " " << vertNo+3 << endl;
399  os << "l " << vertNo+3 << " " << vertNo << endl;
400 
401  os << "l " << vertNo+4 << " " << vertNo+5 << endl;
402  os << "l " << vertNo+5 << " " << vertNo+6 << endl;
403  os << "l " << vertNo+6 << " " << vertNo+7 << endl;
404  os << "l " << vertNo+7 << " " << vertNo << endl;
405 
406  os << "l " << vertNo << " " << vertNo+4 << endl;
407  os << "l " << vertNo+1 << " " << vertNo+5 << endl;
408  os << "l " << vertNo+2 << " " << vertNo+6 << endl;
409  os << "l " << vertNo+3 << " " << vertNo+7 << endl;
410 
411  vertNo += 8;
412 }
413 
414 
415 template <class Type>
417 (
418  Ostream& os,
419  const label level
420 ) const
421 {
422  label nItems = size();
423 
424  space(os, level);
425 
426  os << "leaf:" << this->bb() << " has size:" << nItems << endl;
427 
428  return nItems;
429 }
430 
431 
432 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
433 
434 template <class Type>
436 {
437  is >> leaf.bb() >> leaf.indices_;
438 
439  // Was written trimmed
440  leaf.size_ = leaf.indices_.size();
441  return is;
442 }
443 
444 
445 template <class Type>
446 Foam::Ostream& Foam::operator<< (Ostream& os, const treeLeaf<Type>& leaf)
447 {
448  os << leaf.bb();
449 
450  if (leaf.indices().size() == leaf.size())
451  {
452  os << leaf.indices();
453  }
454  else
455  {
456  // Storage not trimmed
457  os << token::SPACE << leaf.size() << token::SPACE << token::BEGIN_LIST;
458  for (label i = 0; i < leaf.size(); i++)
459  {
460  os << token::SPACE << leaf.indices()[i];
461  }
462  os << token::END_LIST;
463  }
464  return os;
465 }
466 
467 
468 // ************************ vim: set sw=4 sts=4 et: ************************ //