]> OCCT Git - occt.git/commitdiff
0027848: Visualization - sensitivity of lines is too high
authormzernova <mzernova@opencascade.com>
Tue, 22 Nov 2022 11:30:24 +0000 (11:30 +0000)
committervglukhik <vglukhik@opencascade.com>
Fri, 17 Mar 2023 23:04:14 +0000 (23:04 +0000)
Improved objects sorting by depth.

The sensitivity calculation for the manipulator has been changed.
Now the sensitivity of the elements of the manipulator depends on its size.

Also fixed the problem of erroneous selection of unfilled circles (SelectMgr_Frustum<N>::hasCircleOverlap() function).

Test case vselect/bugs/bug27848 added.

13 files changed:
src/AIS/AIS_Manipulator.cxx
src/SelectMgr/SelectMgr_Frustum.lxx
src/SelectMgr/SelectMgr_SortCriterion.hxx
src/SelectMgr/SelectMgr_ViewerSelector.cxx
tests/v3d/dimensions/bug24389
tests/v3d/manipulator/drag_in_2d_view
tests/v3d/manipulator/dragg
tests/v3d/manipulator/rotate
tests/v3d/manipulator/translate
tests/vselect/bugs/bug23012
tests/vselect/bugs/bug23539_2
tests/vselect/bugs/bug27848 [new file with mode: 0644]
tests/vselect/edge/A10

index a6f739bdb0ac2b1bfa854dd5c96272415fe08988..4cd43844b826579ea07d30ba18e827773a80a737 100644 (file)
@@ -1116,18 +1116,23 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
                                         const Standard_Integer theMode)
 {
   //Check mode
-  AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
+  const AIS_ManipulatorMode aMode = (AIS_ManipulatorMode) theMode;
   if (aMode == AIS_MM_None)
   {
     return;
   }
   Handle(SelectMgr_EntityOwner) anOwner;
-  if (aMode == AIS_MM_None)
-  {
-    anOwner = new SelectMgr_EntityOwner (this, 5);
-  }
 
-  if (aMode == AIS_MM_Translation || aMode == AIS_MM_None)
+  // Sensitivity calculation for manipulator parts allows to avoid
+  // overlapping of sensitive areas when size of manipulator is small.
+  // Sensitivity is calculated relative to the default size of the manipulator (100.0f).
+  const Standard_ShortReal aSensitivityCoef = myAxes[0].Size() / 100.0f;
+  const Standard_Integer aHighSensitivity = Max (Min (RealToInt (aSensitivityCoef * 15), 15), 3); // clamp sensitivity within range [3, 15]
+  const Standard_Integer aLowSensitivity  = Max (Min (RealToInt (aSensitivityCoef * 10), 10), 2); // clamp sensitivity within range [2, 10]
+
+  switch (aMode)
+  {
+  case AIS_MM_Translation:
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1136,23 +1141,21 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
         continue;
       }
       const Axis& anAxis = myAxes[anIt];
-      if (aMode != AIS_MM_None)
-      {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Translation, 9);
-      }
+      anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Translation, 9);
+
       // define sensitivity by line
-      Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment (anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
-      aLine->SetSensitivityFactor (15);
+      Handle(Select3D_SensitiveSegment) aLine = new Select3D_SensitiveSegment(anOwner, gp::Origin(), anAxis.TranslatorTipPosition());
+      aLine->SetSensitivityFactor (aHighSensitivity);
       theSelection->Add (aLine);
 
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray (anOwner);
+      Handle(Select3D_SensitivePrimitiveArray) aTri = new Select3D_SensitivePrimitiveArray(anOwner);
       aTri->InitTriangulation (anAxis.TriangleArray()->Attributes(), anAxis.TriangleArray()->Indices(), TopLoc_Location());
       theSelection->Add (aTri);
     }
+    break;
   }
-
-  if (aMode == AIS_MM_Rotation || aMode == AIS_MM_None)
+  case AIS_MM_Rotation:
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1161,22 +1164,20 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
         continue;
       }
       const Axis& anAxis = myAxes[anIt];
-      if (aMode != AIS_MM_None)
-      {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Rotation, 9);
-      }
+      anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Rotation, 9);
+
       // define sensitivity by circle
