1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0032182: Visualization - add Select3D_SensitiveSphere

- created Select3D_SensitiveSphere class
- implemented interfaces for intersection methods
- added tests
This commit is contained in:
mkrylova
2021-03-17 17:38:00 +03:00
committed by bugmaster
parent c123c310df
commit 503374ad84
25 changed files with 779 additions and 2 deletions

View File

@@ -495,6 +495,58 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
&& !theClipRange.IsClipped (thePickResult.Depth());
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
(void )theInside;
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
{
return Standard_False;
}
if (theInside != NULL)
{
*theInside &= (aTimeEnter >= 0.0);
}
return Standard_True;
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
{
return Standard_False;
}
Standard_Real aDepth = 0.0;
Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
aRange.GetMin (aDepth);
if (!theClipRange.GetNearestDepth (aRange, aDepth))
{
return Standard_False;
}
thePickResult.SetDepth (aDepth);
return Standard_True;
}
//=======================================================================
// function : GetNearPnt
// purpose :

View File

@@ -98,6 +98,19 @@ public:
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Intersection test between defined axis and given sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Intersection test between defined axis and given sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
public:
//! Measures distance between start axis point and given point theCOG.

View File

@@ -99,6 +99,49 @@ void SelectMgr_BaseFrustum::SetBuilder (const Handle(SelectMgr_FrustumBuilder)&
}
}
//=======================================================================
// function : IsBoundariesIntersectSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_BaseFrustum::IsBoundaryIntersectSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const gp_Dir& thePlaneNormal,
const TColgp_Array1OfPnt& theBoundaries,
Standard_Boolean& theBoundaryInside) const
{
for (Standard_Integer anIdx = theBoundaries.Lower(); anIdx < theBoundaries.Upper(); ++anIdx)
{
const Standard_Integer aNextIdx = ((anIdx + 1) == theBoundaries.Upper()) ? theBoundaries.Lower() : (anIdx + 1);
const gp_Pnt aPnt1 = theBoundaries.Value (anIdx);
const gp_Pnt aPnt2 = theBoundaries.Value (aNextIdx);
if (aPnt1.Distance (aPnt2) < Precision::Confusion())
{
continue;
}
// Projections of the points on the plane
const gp_Pnt aPntProj1 = aPnt1.XYZ() - thePlaneNormal.XYZ() * aPnt1.XYZ().Dot (thePlaneNormal.XYZ());
const gp_Pnt aPntProj2 = aPnt2.XYZ() - thePlaneNormal.XYZ() * aPnt2.XYZ().Dot (thePlaneNormal.XYZ());
if (aPntProj1.Distance (theCenter) < theRadius || aPntProj2.Distance (theCenter) < theRadius) // polygon intersects the sphere
{
theBoundaryInside = Standard_True;
return Standard_True;
}
gp_Dir aRayDir (gp_Vec (aPntProj1, aPntProj2));
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (RaySphereIntersection (theCenter, theRadius, aPntProj1, aRayDir, aTimeEnter, aTimeLeave))
{
if ((aTimeEnter > 0 && aTimeEnter < aPntProj1.Distance (aPntProj2))
|| (aTimeLeave > 0 && aTimeLeave < aPntProj1.Distance (aPntProj2)))
{
return Standard_True; // polygon crosses the sphere
}
}
}
return Standard_False;
}
//=======================================================================
//function : DumpJson
//purpose :

View File

@@ -54,6 +54,13 @@ public:
const Standard_Real theWidth,
const Standard_Real theHeight) Standard_OVERRIDE;
//! Checks whether the boundary of the current volume selection intersects with a sphere or are there it's boundaries lying inside the sphere
Standard_EXPORT Standard_Boolean IsBoundaryIntersectSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const gp_Dir& thePlaneNormal,
const TColgp_Array1OfPnt& theBoundaries,
Standard_Boolean& theBoundaryInside) const;
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;

View File

