0026973: Visualization - selection of entities hidden by clipping planes is broken
authorvpa <vpa@opencascade.com>
Wed, 16 Dec 2015 09:25:03 +0000 (12:25 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 17 Dec 2015 15:07:57 +0000 (18:07 +0300)
- misprint in distance calculation in SelectMgr_RectangularFrustum::IsClipped is corrected;
- selecting volume manager in clipping check in SelectMgr_ViewerSelector::checkOverlap was replaced ;
- added view-defined clipping planes check to SelectMgr_RectangularFrustum;
- test case for issue #26973.

12 files changed:
src/SelectMgr/FILES
src/SelectMgr/SelectMgr_BaseFrustum.cxx
src/SelectMgr/SelectMgr_BaseFrustum.hxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_ViewClipRange.hxx [new file with mode: 0644]
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/StdSelect/StdSelect_ViewerSelector3d.cxx
src/StdSelect/StdSelect_ViewerSelector3d.hxx
tests/bugs/vis/bug26973 [new file with mode: 0644]

index cd3af8a..d91a639 100755 (executable)
@@ -58,6 +58,7 @@ SelectMgr_TriangularFrustumSet.hxx
 SelectMgr_TypeOfBVHUpdate.hxx
 SelectMgr_TypeOfUpdate.hxx
 SelectMgr_VectorTypes.hxx
+SelectMgr_ViewClipRange.hxx
 SelectMgr_ViewerSelector.cxx
 SelectMgr_ViewerSelector.hxx
 SelectMgr_ViewerSelector.lxx
index 88ac8d7..aecd3ad 100644 (file)
@@ -220,6 +220,10 @@ Standard_Real SelectMgr_BaseFrustum::DistToGeometryCenter (const gp_Pnt& /*theCO
   return DBL_MAX;
 }
 
+//=======================================================================
+// function : DetectedPoint
+// purpose  :
+//=======================================================================
 gp_Pnt SelectMgr_BaseFrustum::DetectedPoint (const Standard_Real /*theDepth*/) const
 {
   return gp_Pnt (RealLast(), RealLast(), RealLast());
index b1ba2d5..c4adf95 100644 (file)
@@ -158,6 +158,10 @@ public:
   Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                                       const Standard_Real theDepth);
 
+  //! Valid for point selection only!
+  //! Computes depth range for global (defined for the whole view) clipping planes.
+  Standard_EXPORT virtual void SetViewClipping (const Graphic3d_SequenceOfHClipPlane& /*thePlanes*/) {};
+
   DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseFrustum,Standard_Transient)
 
 protected:
index 71d1142..ff65aa7 100644 (file)
@@ -276,6 +276,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
+  myViewClipRange.Clear();
+
   myScale = 1.0;
 }
 
@@ -304,6 +306,8 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
   // {i, j, k} vectors and store them to corresponding class fields
   cacheVertexProjections (this);
 
+  myViewClipRange.Clear();
+
   myScale = 1.0;
 }
 
@@ -395,6 +399,8 @@ NCollection_Handle<SelectMgr_BaseFrustum> SelectMgr_RectangularFrustum::ScaleAnd
 
   cacheVertexProjections (aRes);
 
+  aRes->myViewClipRange = myViewClipRange;
+
   return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
 }
 
@@ -430,7 +436,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const SelectMgr_Vec3& t
 
   theDepth = aNearestPnt.Distance (myNearPickedPnt);
 
-  return Standard_True;
+  return isViewClippingOk (theDepth);
 }
 
 // =======================================================================
@@ -449,7 +455,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt,
 
   theDepth = aDetectedPnt.Distance (myNearPickedPnt) * myScale;
 
-  return Standard_True;
+  return isViewClippingOk (theDepth);
 }
 
 // =======================================================================
@@ -474,7 +480,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
     return Standard_False;
 
   segmentSegmentDistance (thePnt1, thePnt2, theDepth);
