aSc = (Abs (aSn) < Precision::Confusion() ? 0.0 : aSn / aSd);
aTc = (Abs (aTn) < Precision::Confusion() ? 0.0 : aTn / aTd);
- SelectMgr_Vec3 aDiff = aW + (anU * aSc) - (aV * aTc);
SelectMgr_Vec3 aClosestPnt = myNearPickedPnt + myViewRayDir * aTc;
theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
}
theDepth = DISTANCE (myNearPickedPnt, aClosestPnt);
}
+namespace
+{
+ // =======================================================================
+ // function : computeNormals
+ // purpose : Computes normals to frustum faces
+ // =======================================================================
+ void computeNormals (const SelectMgr_Vec3* theVertices, SelectMgr_Vec3* theNormals)
+ {
+ // Top
+ theNormals[0] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
+ theVertices[4] - theVertices[0]);
+ // Bottom
+ theNormals[1] = SelectMgr_Vec3::Cross (theVertices[3] - theVertices[2],
+ theVertices[6] - theVertices[2]);
+ // Left
+ theNormals[2] = SelectMgr_Vec3::Cross (theVertices[1] - theVertices[0],
+ theVertices[2] - theVertices[0]);
+ // Right
+ theNormals[3] = SelectMgr_Vec3::Cross (theVertices[5] - theVertices[4],
+ theVertices[6] - theVertices[4]);
+ // Near
+ theNormals[4] = SelectMgr_Vec3::Cross (theVertices[6] - theVertices[4],
+ theVertices[0] - theVertices[4]);
+ // Far
+ theNormals[5] = SelectMgr_Vec3::Cross (theVertices[7] - theVertices[5],
+ theVertices[1] - theVertices[5]);
+ }
+}
+
// =======================================================================
// function : Build
// purpose : Build volume according to the point and given pixel
myNearPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 0.0);
myFarPickedPnt = myBuilder->ProjectPntOnViewPlane (thePoint.X(), thePoint.Y(), 1.0);
myViewRayDir = myFarPickedPnt - myNearPickedPnt;
+ myMousePos = thePoint;
// LeftTopNear
myVertices[0] = myBuilder->ProjectPntOnViewPlane (thePoint.X() - myPixelTolerance / 2.0,
myVertices[7] = myBuilder->ProjectPntOnViewPlane (thePoint.X() + myPixelTolerance / 2.0,
thePoint.Y() - myPixelTolerance / 2.0,
1.0);
- // Top
- myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
- myVertices[0],
- myVertices[5],
- myVertices[6]);
- // Bottom
- myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
- myVertices[2],
- myVertices[7],
- myVertices[4]);
- // Left
- myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
- myVertices[0],
- myVertices[2],
- myVertices[6]);
- // Right
- myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
- myVertices[4],
- myVertices[6],
- myVertices[2]);
- // Near
- myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
- myVertices[6],
- myVertices[2],
- myVertices[3]);
- // Far
- myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
- myVertices[7],
- myVertices[3],
- myVertices[2]);
+
+ // compute frustum normals
+ computeNormals (myVertices, myPlanes);
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
{
theMinPnt.Y(),
0.0);
// RightBottomFar
- myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X() ,
+ myVertices[7] = myBuilder->ProjectPntOnViewPlane (theMaxPnt.X(),
theMinPnt.Y(),
1.0);
- // Top
- myPlanes[0] = myBuilder->PlaneEquation (myVertices[1],
- myVertices[0],
- myVertices[5],
- myVertices[6]);
- // Bottom
- myPlanes[1] = myBuilder->PlaneEquation (myVertices[3],
- myVertices[2],
- myVertices[7],
- myVertices[4]);
- // Left
- myPlanes[2] = myBuilder->PlaneEquation (myVertices[1],
- myVertices[0],
- myVertices[2],
- myVertices[6]);
- // Right
- myPlanes[3] = myBuilder->PlaneEquation (myVertices[5],
- myVertices[4],
- myVertices[6],
- myVertices[2]);
- // Near
- myPlanes[4] = myBuilder->PlaneEquation (myVertices[4],
- myVertices[6],
- myVertices[2],
- myVertices[3]);
- // Far
- myPlanes[5] = myBuilder->PlaneEquation (myVertices[5],
- myVertices[7],
- myVertices[3],
- myVertices[2]);
+ // compute frustum normals
+ computeNormals (myVertices, myPlanes);
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
{
// RightBottomFar
aRes->myVertices[7] = SelectMgr_MatOp::Transform (theTrsf, myVertices[7]);
- // Top
- aRes->myPlanes[0] = myBuilder->PlaneEquation (aRes->myVertices[1],
- aRes->myVertices[0],
- aRes->myVertices[5],
- aRes->myVertices[6]);
- // Bottom
- aRes->myPlanes[1] = myBuilder->PlaneEquation (aRes->myVertices[3],
- aRes->myVertices[2],
- aRes->myVertices[7],
- aRes->myVertices[4]);
- // Left
- aRes->myPlanes[2] = myBuilder->PlaneEquation (aRes->myVertices[1],
- aRes->myVertices[0],
- aRes->myVertices[2],
- aRes->myVertices[6]);
- // Right
- aRes->myPlanes[3] = myBuilder->PlaneEquation (aRes->myVertices[5],
- aRes->myVertices[4],
- aRes->myVertices[6],
- aRes->myVertices[2]);
- // Near
- aRes->myPlanes[4] = myBuilder->PlaneEquation (aRes->myVertices[4],
- aRes->myVertices[6],
- aRes->myVertices[2],
- aRes->myVertices[3]);
- // Far
- aRes->myPlanes[5] = myBuilder->PlaneEquation (aRes->myVertices[5],
- aRes->myVertices[7],
- aRes->myVertices[3],
- aRes->myVertices[2]);
+ // compute frustum normals
+ computeNormals (aRes->myVertices, aRes->myPlanes);
+
+ for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
+ {
+ Standard_Real aMax = -DBL_MAX;
+ Standard_Real aMin = DBL_MAX;
+ const SelectMgr_Vec3 aPlane = aRes->myPlanes[aPlaneIdx];
+ for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
+ {
+ Standard_Real aProjection = DOT (aPlane, aRes->myVertices[aVertIdx]);
+ aMax = Max (aMax, aProjection);
+ aMin = Min (aMin, aProjection);
+ }
+ aRes->myMaxVertsProjections[aPlaneIdx] = aMax;
+ aRes->myMinVertsProjections[aPlaneIdx] = aMin;
+ }
+
+ SelectMgr_Vec3 aDimensions[3] =
+ {
+ SelectMgr_Vec3 (1.0, 0.0, 0.0),
+ SelectMgr_Vec3 (0.0, 1.0, 0.0),
+ SelectMgr_Vec3 (0.0, 0.0, 1.0)
+ };
+
+ for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
+ {
+ Standard_Real aMax = -DBL_MAX;
+ Standard_Real aMin = DBL_MAX;
+ for (Standard_Integer aVertIdx = 0; aVertIdx < 8; ++aVertIdx)
+ {
+ Standard_Real aProjection = DOT (aDimensions[aDim], aRes->myVertices[aVertIdx]);
+ aMax = Max (aMax, aProjection);
+ aMin = Min (aMin, aProjection);
+ }
+ aRes->myMaxOrthoVertsProjections[aDim] = aMax;
+ aRes->myMinOrthoVertsProjections[aDim] = aMin;
+ }
+
+ // Horizontal
+ aRes->myEdgeDirs[0] = aRes->myVertices[4] - aRes->myVertices[0];
+ // Vertical
+ aRes->myEdgeDirs[1] = aRes->myVertices[2] - aRes->myVertices[0];
+ // LeftLower
+ aRes->myEdgeDirs[2] = aRes->myVertices[2] - aRes->myVertices[3];
+ // RightLower
+ aRes->myEdgeDirs[3] = aRes->myVertices[6] - aRes->myVertices[7];
+ // LeftUpper
+ aRes->myEdgeDirs[4] = aRes->myVertices[0] - aRes->myVertices[1];
+ // RightUpper
+ aRes->myEdgeDirs[5] = aRes->myVertices[4] - aRes->myVertices[5];
+
+ return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
+}
+
+// =======================================================================
+// function : Scale
+// purpose : IMPORTANT: Makes sense only for frustum built on a single point!
+// Returns a copy of the frustum resized according to the scale factor given
+// =======================================================================
+NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::Scale (const Standard_Real theScaleFactor)
+{
+ SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum();
+
+ aRes->myNearPickedPnt = myNearPickedPnt;
+ aRes->myFarPickedPnt = myFarPickedPnt;
+ aRes->myViewRayDir = myViewRayDir;
+
+ aRes->myIsOrthographic = myIsOrthographic;
+
+ // LeftTopNear
+ aRes->myVertices[0] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
+ myMousePos.Y() + theScaleFactor / 2.0,
+ 0.0);
+ // LeftTopFar
+ aRes->myVertices[1] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
+ myMousePos.Y() + theScaleFactor / 2.0,
+ 1.0);
+ // LeftBottomNear
+ aRes->myVertices[2] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
+ myMousePos.Y() - theScaleFactor / 2.0,
+ 0.0);
+ // LeftBottomFar
+ aRes->myVertices[3] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() - theScaleFactor / 2.0,
+ myMousePos.Y() - theScaleFactor / 2.0,
+ 1.0);
+ // RightTopNear
+ aRes->myVertices[4] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
+ myMousePos.Y() + theScaleFactor / 2.0,
+ 0.0);
+ // RightTopFar
+ aRes->myVertices[5] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
+ myMousePos.Y() + theScaleFactor / 2.0,
+ 1.0);
+ // RightBottomNear
+ aRes->myVertices[6] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
+ myMousePos.Y() - theScaleFactor / 2.0,
+ 0.0);
+ // RightBottomFar
+ aRes->myVertices[7] = myBuilder->ProjectPntOnViewPlane (myMousePos.X() + theScaleFactor / 2.0,
+ myMousePos.Y() - theScaleFactor / 2.0,
+ 1.0);
+ // compute frustum normals
+ computeNormals (aRes->myVertices, aRes->myPlanes);
for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 6; ++aPlaneIdx)
{
// axis-aligned bounding box with minimum corner at point
// theMinPnt and maximum at point theMaxPnt
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPnt,
- const SelectMgr_Vec3& theMaxPnt)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
+ const SelectMgr_Vec3& theBoxMax,
+ Standard_Boolean* theInside)
{
- return hasOverlap (theMinPnt, theMaxPnt);
+ return hasOverlap (theBoxMin, theBoxMax, theInside);
}
// =======================================================================
// purpose : SAT intersection test between defined volume and
// given axis-aligned box
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
- Standard_Real& theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const BVH_Box<Standard_Real, 3>& theBox,
+ Standard_Real& theDepth)
{
const SelectMgr_Vec3& aMinPnt = theBox.CornerMin();
const SelectMgr_Vec3& aMaxPnt = theBox.CornerMax();
// function : Overlaps
// purpose : Intersection test between defined volume and given point
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
- Standard_Real& theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
+ Standard_Real& theDepth)
{
if (!hasOverlap (thePnt))
return Standard_False;
// function : Overlaps
// purpose : Checks if line segment overlaps selecting frustum
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
- const gp_Pnt& thePnt2,
- Standard_Real& theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
+ const gp_Pnt& thePnt2,
+ Standard_Real& theDepth)
{
theDepth = -DBL_MAX;
if (!hasOverlap (thePnt1, thePnt2))
// may be considered of interior part or boundary line defined
// by segments depending on given sensitivity type
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
- Select3D_TypeOfSensitivity theSensType,
- Standard_Real& theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts,
+ Select3D_TypeOfSensitivity theSensType,
+ Standard_Real& theDepth)
{
if (theSensType == Select3D_TOS_BOUNDARY)
{
// boundary line defined by triangle vertices depending on
// given sensitivity type
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
- const gp_Pnt& thePnt2,
- const gp_Pnt& thePnt3,
- Select3D_TypeOfSensitivity theSensType,
- Standard_Real& theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
+ const gp_Pnt& thePnt2,
+ const gp_Pnt& thePnt3,
+ Select3D_TypeOfSensitivity theSensType,
+ Standard_Real& theDepth)
{
if (theSensType == Select3D_TOS_BOUNDARY)
{
// purpose : Measures distance between 3d projection of user-picked
// screen point and given point theCOG
// =======================================================================
-const Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
+Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
{
const SelectMgr_Vec3& aCOG = SelectMgr_Vec3 (theCOG.X(), theCOG.Y(), theCOG.Z());
return DISTANCE (aCOG, myNearPickedPnt);
// =======================================================================
SelectMgr_Vec3 SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth) const
{
- return myNearPickedPnt + myViewRayDir * theDepth;
+ return myNearPickedPnt + myViewRayDir.Normalized() * theDepth;
}
// =======================================================================
// purpose : Checks if the point of sensitive in which selection was
// detected belongs to the region defined by clipping planes
// =======================================================================
-const Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
- const Standard_Real theDepth)
+Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
+ const Standard_Real theDepth)
{
Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
Standard_Real aMaxDepth = DBL_MAX;