@@ -122,6 +122,48 @@ const gp_Pnt2d& SelectMgr_BaseIntersector::GetMousePosition() const
return aPnt;
}
//=======================================================================
// function : RaySphereIntersection
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_BaseIntersector::RaySphereIntersection (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
Standard_Real& theTimeEnter,
Standard_Real& theTimeLeave) const
{
// to find the intersection of the ray (theLoc, theRayDir) and sphere with theCenter(x0, y0, z0) and theRadius(R), you need to solve the equation
// (x' - x0)^2 + (y' - y0)^2 + (z' - z0)^2 = R^2, where P(x',y',z') = theLoc(x,y,z) + theRayDir(vx,vy,vz) * T
// at the end of solving, you receive a square equation with respect to T
// T^2 * (vx^2 + vy^2 + vz^2) + 2 * T * (vx*(x - x0) + vy*(y - y0) + vz*(z - z0)) + ((x-x0)^2 + (y-y0)^2 + (z-z0)^2 -R^2) = 0 (= A*T^2 + K*T + C)
// and find T by discriminant D = K^2 - A*C
const Standard_Real anA = theRayDir.Dot (theRayDir);
const Standard_Real aK = theRayDir.X() * (theLoc.X() - theCenter.X())
+ theRayDir.Y() * (theLoc.Y() - theCenter.Y())
+ theRayDir.Z() * (theLoc.Z() - theCenter.Z());
const Standard_Real aC = theLoc.Distance (theCenter) * theLoc.Distance (theCenter) - theRadius * theRadius;
const Standard_Real aDiscr = aK * aK - anA * aC;
if (aDiscr < 0)
{
return Standard_False;
}
const Standard_Real aTime1 = (-aK - Sqrt (aDiscr)) / anA;
const Standard_Real aTime2 = (-aK + Sqrt (aDiscr)) / anA;
if (Abs (aTime1) < Abs (aTime2))
{
theTimeEnter = aTime1;
theTimeLeave = aTime2;
}
else
{
theTimeEnter = aTime2;
theTimeLeave = aTime1;
}
return Standard_True;
}
//=======================================================================
// function : DistToGeometryCenter
// purpose :

View File

@@ -168,6 +168,19 @@ public:
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const = 0;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const = 0;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const = 0;
public:
//! Measures distance between 3d projection of user-picked
@@ -184,6 +197,15 @@ public:
//! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
//! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
//! with the sphere with center at theCenter and radius TheRadius
Standard_EXPORT virtual Standard_Boolean RaySphereIntersection (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
Standard_Real& theTimeEnter,
Standard_Real& theTimeLeave) const;
DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient)
protected:

View File

@@ -88,6 +88,11 @@ protected:
const gp_Pnt& thePnt3,
gp_Vec& theNormal) const;
//! Intersection test between defined volume and given sphere
Standard_Boolean hasSphereOverlap (const gp_Pnt& thePnt1,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const;
private:
//! Checks if AABB and frustum are separated along the given axis

View File

@@ -459,10 +459,63 @@ Standard_Boolean SelectMgr_Frustum<N>::hasTriangleOverlap (const gp_Pnt& thePnt1
}
}
}
return Standard_True;
}
// =======================================================================
// function : hasSphereOverlap
// purpose :
// =======================================================================
template <int N>
Standard_Boolean SelectMgr_Frustum<N>::hasSphereOverlap (const gp_Pnt& thePnt,
const Standard_Real theRadius,
Standard_Boolean* theInside) const
{
Standard_Boolean isOverlapFull = Standard_True;
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < N; aPlaneIdx += anIncFactor)
{
const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ();
const Standard_Real aNormVecLen = Sqrt (aPlane.Dot (aPlane));
const Standard_Real aCenterProj = aPlane.Dot (thePnt.XYZ()) / aNormVecLen;
const Standard_Real aMaxDist = myMaxVertsProjections[aPlaneIdx] / aNormVecLen;
const Standard_Real aMinDist = myMinVertsProjections[aPlaneIdx] / aNormVecLen;
if (aCenterProj > (aMaxDist + theRadius)
|| aCenterProj < (aMinDist - theRadius))
{
return Standard_False; // fully separated
}
else if (theInside)
{
*theInside &= aCenterProj >= (aMinDist + theRadius)
&& aCenterProj <= (aMaxDist - theRadius);
}
isOverlapFull &= aCenterProj >= (aMinDist + theRadius)
&& aCenterProj <= (aMaxDist - theRadius);
}
if (theInside || isOverlapFull)
{
return Standard_True;
}
const gp_Vec aVecPlane1 (myVertices[0], myVertices[2]);
const gp_Vec aVecPlane2 (myVertices[0], myVertices[2 * N - 2]);
if (aVecPlane1.IsParallel (aVecPlane2, Precision::Angular()))
{
return Standard_False;
}
const gp_Dir aNorm (aVecPlane1.Crossed (aVecPlane2));
gp_Pnt aBoundariesCArr[5];
NCollection_Array1<gp_Pnt> aBoundaries (aBoundariesCArr[0], 0, N);
for (Standard_Integer anIdx = 0; anIdx < N * 2; anIdx += 2)
{
aBoundaries.SetValue (anIdx / 2, myVertices[anIdx]);
}
// distance from point(x,y,z) to plane(A,B,C,D) d = | Ax + By + Cz + D | / sqrt (A^2 + B^2 + C^2) = aPnt.Dot (Norm) / 1
const gp_Pnt aCenterProj = thePnt.XYZ() - aNorm.XYZ() * thePnt.XYZ().Dot (aNorm.XYZ());
Standard_Boolean isBoundaryInside = Standard_False;
return IsBoundaryIntersectSphere (aCenterProj, theRadius, aNorm, aBoundaries, isBoundaryInside);
}
//=======================================================================
//function : DumpJson
//purpose :

