1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0030765: Visualization - Incorrect intersection with Select3D_SensitiveBox when clipping is turned on

SelectMgr_RectangularFrustum::Overlaps method for computing intersection of box with frustum was reworked. Now the nearest non-clipped point is calculated.
This commit is contained in:
age 2019-06-05 12:30:01 +03:00 committed by bugmaster
parent 8d2c79f4e3
commit d31fb73a09
3 changed files with 186 additions and 6 deletions

View File

@ -204,6 +204,56 @@ namespace
// Far
theNormals[5] = -theNormals[4];
}
// =======================================================================
// function : rayBoxIntersection
// purpose : Computes an intersection of ray with box
// Returns distances to the first (or 0.0 if the ray origin is inside the box) and second intersection
// If the ray has no intersection with the box returns DBL_MAX
// =======================================================================
Bnd_Range rayBoxIntersection (const gp_Ax1& theRay, const gp_Pnt& theBoxMin, const gp_Pnt& theBoxMax)
{
Standard_Real aTimeMinX = -DBL_MAX;
Standard_Real aTimeMinY = -DBL_MAX;
Standard_Real aTimeMinZ = -DBL_MAX;
Standard_Real aTimeMaxX = DBL_MAX;
Standard_Real aTimeMaxY = DBL_MAX;
Standard_Real aTimeMaxZ = DBL_MAX;
Standard_Real aTime1;
Standard_Real aTime2;
if (Abs (theRay.Direction().X()) > DBL_EPSILON)
{
aTime1 = (theBoxMin.X() - theRay.Location().X()) / theRay.Direction().X();
aTime2 = (theBoxMax.X() - theRay.Location().X()) / theRay.Direction().X();
aTimeMinX = Min (aTime1, aTime2);
aTimeMaxX = Max (aTime1, aTime2);
}
if (Abs (theRay.Direction().Y()) > DBL_EPSILON)
{
aTime1 = (theBoxMin.Y() - theRay.Location().Y()) / theRay.Direction().Y();
aTime2 = (theBoxMax.Y() - theRay.Location().Y()) / theRay.Direction().Y();
aTimeMinY = Min (aTime1, aTime2);
aTimeMaxY = Max (aTime1, aTime2);
}
if (Abs (theRay.Direction().Z()) > DBL_EPSILON)
{
aTime1 = (theBoxMin.Z() - theRay.Location().Z()) / theRay.Direction().Z();
aTime2 = (theBoxMax.Z() - theRay.Location().Z()) / theRay.Direction().Z();
aTimeMinZ = Min (aTime1, aTime2);
aTimeMaxZ = Max (aTime1, aTime2);
}
Standard_Real aTimeMin = Max (aTimeMinX, Max (aTimeMinY, aTimeMinZ));
Standard_Real aTimeMax = Min (aTimeMaxX, Min (aTimeMaxY, aTimeMaxZ));
return aTimeMin > aTimeMax || aTimeMax < 0.0 ? Bnd_Range (DBL_MAX, DBL_MAX)
: Bnd_Range (Max (aTimeMin, 0.0), aTimeMax);
}
}
// =======================================================================
@ -446,14 +496,34 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
if (!hasOverlap (theBoxMin, theBoxMax))
return Standard_False;
gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast());
aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x()));
aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y()));
aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z()));
gp_Ax1 aRay (myNearPickedPnt, myViewRayDir);
Bnd_Range aRange = rayBoxIntersection (aRay,
gp_Pnt (theBoxMin.x(), theBoxMin.y(), theBoxMin.z()),
gp_Pnt (theBoxMax.x(), theBoxMax.y(), theBoxMax.z()));
thePickResult.SetDepth (aNearestPnt.Distance (myNearPickedPnt));
Standard_Real aDepth = 0.0;
aRange.GetMin (aDepth);
return isViewClippingOk (thePickResult);
if (aDepth == DBL_MAX)
{
gp_Pnt aNearestPnt (RealLast(), RealLast(), RealLast());
aNearestPnt.SetX (Max (Min (myNearPickedPnt.X(), theBoxMax.x()), theBoxMin.x()));
aNearestPnt.SetY (Max (Min (myNearPickedPnt.Y(), theBoxMax.y()), theBoxMin.y()));
aNearestPnt.SetZ (Max (Min (myNearPickedPnt.Z(), theBoxMax.z()), theBoxMin.z()));
aDepth = aNearestPnt.Distance (myNearPickedPnt);
thePickResult.SetDepth (aDepth);
return isViewClippingOk (thePickResult);
}
if (myIsViewClipEnabled && !myViewClipRange.GetNearestDepth (aRange, aDepth))
{
return Standard_False;
}
thePickResult.SetDepth (aDepth);
return Standard_True;
}
// =======================================================================

