]> OCCT Git - occt.git/commitdiff
0032387: Visualization - use interface of ray-picking for selection/highlighting...
authorosa <osa@opencascade.com>
Mon, 24 May 2021 12:27:33 +0000 (15:27 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 26 May 2021 17:06:45 +0000 (20:06 +0300)
Fixed regression of SelectMgr_ViewerSelector::SetPixelTolerance(). Removed redundant myToUpdateTolerance flag.

SelectMgr_AxisIntersector::raySegmentDistance() - fixed usage of SquareModulus() instead of Modulus().
SelectMgr_ViewerSelector::TraverseSensitives() now skips both BVHSubset_2dPersistent and BVHSubset_3dPersistent relying on Camera.

AIS_ViewController::handleXRMoveTo() now uses interface for picking by Axis explicitly
instead of emulating axis by point picking.

12 files changed:
src/AIS/AIS_InteractiveContext.cxx
src/AIS/AIS_InteractiveContext.hxx
src/AIS/AIS_ViewController.cxx
src/AIS/AIS_ViewController.hxx
src/Graphic3d/Graphic3d_CView.hxx
src/IVtkOCC/IVtkOCC_ViewerSelector.cxx
src/SelectMgr/SelectMgr_AxisIntersector.cxx
src/SelectMgr/SelectMgr_SelectionManager.cxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
src/SelectMgr/SelectMgr_ViewerSelector.hxx
src/SelectMgr/SelectMgr_ViewerSelector3d.cxx
tests/vselect/axis/A2 [new file with mode: 0644]

index 35aada5f86443184c0372cf5675af3cba4747d24..3566fcab4e9881088224add888a3cdf8484dd8e6 100644 (file)
@@ -2730,7 +2730,33 @@ AIS_StatusOfDetection AIS_InteractiveContext::MoveTo (const Standard_Integer  th
   {
     throw Standard_ProgramError ("AIS_InteractiveContext::MoveTo() - invalid argument");
   }
+  myMainSel->Pick (theXPix, theYPix, theView);
+  return moveTo (theView, theToRedrawOnUpdate);
+}
 
+//=======================================================================
+//function : MoveTo
+//purpose  :
+//=======================================================================
+AIS_StatusOfDetection AIS_InteractiveContext::MoveTo (const gp_Ax1& theAxis,
+                                                      const Handle(V3d_View)& theView,
+                                                      const Standard_Boolean  theToRedrawOnUpdate)
+{
+  if (theView->Viewer() != myMainVwr)
+  {
+    throw Standard_ProgramError ("AIS_InteractiveContext::MoveTo() - invalid argument");
+  }
+  myMainSel->Pick (theAxis, theView);
+  return moveTo (theView, theToRedrawOnUpdate);
+}
+
+//=======================================================================
+//function : moveTo
+//purpose  :
+//=======================================================================
+AIS_StatusOfDetection AIS_InteractiveContext::moveTo (const Handle(V3d_View)& theView,
+                                                      const Standard_Boolean  theToRedrawOnUpdate)
+{
   myCurDetected = 0;
   myCurHighlighted = 0;
   myDetectedSeq.Clear();
@@ -2741,7 +2767,6 @@ AIS_StatusOfDetection AIS_InteractiveContext::MoveTo (const Standard_Integer  th
   Standard_Boolean      toUpdateViewer = Standard_False;
 
   myFilters->SetDisabledObjects (theView->View()->HiddenObjects());
-  myMainSel->Pick (theXPix, theYPix, theView);
 
   // filling of myAISDetectedSeq sequence storing information about detected AIS objects
   // (the objects must be AIS_Shapes)
index eebacf247395f5ad4adc15cc4be2ce4a05e12b34..c414e66445a9e06b23662abe4b2cc60b95c4ab6d 100644 (file)
@@ -374,6 +374,14 @@ public: //! @name mouse picking logic (detection and dynamic highlighting of ent
                                                 const Handle(V3d_View)& theView,
                                                 const Standard_Boolean  theToRedrawOnUpdate);
 
+  //! Relays axis theAxis to the interactive context selectors.
+  //! This is done by the view theView passing this axis to the main viewer and updating it.
+  //! If theToRedrawOnUpdate is set to false, callee should call RedrawImmediate() to highlight detected object.
+  //! @sa PickingStrategy()
+  Standard_EXPORT AIS_StatusOfDetection MoveTo (const gp_Ax1& theAxis,
+                                                const Handle(V3d_View)& theView,
+                                                const Standard_Boolean  theToRedrawOnUpdate);
+
   //! Clears the list of entities detected by MoveTo() and resets dynamic highlighting.
   //! @param theToRedrawImmediate if TRUE, the main Viewer will be redrawn on update
   //! @return TRUE if viewer needs to be updated (e.g. there were actually dynamically highlighted entities)
@@ -1248,6 +1256,11 @@ protected: //! @name internal methods
   
   Standard_EXPORT void InitAttributes();
 
+  //! Highlights detected objects.
+  //! If theToRedrawOnUpdate is set to false, callee should call RedrawImmediate() to update view.
+  Standard_EXPORT AIS_StatusOfDetection moveTo (const Handle(V3d_View)& theView,
+                                                const Standard_Boolean  theToRedrawOnUpdate);
+
   //! Helper function to unhighlight all entity owners currently highlighted with seleciton color.
   Standard_EXPORT void unselectOwners (const Handle(AIS_InteractiveObject)& theObject);
 
index 63ab92ebfd4e91853790de4b026a7a83e13941dc..2630dca3b2f931ef45356b80d2406ede76d9100c 100644 (file)
@@ -2288,10 +2288,6 @@ void AIS_ViewController::handleXRInput (const Handle(AIS_InteractiveContext)& th
   {
     return;
   }
-  if (myXRCameraTmp.IsNull())
-  {
-    myXRCameraTmp = new Graphic3d_Camera();
-  }
   handleXRTurnPad (theCtx, theView);
   handleXRTeleport(theCtx, theView);
   handleXRPicking (theCtx, theView);
@@ -2959,53 +2955,25 @@ Standard_Integer AIS_ViewController::handleXRMoveTo (const Handle(AIS_Interactiv
                                                      const Standard_Boolean theToHighlight)
 {
   //ResetPreviousMoveTo();
+  const gp_Ax1 aViewAxis = theView->View()->ViewAxisInWorld (thePose);
   Standard_Integer aPickResult = 0;
-
-  Handle(Graphic3d_Camera) aCamBack = theView->Camera();
-  myXRCameraTmp->Copy (aCamBack);
-  theView->View()->ComputeXRPosedCameraFromBase (*myXRCameraTmp, thePose);
-  theView->SetCamera (myXRCameraTmp);
-  Graphic3d_Vec2i aPickPixel;
-  theView->Window()->Size (aPickPixel.x(), aPickPixel.y());
-  aPickPixel /= 2;
-  const Standard_Integer aSelTolerBack = theCtx->MainSelector()->CustomPixelTolerance();
-  theCtx->MainSelector()->SetPixelTolerance (1);
-  theView->AutoZFit();
   if (theToHighlight)
   {
-    theCtx->MoveTo (aPickPixel.x(), aPickPixel.y(), theView, false);
+    theCtx->MoveTo (aViewAxis, theView, false);
     if (!theCtx->DetectedOwner().IsNull())
     {
-      // ignore 2D objects
-      for (aPickResult = 1; !theCtx->DetectedOwner()->Selectable()->TransformPersistence().IsNull(); ++aPickResult)
-      {
-        if (theCtx->HilightNextDetected (theView, false) <= 1)
-        {
-          theCtx->ClearDetected();
-          aPickResult = 0;
-          break;
-        }
-      }
+      aPickResult = 1;
     }
   }
   else
   {
-    theCtx->MainSelector()->Pick (aPickPixel.x(), aPickPixel.y(), theView);
-    for (Standard_Integer aPickIter = 1; aPickIter <= theCtx->MainSelector()->NbPicked(); ++aPickIter)
+    theCtx->MainSelector()->Pick (aViewAxis, theView);
+    if (theCtx->MainSelector()->NbPicked() >= 1)
     {
-      const SelectMgr_SortCriterion& aPickedData = theCtx->MainSelector()->PickedData (aPickIter);
-      if (!aPickedData.Entity->OwnerId()->Selectable()->TransformPersistence().IsNull())
-      {
-        // skip 2d objects
-        continue;
-      }
-
-      aPickResult = aPickIter;
-      break;
+      aPickResult = 1;
     }
   }
-  theCtx->MainSelector()->SetPixelTolerance (aSelTolerBack);
-  theView->SetCamera (aCamBack);
+
   return aPickResult;
 }
 
index eefabc6cee928a4b9aeab0540c12e558c98ab45c..37d436fa9de7e41549aafbcfd91d46266e629112 100644 (file)
@@ -715,7 +715,6 @@ protected:
 protected: //! @name XR input variables
 
   NCollection_Array1<Handle(AIS_XRTrackedDevice)> myXRPrsDevices; //!< array of XR tracked devices presentations
-  Handle(Graphic3d_Camera)   myXRCameraTmp;       //!< temporary camera
   Quantity_Color             myXRLaserTeleColor;  //!< color of teleport laser
   Quantity_Color             myXRLaserPickColor;  //!< color of picking  laser
   Aspect_XRTrackedDeviceRole myXRLastTeleportHand;//!< active hand for teleport
index 8e17165b7e4770cd0b537eed8704d702d9af32be..9af619b8f283d2bf96ac54bf6db11e6f2cc75f8e 100644 (file)
@@ -485,7 +485,7 @@ public:
   void SetBaseXRCamera (const Handle(Graphic3d_Camera)& theCamera) { myBaseXRCamera = theCamera; }
 
   //! Convert XR pose to world space.
-  //! @param theTrsfXR [in] transformation defined in VR local coordinate system,
+  //! @param thePoseXR [in] transformation defined in VR local coordinate system,
   //!                       oriented as Y-up, X-right and -Z-forward
   //! @return transformation defining orientation of XR pose in world space
   gp_Trsf PoseXRToWorld (const gp_Trsf& thePoseXR) const
@@ -498,6 +498,14 @@ public:
     return aTrsfCS * thePoseXR;
   }
 
+  //! Returns view direction in the world space based on XR pose.
+  //! @param thePoseXR [in] transformation defined in VR local coordinate system,
+  //!                       oriented as Y-up, X-right and -Z-forward
+  gp_Ax1 ViewAxisInWorld (const gp_Trsf& thePoseXR) const
+  {
+    return gp_Ax1 (gp::Origin(), -gp::DZ()).Transformed (PoseXRToWorld (thePoseXR));
+  }
+
   //! Recomputes PosedXRCamera() based on BaseXRCamera() and head orientation.
   Standard_EXPORT void SynchronizeXRBaseToPosedCamera();
 
index 982a12ddc18622208ac7a75f6532c24ca234a93f..d942f50931a600b5c04af1492ee4bd405712263a 100644 (file)
@@ -195,7 +195,6 @@ void IVtkOCC_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSel
   {
     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
     myTolerances.Add (theSelection->Sensitivity());
-    myToUpdateTolerance = Standard_True;
   }
 }
 
@@ -214,6 +213,5 @@ void IVtkOCC_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theS
   {
     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
     myTolerances.Decrement (theSelection->Sensitivity());
-    myToUpdateTolerance = Standard_True;
   }
 }
index c3e252f8e109ceb8516e8d603a51abc3fc96f4b7..ae1e024703aaaff0786d2a9155b716663628fa20 100644 (file)
@@ -124,21 +124,29 @@ Standard_Boolean SelectMgr_AxisIntersector::raySegmentDistance (const gp_Pnt& th
                                                                 const gp_Pnt& theSegPnt2,
                                                                 SelectBasics_PickResult& thePickResult) const
 {
-  gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
-  gp_XYZ aV = myAxis.Direction().XYZ();
-  gp_XYZ aW = theSegPnt1.XYZ() - myAxis.Location().XYZ();
-
-  gp_XYZ anUVNormVec = aV.Crossed (anU);
-  gp_XYZ anUWNormVec = aW.Crossed (anU);
-  if (anUVNormVec.Modulus() <= Precision::Confusion() ||
-      anUWNormVec.Modulus() <= Precision::Confusion())
+  const gp_XYZ anU = theSegPnt2.XYZ() - theSegPnt1.XYZ();
+  const gp_XYZ aV = myAxis.Direction().XYZ();
+  const gp_XYZ aW = theSegPnt1.XYZ() - myAxis.Location().XYZ();
+
+  const gp_XYZ anUVNormVec = aV.Crossed (anU);
+  const Standard_Real anUVNormVecMod = anUVNormVec.Modulus();
+  if (anUVNormVecMod <= Precision::Confusion())
   {
     // Lines have no intersection
     thePickResult.Invalidate();
     return false;
   }
 
-  Standard_Real aParam = anUWNormVec.Dot (anUVNormVec) / anUVNormVec.SquareModulus();
+  const gp_XYZ anUWNormVec = aW.Crossed (anU);
+  const Standard_Real anUWNormVecMod = anUWNormVec.Modulus();
+  if (anUWNormVecMod <= Precision::Confusion())
+  {
+    // Lines have no intersection
+    thePickResult.Invalidate();
+    return false;
+  }
+
+  const Standard_Real aParam = anUWNormVec.Dot (anUVNormVec) / anUVNormVecMod;
   if (aParam < 0.0)
   {
     // Intersection is out of axis start point
@@ -146,10 +154,10 @@ Standard_Boolean SelectMgr_AxisIntersector::raySegmentDistance (const gp_Pnt& th
     return false;
   }
 
-  gp_XYZ anIntersectPnt = myAxis.Location().XYZ() + aV * aParam;
-  if ((anIntersectPnt - theSegPnt1.XYZ()).SquareModulus() +
-      (anIntersectPnt - theSegPnt2.XYZ()).SquareModulus() >
-       anU.SquareModulus() + Precision::Confusion())
+  const gp_XYZ anIntersectPnt = myAxis.Location().XYZ() + aV * aParam;
+  if ((anIntersectPnt - theSegPnt1.XYZ()).Modulus() +
+      (anIntersectPnt - theSegPnt2.XYZ()).Modulus() >
+       anU.Modulus() + Precision::Confusion())
   {
     // Intersection point doesn't lie on the segment
     thePickResult.Invalidate();
@@ -417,7 +425,8 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
         }
       }
       thePickResult.SetSurfaceNormal (aTriangleNormal);
-      return !theClipRange.IsClipped (thePickResult.Depth());
+      return thePickResult.IsValid()
+         && !theClipRange.IsClipped (thePickResult.Depth());
     }
 
     // check if intersection point belongs to triangle's interior part
@@ -464,7 +473,8 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
     }
   }
 