View File

@@ -16,6 +16,7 @@
#include <SelectMgr_RectangularFrustum.hxx>
#include <BVH_Tools.hxx>
#include <gp_Pln.hxx>
#include <NCollection_Vector.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <SelectMgr_FrustumBuilder.hxx>
@@ -752,6 +753,53 @@ const gp_Pnt2d& SelectMgr_RectangularFrustum::GetMousePosition() const
return base_type::GetMousePosition();
}
// =======================================================================
// function : OverlapsSphere
// purpose :
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
if (!hasSphereOverlap (theCenter, theRadius))
{
return Standard_False;
}
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myNearPickedPnt, myViewRayDir, aTimeEnter, aTimeLeave))
{
return Standard_False;
}
thePickResult.SetDepth (aTimeEnter * myScale);
if (theClipRange.IsClipped (thePickResult.Depth()))
{
thePickResult.SetDepth (aTimeLeave * myScale);
}
gp_Pnt aPntOnSphere (myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * thePickResult.Depth());
gp_Vec aNormal (aPntOnSphere.XYZ() - theCenter.XYZ());
thePickResult.SetPickedPoint (aPntOnSphere);
thePickResult.SetSurfaceNormal (aNormal);
return !theClipRange.IsClipped (thePickResult.Depth());
}
// =======================================================================
// function : OverlapsSphere
// purpose :
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
return hasSphereOverlap (theCenter, theRadius, theInside);
}
// =======================================================================
// function : DistToGeometryCenter
// purpose : Measures distance between 3d projection of user-picked

View File

@@ -133,6 +133,17 @@ public:
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Intersection test between defined volume and given sphere
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Intersection test between defined volume and given sphere
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside) const Standard_OVERRIDE;
//! Measures distance between 3d projection of user-picked
//! screen point and given point theCOG.
//! It makes sense only for frustums built on a single point.

View File

@@ -388,6 +388,36 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsTriangle (const gp_Pn
myViewClipRange, thePickResult);
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
SelectBasics_PickResult& thePickResult) const
{
if (myActiveSelectingVolume.IsNull())
{
return Standard_False;
}
return myActiveSelectingVolume->OverlapsSphere (theCenter, theRadius, myViewClipRange, thePickResult);
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside) const
{
if (myActiveSelectingVolume.IsNull())
{
return Standard_False;
}
return myActiveSelectingVolume->OverlapsSphere (theCenter, theRadius, theInside);
}
//=======================================================================
// function : DistToGeometryCenter
// purpose : Measures distance between 3d projection of user-picked

View File

@@ -152,6 +152,16 @@ public:
Standard_Integer theSensType,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Intersection test between defined volume and given sphere
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Intersection test between defined volume and given sphere
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Measures distance between 3d projection of user-picked
//! screen point and given point theCOG
Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const Standard_OVERRIDE;

View File

@@ -16,6 +16,7 @@
#include <SelectMgr_TriangularFrustum.hxx>
#include <SelectMgr_FrustumBuilder.hxx>
#include <SelectMgr_ViewClipRange.hxx>
IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum, Standard_Transient)
@@ -301,6 +302,33 @@ Standard_Boolean SelectMgr_TriangularFrustum::OverlapsTriangle (const gp_Pnt& th
return Standard_True;
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustum::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside) const
{
(void) theInside;
return hasBoxOverlap (SelectMgr_Vec3 (theCenter.X() - theRadius, theCenter.Y() - theRadius, theCenter.Z() - theRadius),
SelectMgr_Vec3 (theCenter.X() + theRadius, theCenter.Y() + theRadius, theCenter.Z() + theRadius), NULL);
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustum::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
(void )theClipRange;
(void )thePickResult;
return hasSphereOverlap (theCenter, theRadius);
}
// =======================================================================
// function : Clear
// purpose : Nullifies the handle for corresponding builder instance to prevent

View File

@@ -104,6 +104,19 @@ public: //! @name SAT Tests for different objects
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
public:
//! Nullifies the handle to corresponding builder instance to prevent memory leaks

View File