-  return Standard_True;
+
+  return isViewClippingOk (theDepth);
 }
 
 // =======================================================================
@@ -524,7 +531,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr
                               theDepth);
   }
 
-  return Standard_True;
+  return isViewClippingOk (theDepth);
 }
 
 // =======================================================================
@@ -574,7 +581,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
       // 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 Standard_True;
+
+      return isViewClippingOk (theDepth);
     }
 
     gp_XYZ anEdge = (thePnt1.XYZ() - myNearPickedPnt.XYZ()) * (1.0 / anAlpha);
@@ -592,7 +600,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
     {
       gp_Pnt aDetectedPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aTime;
       theDepth = myNearPickedPnt.Distance (aDetectedPnt) * myScale;
-      return Standard_True;
+
+      return isViewClippingOk (theDepth);
     }
 
     gp_Pnt aPnts[3] = {thePnt1, thePnt2, thePnt3};
@@ -613,7 +622,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1,
     segmentSegmentDistance (aPnts[aNearestEdgeIdx], aPnts[(aNearestEdgeIdx + 1) % 3], theDepth);
   }
 
-  return Standard_True;
+  return isViewClippingOk (theDepth);
 }
 
 // =======================================================================
@@ -637,18 +646,17 @@ gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth
 }
 
 // =======================================================================
-// function : IsClipped
-// purpose  : Checks if the point of sensitive in which selection was
-//            detected belongs to the region defined by clipping planes
+// function : computeClippingRange
+// purpose  :
 // =======================================================================
-Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
-                                                          const Standard_Real theDepth)
+void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
+                                                         Standard_Real& theDepthMin,
+                                                         Standard_Real& theDepthMax)
 {
-  Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes);
-  Standard_Real aMaxDepth = DBL_MAX;
-  Standard_Real aMinDepth = -DBL_MAX;
+  theDepthMax = DBL_MAX;
+  theDepthMin = -DBL_MAX;
   Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
-  for ( ; aPlaneIt.More(); aPlaneIt.Next())
+  for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
     if (!aClipPlane->IsOn())
@@ -660,9 +668,9 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen
 
     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 aDotProduct = myViewRayDir.XYZ ().Dot (aPlaneDirXYZ);
+    Standard_Real aDistance = - myNearPickedPnt.XYZ ().Dot (aPlaneDirXYZ)
+                              - aPlaneD;
 
     // check whether the pick line is parallel to clip plane
     if (Abs (aDotProduct) < Precision::Angular())
@@ -687,13 +695,55 @@ Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_Sequen
     // change depth limits for case of opposite and directed planes
     if (aDotProduct < 0.0)
     {
-      aMaxDepth = Min (aDistToPln, aMaxDepth);
+      theDepthMax = Min (aDistToPln, theDepthMax);
     }
-    else if (aDistToPln > aMinDepth)
+    else if (aDistToPln > theDepthMin)
     {
-      aMinDepth = Max (aDistToPln, aMinDepth);
+      theDepthMin = Max (aDistToPln, theDepthMin);
     }
   }
+}
+
+// =======================================================================
+// function : IsClipped
+// purpose  : Checks if the point of sensitive in which selection was
+//            detected belongs to the region defined by clipping planes
+// =======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
+                                                          const Standard_Real theDepth)
+{
+  Standard_Real aMaxDepth, aMinDepth;
+  computeClippingRange (thePlanes, aMinDepth, aMaxDepth);
 
   return (theDepth <= aMinDepth || theDepth >= aMaxDepth);
 }