-  return !theClipRange.IsClipped (thePickResult.Depth());
+  return thePickResult.IsValid()
+     && !theClipRange.IsClipped (thePickResult.Depth());
 }
 
 //=======================================================================
index a3e27f17933b79abb5796abcab803f4312493350..5aaad68ab4d0ca465d6362c2d2af9ec4b4e47406 100644 (file)
@@ -593,7 +593,6 @@ void SelectMgr_SelectionManager::SetSelectionSensitivity (const Handle(SelectMgr
   {
     mySelector->myTolerances.Decrement (aPrevSens);
     mySelector->myTolerances.Add (theNewSens);
-    mySelector->myToUpdateTolerance = Standard_True;
   }
 }
 
index 6056fce00bdd5e7d33a1df6482c7c748271dbe79..3ba3ce93bdc065101a6b3ccbf9c04faeba7e1e33 100644 (file)
@@ -163,7 +163,6 @@ SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
 : myDepthTolerance (0.0),
   myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
   myToPreferClosest (Standard_True),
-  myToUpdateTolerance (Standard_True),
   myCameraScale (1.0),
   myToPrebuildBVH (Standard_False),
   myIsLeftChildQueuedFirst (Standard_False)
@@ -181,8 +180,6 @@ void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTole
   {
     return;
   }
-
-  myToUpdateTolerance = Standard_True;
   if (theTolerance < 0)
   {
     myTolerances.ResetDefaults();
@@ -209,7 +206,6 @@ void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theS
     theSelection->SetSelectionState (SelectMgr_SOS_Activated);
 
     myTolerances.Add (theSelection->Sensitivity());
-    myToUpdateTolerance = Standard_True;
   }
 }
 