@@ -389,6 +389,115 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsTriangle (const gp_Pnt&
return Standard_False;
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* /*theInside*/) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline,
"Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (anIter.Value()->OverlapsSphere (theCenter, theRadius, NULL))
{
// select 3 points of the frustum and build a plane on them
Standard_Real aMaxDist1 = 0.0, aMaxDist2 = 0.0;
Standard_Integer anIdx1 = myBoundaryPoints.Lower();
Standard_Integer anIdx2 = myBoundaryPoints.Lower();
Standard_Integer anIdx3 = myBoundaryPoints.Lower();
for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx < myBoundaryPoints.Size() / 2 + myBoundaryPoints.Lower(); anIdx++)
{
if (myBoundaryPoints[anIdx1].Distance (myBoundaryPoints[anIdx]) < Precision::Confusion())
{
continue;
}
else if (aMaxDist1 < myBoundaryPoints[anIdx1].Distance (myBoundaryPoints[anIdx]))
{
if (anIdx2 != anIdx3)
{
anIdx3 = anIdx2;
aMaxDist2 = aMaxDist1;
}
anIdx2 = anIdx;
aMaxDist1 = myBoundaryPoints[anIdx1].Distance (myBoundaryPoints[anIdx]);
}
else if (aMaxDist2 < myBoundaryPoints[anIdx2].Distance (myBoundaryPoints[anIdx]))
{
anIdx3 = anIdx;
aMaxDist2 = myBoundaryPoints[anIdx2].Distance (myBoundaryPoints[anIdx]);
}
}
gp_Vec aVecPlane1 (myBoundaryPoints[anIdx1], myBoundaryPoints[anIdx2]);
gp_Vec aVecPlane2 (myBoundaryPoints[anIdx1], myBoundaryPoints[anIdx3]);
const gp_Dir aNorm (aVecPlane1.Crossed (aVecPlane2));
// distance from point(x,y,z) to plane(A,B,C,D) d = | Ax + By + Cz + D | / sqrt (A^2 + B^2 + C^2) = aPnt.Dot (Norm) / 1
const gp_Pnt aCenterProj = theCenter.XYZ() - aNorm.XYZ() * theCenter.XYZ().Dot (aNorm.XYZ());
// If the center of the sphere is inside of the volume projection, then anAngleSum will be equal 2*M_PI
Standard_Real anAngleSum = 0.0;
TColgp_Array1OfPnt aBoundaries (myBoundaryPoints.Lower(), myBoundaryPoints.Size() / 2 + myBoundaryPoints.Lower());
for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx < myBoundaryPoints.Size() / 2 + myBoundaryPoints.Lower(); anIdx++)
{
aBoundaries.SetValue (anIdx, myBoundaryPoints[anIdx]);
gp_Pnt aPnt1 = myBoundaryPoints.Value (anIdx);
gp_Pnt aPnt2 = myBoundaryPoints.Value (anIdx + 1);
// Projections of the points on the plane
gp_Pnt aPntProj1 = aPnt1.XYZ() - aNorm.XYZ() * aPnt1.XYZ().Dot (aNorm.XYZ());
gp_Pnt aPntProj2 = aPnt2.XYZ() - aNorm.XYZ() * aPnt2.XYZ().Dot (aNorm.XYZ());
gp_Vec aVecAngle1 (aCenterProj, aPntProj1);
gp_Vec aVecAngle2 (aCenterProj, aPntProj2);
anAngleSum += aVecAngle1.Angle (aVecAngle2);
}
Standard_Boolean isCenterInside = Abs (anAngleSum - 2 * M_PI) < Precision::Confusion();
Standard_Boolean isBoundaryInside = Standard_False;
Standard_Boolean isIntersectSphereBoundaries = IsBoundaryIntersectSphere (aCenterProj, theRadius, aNorm, aBoundaries, isBoundaryInside);
if (myToAllowOverlap)
{
return isIntersectSphereBoundaries
|| isCenterInside;
}
else
{
return !isIntersectSphereBoundaries
&& isCenterInside
&& !isBoundaryInside;
}
}
}
return Standard_False;
}
//=======================================================================
// function : OverlapsSphere
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline,
"Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (anIter.Value()->OverlapsSphere (theCenter, theRadius, theClipRange, thePickResult))
{
return Standard_True;
}
}
return Standard_False;
}
// =======================================================================
// function : GetPlanes
// purpose :

View File

@@ -105,6 +105,19 @@ public:
//! Calculates the point on a view ray that was detected during the run of selection algo by given depth
Standard_EXPORT virtual gp_Pnt DetectedPoint (const Standard_Real theDepth) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by sphere with center theCenter
//! and radius theRadius
Standard_EXPORT virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Stores plane equation coefficients (in the following form:
//! Ax + By + Cz + D = 0) to the given vector
Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;