+
+// =======================================================================
+// function : SetViewClipping
+// purpose  :
+// =======================================================================
+void SelectMgr_RectangularFrustum::SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes)
+{
+  if (thePlanes.Size() == 0)
+  {
+    myViewClipRange.Clear();
+    return;
+  }
+
+  Standard_Real aMaxDepth, aMinDepth;
+  computeClippingRange (thePlanes, aMinDepth, aMaxDepth);
+  myViewClipRange.Set (aMinDepth, aMaxDepth);
+}
+
+// =======================================================================
+// function : isViewClippingOk
+// purpose  :
+// =======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const
+{
+  if (!myViewClipRange.IsValid())
+    return Standard_True;
+
+  return myViewClipRange.MaxDepth() > theDepth
+    && myViewClipRange.MinDepth() < theDepth;
+}
index ba229c0..c1d4ca7 100644 (file)
@@ -17,6 +17,7 @@
 #define _SelectMgr_RectangularFrustum_HeaderFile
 
 #include <SelectMgr_Frustum.hxx>
+#include <SelectMgr_ViewClipRange.hxx>
 
 //! This class contains representation of rectangular selecting frustum, created in case
 //! of point and box selection, and algorithms for overlap detection between selecting
@@ -106,6 +107,10 @@ public:
   Standard_EXPORT virtual Standard_Boolean IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                                       const Standard_Real theDepth) Standard_OVERRIDE;
 
+  //! Valid for point selection only!
+  //! Computes depth range for global (defined for the whole view) clipping planes.
+  Standard_EXPORT virtual void SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes) Standard_OVERRIDE;
+
   //! A set of helper functions that return rectangular selecting frustum data
   inline const gp_Pnt* GetVertices() const { return myVertices; }
 
@@ -122,6 +127,14 @@ protected:
                                                  const gp_Pnt& thePntOnPlane,
                                                  Standard_Real& theDepth);
 
+  //! Computes valid depth range for the given clipping planes
+  Standard_EXPORT void computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
+                                             Standard_Real& theDepthMin,
+                                             Standard_Real& theDepthMax);
+
+  //! Returns false if theDepth must be clipped by current view clip range
+  Standard_EXPORT Standard_Boolean isViewClippingOk (const Standard_Real theDepth) const;
+
 private:
 
   void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum);
@@ -134,11 +147,12 @@ private:
 
 private:
 
-  gp_Pnt   myNearPickedPnt;             //!< 3d projection of user-picked selection point onto near view plane
-  gp_Pnt   myFarPickedPnt;              //!< 3d projection of user-picked selection point onto far view plane
-  gp_Vec   myViewRayDir;
-  gp_Pnt2d myMousePos;                  //!< Mouse coordinates
-  Standard_Real myScale;                //!< Scale factor of applied transformation, if there was any
+  gp_Pnt                  myNearPickedPnt;             //!< 3d projection of user-picked selection point onto near view plane
+  gp_Pnt                  myFarPickedPnt;              //!< 3d projection of user-picked selection point onto far view plane
+  gp_Vec                  myViewRayDir;
+  gp_Pnt2d                myMousePos;                  //!< Mouse coordinates
+  Standard_Real           myScale;                     //!< Scale factor of applied transformation, if there was any
+  SelectMgr_ViewClipRange myViewClipRange;
 };
 
 #endif // _SelectMgr_RectangularFrustum_HeaderFile
index d558502..69a7ca4 100644 (file)
@@ -361,7 +361,7 @@ gp_Pnt SelectMgr_SelectingVolumeManager::DetectedPoint (const Standard_Real theD
 Standard_Boolean SelectMgr_SelectingVolumeManager::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
                                                               const Standard_Real& theDepth)
 {
-  if (myActiveSelectionType == Point)
+  if (myActiveSelectionType != Point)
     return Standard_False;
 
   return mySelectingVolumes[Frustum]->IsClipped (thePlanes, theDepth);
@@ -428,3 +428,15 @@ gp_Pnt SelectMgr_SelectingVolumeManager::GetFarPnt() const
      reinterpret_cast<const SelectMgr_RectangularFrustum*> (mySelectingVolumes[myActiveSelectionType / 2].get());
   return aFr->GetFarPnt();
 }