View File

@ -48,6 +48,50 @@ public:
}
return Standard_False;
}
//! Calculates the min not clipped value from the range.
//! Returns FALSE if the whole range is clipped.
Standard_Boolean GetNearestDepth (const Bnd_Range& theRange, Standard_Real& theDepth) const
{
if (!myUnclipRange.IsVoid() && myUnclipRange.IsOut (theRange))
{
return false;
}
Bnd_Range aCommonClipRange;
theRange.GetMin (theDepth);
if (!myUnclipRange.IsVoid() && myUnclipRange.IsOut (theDepth))
{
myUnclipRange.GetMin (theDepth);
}
for (size_t aRangeIter = 0; aRangeIter < myClipRanges.size(); ++aRangeIter)
{
if (!myClipRanges[aRangeIter].IsOut (theDepth))
{
aCommonClipRange = myClipRanges[aRangeIter];
break;
}
}
if (aCommonClipRange.IsVoid())
{
return true;
}
for (size_t aRangeIter = 0; aRangeIter < myClipRanges.size(); ++aRangeIter)
{
if (!aCommonClipRange.IsOut (myClipRanges[aRangeIter]))
{
aCommonClipRange.Add (myClipRanges[aRangeIter]);
}
}
aCommonClipRange.GetMax (theDepth);
return !theRange.IsOut (theDepth);
}
//! Clears clipping range.
void SetVoid()

View File

@ -0,0 +1,66 @@
puts "========"
puts "Sensitive box selection"
puts "========"
proc checkPoint {theName theValue theExpected} {
set e 0.0001
foreach i {0 1 2} { if { [expr abs([lindex $theValue $i] - [lindex $theExpected $i])] > $e } { puts "Error: wrong picked point $theName" } }
return
}
# create sphere
sphere ss 10
mkface s ss
incmesh s 0.01
# draw sphere
vinit View1
vclear
vsetdispmode 1
vpointcloud p s -nonormals
vselmode p 2 1
vaxo
vfit
vclipplane pl1 -set -equation -1 0 0 0
set p1 [vmoveto 200 200]
if {[string first "e+308" $p1] != -1} {
puts "Faulty : Selection 1"
}
vpoint pp1 {*}$p1
checkPoint pp1 $p1 {-1.7763568394002505e-15 -0.51078486684208357 0.59985611160264973}
vdump $::imagedir/${::casename}_clip1_selection_axo.png
vtop
vdump $::imagedir/${::casename}_clip1_selection_top.png
vaxo
verase pp1
vmoveto 300 200
vdump $::imagedir/${::casename}_clip1_no_selection.png
vclipplane pl1 -set -equation -1 0 0 3
vclipplane pl2 -set -equation 1 0 0 3
set p2 [vmoveto 200 200]
if {[string first "e+308" $p2] != -1} {
puts "Faulty : Selection 2"
}
vpoint pp2 {*}$p2
checkPoint pp2 $p2 {2.9999999999999991 -3.5107848668420845 3.5998561116026506}
vdump $::imagedir/${::casename}_clip2_selection_axo.png
vtop
vdump $::imagedir/${::casename}_clip2_selection_top.png
vaxo
verase pp2
vmoveto 75 200
vdump $::imagedir/${::casename}_clip2_no_selection.png
vtop
vmoveto 250 200
vdump $::imagedir/${::casename}_clip2_no_selection_top.png
vaxo
vfit
vclipplane pl1 -delete
vclipplane pl2 -delete
vmoveto 200 200