// =======================================================================
void SelectMgr_RectangularFrustum::segmentSegmentDistance (const gp_Pnt& theSegPnt1,
const gp_Pnt& theSegPnt2,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
gp_XYZ aV = myViewRayDir.XYZ();
}
aTc = (Abs (aTd) < gp::Resolution() ? 0.0 : aTn / aTd);
- gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc;
- theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale;
+ const gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTc;
+ thePickResult.SetDepth (myNearPickedPnt.Distance (aClosestPnt) * myScale);
+
+ const gp_Vec aPickedVec = aClosestPnt.XYZ() - theSegPnt1.XYZ();
+ const gp_Vec aFigureVec = theSegPnt2.XYZ() - theSegPnt1.XYZ();
+ const Standard_Real aPickedVecMod = aPickedVec.Magnitude();
+ const Standard_Real aFigureVecMod = aFigureVec.Magnitude();
+ if (aPickedVecMod <= gp::Resolution()
+ || aFigureVecMod <= gp::Resolution())
+ {
+ thePickResult.SetPickedPoint (aClosestPnt);
+ return;
+ }
+
+ const Standard_Real aCosOfAngle = aFigureVec.Dot (aPickedVec) / (aPickedVecMod * aFigureVecMod);
+ const Standard_Real aSegPntShift = Min(aFigureVecMod, Max(0.0, aCosOfAngle * aPickedVecMod));
+ thePickResult.SetPickedPoint (theSegPnt1.XYZ() + aFigureVec.XYZ() * (aSegPntShift / aFigureVecMod));
}
// =======================================================================
// function : segmentPlaneIntersection
// purpose :
// =======================================================================
-void SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane,
+bool SelectMgr_RectangularFrustum::segmentPlaneIntersection (const gp_Vec& thePlane,
const gp_Pnt& thePntOnPlane,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
gp_XYZ anU = myViewRayDir.XYZ();
gp_XYZ aW = myNearPickedPnt.XYZ() - thePntOnPlane.XYZ();
{
if (Abs (aN) < Precision::Angular())
{
- theDepth = DBL_MAX;
- return;
+ thePickResult.Invalidate();
+ return false;
}
else
{
- theDepth = DBL_MAX;
- return;
+ thePickResult.Invalidate();
+ return false;
}
}
Standard_Real aParam = aN / aD;
if (aParam < 0.0 || aParam > 1.0)
{
- theDepth = DBL_MAX;
- return;
+ thePickResult.Invalidate();
+ return false;
}
gp_Pnt aClosestPnt = myNearPickedPnt.XYZ() + anU * aParam;
- theDepth = myNearPickedPnt.Distance (aClosestPnt) * myScale;
+ thePickResult.SetDepth (myNearPickedPnt.Distance (aClosestPnt) * myScale);
+ return true;
}
namespace
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
const SelectMgr_Vec3& theBoxMax,
- Standard_Boolean* theInside)
+ Standard_Boolean* theInside) const
{
return hasOverlap (theBoxMin, theBoxMax, theInside);
}
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& theBoxMin,
const SelectMgr_Vec3& theBoxMax,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
if (!hasOverlap (theBoxMin, theBoxMax))
return Standard_False;
aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y()));
aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z()));
- theDepth = aNearestPnt.Distance (myNearPickedPnt);
+ thePickResult.SetDepth (aNearestPnt.Distance (myNearPickedPnt));
- return isViewClippingOk (theDepth);
+ return isViewClippingOk (thePickResult);
}
// =======================================================================
// purpose : Intersection test between defined volume and given point
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
if (!hasOverlap (thePnt))
return Standard_False;
gp_Pnt aDetectedPnt =
myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * (aV.Dot (myViewRayDir.XYZ()) / myViewRayDir.Dot (myViewRayDir));
- theDepth = aDetectedPnt.Distance (myNearPickedPnt) * myScale;
+ thePickResult.SetDepth (aDetectedPnt.Distance (myNearPickedPnt) * myScale);
+ thePickResult.SetPickedPoint (thePnt);
- return isViewClippingOk (theDepth);
+ return isViewClippingOk (thePickResult);
}
// =======================================================================
// function : Overlaps
// purpose : Intersection test between defined volume and given point
// =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt)
+Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt) const
{
return hasOverlap (thePnt);
}
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
const gp_Pnt& thePnt2,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
- theDepth = -DBL_MAX;
if (!hasOverlap (thePnt1, thePnt2))
return Standard_False;
- segmentSegmentDistance (thePnt1, thePnt2, theDepth);
+ segmentSegmentDistance (thePnt1, thePnt2, thePickResult);
- return isViewClippingOk (theDepth);
+ return isViewClippingOk (thePickResult);
}
// =======================================================================
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts,
Select3D_TypeOfSensitivity theSensType,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
if (theSensType == Select3D_TOS_BOUNDARY)
{
Standard_Integer aMatchingSegmentsNb = -1;
- theDepth = DBL_MAX;
+ SelectBasics_PickResult aPickResult;
+ thePickResult.Invalidate();
const Standard_Integer aLower = theArrayOfPnts.Lower();
const Standard_Integer anUpper = theArrayOfPnts.Upper();
for (Standard_Integer aPntIter = aLower; aPntIter <= anUpper; ++aPntIter)
if (hasOverlap (aStartPnt, aEndPnt))
{
aMatchingSegmentsNb++;
- Standard_Real aSegmentDepth = RealLast();
- segmentSegmentDistance (aStartPnt, aEndPnt, aSegmentDepth);
- theDepth = Min (theDepth, aSegmentDepth);
+ segmentSegmentDistance (aStartPnt, aEndPnt, aPickResult);
+ thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
}
}
else if (theSensType == Select3D_TOS_INTERIOR)
{
gp_Vec aPolyNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
- if (!hasOverlap (theArrayOfPnts, aPolyNorm))
+ if (!hasOverlap (theArrayOfPnts, aPolyNorm)
+ || !segmentPlaneIntersection (aPolyNorm,
+ theArrayOfPnts.First(),
+ thePickResult))
+ {
return Standard_False;
-
- segmentPlaneIntersection (aPolyNorm,
- theArrayOfPnts.Value (theArrayOfPnts.Lower()),
- theDepth);
+ }
}
- return isViewClippingOk (theDepth);
+ return isViewClippingOk (thePickResult);
}
// =======================================================================
const gp_Pnt& thePnt2,
const gp_Pnt& thePnt3,
Select3D_TypeOfSensitivity theSensType,
- Standard_Real& theDepth)
+ SelectBasics_PickResult& thePickResult) const
{
if (theSensType == Select3D_TOS_BOUNDARY)
{
const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 };
const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 4);
- return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theDepth);
+ return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, thePickResult);
}
else if (theSensType == Select3D_TOS_INTERIOR)
{
// handle degenerated triangles: in this case, there is no possible way to detect overlap correctly.
if (aTriangleNormal.SquareMagnitude() < gp::Resolution())
{
- theDepth = std::numeric_limits<Standard_Real>::max();
return Standard_False;
}
// handle the case when triangle normal and selecting frustum direction are orthogonal: for this case, overlap
// is detected correctly, and distance to triangle's plane can be measured as distance to its arbitrary vertex.
const gp_XYZ aDiff = myNearPickedPnt.XYZ() - thePnt1.XYZ();
- theDepth = aTriangleNormal.Dot (aDiff) * myScale;
-
- return isViewClippingOk (theDepth);
+ thePickResult.SetDepth (aTriangleNormal.Dot (aDiff) * myScale);
+ thePickResult.SetPickedPoint (thePnt1);
+ return isViewClippingOk (thePickResult);
}
gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / anAlpha);
Standard_Real anU = aVec.Dot (aTrEdges[2]);
Standard_Real aV = aVec.Dot (aTrEdges[0]);
- Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
-
+ const Standard_Boolean isInterior = (aTime >= 0.0) && (anU >= 0.0) && (aV >= 0.0) && (anU + aV <= 1.0);
+ const gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
if (isInterior)
{
- gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
- theDepth = myNearPickedPnt.Distance (aDetectedPnt) * myScale;
-
- return isViewClippingOk (theDepth);
+ thePickResult.SetDepth (myNearPickedPnt.Distance (aPtOnPlane) * myScale);
+ thePickResult.SetPickedPoint (aPtOnPlane);
+ return isViewClippingOk (thePickResult);
}
gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
Standard_Real aMinDist = RealLast();
Standard_Integer aNearestEdgeIdx = -1;
- gp_Pnt aPtOnPlane = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
for (Standard_Integer anEdgeIdx = 0; anEdgeIdx < 3; ++anEdgeIdx)
{
gp_XYZ aW = aPtOnPlane.XYZ() - aPnts[anEdgeIdx].XYZ();
aNearestEdgeIdx = anEdgeIdx;
}
}
- segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], theDepth);
+ segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], thePickResult);
}
- return isViewClippingOk (theDepth);
+ return isViewClippingOk (thePickResult);
}
// =======================================================================
// purpose : Measures distance between 3d projection of user-picked
// screen point and given point theCOG
// =======================================================================
-Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG)
+Standard_Real SelectMgr_RectangularFrustum::DistToGeometryCenter (const gp_Pnt& theCOG) const
{
return theCOG.Distance (myNearPickedPnt) * myScale;
}
// purpose :
// =======================================================================
void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
- SelectMgr_ViewClipRange& theRange)
+ SelectMgr_ViewClipRange& theRange) const
{
Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next())
const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ);
Standard_Real aDistance = -myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) - aPlaneD;
+ Standard_Real aDistToPln = 0.0;
// check whether the pick line is parallel to clip plane
if (Abs (aDotProduct) < Precision::Angular())
{
- // line lies below the plane and is not clipped, skip
- continue;
+ if (aDistance < 0.0)
+ {
+ continue;
+ }
+ aDistToPln = RealLast();
+ aDotProduct = 1.0;
}
-
- // compute distance to point of pick line intersection with the plane
- const Standard_Real aParam = aDistance / aDotProduct;
-
- const gp_Pnt anIntersectionPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
- Standard_Real aDistToPln = anIntersectionPnt.Distance (myNearPickedPnt);
- if (aParam < 0.0)
+ else
{
- // the plane is "behind" the ray
- aDistToPln = -aDistToPln;
+ // compute distance to point of pick line intersection with the plane
+ const Standard_Real aParam = aDistance / aDotProduct;
+
+ const gp_Pnt anIntersectionPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
+ aDistToPln = anIntersectionPnt.Distance (myNearPickedPnt);
+ if (aParam < 0.0)
+ {
+ // the plane is "behind" the ray
+ aDistToPln = -aDistToPln;
+ }
}
// change depth limits for case of opposite and directed planes
{
if (aDotProduct < 0.0)
{
- theRange.ChangeMain().Add (Bnd_Range (aDistToPln, RealLast()));
+ theRange.ChangeUnclipRange().TrimTo (aDistToPln);
}
else
{
- theRange.ChangeMain().Add (Bnd_Range (RealFirst(), aDistToPln));
+ theRange.ChangeUnclipRange().TrimFrom (aDistToPln);
}
}
else
if (!aSubRange.IsVoid()
&& aClipPlane->IsChain())
{
- theRange.AddSubRange (aSubRange);
+ theRange.AddClipSubRange (aSubRange);
}
}
}
// detected belongs to the region defined by clipping planes
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
- const Standard_Real theDepth)
+ const Standard_Real theDepth) const
{
SelectMgr_ViewClipRange aRange;
computeClippingRange (thePlanes, aRange);
// function : isViewClippingOk
// purpose :
// =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const
+Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const SelectBasics_PickResult& thePickResult) const
{
return !myIsViewClipEnabled
- || !myViewClipRange.IsClipped (theDepth);
+ || !myViewClipRange.IsClipped (thePickResult.Depth());
}
// =======================================================================