+
+//=======================================================================
+// function : SetViewClipping
+// purpose  :
+//=======================================================================
+void SelectMgr_SelectingVolumeManager::SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes)
+{
+  if (myActiveSelectionType != Point)
+    return;
+
+  mySelectingVolumes[Frustum]->SetViewClipping (thePlanes);
+}
index d4e1dd6..ec63b43 100644 (file)
@@ -155,6 +155,10 @@ public:
 
   Standard_EXPORT virtual Standard_Boolean IsOverlapAllowed() const Standard_OVERRIDE;
 
+  //! Valid for point selection only!
+  //! Computes depth range for global (defined for the whole view) clipping planes.
+  Standard_EXPORT void SetViewClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes);
+
   //! A set of helper functions that return rectangular selecting frustum data
   Standard_EXPORT const gp_Pnt* GetVertices() const;
 
diff --git a/src/SelectMgr/SelectMgr_ViewClipRange.hxx b/src/SelectMgr/SelectMgr_ViewClipRange.hxx
new file mode 100644 (file)
index 0000000..7fc0931
--- /dev/null
@@ -0,0 +1,73 @@
+// Created on: 2015-12-15
+// Created by: Varvara POSKONINA
+// Copyright (c) 2005-2014 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 _SelectMgr_ViewClipRange_HeaderFile
+#define _SelectMgr_ViewClipRange_HeaderFile
+
+#include <Standard_TypeDef.hxx>
+
+//! Class for handling depth clipping range.
+//! It is used to perform checks in case if global (for the whole view)
+//! clipping planes are defined inside of SelectMgr_RectangularFrustum
+//! class methods.
+class SelectMgr_ViewClipRange
+{
+public:
+  //! Creates new empty view clip range
+  SelectMgr_ViewClipRange()
+  {
+    Clear();
+  }
+
+  //! Sets boundaries and validates view clipping range
+  void Set (const Standard_Real theDepthMin, const Standard_Real theDepthMax)
+  {
+    myMin = theDepthMin;
+    myMax = theDepthMax;
+    myIsValid = Standard_True;
+  }
+
+  //! Returns true if clip range is set and depth of each matched
+  //! primitive must be tested for satisfying the defined interval
+  Standard_Boolean IsValid() const
+  {
+    return myIsValid;
+  }
+
+  //! Returns the upper bound of valid depth range
+  Standard_Real MaxDepth() const
+  {
+    return myMax;
+  }
+
+  //! Returns the lower bound of valid depth range
+  Standard_Real MinDepth() const
+  {
+    return myMin;
+  }
+
+  //! Invalidates view clipping range
+  void Clear()
+  {
+    myIsValid = Standard_False;
+  }
+
+private:
+  Standard_Real    myMin;      //!< Lower bound of valid depth range
+  Standard_Real    myMax;      //!< Upper bound of valid depth range
+  Standard_Boolean myIsValid;  //!< The flag is set to true when range boundaries are set and depth check must be performed
+};
+
+#endif // _SelectMgr_ViewClipRange_HeaderFile
index 94c2bf4..1e2d3d9 100644 (file)
@@ -230,8 +230,8 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
     {
       if (HasDepthClipping (anOwner) && theMgr.GetActiveSelectionType() == SelectMgr_SelectingVolumeManager::Point)
       {
-        Standard_Boolean isClipped = theMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
-                                                       aPickResult.Depth());
+        Standard_Boolean isClipped = mySelectingVolumeMgr.IsClipped (anOwner->Selectable()->GetClipPlanes(),
+                                                                     aPickResult.Depth());
         if (isClipped)
           return;
       }
index d9021b3..b45f8eb 100644 (file)
@@ -113,8 +113,6 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
                                        const Standard_Integer theYPix,
                                        const Handle(V3d_View)& theView)
 {
-  SetClipping (theView->GetClipPlanes());
-
   if(myToUpdateTolerance)
   {
     mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
@@ -129,6 +127,7 @@ void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
   gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
                       static_cast<Standard_Real> (theYPix));
   mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
+  mySelectingVolumeMgr.SetViewClipping (theView->GetClipPlanes());
 
   TraverseSensitives();
 }
