Loading...
Searching...
No Matches
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 | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2015-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
30
31// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32
33namespace Foam
34{
37 (
40 dict
41 );
43 (
46 dict,
47 cone
48 );
49}
50
51
52// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55{
56 return tmp<pointField>::New(1, 0.5*(point1_ + point2_));
57}
58
59
61(
62 pointField& centres,
63 scalarField& radiusSqr
64) const
65{
66 centres.setSize(1);
67 centres[0] = 0.5*(point1_ + point2_);
68
69 radiusSqr.setSize(1);
70 if (radius1_ > radius2_)
71 {
72 radiusSqr[0] = Foam::magSqr(point1_-centres[0]) + Foam::sqr(radius1_);
73 }
74 else
75 {
76 radiusSqr[0] = Foam::magSqr(point2_-centres[0]) + Foam::sqr(radius2_);
77 }
78
79 // Add a bit to make sure all points are tested inside
80 radiusSqr += Foam::sqr(SMALL);
81}
82
83
85{
86 auto tpts = tmp<pointField>::New(2);
87 auto& pts = tpts.ref();
88
89 pts[0] = point1_;
90 pts[1] = point2_;
91
92 return tpts;
93}
94
95
96void Foam::searchableCone::findNearestAndNormal
97(
98 const point& sample,
99 const scalar nearestDistSqr,
100 pointIndexHit& info,
101 vector& nearNormal
102) const
103{
104 vector v(sample - point1_);
105
106 // Decompose sample-point1 into normal and parallel component
107 const scalar parallel = (v & unitDir_);
108
109 // Remove the parallel component and normalise
110 v -= parallel*unitDir_;
111
112 const scalar magV = mag(v);
113 v.normalise();
114
115 // Nearest and normal on disk at point1
116 point disk1Point(point1_ + clamp(magV, innerRadius1_, radius1_)*v);
117 vector disk1Normal(-unitDir_);
118
119 // Nearest and normal on disk at point2
120 point disk2Point(point2_ + clamp(magV, innerRadius2_, radius2_)*v);
121 vector disk2Normal(unitDir_);
122
123 // Nearest and normal on cone. Initialise to far-away point so if not
124 // set it picks one of the disk points
125 point nearCone(point::uniform(GREAT));
126 vector normalCone(1, 0, 0);
127
128 // Nearest and normal on inner cone. Initialise to far-away point
129 point iCnearCone(point::uniform(GREAT));
130 vector iCnormalCone(1, 0, 0);
131
132 point projPt1 = point1_+ radius1_*v;
133 point projPt2 = point2_+ radius2_*v;
134
135 vector p1 = (projPt1 - point1_);
136 if (mag(p1) > ROOTVSMALL)
137 {
138 p1 /= mag(p1);
139
140 // Find vector along the two end of cone
141 const vector b = normalised(projPt2 - projPt1);
142
143 // Find the vector along sample pt and pt at one end of cone
144 vector a = (sample - projPt1);
145
146 if (mag(a) <= ROOTVSMALL)
147 {
148 // Exception: sample on disk1. Redo with projPt2.
149 a = (sample - projPt2);
150
151 // Find normal unitvector
152 nearCone = (a & b)*b + projPt2;
153
154 vector b1 = (p1 & b)*b;
155 normalCone = normalised(p1 - b1);
156 }
157 else
158 {
159 // Find nearest point on cone surface
160 nearCone = (a & b)*b + projPt1;
161
162 // Find projection along surface of cone
163 vector b1 = (p1 & b)*b;
164 normalCone = normalised(p1 - b1);
165 }
166
167 if (innerRadius1_ > 0 || innerRadius2_ > 0)
168 {
169 // Same for inner radius
170 point iCprojPt1 = point1_+ innerRadius1_*v;
171 point iCprojPt2 = point2_+ innerRadius2_*v;
172
173 const vector iCp1 = normalised(iCprojPt1 - point1_);
174
175 // Find vector along the two end of cone
176 const vector iCb = normalised(iCprojPt2 - iCprojPt1);
177
178
179 // Find the vector along sample pt and pt at one end of conde
180 vector iCa(sample - iCprojPt1);
181
182 if (mag(iCa) <= ROOTVSMALL)
183 {
184 iCa = (sample - iCprojPt2);
185
186 // Find normal unitvector
187 iCnearCone = (iCa & iCb)*iCb+iCprojPt2;
188
189 vector b1 = (iCp1 & iCb)*iCb;
190 iCnormalCone = normalised(iCp1 - b1);
191 }
192 else
193 {
194 // Find nearest point on cone surface
195 iCnearCone = (iCa & iCb)*iCb+iCprojPt1;
196
197 // Find projection along surface of cone
198 vector b1 = (iCp1 & iCb)*iCb;
199 iCnormalCone = normalised(iCp1 - b1);
200 }
201 }
202 }
203
204
205 // Select nearest out of the 4 points (outer cone, disk1, disk2, inner
206 // cone)
207
209 dist[0] = sample.distSqr(nearCone);
210 dist[1] = sample.distSqr(disk1Point);
211 dist[2] = sample.distSqr(disk2Point);
212 dist[3] = sample.distSqr(iCnearCone);
213
214 const label minI = findMin(dist);
215
216
217 // Snap the point to the corresponding surface
218
219 if (minI == 0) // Outer cone
220 {
221 // Closest to (infinite) outer cone. See if needs clipping to end disks
222
223 {
224 vector v1(nearCone-point1_);
225 scalar para = (v1 & unitDir_);
226 // Remove the parallel component and normalise
227 v1 -= para*unitDir_;
228 const scalar magV1 = mag(v1);
229 v1 = v1/magV1;
230
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
277 const scalar magV1 = mag(v1);
278 v1 = v1/magV1;
279
280 if (para < 0.0 && magV1 >= innerRadius1_)
281 {
282 iCnearCone = disk1Point;
283 }
284 else if (para < 0.0 && magV1 < innerRadius1_)
285 {
286 iCnearCone = disk1Point;
287 iCnormalCone = disk1Normal;
288 }
289 else if (para > magDir_ && magV1 >= innerRadius2_)
290 {
291 iCnearCone = disk2Point;
292 }
293 else if (para > magDir_ && magV1 < innerRadius2_)
294 {
295 iCnearCone = disk2Point;
296 iCnormalCone = disk2Normal;
297 }
298 }
299 info.setPoint(iCnearCone);
300 nearNormal = iCnormalCone;
301 }
302
303
304 if (info.point().distSqr(sample) < nearestDistSqr)
305 {
306 info.setHit();
307 info.setIndex(0);
308 }
309}
310
311
312Foam::scalar Foam::searchableCone::radius2
313(
314 const searchableCone& cone,
315 const point& pt
316)
317{
318 const vector x = (pt-cone.point1_) ^ cone.unitDir_;
319 return x&x;
320}
321
322
323// From mrl.nyu.edu/~dzorin/rend05/lecture2.pdf,
324// Ray Tracing II, Infinite cone ray intersection.
325void Foam::searchableCone::findLineAll
326(
327 const searchableCone& cone,
328 const scalar innerRadius1,
329 const scalar innerRadius2,
330 const point& start,
331 const point& end,
332 pointIndexHit& near,
333 pointIndexHit& far
334) const
335{
336 near.setMiss();
337 far.setMiss();
338
339 vector point1Start(start-cone.point1_);
340 vector point2Start(start-cone.point2_);
341 vector point1End(end-cone.point1_);
342
343 // Quick rejection of complete vector outside endcaps
344 scalar s1 = point1Start & (cone.unitDir_);
345 scalar s2 = point1End & (cone.unitDir_);
346
347 if ((s1 < 0.0 && s2 < 0.0) || (s1 > cone.magDir_ && s2 > cone.magDir_))
348 {
349 return;
350 }
351
352 // Line as P = start+t*V where V is unit vector and t=[0..mag(end-start)]
353 vector V(end-start);
354 scalar magV = mag(V);
355 if (magV < ROOTVSMALL)
356 {
357 return;
358 }
359 V /= magV;
360
361
362 // We now get the nearest intersections to start. This can either be
363 // the intersection with the end plane or with the cylinder side.
364
365 // Get the two points (expressed in t) on the end planes. This is to
366 // clip any cylinder intersection against.
367 scalar tPoint1;
368 scalar tPoint2;
369
370 // Maintain the two intersections with the endcaps
371 scalar tNear = VGREAT;
372 scalar tFar = VGREAT;
373
374 scalar radius_sec = cone.radius1_;
375
376 {
377 // Find dot product: mag(s)>VSMALL suggest that it is greater
378 scalar s = (V & unitDir_);
379 if (mag(s) > VSMALL)
380 {
381 tPoint1 = -s1/s;
382 tPoint2 = -(point2Start&(cone.unitDir_))/s;
383
384 if (tPoint2 < tPoint1)
385 {
386 std::swap(tPoint1, tPoint2);
387 }
388 if (tPoint1 > magV || tPoint2 < 0)
389 {
390 return;
391 }
392 // See if the points on the endcaps are actually inside the cylinder
393 if (tPoint1 >= 0 && tPoint1 <= magV)
394 {
395 scalar r2 = radius2(cone, start+tPoint1*V);
396 vector p1 = (start+tPoint1*V-point1_);
397 vector p2 = (start+tPoint1*V-point2_);
398 radius_sec = cone.radius1_;
399 scalar inC_radius_sec = innerRadius1_;
400
401 if (mag(p2&(cone.unitDir_)) < mag(p1&(cone.unitDir_)))
402 {
403 radius_sec = cone.radius2_;
404 inC_radius_sec = innerRadius2_;
405 }
406
407 if (r2 <= sqr(radius_sec) && r2 >= sqr(inC_radius_sec))
408 {
409 tNear = tPoint1;
410 }
411 }
412 if (tPoint2 >= 0 && tPoint2 <= magV)
413 {
414 // Decompose sample-point1 into normal and parallel component
415 vector p1 = (start+tPoint2*V-cone.point1_);
416 vector p2 = (start+tPoint2*V-cone.point2_);
417 radius_sec = cone.radius1_;
418 scalar inC_radius_sec = innerRadius1_;
419 if (mag(p2&(cone.unitDir_)) < mag(p1&(cone.unitDir_)))
420 {
421 radius_sec = cone.radius2_;
422 inC_radius_sec = innerRadius2_;
423 }
424 scalar r2 = radius2(cone, start+tPoint2*V);
425 if (r2 <= sqr(radius_sec) && r2 >= sqr(inC_radius_sec))
426 {
427 // Check if already have a near hit from point1
428 if (tNear <= 1)
429 {
430 tFar = tPoint2;
431 }
432 else
433 {
434 tNear = tPoint2;
435 }
436 }
437 }
438 }
439 else
440 {
441 // Vector perpendicular to cylinder. Check for outside already done
442 // above so just set tpoint to allow all.
443 tPoint1 = -VGREAT;
444 tPoint2 = VGREAT;
445 }
446 }
447
448
449 // Second order equation of the form a*t^2 + b*t + c
450 scalar a, b, c;
451
452 scalar deltaRadius = cone.radius2_-cone.radius1_;
453 if (mag(deltaRadius) <= ROOTVSMALL)
454 {
455 vector point1Start(start-cone.point1_);
456 const vector x = point1Start ^ cone.unitDir_;
457 const vector y = V ^ cone.unitDir_;
458 const scalar d = sqr(0.5*(cone.radius1_ + cone.radius2_));
459
460 a = (y&y);
461 b = 2*(x&y);
462 c = (x&x)-d;
463 }
464 else
465 {
466 vector va = cone.unitDir_;
467 vector v1 = normalised(end-start);
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 std::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.hitPoint(start+tNear*V);
593 near.setIndex(0);
594 if (tFar <= magV)
595 {
596 far.hitPoint(start+tFar*V);
597 far.setIndex(0);
598 }
599 }
600 else if (tFar>=0 && tFar <= magV)
601 {
602 near.hitPoint(start+tFar*V);
603 near.setIndex(0);
604 }
605}
606
607
608void Foam::searchableCone::insertHit
609(
610 const point& start,
611 const point& end,
613 const pointIndexHit& hit
614) const
615{
616 scalar smallDistSqr = SMALL*magSqr(end-start);
617
618 scalar hitMagSqr = hit.hitPoint().distSqr(start);
619
620 forAll(info, i)
621 {
622 scalar d2 = info[i].hitPoint().distSqr(start);
623
624 if (d2 > hitMagSqr+smallDistSqr)
625 {
626 // Insert at i.
627 label sz = info.size();
628 info.setSize(sz+1);
629 for (label j = sz; j > i; --j)
630 {
631 info[j] = info[j-1];
632 }
633 info[i] = hit;
634 return;
635 }
636 else if (d2 > hitMagSqr-smallDistSqr)
637 {
638 // hit is same point as info[i].
639 return;
640 }
641 }
642 // Append
643 label sz = info.size();
644 info.setSize(sz+1);
645 info[sz] = hit;
646}
647
648
649Foam::boundBox Foam::searchableCone::calcBounds() const
650{
651 // Adapted from
652 // http://www.gamedev.net/community/forums
653 // /topic.asp?topic_id=338522&forum_id=20&gforum_id=0
654
655 // Let cylinder have end points A,B and radius r,
656
657 // Bounds in direction X (same for Y and Z) can be found as:
658 // Let A.X<B.X (otherwise swap points)
659 // Good approximate lowest bound is A.X-r and highest is B.X+r (precise for
660 // capsule). At worst, in one direction it can be larger than needed by 2*r.
661
662 // Accurate bounds for cylinder is
663 // A.X-kx*r, B.X+kx*r
664 // where
665 // 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))
666
667 // similar thing for Y and Z
668 // (i.e.
669 // 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))
670 // 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))
671 // )
672
673 // How derived: geometric reasoning. Bounds of cylinder is same as for 2
674 // circles centered on A and B. This sqrt thingy gives sine of angle between
675 // axis and direction, used to find projection of radius.
676
677 vector kr
678 (
679 sqrt(sqr(unitDir_.y()) + sqr(unitDir_.z())),
680 sqrt(sqr(unitDir_.x()) + sqr(unitDir_.z())),
681 sqrt(sqr(unitDir_.x()) + sqr(unitDir_.y()))
682 );
683
684 if (radius2_ >= radius1_)
685 {
686 kr *= radius2_;
687 }
688 else
689 {
690 kr *= radius1_;
691 }
692
693 point min = point1_ - kr;
694 point max = point1_ + kr;
695
696 min = ::Foam::min(min, point2_ - kr);
697 max = ::Foam::max(max, point2_ + kr);
699 return boundBox(min, max);
700}
701
702
703// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
704
705Foam::searchableCone::searchableCone
706(
707 const IOobject& io,
708 const point& point1,
709 const scalar radius1,
710 const scalar innerRadius1,
711 const point& point2,
712 const scalar radius2,
713 const scalar innerRadius2
714)
715:
717 point1_(point1),
718 radius1_(radius1),
719 innerRadius1_(innerRadius1),
720 point2_(point2),
721 radius2_(radius2),
722 innerRadius2_(innerRadius2),
723 magDir_(mag(point2_-point1_)),
724 unitDir_((point2_-point1_)/magDir_)
725{
726 bounds() = calcBounds();
727}
728
729
730Foam::searchableCone::searchableCone
731(
732 const IOobject& io,
733 const dictionary& dict
734)
735:
737 point1_(dict.get<point>("point1")),
738 radius1_(dict.get<scalar>("radius1")),
739 innerRadius1_(dict.getOrDefault<scalar>("innerRadius1", 0)),
740 point2_(dict.get<point>("point2")),
741 radius2_(dict.get<scalar>("radius2")),
742 innerRadius2_(dict.getOrDefault<scalar>("innerRadius2", 0)),
743 magDir_(mag(point2_-point1_)),
744 unitDir_((point2_-point1_)/magDir_)
746 bounds() = calcBounds();
747}
748
749
750// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
751
753{
754 if (regions_.empty())
755 {
756 regions_.setSize(1);
757 regions_[0] = "region0";
758 }
759 return regions_;
760}
761
762
764(
765 const pointField& samples,
766 const scalarField& nearestDistSqr,
767 List<pointIndexHit>& info
768) const
769{
770 info.setSize(samples.size());
771
772 forAll(samples, i)
774 vector normal;
775 findNearestAndNormal(samples[i], nearestDistSqr[i], info[i], normal);
776 }
777}
778
779
781(
782 const pointField& start,
783 const pointField& end,
784 List<pointIndexHit>& info
785) const
786{
787 info.setSize(start.size());
788
789 forAll(start, i)
790 {
791 // Pick nearest intersection. If none intersected take second one.
793 findLineAll
794 (
795 *this,
796 innerRadius1_,
797 innerRadius2_,
798 start[i],
799 end[i],
800 info[i],
801 b
802 );
803 if (!info[i].hit() && b.hit())
804 {
805 info[i] = b;
806 }
807 }
808
809
810 if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
811 {
812 IOobject io(*this);
813 io.rename(name()+"Inner");
814 searchableCone innerCone
815 (
816 io,
817 point1_,
818 innerRadius1_,
819 0.0,
820 point2_,
821 innerRadius2_,
822 0.0
823 );
824
825 forAll(info, i)
826 {
827 point newEnd;
828 if (info[i].hit())
829 {
830 newEnd = info[i].point();
831 }
832 else
833 {
834 newEnd = end[i];
835 }
836 pointIndexHit near;
837 pointIndexHit far;
838 findLineAll
839 (
840 innerCone,
841 innerRadius1_,
842 innerRadius2_,
843 start[i],
844 newEnd,
845 near,
846 far
847 );
848
849 if (near.hit())
850 {
851 info[i] = near;
852 }
853 else if (far.hit())
854 {
855 info[i] = far;
856 }
857 }
858 }
859}
860
861
863(
864 const pointField& start,
865 const pointField& end,
867) const
868{
869 info.setSize(start.size());
870
871 forAll(start, i)
872 {
873 // Discard far intersection
875 findLineAll
876 (
877 *this,
878 innerRadius1_,
879 innerRadius2_,
880 start[i],
881 end[i],
882 info[i],
883 b
884 );
885 if (!info[i].hit() && b.hit())
886 {
887 info[i] = b;
888 }
889 }
890 if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
891 {
892 IOobject io(*this);
893 io.rename(name()+"Inner");
894 searchableCone cone
895 (
896 io,
897 point1_,
898 innerRadius1_,
899 0.0,
900 point2_,
901 innerRadius2_,
902 0.0
903 );
904
905 forAll(info, i)
906 {
907 if (!info[i].hit())
908 {
910 findLineAll
911 (
912 cone,
913 innerRadius1_,
914 innerRadius2_,
915 start[i],
916 end[i],
917 info[i],
918 b
919 );
920 if (!info[i].hit() && b.hit())
921 {
922 info[i] = b;
924 }
925 }
926 }
927}
928
929
930void Foam::searchableCone::findLineAll
931(
932 const pointField& start,
933 const pointField& end,
935) const
936{
937 info.setSize(start.size());
938
939 forAll(start, i)
940 {
941 pointIndexHit near, far;
942 findLineAll
943 (
944 *this,
945 innerRadius1_,
946 innerRadius2_,
947 start[i],
948 end[i],
949 near,
950 far
951 );
952
953 if (near.hit())
954 {
955 if (far.hit())
956 {
957 info[i].setSize(2);
958 info[i][0] = near;
959 info[i][1] = far;
960 }
961 else
962 {
963 info[i].setSize(1);
964 info[i][0] = near;
965 }
966 }
967 else
968 {
969 if (far.hit())
970 {
971 info[i].setSize(1);
972 info[i][0] = far;
973 }
974 else
975 {
976 info[i].clear();
977 }
978 }
979 }
980
981 if (innerRadius1_ > 0.0 || innerRadius2_ > 0.0)
982 {
983 IOobject io(*this);
984 io.rename(name()+"Inner");
985 searchableCone cone
986 (
987 io,
988 point1_,
989 innerRadius1_,
990 0.0,
991 point2_,
992 innerRadius2_,
993 0.0
994 );
995
996 forAll(info, i)
997 {
998 pointIndexHit near;
999 pointIndexHit far;
1000 findLineAll
1001 (
1002 cone,
1003 innerRadius1_,
1004 innerRadius2_,
1005 start[i],
1006 end[i],
1007 near,
1008 far
1009 );
1010
1011 if (near.hit())
1012 {
1013 insertHit(start[i], end[i], info[i], near);
1014 }
1015 if (far.hit())
1016 {
1017 insertHit(start[i], end[i], info[i], far);
1018 }
1019 }
1020 }
1021}
1022
1023
1025(
1026 const List<pointIndexHit>& info,
1027 labelList& region
1028) const
1029{
1030 region.setSize(info.size());
1031 region = 0;
1032}
1033
1034
1036(
1037 const List<pointIndexHit>& info,
1038 vectorField& normal
1039) const
1040{
1041 normal.setSize(info.size());
1042 normal = Zero;
1043
1044 forAll(info, i)
1045 {
1046 if (info[i].hit())
1047 {
1048 pointIndexHit nearInfo;
1049 findNearestAndNormal
1050 (
1051 info[i].point(),
1052 Foam::sqr(GREAT),
1053 nearInfo,
1054 normal[i]
1055 );
1056 }
1057 }
1058}
1059
1060
1062(
1063 const pointField& points,
1064 List<volumeType>& volType
1065) const
1066{
1067 volType.setSize(points.size());
1068
1069 forAll(points, pointi)
1070 {
1071 const point& pt = points[pointi];
1072
1073 volType[pointi] = volumeType::OUTSIDE;
1074
1075 vector v(pt - point1_);
1076
1077 // Decompose sample-point1 into normal and parallel component
1078 const scalar parallel = (v & unitDir_);
1079
1080 // Quick rejection. Left of point1 endcap, or right of point2 endcap
1081 if (parallel < 0 || parallel > magDir_)
1082 {
1083 continue;
1084 }
1085
1086 const scalar radius_sec =
1087 radius1_ + parallel * (radius2_-radius1_)/magDir_;
1088
1089 const scalar radius_sec_inner =
1090 innerRadius1_ + parallel * (innerRadius2_-innerRadius1_)/magDir_;
1091
1092 // Remove the parallel component
1093 v -= parallel*unitDir_;
1094
1095 if (mag(v) >= radius_sec_inner && mag(v) <= radius_sec)
1096 {
1097 volType[pointi] = volumeType::INSIDE;
1098 }
1099 }
1100}
1101
1102
1103// ************************************************************************* //
scalar y
Macros for easy insertion into run-time selection tables.
#define addNamedToRunTimeSelectionTable(baseType, thisType, argNames, lookupName)
Add to construction table with 'lookupName' as the key.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
A 1D vector of objects of type <T> with a fixed length <N>.
Definition FixedList.H:73
Minimal example by using system/controlDict.functions:
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
InfoProxy< IOobject > info() const noexcept
Return info proxy, for printing information to a stream.
Definition IOobject.H:1041
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void setSize(label n)
Alias for resize().
Definition List.H:536
void setHit() noexcept
Set the hit status on.
void setIndex(const label index) noexcept
Set the index.
void setPoint(const point_type &p)
Set the point.
bool hit() const noexcept
Is there a hit?
const point_type & point() const noexcept
Return point, no checks.
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static Form uniform(const Cmpt &s)
Return a VectorSpace with all elements = s.
scalar distSqr(const Vector< Cmpt > &v2) const
The L2-norm distance squared from another vector. The magSqr() of the difference.
Definition VectorI.H:95
A bounding box defined in terms of min/max extrema points.
Definition boundBox.H:71
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
Searching on (optionally hollow) cone.
virtual void findLine(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find nearest intersection on line from start to end.
virtual void findLineAny(const pointField &start, const pointField &end, List< pointIndexHit > &) const
Find any intersection on line from start to end.
virtual void boundingSpheres(pointField &centres, scalarField &radiusSqr) const
Get bounding spheres (centre and radius squared), one per element.
virtual void getVolumeType(const pointField &points, List< volumeType > &volType) const
Determine type (inside/outside/mixed) for point.
virtual void getNormal(const List< pointIndexHit > &, vectorField &normal) const
From a set of points and indices get the normal.
virtual void getRegion(const List< pointIndexHit > &, labelList &region) const
From a set of points and indices get the region.
virtual const wordList & regions() const
Names of regions.
virtual void findNearest(const pointField &sample, const scalarField &nearestDistSqr, List< pointIndexHit > &) const
Find nearest point on cylinder.
virtual tmp< pointField > coordinates() const
Get representative set of element coordinates.
virtual tmp< pointField > points() const
Get the points that define the surface.
Base class of (analytical or triangulated) surface. Encapsulates all the search routines....
virtual const boundBox & bounds() const
Return const reference to boundBox.
A class for managing temporary objects.
Definition tmp.H:75
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition tmp.H:215
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
@ OUTSIDE
A location outside the volume.
Definition volumeType.H:66
@ INSIDE
A location inside the volume.
Definition volumeType.H:65
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
volScalarField & p
const auto & io
auto & name
const pointField & points
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.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))
const expr V(m.psi().mesh().V())
const char * end
Definition SVGTools.H:223
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< label > labelList
A List of labels.
Definition List.H:62
dimensionedSymmTensor sqr(const dimensionedVector &dv)
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
label findMin(const ListType &input, label start=0)
Linear search for the index of the min element, similar to std::min_element but for lists and returns...
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
vectorField pointField
pointField is a vectorField.
Vector< scalar > vector
Definition vector.H:57
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
dictionary dict
const pointField & pts
volScalarField & b
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
scalarField samples(nIntervals, Zero)