-      const gp_Circ aGeomCircle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
-      Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle);
-      aCircle->SetSensitivityFactor (15);
-      theSelection->Add (aCircle);
+      const gp_Circ aGeomCircle (gp_Ax2(gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
+      Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle(anOwner, aGeomCircle);
+      aCircle->SetSensitivityFactor (aLowSensitivity);
+      theSelection->Add(aCircle);
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation (anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
+      Handle(Select3D_SensitiveTriangulation) aTri = new ManipSensTriangulation(anOwner, myAxes[anIt].RotatorDisk().Triangulation(), anAxis.ReferenceAxis().Direction());
       theSelection->Add (aTri);
     }
+    break;
   }
-
-  if (aMode == AIS_MM_Scaling || aMode == AIS_MM_None)
+  case AIS_MM_Scaling:
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1184,21 +1185,19 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       {
         continue;
       }
-      if (aMode != AIS_MM_None)
-      {
-        anOwner = new AIS_ManipulatorOwner (this, anIt, AIS_MM_Scaling, 9);
-      }
+      anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_Scaling, 9);
+
       // define sensitivity by point
-      Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint (anOwner, myAxes[anIt].ScalerCubePosition());
-      aPnt->SetSensitivityFactor (15);
+      Handle(Select3D_SensitivePoint) aPnt = new Select3D_SensitivePoint(anOwner, myAxes[anIt].ScalerCubePosition());
+      aPnt->SetSensitivityFactor (aHighSensitivity);
       theSelection->Add (aPnt);
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation (anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
+      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].ScalerCube().Triangulation(), TopLoc_Location(), Standard_True);
       theSelection->Add (aTri);
     }
+    break;
   }
-
-  if (aMode == AIS_MM_TranslationPlane || aMode == AIS_MM_None)
+  case AIS_MM_TranslationPlane:
   {
     for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
     {
@@ -1206,28 +1205,33 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       {
         continue;
       }
-      if (aMode != AIS_MM_None)
-      {
-        anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
-      }
+      anOwner = new AIS_ManipulatorOwner(this, anIt, AIS_MM_TranslationPlane, 9);
 
       // define sensitivity by two crossed lines
-      gp_Pnt aP1, aP2;
-      aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition();
-      aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition();
+      Standard_Real aSensitivityOffset = ZoomPersistence() ? aHighSensitivity * (0.5 + M_SQRT2) : 0.0;
+      gp_Pnt aP1 = myAxes[((anIt + 1) % 3)].TranslatorTipPosition().Translated (myAxes[((anIt + 2) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset);
+      gp_Pnt aP2 = myAxes[((anIt + 2) % 3)].TranslatorTipPosition().Translated (myAxes[((anIt + 1) % 3)].ReferenceAxis().Direction().XYZ() * aSensitivityOffset);
       gp_XYZ aMidP = (aP1.XYZ() + aP2.XYZ()) / 2.0;
+      gp_XYZ anOrig = aMidP.Normalized().Multiplied (aSensitivityOffset);
 
       Handle(Select3D_SensitiveSegment) aLine1 = new Select3D_SensitiveSegment(anOwner, aP1, aP2);
-      aLine1->SetSensitivityFactor(10);
-      theSelection->Add(aLine1);
-      Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, gp::Origin(), aMidP);
-      aLine2->SetSensitivityFactor(10);
-      theSelection->Add(aLine2);
+      aLine1->SetSensitivityFactor(aLowSensitivity);
+      theSelection->Add (aLine1);
+      Handle(Select3D_SensitiveSegment) aLine2 = new Select3D_SensitiveSegment(anOwner, anOrig, aMidP);
+      aLine2->SetSensitivityFactor (aLowSensitivity);
+      theSelection->Add (aLine2);
 
       // enlarge sensitivity by triangulation
-      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True);
-      theSelection->Add(aTri);
+      Handle(Select3D_SensitiveTriangulation) aTri = new Select3D_SensitiveTriangulation(anOwner, myAxes[anIt].DraggerSector().Triangulation(), TopLoc_Location(), Standard_True); 
+      theSelection->Add (aTri);
     }
+    break;
+  }
+  default:
+  {
+    anOwner = new SelectMgr_EntityOwner(this, 5);
+    break;
+  }
   }
 }
 
index c01e50b6bfb617e04e8f24edcaa6872fe9f4ba38..882e74a37d20f9565524b481805cd75c7a0d8b9f 100644 (file)
@@ -869,32 +869,27 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCircleOverlap (const Standard_Real the
   const gp_Pnt aCenterProject (aCoefA * aTCenter,
                                aCoefB * aTCenter,
                                aCoefC * aTCenter);
-  if (isDotInside (aCenterProject, aVertices))
-  {
-    return true;
-  }
 
-  Standard_Boolean isInside = true;
+  const Standard_Boolean isCenterInside = isDotInside (aCenterProject, aVertices);
+
+  Standard_Boolean isInside = false;
   for (Standard_Integer anIdx = aVertices.Lower(); anIdx <= aVertices.Upper(); anIdx++)
   {
     if (aVertices.Value (anIdx).Distance (aCenterProject) > theRadius)
     {
-      isInside = false;
+      isInside = true;
       break;
     }
   }
 
   if (theInside != NULL)
   {
-    *theInside = false;
-  }
-
-  if (!theIsFilled && isInside)
-  {
-    return false;
+    *theInside = isInside && isCenterInside;
   }
 
-  return isInside;
+  return theIsFilled
+       ? !isInside || (isCenterInside && isInside)
+       : isInside && isCenterInside;
 }
 
 //=======================================================================