@@ -229,7 +225,6 @@ void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& th
     theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
 
     myTolerances.Decrement (theSelection->Sensitivity());
-    myToUpdateTolerance = Standard_True;
   }
 }
 
@@ -626,27 +621,25 @@ void SelectMgr_ViewerSelector::TraverseSensitives()
 
   for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
   {
-    SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset =
-      static_cast<SelectMgr_SelectableObjectSet::BVHSubset> (aBVHSetIt);
-
+    const SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = (SelectMgr_SelectableObjectSet::BVHSubset )aBVHSetIt;
     if (mySelectableObjects.IsEmpty (aBVHSubset))
     {
       continue;
     }
+    if (aCamera.IsNull()
+     && aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_3d)
+    {
+      continue;
+    }
 
     gp_GTrsf aTFrustum;
-
     SelectMgr_SelectingVolumeManager aMgr;
 
-    // for 2D space selection transform selecting volumes to perform overap testing
+    // for 2D space selection transform selecting volumes to perform overlap testing
     // directly in camera's eye space omitting the camera position, which is not
     // needed there at all
     if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
     {
-      if (aCamera.IsNull())
-      {
-        continue;
-      }
       const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix();
       aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0));
       aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1));
@@ -1097,7 +1090,6 @@ void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_
   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
