1 // Copyright (c) 2021 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <SelectMgr_AxisIntersector.hxx>
15
16 #include <Bnd_Range.hxx>
17 #include <BVH_Tools.hxx>
18 #include <Precision.hxx>
19 #include <SelectBasics_PickResult.hxx>
20 #include <SelectMgr_ViewClipRange.hxx>
21
22 // =======================================================================
23 // function : Constructor
24 // purpose :
25 // =======================================================================
SelectMgr_AxisIntersector()26 SelectMgr_AxisIntersector::SelectMgr_AxisIntersector()
27 {
28 //
29 }
30
31 // =======================================================================
32 // function : ~SelectMgr_AxisIntersector
33 // purpose :
34 // =======================================================================
~SelectMgr_AxisIntersector()35 SelectMgr_AxisIntersector::~SelectMgr_AxisIntersector()
36 {
37 //
38 }
39
40 // =======================================================================
41 // function : Init
42 // purpose :
43 // =======================================================================
Init(const gp_Ax1 & theAxis)44 void SelectMgr_AxisIntersector::Init (const gp_Ax1& theAxis)
45 {
46 mySelectionType = SelectMgr_SelectionType_Point;
47 myAxis = theAxis;
48 }
49
50 // =======================================================================
51 // function : Build
52 // purpose :
53 // =======================================================================
Build()54 void SelectMgr_AxisIntersector::Build()
55 {
56 }
57
58 //=======================================================================
59 // function : SetCamera
60 // purpose :
61 //=======================================================================
SetCamera(const Handle (Graphic3d_Camera)&)62 void SelectMgr_AxisIntersector::SetCamera (const Handle(Graphic3d_Camera)&)
63 {
64 }
65
66 // =======================================================================
67 // function : ScaleAndTransform
68 // purpose :
69 // =======================================================================
Handle(SelectMgr_BaseIntersector)70 Handle(SelectMgr_BaseIntersector) SelectMgr_AxisIntersector::ScaleAndTransform (const Standard_Integer theScaleFactor,
71 const gp_GTrsf& theTrsf,
72 const Handle(SelectMgr_FrustumBuilder)& theBuilder) const
73 {
74 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
75 "Error! SelectMgr_AxisIntersector::ScaleAndTransform() should be called after selection axis initialization");
76
77 (void )theScaleFactor;
78 (void )theBuilder;
79 if (theTrsf.Form() == gp_Identity)
80 {
81 return new SelectMgr_AxisIntersector();
82 }
83
84 gp_Pnt aTransformedLoc = myAxis.Location();
85 theTrsf.Transforms (aTransformedLoc.ChangeCoord());
86 gp_XYZ aTransformedDir = myAxis.Direction().XYZ();
87 gp_GTrsf aTrsf = theTrsf;
88 aTrsf.SetTranslationPart (gp_XYZ(0., 0., 0.));
89 aTrsf.Transforms (aTransformedDir);
90
91 Handle(SelectMgr_AxisIntersector) aRes = new SelectMgr_AxisIntersector();
92 aRes->myAxis = gp_Ax1(aTransformedLoc, gp_Dir(aTransformedDir));
93 aRes->mySelectionType = mySelectionType;
94 return aRes;
95 }
96
97 // =======================================================================
98 // function : hasIntersection
99 // purpose :
100 // =======================================================================
hasIntersection(const SelectMgr_Vec3 & theBoxMin,const SelectMgr_Vec3 & theBoxMax,Standard_Real & theTimeEnter,Standard_Real & theTimeLeave) const101 Standard_Boolean SelectMgr_AxisIntersector::hasIntersection (const SelectMgr_Vec3& theBoxMin,
102 const SelectMgr_Vec3& theBoxMax,
103 Standard_Real& theTimeEnter,
104 Standard_Real& theTimeLeave) const
105 {
106 const gp_Pnt& anAxisLoc = myAxis.Location();
107 const gp_Dir& anAxisDir = myAxis.Direction();
108 BVH_Ray<Standard_Real, 3> aRay(SelectMgr_Vec3(anAxisLoc.X(), anAxisLoc.Y(), anAxisLoc.Z()),
109 SelectMgr_Vec3(anAxisDir.X(), anAxisDir.Y(), anAxisDir.Z()));
110 if (!BVH_Tools<Standard_Real, 3>::RayBoxIntersection (aRay, theBoxMin, theBoxMax, theTimeEnter, theTimeLeave))
111 {
112 return Standard_False;
113 }
114 return Standard_True;
115 }
116
117 // =======================================================================
118 // function : hasIntersection
119 // purpose :
120 // =======================================================================
hasIntersection(const gp_Pnt & thePnt,Standard_Real & theDepth) const121 Standard_Boolean SelectMgr_AxisIntersector::hasIntersection (const gp_Pnt& thePnt,
122 Standard_Real& theDepth) const
123 {
124 const gp_Pnt& anAxisLoc = myAxis.Location();
125 const gp_Dir& anAxisDir = myAxis.Direction();
126
127 // Check that vectors are co-directed (thePnt lies on this axis)
128 gp_Dir aDirToPnt(thePnt.XYZ() - anAxisLoc.XYZ());
129 if (!anAxisDir.IsEqual (aDirToPnt, Precision::Angular()))
130 {
131 return Standard_False;
132 }
133 theDepth = anAxisLoc.Distance (thePnt);
134 return Standard_True;
135 }
136
137 // =======================================================================
138 // function : raySegmentDistance
139 // purpose :
140 // =======================================================================
raySegmentDistance(const gp_Pnt & theSegPnt1,const gp_Pnt & theSegPnt2,SelectBasics_PickResult & thePickResult) const141 Standard_Boolean SelectMgr_AxisIntersector::raySegmentDistance (const gp_Pnt& theSegPnt1,
142 const gp_Pnt& theSegPnt2,
143 SelectBasics_PickResult& thePickResult) const
144 {
145 const gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
146 const gp_XYZ aV = myAxis.Direction().XYZ();
147 const gp_XYZ aW = theSegPnt1.XYZ() - myAxis.Location().XYZ();
148
149 const gp_XYZ anUVNormVec = aV.Crossed (anU);
150 const Standard_Real anUVNormVecMod = anUVNormVec.Modulus();
151 if (anUVNormVecMod <= Precision::Confusion())
152 {
153 // Lines have no intersection
154 thePickResult.Invalidate();
155 return false;
156 }
157
158 const gp_XYZ anUWNormVec = aW.Crossed (anU);
159 const Standard_Real anUWNormVecMod = anUWNormVec.Modulus();
160 if (anUWNormVecMod <= Precision::Confusion())
161 {
162 // Lines have no intersection
163 thePickResult.Invalidate();
164 return false;
165 }
166
167 const Standard_Real aParam = anUWNormVec.Dot (anUVNormVec) / anUVNormVec.SquareModulus();
168 if (aParam < 0.0)
169 {
170 // Intersection is out of axis start point
171 thePickResult.Invalidate();
172 return false;
173 }
174
175 const gp_XYZ anIntersectPnt = myAxis.Location().XYZ() + aV * aParam;
176 if ((anIntersectPnt - theSegPnt1.XYZ()).Modulus() +
177 (anIntersectPnt - theSegPnt2.XYZ()).Modulus() >
178 anU.Modulus() + Precision::Confusion())
179 {
180 // Intersection point doesn't lie on the segment
181 thePickResult.Invalidate();
182 return false;
183 }
184
185 thePickResult.SetDepth (myAxis.Location().Distance (anIntersectPnt));
186 thePickResult.SetPickedPoint (anIntersectPnt);
187 return true;
188 }
189
190 // =======================================================================
191 // function : rayPlaneIntersection
192 // purpose :
193 // =======================================================================
rayPlaneIntersection(const gp_Vec & thePlane,const gp_Pnt & thePntOnPlane,SelectBasics_PickResult & thePickResult) const194 bool SelectMgr_AxisIntersector::rayPlaneIntersection (const gp_Vec& thePlane,
195 const gp_Pnt& thePntOnPlane,
196 SelectBasics_PickResult& thePickResult) const
197 {
198 gp_XYZ anU = myAxis.Direction().XYZ();
199 gp_XYZ aW = myAxis.Location().XYZ() - thePntOnPlane.XYZ();
200 Standard_Real aD = thePlane.Dot (anU);
201 Standard_Real aN = -thePlane.Dot (aW);
202
203 if (Abs (aD) < Precision::Confusion())
204 {
205 thePickResult.Invalidate();
206 return false;
207 }
208
209 Standard_Real aParam = aN / aD;
210 if (aParam < 0.0)
211 {
212 thePickResult.Invalidate();
213 return false;
214 }
215
216 gp_Pnt aClosestPnt = myAxis.Location().XYZ() + anU * aParam;
217 thePickResult.SetDepth (myAxis.Location().Distance (aClosestPnt));
218 thePickResult.SetPickedPoint (aClosestPnt);
219 return true;
220 }
221
222 // =======================================================================
223 // function : OverlapsBox
224 // purpose :
225 // =======================================================================
OverlapsBox(const SelectMgr_Vec3 & theBoxMin,const SelectMgr_Vec3 & theBoxMax,Standard_Boolean * theInside) const226 Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& theBoxMin,
227 const SelectMgr_Vec3& theBoxMax,
228 Standard_Boolean* theInside) const
229 {
230 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
231 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
232
233 (void )theInside;
234 Standard_Real aTimeEnter, aTimeLeave;
235 if (!hasIntersection (theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
236 {
237 return Standard_False;
238 }
239 if (theInside != NULL)
240 {
241 *theInside &= (aTimeEnter >= 0.0);
242 }
243 return Standard_True;
244 }
245
246 // =======================================================================
247 // function : OverlapsBox
248 // purpose :
249 // =======================================================================
OverlapsBox(const SelectMgr_Vec3 & theBoxMin,const SelectMgr_Vec3 & theBoxMax,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const250 Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& theBoxMin,
251 const SelectMgr_Vec3& theBoxMax,
252 const SelectMgr_ViewClipRange& theClipRange,
253 SelectBasics_PickResult& thePickResult) const
254 {
255 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
256 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
257
258 Standard_Real aTimeEnter, aTimeLeave;
259 if (!hasIntersection (theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
260 {
261 return Standard_False;
262 }
263
264 Standard_Real aDepth = 0.0;
265 Bnd_Range aRange(Max (aTimeEnter, 0.0), aTimeLeave);
266 aRange.GetMin (aDepth);
267
268 if (!theClipRange.GetNearestDepth (aRange, aDepth))
269 {
270 return Standard_False;
271 }
272
273 thePickResult.SetDepth (aDepth);
274
275 return Standard_True;
276 }
277
278 // =======================================================================
279 // function : OverlapsPoint
280 // purpose :
281 // =======================================================================
OverlapsPoint(const gp_Pnt & thePnt,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const282 Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
283 const SelectMgr_ViewClipRange& theClipRange,
284 SelectBasics_PickResult& thePickResult) const
285 {
286 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
287 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
288
289 Standard_Real aDepth = 0.0;
290 if (!hasIntersection (thePnt, aDepth))
291 {
292 return Standard_False;
293 }
294
295 thePickResult.SetDepth (aDepth);
296 thePickResult.SetPickedPoint (thePnt);
297
298 return !theClipRange.IsClipped (thePickResult.Depth());
299 }
300
301 // =======================================================================
302 // function : OverlapsPoint
303 // purpose :
304 // =======================================================================
OverlapsPoint(const gp_Pnt & thePnt) const305 Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt) const
306 {
307 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
308 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
309
310 Standard_Real aDepth = 0.0;
311 return hasIntersection (thePnt, aDepth);
312 }
313
314 // =======================================================================
315 // function : OverlapsSegment
316 // purpose :
317 // =======================================================================
OverlapsSegment(const gp_Pnt & thePnt1,const gp_Pnt & thePnt2,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const318 Standard_Boolean SelectMgr_AxisIntersector::OverlapsSegment (const gp_Pnt& thePnt1,
319 const gp_Pnt& thePnt2,
320 const SelectMgr_ViewClipRange& theClipRange,
321 SelectBasics_PickResult& thePickResult) const
322 {
323 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
324 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
325
326 if (!raySegmentDistance (thePnt1, thePnt2, thePickResult))
327 {
328 return Standard_False;
329 }
330
331 return !theClipRange.IsClipped (thePickResult.Depth());
332 }
333
334 // =======================================================================
335 // function : OverlapsPolygon
336 // purpose :
337 // =======================================================================
OverlapsPolygon(const TColgp_Array1OfPnt & theArrayOfPnts,Select3D_TypeOfSensitivity theSensType,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const338 Standard_Boolean SelectMgr_AxisIntersector::OverlapsPolygon (const TColgp_Array1OfPnt& theArrayOfPnts,
339 Select3D_TypeOfSensitivity theSensType,
340 const SelectMgr_ViewClipRange& theClipRange,
341 SelectBasics_PickResult& thePickResult) const
342 {
343 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
344 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
345
346 if (theSensType == Select3D_TOS_BOUNDARY)
347 {
348 Standard_Integer aMatchingSegmentsNb = -1;
349 SelectBasics_PickResult aPickResult;
350 thePickResult.Invalidate();
351 const Standard_Integer aLower = theArrayOfPnts.Lower();
352 const Standard_Integer anUpper = theArrayOfPnts.Upper();
353 for (Standard_Integer aPntIter = aLower; aPntIter <= anUpper; ++aPntIter)
354 {
355 const gp_Pnt& aStartPnt = theArrayOfPnts.Value (aPntIter);
356 const gp_Pnt& aEndPnt = theArrayOfPnts.Value (aPntIter == anUpper ? aLower : (aPntIter + 1));
357 if (raySegmentDistance (aStartPnt, aEndPnt, aPickResult))
358 {
359 aMatchingSegmentsNb++;
360 thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
361 }
362 }
363
364 if (aMatchingSegmentsNb == -1)
365 {
366 return Standard_False;
367 }
368 }
369 else if (theSensType == Select3D_TOS_INTERIOR)
370 {
371 Standard_Integer aStartIdx = theArrayOfPnts.Lower();
372 const gp_XYZ& aPnt1 = theArrayOfPnts.Value (aStartIdx).XYZ();
373 const gp_XYZ& aPnt2 = theArrayOfPnts.Value (aStartIdx + 1).XYZ();
374 const gp_XYZ& aPnt3 = theArrayOfPnts.Value (aStartIdx + 2).XYZ();
375 const gp_XYZ aVec1 = aPnt1 - aPnt2;
376 const gp_XYZ aVec2 = aPnt3 - aPnt2;
377 gp_Vec aPolyNorm = aVec2.Crossed (aVec1);
378 if (aPolyNorm.Magnitude() <= Precision::Confusion())
379 {
380 // treat degenerated polygon as point
381 return OverlapsPoint (theArrayOfPnts.First(), theClipRange, thePickResult);
382 }
383 else if (!rayPlaneIntersection (aPolyNorm, theArrayOfPnts.First(), thePickResult))
384 {
385 return Standard_False;
386 }
387 }
388
389 return !theClipRange.IsClipped (thePickResult.Depth());
390 }
391
392 // =======================================================================
393 // function : OverlapsTriangle
394 // purpose :
395 // =======================================================================
OverlapsTriangle(const gp_Pnt & thePnt1,const gp_Pnt & thePnt2,const gp_Pnt & thePnt3,Select3D_TypeOfSensitivity theSensType,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const396 Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& thePnt1,
397 const gp_Pnt& thePnt2,
398 const gp_Pnt& thePnt3,
399 Select3D_TypeOfSensitivity theSensType,
400 const SelectMgr_ViewClipRange& theClipRange,
401 SelectBasics_PickResult& thePickResult) const
402 {
403 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
404 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
405
406 if (theSensType == Select3D_TOS_BOUNDARY)
407 {
408 const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 };
409 const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 4);
410 return OverlapsPolygon (aPntsArray, Select3D_TOS_BOUNDARY, theClipRange, thePickResult);
411 }
412 else if (theSensType == Select3D_TOS_INTERIOR)
413 {
414 gp_Vec aTriangleNormal (gp_XYZ (RealLast(), RealLast(), RealLast()));
415 const gp_XYZ aTrEdges[3] = { thePnt2.XYZ() - thePnt1.XYZ(),
416 thePnt3.XYZ() - thePnt2.XYZ(),
417 thePnt1.XYZ() - thePnt3.XYZ() };
418 aTriangleNormal = aTrEdges[2].Crossed (aTrEdges[0]);
419 if (aTriangleNormal.SquareMagnitude() < gp::Resolution())
420 {
421 // consider degenerated triangle as point or segment
422 return aTrEdges[0].SquareModulus() > gp::Resolution()
423 ? OverlapsSegment (thePnt1, thePnt2, theClipRange, thePickResult)
424 : (aTrEdges[1].SquareModulus() > gp::Resolution()
425 ? OverlapsSegment (thePnt2, thePnt3, theClipRange, thePickResult)
426 : OverlapsPoint (thePnt1, theClipRange, thePickResult));
427 }
428
429 const gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
430 const Standard_Real anAlpha = aTriangleNormal.XYZ().Dot (myAxis.Direction().XYZ());
431 if (Abs (anAlpha) < gp::Resolution())
432 {
433 // handle the case when triangle normal and selecting frustum direction are orthogonal
434 SelectBasics_PickResult aPickResult;
435 thePickResult.Invalidate();
436 for (Standard_Integer anEdgeIter = 0; anEdgeIter < 3; ++anEdgeIter)
437 {
438 const gp_Pnt& aStartPnt = aPnts[anEdgeIter];
439 const gp_Pnt& anEndPnt = aPnts[anEdgeIter < 2 ? anEdgeIter + 1 : 0];
440 if (raySegmentDistance (aStartPnt, anEndPnt, aPickResult))
441 {
442 thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
443 }
444 }
445 thePickResult.SetSurfaceNormal (aTriangleNormal);
446 return thePickResult.IsValid()
447 && !theClipRange.IsClipped (thePickResult.Depth());
448 }
449
450 // check if intersection point belongs to triangle's interior part
451 const gp_XYZ anEdge = (thePnt1.XYZ() - myAxis.Location().XYZ()) * (1.0 / anAlpha);
452
453 const Standard_Real aTime = aTriangleNormal.Dot (anEdge);
454 const gp_XYZ aVec = myAxis.Direction().XYZ().Crossed (anEdge);
455 const Standard_Real anU = aVec.Dot (aTrEdges[2]);
456 const Standard_Real aV = aVec.Dot (aTrEdges[0]);
457
458 const Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
459 const gp_Pnt aPtOnPlane = myAxis.Location().XYZ() + myAxis.Direction().XYZ() * aTime;
460 if (isInterior)
461 {
462 thePickResult.SetDepth (myAxis.Location().Distance (aPtOnPlane));
463 thePickResult.SetPickedPoint (aPtOnPlane);
464 thePickResult.SetSurfaceNormal (aTriangleNormal);
465 return !theClipRange.IsClipped (thePickResult.Depth());
466 }
467
468 Standard_Real aMinDist = RealLast();
469 Standard_Integer aNearestEdgeIdx1 = -1;
470 for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx)
471 {
472 gp_XYZ aW = aPtOnPlane.XYZ() - aPnts[anEdgeIdx].XYZ();
473 Standard_Real aCoef = aTrEdges[anEdgeIdx].Dot (aW) / aTrEdges[anEdgeIdx].Dot (aTrEdges[anEdgeIdx]);
474 Standard_Real aDist = aPtOnPlane.Distance (aPnts[anEdgeIdx].XYZ() + aCoef * aTrEdges[anEdgeIdx]);
475 if (aDist < aMinDist)
476 {
477 aMinDist = aDist;
478 aNearestEdgeIdx1 = anEdgeIdx;
479 }
480 }
481 Standard_Integer aNearestEdgeIdx2 = (aNearestEdgeIdx1 + 1) % 3;
482 const gp_Vec aVec12 (aPnts[aNearestEdgeIdx1], aPnts[aNearestEdgeIdx2]);
483 if (aVec12.SquareMagnitude() > gp::Resolution()
484 && myAxis.Direction().IsParallel (aVec12, Precision::Angular()))
485 {
486 aNearestEdgeIdx2 = aNearestEdgeIdx1 == 0 ? 2 : aNearestEdgeIdx1 - 1;
487 }
488 if (raySegmentDistance (aPnts[aNearestEdgeIdx1], aPnts[aNearestEdgeIdx2], thePickResult))
489 {
490 thePickResult.SetSurfaceNormal (aTriangleNormal);
491 }
492 }
493
494 return thePickResult.IsValid()
495 && !theClipRange.IsClipped (thePickResult.Depth());
496 }
497
498 //=======================================================================
499 // function : OverlapsSphere
500 // purpose :
501 //=======================================================================
OverlapsSphere(const gp_Pnt & theCenter,const Standard_Real theRadius,Standard_Boolean * theInside) const502 Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCenter,
503 const Standard_Real theRadius,
504 Standard_Boolean* theInside) const
505 {
506 Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
507 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
508 (void )theInside;
509 Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
510 if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
511 {
512 return Standard_False;
513 }
514 if (theInside != NULL)
515 {
516 *theInside &= (aTimeEnter >= 0.0);
517 }
518 return Standard_True;
519 }
520
521 //=======================================================================
522 // function : OverlapsSphere
523 // purpose :
524 //=======================================================================
OverlapsSphere(const gp_Pnt & theCenter,const Standard_Real theRadius,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const525 Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCenter,
526 const Standard_Real theRadius,
527 const SelectMgr_ViewClipRange& theClipRange,
528 SelectBasics_PickResult& thePickResult) const
529 {
530 Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
531 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
532 Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
533 if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
534 {
535 return Standard_False;
536 }
537
538 Standard_Real aDepth = 0.0;
539 Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
540 aRange.GetMin (aDepth);
541 if (!theClipRange.GetNearestDepth (aRange, aDepth))
542 {
543 return Standard_False;
544 }
545
546 thePickResult.SetDepth (aDepth);
547 return Standard_True;
548 }
549
550 //=======================================================================
551 // function : OverlapsCylinder
552 // purpose :
553 //=======================================================================
OverlapsCylinder(const Standard_Real theBottomRad,const Standard_Real theTopRad,const Standard_Real theHeight,const gp_Trsf & theTrsf,const SelectMgr_ViewClipRange & theClipRange,SelectBasics_PickResult & thePickResult) const554 Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Real theBottomRad,
555 const Standard_Real theTopRad,
556 const Standard_Real theHeight,
557 const gp_Trsf& theTrsf,
558 const SelectMgr_ViewClipRange& theClipRange,
559 SelectBasics_PickResult& thePickResult) const
560 {
561 Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
562 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
563 Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
564 gp_Trsf aTrsfInv = theTrsf.Inverted();
565 gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
566 gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
567 if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
568 {
569 return false;
570 }
571
572 Standard_Real aDepth = 0.0;
573 Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
574 aRange.GetMin (aDepth);
575 if (!theClipRange.GetNearestDepth (aRange, aDepth))
576 {
577 return false;
578 }
579 thePickResult.SetDepth (aDepth);
580 return true;
581 }
582
583 //=======================================================================
584 // function : OverlapsCylinder
585 // purpose :
586 //=======================================================================
OverlapsCylinder(const Standard_Real theBottomRad,const Standard_Real theTopRad,const Standard_Real theHeight,const gp_Trsf & theTrsf,Standard_Boolean * theInside) const587 Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Real theBottomRad,
588 const Standard_Real theTopRad,
589 const Standard_Real theHeight,
590 const gp_Trsf& theTrsf,
591 Standard_Boolean* theInside) const
592 {
593 Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
594 "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
595 Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
596 gp_Trsf aTrsfInv = theTrsf.Inverted();
597 gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
598 gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
599 if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
600 {
601 return false;
602 }
603 if (theInside != NULL)
604 {
605 *theInside &= (aTimeEnter >= 0.0);
606 }
607 return true;
608 }
609
610 //=======================================================================
611 // function : GetNearPnt
612 // purpose :
613 //=======================================================================
GetNearPnt() const614 const gp_Pnt& SelectMgr_AxisIntersector::GetNearPnt() const
615 {
616 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
617 "Error! SelectMgr_AxisIntersector::GetNearPnt() should be called after selection axis initialization");
618
619 return myAxis.Location();
620 }
621
622 //=======================================================================
623 // function : GetFarPnt
624 // purpose :
625 //=======================================================================
GetFarPnt() const626 const gp_Pnt& SelectMgr_AxisIntersector::GetFarPnt() const
627 {
628 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
629 "Error! SelectMgr_AxisIntersector::GetFarPnt() should be called after selection axis initialization");
630
631 static gp_Pnt anInfPnt(RealLast(), RealLast(), RealLast());
632 return anInfPnt;
633 }
634
635 //=======================================================================
636 // function : GetViewRayDirection
637 // purpose :
638 //=======================================================================
GetViewRayDirection() const639 const gp_Dir& SelectMgr_AxisIntersector::GetViewRayDirection() const
640 {
641 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
642 "Error! SelectMgr_AxisIntersector::GetViewRayDirection() should be called after selection axis initialization");
643
644 return myAxis.Direction();
645 }
646
647 // =======================================================================
648 // function : DistToGeometryCenter
649 // purpose :
650 // =======================================================================
DistToGeometryCenter(const gp_Pnt & theCOG) const651 Standard_Real SelectMgr_AxisIntersector::DistToGeometryCenter (const gp_Pnt& theCOG) const
652 {
653 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
654 "Error! SelectMgr_AxisIntersector::DistToGeometryCenter() should be called after selection axis initialization");
655
656 return theCOG.Distance (myAxis.Location());
657 }
658
659 // =======================================================================
660 // function : DetectedPoint
661 // purpose :
662 // =======================================================================
DetectedPoint(const Standard_Real theDepth) const663 gp_Pnt SelectMgr_AxisIntersector::DetectedPoint (const Standard_Real theDepth) const
664 {
665 Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
666 "Error! SelectMgr_AxisIntersector::DetectedPoint() should be called after selection axis initialization");
667
668 return myAxis.Location().XYZ() + myAxis.Direction().XYZ() * theDepth;
669 }
670
671 //=======================================================================
672 //function : DumpJson
673 //purpose :
674 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const675 void SelectMgr_AxisIntersector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
676 {
677 OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_AxisIntersector)
678 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, SelectMgr_BaseIntersector)
679
680 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myAxis)
681 }
682