@@ -651,15 +650,6 @@ void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(Graphic3d_Str
 }
 
 //=======================================================================
-//function : SetClipping
-//purpose  :
-//=======================================================================
-void StdSelect_ViewerSelector3d::SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes)
-{
-  myClipPlanes = thePlanes;
-}
-
-//=======================================================================
 //function : HasDepthClipping
 //purpose  :
 //=======================================================================
index d68f95d..8659b03 100644 (file)
@@ -83,12 +83,6 @@ public:
 
   DEFINE_STANDARD_RTTIEXT(StdSelect_ViewerSelector3d,SelectMgr_ViewerSelector)
 
-protected:
-
-  //! Set view clipping for the selector.
-  //! @param thePlanes [in] the view planes.
-  Standard_EXPORT void SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes);
-
 private:
 
   void ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure,
@@ -97,7 +91,6 @@ private:
                             const Graphic3d_TransformPers& theTransPers);
 
   Graphic3d_SequenceOfStructure myStructs;
-  Graphic3d_SequenceOfHClipPlane myClipPlanes;
 };
 
 DEFINE_STANDARD_HANDLE(StdSelect_ViewerSelector3d, SelectMgr_ViewerSelector)
diff --git a/tests/bugs/vis/bug26973 b/tests/bugs/vis/bug26973
new file mode 100644 (file)
index 0000000..4b3b48e
--- /dev/null
@@ -0,0 +1,79 @@
+puts "============"
+puts "CR26973"
+puts "============"
+puts ""
+
+##########################################################################################
+puts "Visualization - selection of entities hidden by clipping planes is broken"
+##########################################################################################
+
+pload MODELING VISUALIZATION
+
+vinit View1
+vclear
+vaxo
+vsetdispmode 1
+
+proc OCC26973 { toTestViewPlanes toApplyTrsf theImgIdr theCaseName} {
+  if {$toApplyTrsf == "1"} {
+    box b -100 -100 -100 1 1 1
+    ttranslate b 100 100 100
+  } else {
+    box b 1 1 1
+  }
+
+  vdisplay b
+  vfit
+  vselmode b 4 1
+
+  vclipplane create pln
+  if {$toTestViewPlanes == "1"} {
+    vclipplane set pln view Driver1/Viewer1/View1
+  } else {
+    vclipplane set pln object b
+  }
+  vclipplane change pln equation 0 1 0 -0.5
+
+  vselect 200 140
+  set aTestInfo "Test case: "
+  append aTestInfo "clipping planes applied to "
+  set aDumpFileName $theImgIdr/${theCaseName}
+  if {$toTestViewPlanes == "1"} {
+    append aTestInfo "view, "
+    append aDumpFileName "_view"
+  } else {
+    append aTestInfo "object, "
+    append aDumpFileName "_obj"
+  }
+  append aTestInfo "object trsf is "
+  if {$toApplyTrsf == "1"} {
+    append aTestInfo "on"
+    append aDumpFileName "_with_trsf.png"
+  } else {
+    append aTestInfo "off"
+    append aDumpFileName "_wo_trsf.png"
+  }
+
+  if {[vnbselected] != 1} {
+    puts "ERROR: can not select face."
+    puts $aTestInfo
+  }
+  set aSelectedFace [string trim [lindex [split [vstate] "\n"] 1] ]
+  if {$aSelectedFace != "Face #1"} {
+    puts "ERROR: wrong face is selected."
+    puts "Actually seleced face: $aSelectedFace"
+    puts $aTestInfo
+  }
+
+  vdump $aDumpFileName
+  vremove -all
+  vclipplane delete pln
+}
+
+# check global clipping planes selection
+OCC26973 1 0 $imagedir $casename
+OCC26973 1 1 $imagedir $casename
+
+# check object clipping planes selection
+OCC26973 0 0 $imagedir $casename
+OCC26973 0 1 $imagedir $casename