index 6a0d9065d3608f96c6815f75675a324e79d93433..183965efc50ee2a697e8fb90c77cacf2b96e9933 100644 (file)
@@ -58,12 +58,33 @@ public:
       return ZLayerPosition > theOther.ZLayerPosition;
     }
 
-    // closest object is selected unless difference is within tolerance
-    if (Abs (Depth - theOther.Depth) > (Tolerance + theOther.Tolerance))
+    // closest object is selected if their depths are not equal within tolerance
+    if (Abs (Depth - theOther.Depth) > Tolerance + theOther.Tolerance)
     {
       return Depth < theOther.Depth;
     }
 
+    Standard_Real aCos = 1.0;
+    if (Normal.Modulus() > 0 && theOther.Normal.Modulus() > 0)
+    {
+      gp_Dir aNormal (Normal.x(), Normal.y(), Normal.z());
+      gp_Dir anOtherNormal (theOther.Normal.x(), theOther.Normal.y(), theOther.Normal.z());
+      aCos = Abs (Cos (aNormal.Angle (anOtherNormal)));
+    }
+
+    Standard_Real aDepth = Depth - Tolerance;
+    Standard_Real anOtherDepth = theOther.Depth - theOther.Tolerance;
+    // Comparison depths taking into account tolerances occurs when the surfaces are parallel
+    // or have the same sensitivity and the angle between them is less than 60 degrees.
+    if (Abs (aDepth - anOtherDepth) > Precision::Confusion())
+    {
+      if ((aCos > 0.5 && Abs (Tolerance - theOther.Tolerance) < Precision::Confusion())
+       || Abs (aCos - 1.0) < Precision::Confusion())
+      {
+        return aDepth < anOtherDepth;
+      }
+    }
+
     // if two objects have similar depth, select the one with higher priority
     if (Priority > theOther.Priority)
     {
index 4ad9473157fcfddb455822be0adc9203f04a3ec8..5f8607341021a8f98e2b690bc5409b4ae50003f8 100644 (file)
@@ -284,9 +284,9 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEnti
     aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
     if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
     {
+      updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
       if (aCriterion.IsCloserDepth (*aPrevCriterion))
       {
-        updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
         *aPrevCriterion = aCriterion;
       }
     }
index 76ccda5ec080319f40af1dfdca35784334115f75..666c1a57d337b5d4c49b180a0d9b7f8ec528e7a1 100644 (file)
@@ -176,7 +176,7 @@ check_picking $pick_coord $check_coord "diameter dimension (diam1)"
 check_cross_picking $pick_coord diam1 "diameter dimension (diam1)"
 
 # check sensitives "diam2"
-set pick_coord { { 221 99 } { 285 99 } }
+set pick_coord { { 222 99 } { 285 99 } }
 set check_coord { 239 99 }
 check_picking $pick_coord $check_coord "diameter dimension (diam2)"
 check_cross_picking $pick_coord diam2 "diameter dimension (diam2)"
index 9eef222bb672deb24c6dbfb0582873e65480ece7..a648763549957df75692ad40dbcb2a4c400fd41a 100644 (file)
@@ -15,8 +15,8 @@ vmanipulator m -attach b
 
 vdump $imagedir/${casename}_1.png
 
-set mouse_pick {226 214}
-set mouse_drag {306 265}
+set mouse_pick {231 207}
+set mouse_drag {311 258}
 
 # note: mouse events cannot be emulated here, so the original bug cannot be reproduced by this test case
 vmoveto {*}$mouse_pick
index 7cb67c7f1ea71ee260705a799fadd37944987638..db20f78729cbb761bc39988fbc1f8783e253adf9 100644 (file)
@@ -61,7 +61,7 @@ vdump $anImage2
 # -------------------------------------------
 
 set mouse_pick {316 261}
-set mouse_drag {279 286}
+set mouse_drag {281 286}
 
 vmoveto {*}$mouse_pick
 vselect {*}$mouse_pick
index 4b87f97fb681b382c6537c45616a148e7d2c8514..0d2debeaa894df315632180169b8ee9f6649f542 100644 (file)
@@ -47,7 +47,7 @@ vmanipulator m -attach c1 -adjustPosition 1 -adjustSize 0 -enableModes 1 -size 4
 
 vmanipulator m -followRotation 1
 
-set mouse_pick {200 092}
+set mouse_pick {199 092}
 set mouse_drag {176 142}
 
 vmoveto {*}$mouse_pick
@@ -65,8 +65,8 @@ vdump $anImage1
 
 vmanipulator m -followRotation 1
 
-set mouse_pick {173 137}
-set mouse_drag {233 144}
+set mouse_pick {175 135}
+set mouse_drag {232 144}
 
 vmoveto {*}$mouse_pick
 vselect {*}$mouse_pick
@@ -113,7 +113,7 @@ vmanipulator m -followRotation 0
 # test rotation around y axis (world reference frame)
 # ---------------------------------------------------
 
-set mouse_pick {205 087}
+set mouse_pick {205 088}
 set mouse_drag {232 127}
 
 vmoveto {*}$mouse_pick
@@ -129,7 +129,7 @@ vdump $anImage4
 # test rotation around z axis (world reference frame)
 # ---------------------------------------------------
 
-set mouse_pick {228 141}
+set mouse_pick {228 142}
 set mouse_drag {184 143}
 
 vmoveto {*}$mouse_pick
index ddc0ec25636f0cc793c536e5e8e727a1dd2a5799..69daa33716b310945a5f775bc6e6e45eb54e95d9 100644 (file)
@@ -144,7 +144,7 @@ vdump $anImage4
 # ----------------------------------------------------
 
 set mouse_pick {199 164}
-set mouse_drag {246 177}
+set mouse_drag {246 176}
 
 vmoveto {*}$mouse_pick
 vselect {*}$mouse_pick
index de98fe644f4d4e61e9aba6b59b02c248cf9ecdbd..984c036aa0c4496b0e6b2ce2fd825af8fb533a47 100644 (file)
@@ -11,7 +11,7 @@ set x1 210
 set y1 184
 
 set x2 207
-set y2 180
+set y2 182
 
 stepread [locate_data_file OCC23012-Sample_3.stp] a *
 stepread [locate_data_file OCC23012-Sample_9.stp] b *
index 05659b71b59b692beea9d7cf5243e2eb0cc4d6a4..5577a18cae5020f5b03408eb114a489a8e1c2a6b 100644 (file)
@@ -16,7 +16,7 @@ vselect 300 200 300 60 400 60 407 150 -xor
 set NbSelected1 [vnbselected]
 if { ${NbSelected1} != 13 } { puts "Error : Polygonal shift selection doesn't work properly" }
 
-vselect 350 120 -xor
+vselect 350 121 -xor
 
 set NbSelected1 [vnbselected]
 if { ${NbSelected1} != 12 } { puts "Error : (case 2)" }
diff --git a/tests/vselect/bugs/bug27848 b/tests/vselect/bugs/bug27848
new file mode 100644 (file)
index 0000000..19e4d5a
--- /dev/null
@@ -0,0 +1,23 @@
+puts "============="
+puts "0027848: Visualization - sensitivity of lines is too high"
+puts "============="
+
+pload VISUALIZATION
+
+vinit View1
+vclear
+
+box b 10 10 0.1
+vdisplay b -dispmode 1
+
+vline l 0 0 0 10 10 0
+vdisplay l
+
+vpoint p 20 20 0
+
+vtop
+vfit
+
+vselect 100 305
+
+if { [string match "*AIS_Line*" [vstate]] } { puts "Error: AIS_Shape should be detected" }
index f42646f62d97a43ae75d0282aa01ce44790d940d..2738b8c05cf5415139e392d91611936fbd9f9045 100644 (file)
@@ -39,28 +39,28 @@ if { ![check_highlighting 0 $coords] } {
   puts "ERROR: incorrect highlighting of edge 10"
 }
 
-vselnext
-if { ![check_highlighting 1 $coords] } {
-  puts "ERROR: incorrect highlighting of edge 2 after vselnext call"
-}
 vselnext
 if { ![check_highlighting 2 $coords] } {
   puts "ERROR: incorrect highlighting of edge 1 after vselnext call"
 }
 vselnext
+if { ![check_highlighting 1 $coords] } {
+  puts "ERROR: incorrect highlighting of edge 2 after vselnext call"
+}
+vselnext
 if { ![check_highlighting 0 $coords] } {
   puts "ERROR: incorrect highlighting of edge 10 after vselnext call"
 }
 
-vselprev
-if { ![check_highlighting 2 $coords] } {
-  puts "ERROR: incorrect highlighting of edge 1 after vselprev call"
-}
 vselprev
 if { ![check_highlighting 1 $coords] } {
   puts "ERROR: incorrect highlighting of edge 2 after vselprev call"
 }
 vselprev
+if { ![check_highlighting 2 $coords] } {
+  puts "ERROR: incorrect highlighting of edge 1 after vselprev call"
+}
+vselprev
 if { ![check_highlighting 0 $coords] } {
   puts "ERROR: incorrect highlighting of edge 10 after vselprev call"
 }