1 // Created on: 2014-05-22
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <NCollection_Vector.hxx>
17 #include <Poly_Array1OfTriangle.hxx>
19 #include <SelectMgr_RectangularFrustum.hxx>
21 #define DOT(A, B) (A.x() * B.x() + A.y() * B.y() + A.z() * B.z())
22 #define DOTp(A, B) (A.x() * B.X() + A.y() * B.Y() + A.z() * B.Z())
23 #define DISTANCE(A, B) (std::sqrt ((A.x() - B.x()) * (A.x() - B.x()) + (A.y() - B.y()) * (A.y() - B.y()) + (A.z() - B.z()) * (A.z() - B.z())))
24 #define DISTANCEp(A, B) (std::sqrt ((A.x() - B.X()) * (A.x() - B.X()) + (A.y() - B.Y()) * (A.y() - B.Y()) + (A.z() - B.Z()) * (A.z() - B.Z())))
26 // =======================================================================
27 // function : segmentSegmentDistance
29 // =======================================================================
30 void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegPnt1,
31 const gp_Pnt& theSegPnt2,
32 Standard_Real& theDepth)
34 SelectMgr_Vec3 anU = SelectMgr_Vec3 (theSegPnt2.X() - theSegPnt1.X(),
35 theSegPnt2.Y() - theSegPnt1.Y(),
36 theSegPnt2.Z() - theSegPnt1.Z());
37 SelectMgr_Vec3 aV = myViewRayDir;
38 SelectMgr_Vec3 aW = SelectMgr_Vec3 (theSegPnt1.X() - myNearPickedPnt.x(),
39 theSegPnt1.Y() - myNearPickedPnt.y(),
40 theSegPnt1.Z() - myNearPickedPnt.z());
41 Standard_Real anA = DOT (anU, anU);
42 Standard_Real aB = DOT (anU, aV);
43 Standard_Real aC = DOT (aV, aV);
44 Standard_Real aD = DOT (anU, aW);
45 Standard_Real anE = DOT (aV, aW);
46 Standard_Real aCoef = anA * aC - aB * aB;
47 Standard_Real aSc, aSn, aSd = aCoef;
48 Standard_Real aTc, aTn, aTd = aCoef;
50 if (aCoef < Precision::Confusion())
59 aSn = (aB * anE - aC * aD);
60 aTn = (anA * anE - aB * aD);
92 else if ((-aD + aB) > anA)
99 aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd);
100 aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
102 SelectMgr_Vec3 aDiff = aW + (anU * aSc) - (aV * aTc);
103 SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc;
104 theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
107 // =======================================================================
108 // function : segmentPlaneIntersection
110 // =======================================================================
111 void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const SelectMgr_Vec3& thePlane,
112 const gp_Pnt& thePntOnPlane,
113 Standard_Real& theDepth)
115 SelectMgr_Vec3 anU = myViewRayDir;
116 SelectMgr_Vec3 aW = SelectMgr_Vec3 (myNearPickedPnt.x() - thePntOnPlane.X(),
117 myNearPickedPnt.y() - thePntOnPlane.Y(),
118 myNearPickedPnt.z() - thePntOnPlane.Z());
119 Standard_Real aD = DOT (thePlane, anU);
120 Standard_Real aN = -DOT (thePlane, aW);
122 if (Abs (aD) < Precision::Confusion())
124 if (Abs (aN) < Precision::Angular())
136 Standard_Real aParam = aN / aD;
137 if (aParam < 0.0 || aParam > 1.0)
143 SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + anU * aParam;
144 theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
147 // =======================================================================
149 // purpose : Build volume according to the point and given pixel
151 // =======================================================================
152 void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
154 myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0);
155 myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0);
156 myViewRayDir = myFarPickedPnt - myNearPickedPnt;
159 myVertices[0] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
160 thePoint.Y() + myPixelTolerance / 2.0,
163 myVertices[1] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
164 thePoint.Y() + myPixelTolerance / 2.0,
167 myVertices[2] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
168 thePoint.Y() - myPixelTolerance / 2.0,
171 myVertices[3] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
172 thePoint.Y() - myPixelTolerance / 2.0,
175 myVertices[4] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
176 thePoint.Y() + myPixelTolerance / 2.0,
179 myVertices[5] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
180 thePoint.Y() + myPixelTolerance / 2.0,
183 myVertices[6] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
184 thePoint.Y() - myPixelTolerance / 2.0,
187 myVertices[7] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
188 thePoint.Y() - myPixelTolerance / 2.0,
191 myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
196 myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
201 myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
206 myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
211 myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
216 myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
221 for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
223 Standard_Real aMax = -DBL_MAX;
224 Standard_Real aMin = DBL_MAX;
225 const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
226 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
228 Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]);
229 aMax = Max (aMax, aProjection);
230 aMin = Min (aMin, aProjection);
232 myMaxVertsProjections[aPlaneIdx] = aMax;
233 myMinVertsProjections[aPlaneIdx] = aMin;
236 SelectMgr_Vec3 aDimensions[3] =
238 SelectMgr_Vec3 (1.0, 0.0, 0.0),
239 SelectMgr_Vec3 (0.0, 1.0, 0.0),
240 SelectMgr_Vec3 (0.0, 0.0, 1.0)
243 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
245 Standard_Real aMax = -DBL_MAX;
246 Standard_Real aMin = DBL_MAX;
247 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
249 Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]);
250 aMax = Max (aProjection, aMax);
251 aMin = Min (aProjection, aMin);
253 myMaxOrthoVertsProjections[aDim] = aMax;
254 myMinOrthoVertsProjections[aDim] = aMin;
258 myEdgeDirs[0] = myVertices[4] - myVertices[0];
260 myEdgeDirs[1] = myVertices[2] - myVertices[0];
262 myEdgeDirs[2] = myVertices[2] - myVertices[3];
264 myEdgeDirs[3] = myVertices[6] - myVertices[7];
266 myEdgeDirs[4] = myVertices[0] - myVertices[1];
268 myEdgeDirs[5] = myVertices[4] - myVertices[5];
271 // =======================================================================
273 // purpose : Build volume according to the selected rectangle
274 // =======================================================================
275 void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
276 const gp_Pnt2d& theMaxPnt)
278 myNearPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5,
279 (theMinPnt.Y() + theMaxPnt.Y()) * 0.5,
281 myFarPickedPnt = myBuilder->ProjectPntOnViewPlane ((theMinPnt.X() + theMaxPnt.X()) * 0.5,
282 (theMinPnt.Y() + theMaxPnt.Y()) * 0.5,
284 myViewRayDir = myFarPickedPnt - myNearPickedPnt;
287 myVertices[0] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
291 myVertices[1] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
295 myVertices[2] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
299 myVertices[3] = myBuilder->ProjectPntOnViewPlane (theMinPnt.X(),
303 myVertices[4] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
307 myVertices[5] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
311 myVertices[6] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
315 myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X() ,
320 myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
325 myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
330 myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
335 myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
340 myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
345 myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
350 for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
352 Standard_Real aMax = -DBL_MAX;
353 Standard_Real aMin = DBL_MAX;
354 const SelectMgr_Vec3 aPlane = myPlanes[aPlaneIdx];
355 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
357 Standard_Real aProjection = DOT (aPlane, myVertices[aVertIdx]);
358 aMax = Max (aMax, aProjection);
359 aMin = Min (aMin, aProjection);
361 myMaxVertsProjections[aPlaneIdx] = aMax;
362 myMinVertsProjections[aPlaneIdx] = aMin;
365 SelectMgr_Vec3 aDimensions[3] =
367 SelectMgr_Vec3 (1.0, 0.0, 0.0),
368 SelectMgr_Vec3 (0.0, 1.0, 0.0),
369 SelectMgr_Vec3 (0.0, 0.0, 1.0)
372 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
374 Standard_Real aMax = -DBL_MAX;
375 Standard_Real aMin = DBL_MAX;
376 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
378 Standard_Real aProjection = DOT (aDimensions[aDim], myVertices[aVertIdx]);
379 aMax = Max (aMax, aProjection);
380 aMin = Min (aMin, aProjection);
382 myMaxOrthoVertsProjections[aDim] = aMax;
383 myMinOrthoVertsProjections[aDim] = aMin;
387 myEdgeDirs[0] = myVertices[4] - myVertices[0];
389 myEdgeDirs[1] = myVertices[2] - myVertices[0];
391 myEdgeDirs[2] = myVertices[2] - myVertices[3];
393 myEdgeDirs[3] = myVertices[6] - myVertices[7];
395 myEdgeDirs[4] = myVertices[0] - myVertices[1];
397 myEdgeDirs[5] = myVertices[4] - myVertices[5];
400 // =======================================================================
401 // function : Transform
402 // purpose : Returns a copy of the frustum transformed according to the matrix given
403 // =======================================================================
404 NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Transform (const gp_Trsf& theTrsf)
406 SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum();
408 aRes->myNearPickedPnt = SelectMgr_MatOp::Transform (theTrsf, myNearPickedPnt);
409 aRes->myFarPickedPnt = SelectMgr_MatOp::Transform (theTrsf, myFarPickedPnt);
410 aRes->myViewRayDir = aRes->myFarPickedPnt - aRes->myNearPickedPnt;
412 aRes->myIsOrthographic = myIsOrthographic;
415 aRes->myVertices[0] = SelectMgr_MatOp::Transform (theTrsf, myVertices[0]);
417 aRes->myVertices[1] = SelectMgr_MatOp::Transform (theTrsf, myVertices[1]);
419 aRes->myVertices[2] = SelectMgr_MatOp::Transform (theTrsf, myVertices[2]);
421 aRes->myVertices[3] = SelectMgr_MatOp::Transform (theTrsf, myVertices[3]);
423 aRes->myVertices[4] = SelectMgr_MatOp::Transform (theTrsf, myVertices[4]);
425 aRes->myVertices[5] = SelectMgr_MatOp::Transform (theTrsf, myVertices[5]);
427 aRes->myVertices[6] = SelectMgr_MatOp::Transform (theTrsf, myVertices[6]);
429 aRes->myVertices[7] = SelectMgr_MatOp::Transform (theTrsf, myVertices[7]);
432 aRes->myPlanes[0] = myBuilder->PlaneEquation (aRes->myVertices[1],
435 aRes->myVertices[6]);
437 aRes->myPlanes[1] = myBuilder->PlaneEquation (aRes->myVertices[3],
440 aRes->myVertices[4]);
442 aRes->myPlanes[2] = myBuilder->PlaneEquation (aRes->myVertices[1],
445 aRes->myVertices[6]);
447 aRes->myPlanes[3] = myBuilder->PlaneEquation (aRes->myVertices[5],
450 aRes->myVertices[2]);
452 aRes->myPlanes[4] = myBuilder->PlaneEquation (aRes->myVertices[4],
455 aRes->myVertices[3]);
457 aRes->myPlanes[5] = myBuilder->PlaneEquation (aRes->myVertices[5],
460 aRes->myVertices[2]);
462 for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
464 Standard_Real aMax = -DBL_MAX;
465 Standard_Real aMin = DBL_MAX;
466 const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx];
467 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
469 Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]);
470 aMax = Max (aMax, aProjection);
471 aMin = Min (aMin, aProjection);
473 aRes->myMaxVertsProjections[aPlaneIdx] = aMax;
474 aRes->myMinVertsProjections[aPlaneIdx] = aMin;
477 SelectMgr_Vec3 aDimensions[3] =
479 SelectMgr_Vec3 (1.0, 0.0, 0.0),
480 SelectMgr_Vec3 (0.0, 1.0, 0.0),
481 SelectMgr_Vec3 (0.0, 0.0, 1.0)
484 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
486 Standard_Real aMax = -DBL_MAX;
487 Standard_Real aMin = DBL_MAX;
488 for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
490 Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]);
491 aMax = Max (aMax, aProjection);
492 aMin = Min (aMin, aProjection);
494 aRes->myMaxOrthoVertsProjections[aDim] = aMax;
495 aRes->myMinOrthoVertsProjections[aDim] = aMin;
499 aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0];
501 aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0];
503 aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3];
505 aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7];
507 aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1];
509 aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5];
511 return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
514 // =======================================================================
515 // function : Overlaps
516 // purpose : Returns true if selecting volume is overlapped by
517 // axis-aligned bounding box with minimum corner at point
518 // theMinPnt and maximum at point theMaxPnt
519 // =======================================================================
520 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPnt,
521 const SelectMgr_Vec3& theMaxPnt)
523 return hasOverlap (theMinPnt, theMaxPnt);
526 // =======================================================================
527 // function : Overlaps
528 // purpose : SAT intersection test between defined volume and
529 // given axis-aligned box
530 // =======================================================================
531 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
532 Standard_Real& theDepth)
534 const SelectMgr_Vec3& aMinPnt = theBox.CornerMin();
535 const SelectMgr_Vec3& aMaxPnt = theBox.CornerMax();
536 if (!hasOverlap (aMinPnt, aMaxPnt))
537 return Standard_False;
539 SelectMgr_Vec3 aNearestPnt = SelectMgr_Vec3 (RealLast(), RealLast(), RealLast());
540 aNearestPnt.x() = Max (Min (myNearPickedPnt.x(), aMaxPnt.x()), aMinPnt.x());
541 aNearestPnt.y() = Max (Min (myNearPickedPnt.y(), aMaxPnt.y()), aMinPnt.y());
542 aNearestPnt.z() = Max (Min (myNearPickedPnt.z(), aMaxPnt.z()), aMinPnt.z());
544 theDepth = DISTANCE (aNearestPnt, myNearPickedPnt);
546 return Standard_True;
549 // =======================================================================
550 // function : Overlaps
551 // purpose : Intersection test between defined volume and given point
552 // =======================================================================
553 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
554 Standard_Real& theDepth)
556 if (!hasOverlap (thePnt))
557 return Standard_False;
559 SelectMgr_Vec3 aPnt (thePnt.X(), thePnt.Y(), thePnt.Z());
560 SelectMgr_Vec3 aV = aPnt - myNearPickedPnt;
561 SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * (DOT (aV, myViewRayDir) / DOT (myViewRayDir, myViewRayDir));
563 theDepth = DISTANCE (aDetectedPnt, myNearPickedPnt);
565 return Standard_True;
568 // =======================================================================
569 // function : Overlaps
570 // purpose : Checks if line segment overlaps selecting frustum
571 // =======================================================================
572 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
573 const gp_Pnt& thePnt2,
574 Standard_Real& theDepth)
577 if (!hasOverlap (thePnt1, thePnt2))
578 return Standard_False;
580 segmentSegmentDistance (thePnt1, thePnt2, theDepth);
581 return Standard_True;
584 // =======================================================================
585 // function : Overlaps
586 // purpose : SAT intersection test between defined volume and given
587 // ordered set of points, representing line segments. The test
588 // may be considered of interior part or boundary line defined
589 // by segments depending on given sensitivity type
590 // =======================================================================
591 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
592 Select3D_TypeOfSensitivity theSensType,
593 Standard_Real& theDepth)
595 if (theSensType == Select3D_TOS_BOUNDARY)
597 Standard_Integer aMatchingSegmentsNb = -1;
599 Standard_Integer aLower = theArrayOfPnts->Lower();
600 Standard_Integer anUpper = theArrayOfPnts->Upper();
602 for (Standard_Integer aPntIter = aLower; aPntIter <= anUpper; ++aPntIter)
604 const gp_Pnt& aStartPnt = theArrayOfPnts->Value (aPntIter);
605 const gp_Pnt& aEndPnt = aPntIter == anUpper ? theArrayOfPnts->Value (aLower)
606 : theArrayOfPnts->Value (aPntIter + 1);
608 if (hasOverlap (aStartPnt, aEndPnt))
610 aMatchingSegmentsNb++;
611 Standard_Real aSegmentDepth = RealLast();
612 segmentSegmentDistance (aStartPnt, aEndPnt, aSegmentDepth);
613 theDepth = Min (theDepth, aSegmentDepth);
617 if (aMatchingSegmentsNb == -1)
618 return Standard_False;
620 else if (theSensType == Select3D_TOS_INTERIOR)
622 SelectMgr_Vec3 aPolyNorm (RealLast());
623 if (!hasOverlap (theArrayOfPnts, aPolyNorm))
624 return Standard_False;
626 segmentPlaneIntersection (aPolyNorm,
627 theArrayOfPnts->Value (theArrayOfPnts->Lower()),
631 return Standard_True;
634 // =======================================================================
635 // function : Overlaps
636 // purpose : SAT intersection test between defined volume and given
637 // triangle. The test may be considered of interior part or
638 // boundary line defined by triangle vertices depending on
639 // given sensitivity type
640 // =======================================================================
641 const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
642 const gp_Pnt& thePnt2,
643 const gp_Pnt& thePnt3,
644 Select3D_TypeOfSensitivity theSensType,
645 Standard_Real& theDepth)
647 if (theSensType == Select3D_TOS_BOUNDARY)
649 Handle(TColgp_HArray1OfPnt) aPntsArray = new TColgp_HArray1OfPnt(1, 4);
650 aPntsArray->SetValue (1, thePnt1);
651 aPntsArray->SetValue (2, thePnt2);
652 aPntsArray->SetValue (3, thePnt3);
653 aPntsArray->SetValue (4, thePnt1);
654 return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theDepth);
656 else if (theSensType == Select3D_TOS_INTERIOR)
658 SelectMgr_Vec3 aTriangleNormal (RealLast());
659 if (!hasOverlap (thePnt1, thePnt2, thePnt3, aTriangleNormal))
660 return Standard_False;
662 // check if intersection point belongs to triangle's interior part
663 SelectMgr_Vec3 aPnt1 (thePnt1.X(), thePnt1.Y(), thePnt1.Z());
664 SelectMgr_Vec3 aTrEdges[3] = { SelectMgr_Vec3 (thePnt2.X() - thePnt1.X(), thePnt2.Y() - thePnt1.Y(), thePnt2.Z() - thePnt1.Z()),
665 SelectMgr_Vec3 (thePnt3.X() - thePnt2.X(), thePnt3.Y() - thePnt2.Y(), thePnt3.Z() - thePnt2.Z()),
666 SelectMgr_Vec3 (thePnt1.X() - thePnt3.X(), thePnt1.Y() - thePnt3.Y(), thePnt1.Z() - thePnt3.Z()) };
667 SelectMgr_Vec3 anEdge = (aPnt1 - myNearPickedPnt) * (1.0 / DOT (aTriangleNormal, myViewRayDir));
669 Standard_Real aTime = DOT (aTriangleNormal, anEdge);
671 SelectMgr_Vec3 aVec = SelectMgr_Vec3 (myViewRayDir.y() * anEdge.z() - myViewRayDir.z() * anEdge.y(),
672 myViewRayDir.z() * anEdge.x() - myViewRayDir.x() * anEdge.z(),
673 myViewRayDir.x() * anEdge.y() - myViewRayDir.y() * anEdge.x());
675 Standard_Real anU = DOT (aVec, aTrEdges[2]);
676 Standard_Real aV = DOT (aVec, aTrEdges[0]);
678 Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
682 SelectMgr_Vec3 aDetectedPnt = myNearPickedPnt + myViewRayDir * aTime;
683 theDepth = DISTANCE (myNearPickedPnt, aDetectedPnt);
684 return Standard_True;
687 gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
688 Standard_Real aMinDist = RealLast();
689 Standard_Integer aNearestEdgeIdx = -1;
690 SelectMgr_Vec3 aPtOnPlane = myNearPickedPnt + myViewRayDir * aTime;
691 for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx)
693 SelectMgr_Vec3 aW = SelectMgr_Vec3 (aPtOnPlane.x() - aPnts[anEdgeIdx].X(),
694 aPtOnPlane.y() - aPnts[anEdgeIdx].Y(),
695 aPtOnPlane.z() - aPnts[anEdgeIdx].Z());
696 Standard_Real aCoef = DOT (aTrEdges[anEdgeIdx], aW) / DOT (aTrEdges[anEdgeIdx], aTrEdges[anEdgeIdx]);
697 Standard_Real aDist = DISTANCE (aPtOnPlane, SelectMgr_Vec3 (aPnts[anEdgeIdx].X() + aCoef * aTrEdges[anEdgeIdx].x(),
698 aPnts[anEdgeIdx].Y() + aCoef * aTrEdges[anEdgeIdx].y(),
699 aPnts[anEdgeIdx].Z() + aCoef * aTrEdges[anEdgeIdx].z()));
700 if (aMinDist > aDist)
703 aNearestEdgeIdx = anEdgeIdx;
706 segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], theDepth);
709 return Standard_True;
712 // =======================================================================
713 // function : DistToGeometryCenter
714 // purpose : Measures distance between 3d projection of user-picked
715 // screen point and given point theCOG
716 // =======================================================================
717 const Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
719 const SelectMgr_Vec3& aCOG = SelectMgr_Vec3 (theCOG.X(), theCOG.Y(), theCOG.Z());
720 return DISTANCE (aCOG, myNearPickedPnt);
723 // =======================================================================
724 // function : DetectedPoint
725 // purpose : Calculates the point on a view ray that was detected during
726 // the run of selection algo by given depth
727 // =======================================================================
728 SelectMgr_Vec3 SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
730 return myNearPickedPnt + myViewRayDir * theDepth;
733 // =======================================================================
734 // function : IsClipped
735 // purpose : Checks if the point of sensitive in which selection was
736 // detected belongs to the region defined by clipping planes
737 // =======================================================================
738 const Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
739 const Standard_Real theDepth)
741 Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
742 Standard_Real aMaxDepth = DBL_MAX;
743 Standard_Real aMinDepth = -DBL_MAX;
744 Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
745 for ( ; aPlaneIt.More(); aPlaneIt.Next())
747 const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
748 if (!aClipPlane->IsOn())
751 gp_Pln aGeomPlane = aClipPlane->ToPlane();
753 aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
755 const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
757 Standard_Real aDotProduct = DOTp (myViewRayDir, aPlaneDirXYZ);
758 Standard_Real aDistance = - (DOTp (myNearPickedPnt, aPlaneDirXYZ) + aPlaneD);
760 // check whether the pick line is parallel to clip plane
761 if (Abs (aDotProduct) < Precision::Angular())
763 // line lies below the plane and is not clipped, skip
767 // compute distance to point of pick line intersection with the plane
768 Standard_Real aParam = aDistance / aDotProduct;
770 // check if ray intersects the plane, in case aIntDist < 0
771 // the plane is "behind" the ray
777 const SelectMgr_Vec3 anIntersectionPt = myNearPickedPnt + myViewRayDir * aParam;
778 const Standard_Real aDistToPln = DISTANCE (anIntersectionPt, myNearPickedPnt);
780 // change depth limits for case of opposite and directed planes
781 if (aDotProduct < 0.0)
783 aMaxDepth = Min (aDistToPln, aMaxDepth);
785 else if (aDistToPln > aMinDepth)
787 aMinDepth = Max (aDistToPln, aMinDepth);
791 return (theDepth <= aMinDepth || theDepth >= aMaxDepth);