searchableCone.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) 2015 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 \*---------------------------------------------------------------------------*/
25 
26 #include "searchableCone.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33 
34 defineTypeNameAndDebug(searchableCone, 0);
35 addToRunTimeSelectionTable(searchableSurface, searchableCone, dict);
36 
37 }
38 
39 
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 
43 {
44  tmp<pointField> tCtrs(new pointField(1, 0.5*(point1_ + point2_)));
45 
46  return tCtrs;
47 }
48 
49 
51 (
52  pointField& centres,
53  scalarField& radiusSqr
54 ) const
55 {
56  centres.setSize(1);
57  centres[0] = 0.5*(point1_ + point2_);
58 
59  radiusSqr.setSize(1);
60  if (radius1_ > radius2_)
61  {
62  radiusSqr[0] = Foam::magSqr(point1_-centres[0]) + Foam::sqr(radius1_);
63  }
64  else
65  {
66  radiusSqr[0] = Foam::magSqr(point2_-centres[0]) + Foam::sqr(radius2_);
67  }
68 
69  // Add a bit to make sure all points are tested inside
70  radiusSqr += Foam::sqr(SMALL);
71 }
72 
73 
75 {
76  tmp<pointField> tPts(new pointField(2));
77  pointField& pts = tPts();
78 
79  pts[0] = point1_;
80  pts[1] = point2_;
81 
82  return tPts;
83 }
84 
85 
87 (
88  const point& sample,
89  const scalar nearestDistSqr,
90  pointIndexHit& info,
91  vector& nearNormal
92 ) const
93 {
94  vector v(sample - point1_);
95 
96  // Decompose sample-point1 into normal and parallel component
97  scalar parallel = (v & unitDir_);
98 
99  // Remove the parallel component and normalise
100  v -= parallel*unitDir_;
101 
102  scalar magV = mag(v);
103  if (magV < ROOTVSMALL)
104  {
105  v = vector::zero;
106  }
107  else
108  {
109  v /= magV;
110  }
111 
112  // Nearest and normal on disk at point1
113  point disk1Point(point1_ + min(max(magV, innerRadius1_), radius1_)*v);
114  vector disk1Normal(-unitDir_);
115 
116  // Nearest and normal on disk at point2
117  point disk2Point(point2_ + min(max(magV, innerRadius2_), radius2_)*v);
118  vector disk2Normal(unitDir_);
119 
120  // Nearest and normal on cone. Initialise to far-away point so if not
121  // set it picks one of the disk points
122  point nearCone(GREAT, GREAT, GREAT);
123  vector normalCone(1, 0, 0);
124 
125  // Nearest and normal on inner cone. Initialise to far-away point
126  point iCnearCone(GREAT, GREAT, GREAT);
127  vector iCnormalCone(1, 0, 0);
128 
129  point projPt1 = point1_+ radius1_*v;
130  point projPt2 = point2_+ radius2_*v;
131 
132  vector p1 = (projPt1 - point1_);
133  if (mag(p1) > ROOTVSMALL)
134  {
135  p1 /= mag(p1);
136 
137  // Find vector along the two end of cone
138  vector b(projPt2 - projPt1);
139  scalar magS = mag(b);
140  b /= magS;
141 
142  // Find the vector along sample pt and pt at one end of conde
143  vector a(sample - projPt1);
144 
145  if (mag(a) <= ROOTVSMALL)
146  {
147  // Exception: sample on disk1. Redo with projPt2.
148  vector a(sample - projPt2);
149  // Find normal unitvector
150  nearCone = (a & b)*b+projPt2;
151  vector b1 = (p1 & b)*b;
152  normalCone = p1 - b1;
153  normalCone /= mag(normalCone);
154  }
155  else
156  {
157  // Find neartest point on cone surface
158  nearCone = (a & b)*b+projPt1;
159  // Find projection along surface of cone
160  vector b1 = (p1 & b)*b;
161  normalCone = p1 - b1;
162  normalCone /= mag(normalCone);
163  }
164 
165  if (innerRadius1_ > 0 || innerRadius2_ > 0)
166  {
167  // Same for inner radius
168  point iCprojPt1 = point1_+ innerRadius1_*v;
169  point iCprojPt2 = point2_+ innerRadius2_*v;
170 
171  vector iCp1 = (iCprojPt1 - point1_);
172  iCp1 /= mag(iCp1);
173 
174  // Find vector along the two end of cone
175  vector iCb(iCprojPt2 - iCprojPt1);
176  magS = mag(iCb);
177  iCb /= magS;
178 
179 
180  // Find the vector along sample pt and pt at one end of conde
181  vector iCa(sample - iCprojPt1);
182 
183  if (mag(iCa) <= ROOTVSMALL)
184  {
185  vector iCa(sample - iCprojPt2);
186 
187  // Find normal unitvector
188  iCnearCone = (iCa & iCb)*iCb+iCprojPt2;
189  vector b1 = (iCp1 & iCb)*iCb;
190  iCnormalCone = iCp1 - b1;
191  iCnormalCone /= mag(iCnormalCone);
192  }
193  else
194  {
195  // Find nearest point on cone surface
196  iCnearCone = (iCa & iCb)*iCb+iCprojPt1;
197  // Find projection along surface of cone
198  vector b1 = (iCp1 & iCb)*iCb;
199  iCnormalCone = iCp1 - b1;
200  iCnormalCone /= mag(iCnormalCone);
201  }
202  }
203  }
204 
205 
206  // Select nearest out of the 4 points (outer cone, disk1, disk2, inner
207  // cone)
208 
210  dist[0] = magSqr(nearCone-sample);
211  dist[1] = magSqr(disk1Point-sample);
212  dist[2] = magSqr(disk2Point-sample);
213  dist[3] = magSqr(iCnearCone-sample);
214 
215  label minI = findMin(dist);
216 
217 
218  // Snap the point to the corresponding surface
219 
220  if (minI == 0) // Outer cone
221  {
222  // Closest to (infinite) outer cone. See if needs clipping to end disks
223 
224  {
225  vector v1(nearCone-point1_);
226  scalar para = (v1 & unitDir_);
227  // Remove the parallel component and normalise
228  v1 -= para*unitDir_;
229  scalar magV1 = mag(v1);
230  v1 = v1/magV1;
231  if (para < 0.0 && magV1 >= radius1_)
232  {
233  // Near point 1. Set point to intersection of disk and cone.
234  // Keep normal from cone.
235  nearCone = disk1Point;
236  }
237  else if (para < 0.0 && magV1 < radius1_)
238  {
239  // On disk1
240  nearCone = disk1Point;
241  normalCone = disk1Normal;
242  }
243  else if (para > magDir_ && magV1 >= radius2_)
244  {
245  // Near point 2. Set point to intersection of disk and cone.
246  // Keep normal from cone.
247  nearCone = disk2Point;
248  }
249  else if (para > magDir_ && magV1 < radius2_)
250  {
251  // On disk2
252  nearCone = disk2Point;
253  normalCone = disk2Normal;
254  }
255  }
256  info.setPoint(nearCone);
257  nearNormal = normalCone;
258  }
259  else if (minI == 1) // Near to disk1
260  {
261  info.setPoint(disk1Point);
262  nearNormal = disk1Normal;
263  }
264  else if (minI == 2) // Near to disk2
265  {
266  info.setPoint(disk2Point);
267  nearNormal = disk2Normal;
268  }
269  else // Near to inner cone
270  {
271  {
272  vector v1(iCnearCone-point1_);
273  scalar para = (v1 & unitDir_);
274  // Remove the parallel component and normalise
275  v1 -= para*unitDir_;
276  scalar magV1 = mag(v1);
277  v1 = v1/magV1;
278 
279  if (para < 0.0 && magV1 >= innerRadius1_)
280  {
281  iCnearCone = disk1Point;
282  }
283  else if (para < 0.0 && magV1 < innerRadius1_)
284  {
285  iCnearCone = disk1Point;
286  iCnormalCone = disk1Normal;
287  }
288  else if (para > magDir_ && magV1 >= innerRadius2_)
289  {
290  iCnearCone = disk2Point;
291  }
292  else if (para > magDir_ && magV1 < innerRadius2_)
293  {
294  iCnearCone = disk2Point;
295  iCnormalCone = disk2Normal;
296  }
297  }
298  info.setPoint(iCnearCone);
299  nearNormal = iCnormalCone;
300  }
301 
302 
303  if (magSqr(sample - info.rawPoint()) < nearestDistSqr)
304  {
305  info.setHit();
306  info.setIndex(0);
307  }
308 }
309 
310 
312 (
313  const searchableCone& cone,
314  const point& pt
315 )
316 {
317  const vector x = (pt-cone.point1_) ^ cone.unitDir_;
318  return x&x;
319 }
320 
321 
322 // From mrl.nyu.edu/~dzorin/rend05/lecture2.pdf,
323 // Ray Tracing II, Infinite cone ray intersection.
325 (
326  const searchableCone& cone,
327  const scalar innerRadius1,
328  const scalar innerRadius2,
329  const point& start,
330  const point& end,
331  pointIndexHit& near,
332  pointIndexHit& far
333 ) const
334 {
335  near.setMiss();
336  far.setMiss();
337 
338  vector point1Start(start-cone.point1_);
339  vector point2Start(start-cone.point2_);
340  vector point1End(end-cone.point1_);
341 
342  // Quick rejection of complete vector outside endcaps
343  scalar s1 = point1Start&(cone.unitDir_);
344  scalar s2 = point1End&(cone.unitDir_);
345 
346  if ((s1 < 0.0 && s2 < 0.0) || (s1 > cone.magDir_ && s2 > cone.magDir_))
347  {
348  return;
349  }
350 
351  // Line as P = start+t*V where V is unit vector and t=[0..mag(end-start)]
352  vector V(end-start);
353  scalar magV = mag(V);
354  if (magV < ROOTVSMALL)
355  {
356  return;
357  }
358  V /= magV;
359 
360 
361  // We now get the nearest intersections to start. This can either be
362  // the intersection with the end plane or with the cylinder side.
363 
364  // Get the two points (expressed in t) on the end planes. This is to
365  // clip any cylinder intersection against.
366  scalar tPoint1;
367  scalar tPoint2;
368 
369  // Maintain the two intersections with the endcaps
370  scalar tNear = VGREAT;
371  scalar tFar = VGREAT;
372 
373  scalar radius_sec = cone.radius1_;
374 
375  {
376  // Find dot product: mag(s)>VSMALL suggest that it is greater
377  scalar s = (V&unitDir_);
378  if (mag(s) > VSMALL)
379  {
380  tPoint1 = -s1/s;
381  tPoint2 = -(point2Start&(cone.unitDir_))/s;
382 
383  if (tPoint2 < tPoint1)
384  {
385  Swap(tPoint1, tPoint2);
386  }
387  if (tPoint1 > magV || tPoint2 < 0)
388  {
389  return;
390  }
391  // See if the points on the endcaps are actually inside the cylinder
392  if (tPoint1 >= 0 && tPoint1 <= magV)
393  {
394  scalar r2 = radius2(cone, start+tPoint1*V);
395  vector p1 = (start+tPoint1*V-point1_);
396  vector p2 = (start+tPoint1*V-point2_);
397  radius_sec = cone.radius1_;
398  scalar inC_radius_sec = innerRadius1_;
399 
400  if (mag(p2&(cone.unitDir_)) < mag(p1&(cone.unitDir_)))
401  {
402  radius_sec = cone.radius2_;
403  inC_radius_sec = innerRadius2_;
404  }
405 
406  if (r2 <= sqr(radius_sec) && r2 >= sqr(inC_radius_sec))
407  {
408  tNear = tPoint1;
409  }
410  }
411  if (tPoint2 >= 0 && tPoint2 <= magV)
412  {
413  // Decompose sample-point1 into normal and parallel component
414  vector p1 = (start+tPoint2*V-cone.point1_);
415  vector p2 = (start+tPoint2*V-cone.point2_);
416  radius_sec = cone.radius1_;
417  scalar inC_radius_sec = innerRadius1_;
418  if (mag(p2&(cone.unitDir_)) < mag(p1&(cone.unitDir_)))
419  {
420  radius_sec = cone.radius2_;
421  inC_radius_sec = innerRadius2_;
422  }
423  scalar r2 = radius2(cone, start+tPoint2*V);
424  if (r2 <= sqr(radius_sec) && r2 >= sqr(inC_radius_sec))
425  {
426  // Check if already have a near hit from point1
427  if (tNear <= 1)
428  {
429  tFar = tPoint2;
430  }
431  else
432  {
433  tNear = tPoint2;
434  }
435  }
436  }
437  }
438  else
439  {
440  // Vector perpendicular to cylinder. Check for outside already done
441  // above so just set tpoint to allow all.
442  tPoint1 = -VGREAT;
443  tPoint2 = VGREAT;
444  }
445  }
446 
447 
448  // Second order equation of the form a*t^2 + b*t + c
449  scalar a, b, c;
450 
451  scalar deltaRadius = cone.radius2_-cone.radius1_;
452  if (mag(deltaRadius) <= ROOTVSMALL)
453  {
454  vector point1Start(start-cone.point1_);
455  const vector x = point1Start ^ cone.unitDir_;
456  const vector y = V ^ cone.unitDir_;
457  const scalar d = sqr(0.5*(cone.radius1_ + cone.radius2_));
458 
459  a = (y&y);
460  b = 2*(x&y);
461  c = (x&x)-d;
462  }
463  else
464  {
465  vector va = cone.unitDir_;
466  vector v1(end-start);
467  v1 = v1/mag(v1);
468  scalar p = (va&v1);
469  vector a1 = (v1-p*va);
470 
471  // Determine the end point of the cone
472  point pa =
473  cone.unitDir_*cone.radius1_*mag(cone.point2_-cone.point1_)
474  /(-deltaRadius)
475  +cone.point1_;
476 
477  scalar l2 = sqr(deltaRadius)+sqr(cone.magDir_);
478  scalar sqrCosAlpha = sqr(cone.magDir_)/l2;
479  scalar sqrSinAlpha = sqr(deltaRadius)/l2;
480 
481 
482  vector delP(start-pa);
483  vector p1 = (delP-(delP&va)*va);
484 
485  a = sqrCosAlpha*((v1-p*va)&(v1-p*va))-sqrSinAlpha*p*p;
486  b =
487  2.0*sqrCosAlpha*(a1&p1)
488  -2.0*sqrSinAlpha*(v1&va)*(delP&va);
489  c =
490  sqrCosAlpha
491  *((delP-(delP&va)*va)&(delP-(delP&va)*va))
492  -sqrSinAlpha*sqr(delP&va);
493  }
494 
495  const scalar disc = b*b-4.0*a*c;
496 
497  scalar t1 = -VGREAT;
498  scalar t2 = VGREAT;
499 
500  if (disc < 0)
501  {
502  // Fully outside
503  return;
504  }
505  else if (disc < ROOTVSMALL)
506  {
507  // Single solution
508  if (mag(a) > ROOTVSMALL)
509  {
510  t1 = -b/(2.0*a);
511 
512  if (t1 >= 0.0 && t1 <= magV && t1 >= tPoint1 && t1 <= tPoint2)
513  {
514  // Valid. Insert sorted.
515  if (t1 < tNear)
516  {
517  tFar = tNear;
518  tNear = t1;
519  }
520  else if (t1 < tFar)
521  {
522  tFar = t1;
523  }
524  }
525  else
526  {
527  return;
528  }
529  }
530  else
531  {
532  // Aligned with axis. Check if outside radius
533  if (c > 0.0)
534  {
535  return;
536  }
537  }
538  }
539  else
540  {
541  if (mag(a) > ROOTVSMALL)
542  {
543  scalar sqrtDisc = sqrt(disc);
544 
545  t1 = (-b - sqrtDisc)/(2.0*a);
546  t2 = (-b + sqrtDisc)/(2.0*a);
547  if (t2 < t1)
548  {
549  Swap(t1, t2);
550  }
551 
552  if (t1 >= 0.0 && t1 <= magV && t1 >= tPoint1 && t1 <= tPoint2)
553  {
554  // Valid. Insert sorted.
555  if (t1 < tNear)
556  {
557  tFar = tNear;
558  tNear = t1;
559  }
560  else if (t1 < tFar)
561  {
562  tFar = t1;
563  }
564  }
565  if (t2>=0 && t2 <= magV && t2 >= tPoint1 && t2 <= tPoint2)
566  {
567  // Valid. Insert sorted.
568  if (t2 < tNear)
569  {
570  tFar = tNear;
571  tNear = t2;
572  }
573  else if (t2 < tFar)
574  {
575  tFar = t2;
576  }
577  }
578  }
579  else
580  {
581  // Aligned with axis. Check if outside radius
582  if (c > 0.0)
583  {
584  return;
585  }
586  }
587  }
588 
589  // Check tNear, tFar
590  if (tNear>=0 && tNear <= magV)
591  {
592  near.setPoint(start+tNear*V);
593  near.setHit();
594  near.setIndex(0);
595  if (tFar <= magV)
596  {
597  far.setPoint(start+tFar*V);
598  far.setHit();
599  far.setIndex(0);
600  }
601  }
602  else if (tFar>=0 && tFar <= magV)
603  {
604  near.setPoint(start+tFar*V);
605  near.setHit();
606  near.setIndex(0);
607  }
608 }
609 
610 
612 (
613  const point& start,
614  const point& end,
615  List<pointIndexHit>& info,
616  const pointIndexHit& hit
617 ) const
618 {
619  scalar smallDistSqr = SMALL*magSqr(end-start);
620 
621  scalar hitMagSqr = magSqr(hit.hitPoint()-start);
622 
623  forAll(info, i)
624  {
625  scalar d2 = magSqr(info[i].hitPoint()-start);
626 
627  if (d2 > hitMagSqr+smallDistSqr)
628  {
629  // Insert at i.
630  label sz = info.size();
631  info.setSize(sz+1);
632  for (label j = sz; j > i; --j)
633  {
634  info[j] = info[j-1];
635  }
636  info[i] = hit;
637  return;
638  }
639  else if (d2 > hitMagSqr-smallDistSqr)
640  {
641  // hit is same point as info[i].
642  return;
643  }
644  }
645  // Append
646  label sz = info.size();
647  info.setSize(sz+1);
648  info[sz] = hit;
649 }
650 
651 
653 {
654  // Adapted from
655  // http://www.gamedev.net/community/forums
656  // /topic.asp?topic_id=338522&forum_id=20&gforum_id=0
657 
658  // Let cylinder have end points A,B and radius r,
659 
660  // Bounds in direction X (same for Y and Z) can be found as:
661  // Let A.X<B.X (otherwise swap points)
662  // Good approximate lowest bound is A.X-r and highest is B.X+r (precise for
663  // capsule). At worst, in one direction it can be larger than needed by 2*r.
664 
665  // Accurate bounds for cylinder is
666  // A.X-kx*r, B.X+kx*r
667  // where
668  // kx=sqrt(((A.Y-B.Y)^2+(A.Z-B.Z)^2)/((A.X-B.X)^2+(A.Y-B.Y)^2+(A.Z-B.Z)^2))
669 
670  // similar thing for Y and Z
671  // (i.e.
672  // ky=sqrt(((A.X-B.X)^2+(A.Z-B.Z)^2)/((A.X-B.X)^2+(A.Y-B.Y)^2+(A.Z-B.Z)^2))
673  // kz=sqrt(((A.X-B.X)^2+(A.Y-B.Y)^2)/((A.X-B.X)^2+(A.Y-B.Y)^2+(A.Z-B.Z)^2))
674  // )
675 
676  // How derived: geometric reasoning. Bounds of cylinder is same as for 2
677  // circles centered on A and B. This sqrt thingy gives sine of angle between
678  // axis and direction, used to find projection of radius.
679 
680  vector kr
681  (
682  sqrt(sqr(unitDir_.y()) + sqr(unitDir_.z())),
683  sqrt(sqr(unitDir_.x()) + sqr(unitDir_.z())),
684  sqrt(sqr(unitDir_.x()) + sqr(unitDir_.y()))
685  );
686 
687  if (radius2_ >= radius1_)
688  {
689  kr *= radius2_;
690  }
691  else
692  {
693  kr *= radius1_;
694  }
695 
696  point min = point1_ - kr;
697  point max = point1_ + kr;
698 
699  min = ::Foam::min(min, point2_ - kr);
700  max = ::Foam::max(max, point2_ + kr);
701 
702  return boundBox(min, max);
703 }
704 
705 
706 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
707 
709 (
710  const IOobject& io,
711  const point& point1,
712  const scalar radius1,
713  const scalar innerRadius1,
714  const point& point2,
715  const scalar radius2,
716  const scalar innerRadius2
717 )
718 :
719  searchableSurface(io),
720  point1_(point1),
721  radius1_(radius1),
722  innerRadius1_(innerRadius1),
723  point2_(point2),
724  radius2_(radius2),
725  innerRadius2_(innerRadius2),
726  magDir_(mag(point2_-point1_)),
727  unitDir_((point2_-point1_)/magDir_)
728 {
729  bounds() = calcBounds();
730 }
731 
732 
734 (
735  const IOobject& io,
736  const dictionary& dict
737 )
738 :
739  searchableSurface(io),
740  point1_(dict.lookup("point1")),
741  radius1_(readScalar(dict.lookup("radius1"))),
742  innerRadius1_(dict.lookupOrDefault("innerRadius1", 0.0)),
743  point2_(dict.lookup("point2")),
744  radius2_(readScalar(dict.lookup("radius2"))),
745  innerRadius2_(dict.lookupOrDefault("innerRadius2", 0.0)),
746  magDir_(mag(point2_-point1_)),
747  unitDir_((point2_-point1_)/magDir_)
748 {
749  bounds() = calcBounds();
750 }
751 
752 
753 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
754 
756 {}
757 
758 
759 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
760 
762 {
763  if (regions_.empty())
764  {
765  regions_.setSize(1);
766  regions_[0] = "region0";
767  }
768  return regions_;
769 }
770 
771 
773 (
774  const pointField& samples,
775  const scalarField& nearestDistSqr,
776  List<pointIndexHit>& info
777 ) const
778 {
779  info.setSize(samples.size());
780  forAll(samples, i)
781  {
782  vector normal;
783  findNearestAndNormal(samples[i], nearestDistSqr[i], info[i], normal);
784  }
785 }
786 
787 
789 (
790  const pointField& start,
791  const pointField& end,
792  List<pointIndexHit>& info
793 ) const
794 {
795  info.setSize(start.size());
796 
797  forAll(start, i)
798  {
799  // Pick nearest intersection. If none intersected take second one.
801  findLineAll
802  (
803  *this,
804  innerRadius1_,
805  innerRadius2_,
806  start[i],
807  end[i],
808  info[i],
809  b
810  );
811  if (!info[i].hit() && b.hit())
812  {
813  info[i] = b;
814  }
815  }
816 
817 
818  if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
819  {
820  IOobject io(*this);
821  io.rename(name()+"Inner");
822  searchableCone innerCone
823  (
824  io,
825  point1_,
826  innerRadius1_,
827  0.0,
828  point2_,
829  innerRadius2_,
830  0.0
831  );
832 
833  forAll(info, i)
834  {
835  point newEnd;
836  if (info[i].hit())
837  {
838  newEnd = info[i].hitPoint();
839  }
840  else
841  {
842  newEnd = end[i];
843  }
844  pointIndexHit near;
845  pointIndexHit far;
846  findLineAll
847  (
848  innerCone,
849  innerRadius1_,
850  innerRadius2_,
851  start[i],
852  newEnd,
853  near,
854  far
855  );
856 
857  if (near.hit())
858  {
859  info[i] = near;
860  }
861  else if (far.hit())
862  {
863  info[i] = far;
864  }
865  }
866  }
867 }
868 
869 
871 (
872  const pointField& start,
873  const pointField& end,
874  List<pointIndexHit>& info
875 ) const
876 {
877  info.setSize(start.size());
878 
879  forAll(start, i)
880  {
881  // Discard far intersection
883  findLineAll
884  (
885  *this,
886  innerRadius1_,
887  innerRadius2_,
888  start[i],
889  end[i],
890  info[i],
891  b
892  );
893  if (!info[i].hit() && b.hit())
894  {
895  info[i] = b;
896  }
897  }
898  if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
899  {
900  IOobject io(*this);
901  io.rename(name()+"Inner");
902  searchableCone cone
903  (
904  io,
905  point1_,
906  innerRadius1_,
907  0.0,
908  point2_,
909  innerRadius2_,
910  0.0
911  );
912 
913  forAll(info, i)
914  {
915  if (!info[i].hit())
916  {
918  findLineAll
919  (
920  cone,
921  innerRadius1_,
922  innerRadius2_,
923  start[i],
924  end[i],
925  info[i],
926  b
927  );
928  if (!info[i].hit() && b.hit())
929  {
930  info[i] = b;
931  }
932  }
933  }
934  }
935 }
936 
937 
939 (
940  const pointField& start,
941  const pointField& end,
942  List<List<pointIndexHit> >& info
943 ) const
944 {
945  info.setSize(start.size());
946 
947  forAll(start, i)
948  {
949  pointIndexHit near, far;
950  findLineAll
951  (
952  *this,
953  innerRadius1_,
954  innerRadius2_,
955  start[i],
956  end[i],
957  near,
958  far
959  );
960 
961  if (near.hit())
962  {
963  if (far.hit())
964  {
965  info[i].setSize(2);
966  info[i][0] = near;
967  info[i][1] = far;
968  }
969  else
970  {
971  info[i].setSize(1);
972  info[i][0] = near;
973  }
974  }
975  else
976  {
977  if (far.hit())
978  {
979  info[i].setSize(1);
980  info[i][0] = far;
981  }
982  else
983  {
984  info[i].clear();
985  }
986  }
987  }
988 
989  if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
990  {
991  IOobject io(*this);
992  io.rename(name()+"Inner");
993  searchableCone cone
994  (
995  io,
996  point1_,
997  innerRadius1_,
998  0.0,
999  point2_,
1000  innerRadius2_,
1001  0.0
1002  );
1003 
1004  forAll(info, i)
1005  {
1006  pointIndexHit near;
1007  pointIndexHit far;
1008  findLineAll
1009  (
1010  cone,
1011  innerRadius1_,
1012  innerRadius2_,
1013  start[i],
1014  end[i],
1015  near,
1016  far
1017  );
1018 
1019  if (near.hit())
1020  {
1021  insertHit(start[i], end[i], info[i], near);
1022  }
1023  if (far.hit())
1024  {
1025  insertHit(start[i], end[i], info[i], far);
1026  }
1027  }
1028  }
1029 }
1030 
1031 
1034  const List<pointIndexHit>& info,
1035  labelList& region
1036 ) const
1037 {
1038  region.setSize(info.size());
1039  region = 0;
1040 }
1041 
1042 
1045  const List<pointIndexHit>& info,
1047 ) const
1048 {
1049  normal.setSize(info.size());
1050  normal = vector::zero;
1051 
1052  forAll(info, i)
1053  {
1054  if (info[i].hit())
1055  {
1057  findNearestAndNormal
1058  (
1059  info[i].hitPoint(),
1060  Foam::sqr(GREAT),
1061  nearInfo,
1062  normal[i]
1063  );
1064  }
1065  }
1066 }
1067 
1068 
1071  const pointField& points,
1072  List<volumeType>& volType
1073 ) const
1074 {
1075  volType.setSize(points.size());
1076  volType = volumeType::INSIDE;
1077 
1078  forAll(points, pointI)
1079  {
1080  const point& pt = points[pointI];
1081 
1082  vector v(pt - point1_);
1083 
1084  // Decompose sample-point1 into normal and parallel component
1085  scalar parallel = v & unitDir_;
1086  scalar comp = parallel;
1087  scalar compInner = parallel;
1088 
1089 
1090  scalar radius_sec = radius1_+comp*(radius2_-radius1_)/magDir_;
1091 
1092  scalar radius_sec_inner =
1093  innerRadius1_
1094  +compInner*(innerRadius2_-innerRadius1_)/magDir_;
1095 
1096  if (parallel < 0)
1097  {
1098  // Left of point1 endcap
1099  volType[pointI] = volumeType::OUTSIDE;
1100  }
1101  else if (parallel > magDir_)
1102  {
1103  // Right of point2 endcap
1104  volType[pointI] = volumeType::OUTSIDE;
1105  }
1106  else
1107  {
1108  // Remove the parallel component
1109  v -= parallel*unitDir_;
1110  if (mag(v) >= radius_sec_inner && mag(v) <= radius_sec)
1111  {
1112  volType[pointI] = volumeType::INSIDE;
1113  }
1114  else
1115  {
1116  volType[pointI] = volumeType::OUTSIDE;
1117  }
1118  }
1119  }
1120 }
1121 
1122 
1123 // ************************************************************************* //
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Foam::searchableCone::radius2
static scalar radius2(const searchableCone &cone, const point &pt)
Determine radial coordinate (squared)
Definition: searchableCone.C:312
Foam::volumeType::OUTSIDE
@ OUTSIDE
Definition: volumeType.H:64
Foam::IOobject
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
Foam::volumeType::INSIDE
@ INSIDE
Definition: volumeType.H:63
Foam::searchableCone::findLineAny
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find any intersection on line from start to end.
Definition: searchableCone.C:871
Foam::searchableCone::insertHit
void insertHit(const point &start, const point &end, List< pointIndexHit > &info, const pointIndexHit &hit) const
Insert a hit if it differs (by a tolerance) from the existing ones.
Definition: searchableCone.C:612
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
p
p
Definition: pEqn.H:62
Foam::PointIndexHit::setIndex
void setIndex(const label index)
Definition: PointIndexHit.H:168
Foam::searchableCone::coordinates
virtual tmp< pointField > coordinates() const
Get representative set of element coordinates.
Definition: searchableCone.C:42
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:118
Foam::searchableCone::findNearest
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
Find nearest point on cylinder.
Definition: searchableCone.C:773
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
Foam::searchableCone::regions
virtual const wordList & regions() const
Names of regions.
Definition: searchableCone.C:761
Foam::searchableCone
Searching on (optionally hollow) cone.
Definition: searchableCone.H:97
Foam::dictionary::lookup
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:449
Foam::PointIndexHit::hit
bool hit() const
Is there a hit.
Definition: PointIndexHit.H:105
Foam::dictionary::lookupOrDefault
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
Definition: dictionaryTemplates.C:33
Foam::PointIndexHit::setMiss
void setMiss()
Definition: PointIndexHit.H:158
Foam::searchableCone::radius2_
const scalar radius2_
Outer radius at point2.
Definition: searchableCone.H:117
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::searchableCone::unitDir_
const vector unitDir_
Normalised vector point2-point1.
Definition: searchableCone.H:127
Foam::nearInfo
Tuple2< scalar, label > nearInfo
Private class for finding nearest.
Definition: sampledTriSurfaceMesh.C:64
Foam::searchableCone::getVolumeType
virtual void getVolumeType(const pointField &, List< volumeType > &) const
Determine type (inside/outside/mixed) for point. unknown if.
Definition: searchableCone.C:1070
samples
scalarField samples(nIntervals, 0)
Foam::findMin
label findMin(const ListType &, const label start=0)
Find index of min element (and less than given element).
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:53
Foam::PointIndexHit::rawPoint
const Point & rawPoint() const
Return point with no checking.
Definition: PointIndexHit.H:143
Foam::searchableCone::magDir_
const scalar magDir_
Length of vector point2-point1.
Definition: searchableCone.H:124
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::searchableCone::findNearestAndNormal
void findNearestAndNormal(const point &sample, const scalar nearestDistSqr, pointIndexHit &nearInfo, vector &normal) const
Find nearest point on cylinder.
Definition: searchableCone.C:87
Foam::PointIndexHit::hitPoint
const Point & hitPoint() const
Return hit point.
Definition: PointIndexHit.H:117
Foam::searchableSurface
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
Definition: searchableSurface.H:66
Foam::searchableCone::points
virtual tmp< pointField > points() const
Get the points that define the surface.
Definition: searchableCone.C:74
Foam::PointIndexHit::setHit
void setHit()
Definition: PointIndexHit.H:153
searchableCone.H
Foam::searchableCone::~searchableCone
virtual ~searchableCone()
Destructor.
Definition: searchableCone.C:755
Foam::searchableCone::point1_
const point point1_
'Left' point
Definition: searchableCone.H:104
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::PointIndexHit::setPoint
void setPoint(const Point &p)
Definition: PointIndexHit.H:163
Foam::IOobject::rename
virtual void rename(const word &newName)
Rename.
Definition: IOobject.H:297
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::searchableCone::calcBounds
boundBox calcBounds() const
Return the boundBox of the cylinder.
Definition: searchableCone.C:652
Foam::searchableCone::findLine
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find nearest intersection on line from start to end.
Definition: searchableCone.C:789
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::searchableCone::findLineAll
void findLineAll(const searchableCone &cone, const scalar innerRadius1, const scalar innerRadius2, const point &start, const point &end, pointIndexHit &near, pointIndexHit &far) const
Find both intersections with cone. innerRadii supplied externally.
Definition: searchableCone.C:325
Foam::searchableCone::getRegion
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const
From a set of points and indices get the region.
Definition: searchableCone.C:1033
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::searchableCone::searchableCone
searchableCone(const searchableCone &)
Disallow default bitwise copy construct.
Foam::searchableCone::boundingSpheres
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const
Get bounding spheres (centre and radius squared), one per element.
Definition: searchableCone.C:51
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::readScalar
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:142
Foam::FixedList
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
Foam::searchableCone::getNormal
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
Definition: searchableCone.C:1044
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: List.C:379
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::boundBox
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:55
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::searchableCone::point2_
const point point2_
'Right' point
Definition: searchableCone.H:114
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::Tuple2
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:47
Foam::Swap
void Swap(T &a, T &b)
Definition: Swap.H:43
Foam::searchableCone::radius1_
const scalar radius1_
Outer radius at point1.
Definition: searchableCone.H:107
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
normal
A normal distribution model.
y
scalar y
Definition: LISASMDCalcMethod1.H:14