-  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToUpdateTolerance)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
 
   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
index 01284146fa7240817683d2a379f1aa4459274054..d98277aab80368681ef9e941a1ad87290dd68d31 100644 (file)
@@ -329,7 +329,6 @@ protected:
   Standard_Real                                 myDepthTolerance;
   SelectMgr_TypeOfDepthTolerance                myDepthTolType;
   Standard_Boolean                              myToPreferClosest;
-  Standard_Boolean                              myToUpdateTolerance;
   SelectMgr_IndexedDataMapOfOwnerCriterion      mystored;
   SelectMgr_SelectingVolumeManager              mySelectingVolumeMgr;
   mutable SelectMgr_SelectableObjectSet         mySelectableObjects;
index 94c40d478a8e101a3772c578e8f0a50dfac71e67..426fb28ee5861006f4f8aa4bb7a0a4a78ff662d1 100644 (file)
@@ -54,11 +54,7 @@ void SelectMgr_ViewerSelector3d::Pick (const Standard_Integer theXPix,
                       static_cast<Standard_Real> (theYPix));
   mySelectingVolumeMgr.InitPointSelectingVolume (aMousePos);
 
-  if(myToUpdateTolerance)
-  {
-    mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
-    myToUpdateTolerance = Standard_False;
-  }
+  mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
   mySelectingVolumeMgr.SetCamera (theView->Camera());
   Standard_Integer aWidth = 0, aHeight = 0;
   theView->Window()->Size (aWidth, aHeight);
diff --git a/tests/vselect/axis/A2 b/tests/vselect/axis/A2
new file mode 100644 (file)
index 0000000..dc93534
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "0032338: Visualization - provide straightforward interface for ray-picking"
+puts "========"
+puts ""
+
+pload MODELING VISUALIZATION
+box b 100 200 300
+vinit View1
+vdisplay -dispMode 1 b
+vfit
+vselmode b VERTEX 1
+vselmode b FACE 1
+set point1 [vmoveto 324 320]
+vdump ${imagedir}/${casename}_p1.png
+
+regexp {([-0-9.+eE]+ [-0-9.+eE]+ [-0-9.+eE]+)} ${point1} full p1
+checkpoint "point1" $p1 {100 200 0} 0.001
+
+vselaxis 50 -100 100 0 1 0 -display a
+vmoveto 0 0
+set point2 [vmoveto 324 320]
+vdump ${imagedir}/${casename}_p2.png
+regexp {([-0-9.+eE]+ [-0-9.+eE]+ [-0-9.+eE]+)} ${point1} full p2
+checkpoint "point2" $p2 {100 200 0} 0.001