Select3D_SensitiveSegment.hxx
Select3D_SensitiveSet.cxx
Select3D_SensitiveSet.hxx
+Select3D_SensitiveSphere.cxx
+Select3D_SensitiveSphere.hxx
Select3D_SensitiveTriangle.cxx
Select3D_SensitiveTriangle.hxx
Select3D_SensitiveTriangulation.cxx
--- /dev/null
+// Created on: 2021-03-04
+// Created by: Maria KRYLOVA
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Select3D_SensitiveSphere.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveSphere, Select3D_SensitiveEntity)
+
+// ==================================================
+// Function: Select3D_SensitiveSphere
+// Purpose :
+// ==================================================
+Select3D_SensitiveSphere::Select3D_SensitiveSphere (const Handle(SelectMgr_EntityOwner)& theOwnerId,
+ const gp_Pnt& theCenter,
+ const Standard_Real theRadius)
+: Select3D_SensitiveEntity (theOwnerId),
+ myCenter (theCenter),
+ myRadius (theRadius)
+{
+}
+
+// ==================================================
+// Function: Mathes
+// Purpose :
+// ==================================================
+Standard_Boolean Select3D_SensitiveSphere::Matches (SelectBasics_SelectingVolumeManager& theMgr,
+ SelectBasics_PickResult& thePickResult)
+{
+ if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
+ {
+ if (!theMgr.IsOverlapAllowed())
+ {
+ Standard_Boolean isInside = Standard_True;
+ return theMgr.OverlapsSphere (myCenter, myRadius, &isInside) && isInside;
+ }
+ else
+ {
+ return theMgr.OverlapsSphere (myCenter, myRadius, NULL);
+ }
+ }
+ if (!theMgr.OverlapsSphere (myCenter, myRadius, thePickResult))
+ {
+ return Standard_False;
+ }
+
+ thePickResult.SetDistToGeomCenter (theMgr.DistToGeometryCenter (myCenter));
+ return Standard_True;
+}
+
+// ==================================================
+// Function: GetConnected
+// Purpose :
+// ==================================================
+Handle(Select3D_SensitiveEntity) Select3D_SensitiveSphere::GetConnected()
+{
+ Handle(Select3D_SensitiveEntity) aNewEntity = new Select3D_SensitiveSphere (myOwnerId, myCenter, myRadius);
+ return aNewEntity;
+}
+
+// ==================================================
+// Function: BoundingBox
+// Purpose :
+// ==================================================
+Select3D_BndBox3d Select3D_SensitiveSphere::BoundingBox()
+{
+ const SelectMgr_Vec3 aMinPnt = SelectMgr_Vec3 (myCenter.X() - myRadius, myCenter.Y() - myRadius, myCenter.Z() - myRadius);
+ const SelectMgr_Vec3 aMaxPnt = SelectMgr_Vec3 (myCenter.X() + myRadius, myCenter.Y() + myRadius, myCenter.Z() + myRadius);
+ return Select3D_BndBox3d (aMinPnt, aMaxPnt);
+}
--- /dev/null
+// Created on: 2021-03-04
+// Created by: Maria KRYLOVA
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Select3D_SensitiveSphere_HeaderFile
+#define _Select3D_SensitiveSphere_HeaderFile
+
+#include <Select3D_SensitiveEntity.hxx>
+
+//! A framework to define selection by a sensitive sphere.
+class Select3D_SensitiveSphere : public Select3D_SensitiveEntity
+{
+ DEFINE_STANDARD_RTTIEXT(Select3D_SensitiveSphere, Select3D_SensitiveEntity)
+public:
+
+ //! Constructs a sensitive sphere object defined by the owner theOwnerId,
+ //! the center of the sphere and it's radius.
+ Standard_EXPORT Select3D_SensitiveSphere (const Handle(SelectMgr_EntityOwner)& theOwnerId,
+ const gp_Pnt& theCenter,
+ const Standard_Real theRadius);
+
+ //! Returns the radius of the sphere
+ Standard_Real Radius() const { return myRadius; }
+
+public:
+
+ //! Checks whether the sphere overlaps current selecting volume
+ Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
+ SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
+
+ //! Returns the copy of this
+ Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE;
+
+ //! Returns bounding box of the sphere.
+ //! If location transformation is set, it will be applied
+ Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
+
+ //! Always returns Standard_False
+ virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
+
+ //! Returns the amount of points
+ virtual Standard_Integer NbSubElements() const Standard_OVERRIDE { return 1; }
+
+ //! Returns center of the sphere with transformation applied
+ virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE { return myCenter; };
+
+protected:
+ gp_Pnt myCenter;
+ Standard_Real myRadius;
+};
+
+#endif // _Select3D_SensitiveSphere_HeaderFile
Standard_Integer theSensType,
SelectBasics_PickResult& thePickResult) const = 0;
+ //! Returns true if selecting volume is overlapped by sphere with center theCenter
+ //! and radius theRadius
+ virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
+ const Standard_Real theRadius,
+ SelectBasics_PickResult& thePickResult) const = 0;
+
+ //! Returns true if selecting volume is overlapped by sphere with center theCenter
+ //! and radius theRadius
+ virtual Standard_Boolean OverlapsSphere (const gp_Pnt& theCenter,
+ const Standard_Real theRadius,
+ Standard_Boolean* theInside = NULL) const = 0;
+
public:
//! Calculates distance from 3d projection of user-defined selection point
&& !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 :
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.
}
}
+//=======================================================================
+// 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 :
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;
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 :
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
//! 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:
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
}
}
}
-
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 :
#include <SelectMgr_RectangularFrustum.hxx>
#include <BVH_Tools.hxx>
+#include <gp_Pln.hxx>
#include <NCollection_Vector.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <SelectMgr_FrustumBuilder.hxx>
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
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.
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
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;
#include <SelectMgr_TriangularFrustum.hxx>
#include <SelectMgr_FrustumBuilder.hxx>
+#include <SelectMgr_ViewClipRange.hxx>
IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum, Standard_Transient)
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
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
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 :
//! 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;
#include <GCPnts_TangentialDeflection.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <GeomAdaptor_Curve.hxx>
+#include <Geom_SphericalSurface.hxx>
#include <gp_Circ.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <Poly_Polygon3D.hxx>
#include <Select3D_SensitiveGroup.hxx>
#include <Select3D_SensitivePoint.hxx>
#include <Select3D_SensitiveSegment.hxx>
+#include <Select3D_SensitiveSphere.hxx>
#include <Select3D_SensitiveTriangle.hxx>
#include <Select3D_SensitiveTriangulation.hxx>
#include <Select3D_SensitiveWire.hxx>
TopLoc_Location aLoc;
if (Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (theFace, aLoc))
{
+ TopLoc_Location aLocSurf;
+ const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface (theFace, aLocSurf);
+ if (Handle(Geom_SphericalSurface) aGeomSphere = Handle(Geom_SphericalSurface)::DownCast (aSurf))
+ {
+ bool isFullSphere = theFace.NbChildren() == 0;
+ if (theFace.NbChildren() == 1)
+ {
+ const TopoDS_Iterator aWireIter (theFace);
+ const TopoDS_Wire& aWire = TopoDS::Wire (aWireIter.Value());
+ if (aWire.NbChildren() == 4)
+ {
+ Standard_Integer aNbSeamEdges = 0, aNbDegenEdges = 0;
+ for (TopoDS_Iterator anEdgeIter (aWire); anEdgeIter.More(); anEdgeIter.Next())
+ {
+ const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Value());
+ aNbSeamEdges += BRep_Tool::IsClosed (anEdge, theFace);
+ aNbDegenEdges += BRep_Tool::Degenerated (anEdge);
+ }
+ isFullSphere = aNbSeamEdges == 2 && aNbDegenEdges == 2;
+ }
+ }
+ if (isFullSphere)
+ {
+ gp_Sphere aSphere = BRepAdaptor_Surface (theFace).Sphere();
+ Handle(Select3D_SensitiveSphere) aSensSphere = new Select3D_SensitiveSphere (theOwner, aSphere.Position().Axis().Location(), aSphere.Radius());
+ theSensitiveList.Append (aSensSphere);
+ return Standard_True;
+ }
+ }
Handle(Select3D_SensitiveTriangulation) STG = new Select3D_SensitiveTriangulation (theOwner, aTriangulation, aLoc, theInteriorFlag);
theSensitiveList.Append (STG);
return Standard_True;
set p [vmoveto 200 200]
vpoint pp {*}$p
vsetcolor pp RED
-checkpoint p $p {-0.34896 9.94397 0.27411} 0.0001
+checkpoint p $p {-0.34896 9.99014 0.27411} 0.0001
vdump ${imagedir}/${casename}.png
--- /dev/null
+puts "================================="
+puts "0032182: Visualization - add Select3D_SensitiveSphere"
+puts "Tests depth value returned by Select3D_SenstiveSphere"
+puts "================================="
+
+psphere s 1
+vdisplay -dispMode 1 s
+vfit
+vtop
+set top [vmoveto 300 200]
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+checkpoint top_p $top {0.0013453695513163666 -0.0090115971854718303 0.99995849333074871} 0.0001
+vbottom
+set bottom [vmoveto 300 200]
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+checkpoint bottom_p $bottom {0.0013453695513163666 0.0090115971854718303 -0.99995849333074871} 0.0001
+vright
+set right [vmoveto 300 200]
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+checkpoint right_p $right {0.99995849333074871 0.0013453695513163666 -0.0090115971854718268} 0.0001
+vfront
+set front [vmoveto 300 200]
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+checkpoint front_p $front {0.0013453695513163666 -0.99995832904743187 -0.0090115971854718285} 0.01
+vleft
+set left [vmoveto 300 200]
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
+checkpoint left_p $left {-0.99995817565020639 -0.0013453695513163666 -0.0090115971854718268} 0.0001
--- /dev/null
+puts "================================="
+puts "0032182: Visualization - add Select3D_SensitiveSphere"
+puts "Tests detecting Select3D_SenstiveSphere"
+puts "================================="
+
+psphere s 1
+vdisplay -dispMode 1 s
+vfit
+vmoveto 300 200
+if { ![string match "*Select3D_SensitiveSphere*" [vstate -entities]] } { puts "Error: sphere should be detected" }
--- /dev/null
+puts "================================="
+puts "0032182: Visualization - add Select3D_SensitiveSphere"
+puts "Tests polygon selection of Select3D_SenstiveSphere"
+puts "================================="
+
+psphere s1 1
+psphere s2 1
+psphere s3 1
+psphere s4 1
+ttranslate s1 2 2 0
+ttranslate s2 2 -2 0
+ttranslate s3 -2 2 0
+ttranslate s4 -2 -2 0
+vdisplay -dispMode 1 s1 s2 s3 s4
+vfit
+vselect 15 200 300 15 585 200 300 385
+if { ![string match "*Selected*" [vstate s1]] ||
+ ![string match "*Selected*" [vstate s2]] ||
+ ![string match "*Selected*" [vstate s3]] ||
+ ![string match "*Selected*" [vstate s4]]} { puts "Error: all spheres should be selected" }
+vtop
+vselect 170 200 300 80 430 200 300 320
+if { [string match "*Selected*" [vstate s1]] ||
+ [string match "*Selected*" [vstate s2]] ||
+ [string match "*Selected*" [vstate s3]] ||
+ [string match "*Selected*" [vstate s4]]} { puts "Error: all spheres should be unselected" }
+vselect 177 78 422 78 422 322 177 322 -allowoverlap 1
+if { ![string match "*Selected*" [vstate s1]] ||
+ ![string match "*Selected*" [vstate s2]] ||
+ ![string match "*Selected*" [vstate s3]] ||
+ ![string match "*Selected*" [vstate s4]]} { puts "Error: all spheres should be selected" }
+vright
+vselect 181 323 289 196 147 85 59 206
+if { [string match "*Selected*" [vstate s1]] ||
+ ![string match "*Selected*" [vstate s2]] ||
+ [string match "*Selected*" [vstate s3]] ||
+ ![string match "*Selected*" [vstate s4]]} { puts "Error: spheres s1 and s3 should be unselected" }
+vselect 131 197 177 156 219 198 179 247
+if { [string match "*Selected*" [vstate s1]] ||
+ [string match "*Selected*" [vstate s2]] ||
+ [string match "*Selected*" [vstate s3]] ||
+ [string match "*Selected*" [vstate s4]]} { puts "Error: all spheres should be unselected" }
+vselect 131 197 177 156 219 198 179 247 -allowoverlap 1
+if { [string match "*Selected*" [vstate s1]] ||
+ ![string match "*Selected*" [vstate s2]] ||
+ [string match "*Selected*" [vstate s3]] ||
+ ![string match "*Selected*" [vstate s4]]} { puts "Error: spheres s1 and s3 should be unselected" }
+vselect 227 147 282 268 367 151 -allowoverlap 1
+if { [string match "*Selected*" [vstate s1]] ||
+ [string match "*Selected*" [vstate s2]] ||
+ [string match "*Selected*" [vstate s3]] ||
+ [string match "*Selected*" [vstate s4]]} { puts "Error: all spheres should be unselected" }