// 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);
+ }
}
// =======================================================================
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;
}
// =======================================================================
}
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()
--- /dev/null
+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
\ No newline at end of file