]> OCCT Git - occt.git/commitdiff
0033664: Visualization - Selection does not work for simple shape CR33664_1
authormzernova <mzernova@opencascade.com>
Thu, 18 Jul 2024 23:16:11 +0000 (00:16 +0100)
committermzernova <mzernova@opencascade.com>
Fri, 6 Sep 2024 14:49:07 +0000 (15:49 +0100)
Fixed direction calculation for Select3D_SensitiveCylinder created from Geom_CylindricalSurface

src/StdSelect/StdSelect_BRepSelectionTool.cxx
tests/v3d/bugs/bug33664_1 [new file with mode: 0644]
tests/v3d/bugs/bug33664_2 [new file with mode: 0644]

index 07b5a96543ffe528a78104206805823dd05f2094..9e5542ceb89ca407007bb051efcce22aac7a710c 100644 (file)
@@ -562,54 +562,40 @@ void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape
 }
 
 //=======================================================================
-//function : getCylinderHeight
+//function : getCylinderCircles
 //purpose  :
 //=======================================================================
-static Standard_Real getCylinderHeight (const Handle(Poly_Triangulation)& theTriangulation,
-                                        const TopLoc_Location& theLoc)
+static NCollection_Array1<gp_Circ> getCylinderCircles (const TopoDS_Face& theHollowCylinder, Standard_Size& theNumCircles)
 {
-  Bnd_Box aBox;
-  gp_Trsf aScaleTrsf;
-  aScaleTrsf.SetScaleFactor (theLoc.Transformation().ScaleFactor());
-  theTriangulation->MinMax (aBox, aScaleTrsf);
-  return aBox.CornerMax().Z() - aBox.CornerMin().Z();
-}
-
-//=======================================================================
-//function : isCylinderOrCone
-//purpose  :
-//=======================================================================
-static Standard_Boolean isCylinderOrCone (const TopoDS_Face& theHollowCylinder, const gp_Pnt& theLocation, gp_Dir& theDirection)
-{
-  Standard_Integer aCirclesNb = 0;
-  Standard_Boolean isCylinder = Standard_False;
-  gp_Pnt aPos;
+  NCollection_Array1<gp_Circ> aCircles (1, 2);
+  theNumCircles = 0;
+  Standard_Integer aLinesNb = 0;
 
   TopExp_Explorer anEdgeExp;
   for (anEdgeExp.Init (theHollowCylinder, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
   {
     const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeExp.Current());
     BRepAdaptor_Curve anAdaptor (anEdge);
+    aLinesNb++;
 
     if (anAdaptor.GetType() == GeomAbs_Circle
      && BRep_Tool::IsClosed (anEdge))
     {
-      aCirclesNb++;
-      isCylinder = Standard_True;
-      if (aCirclesNb == 2)
-      {
-        // Reverse the direction of the cylinder, relevant if the cylinder was created as a prism
-        if (aPos.IsEqual (theLocation, Precision::Confusion()))
-        {
-          theDirection.Reverse();
-        }
-        return Standard_True;
-      }
-      aPos = anAdaptor.Circle().Location().XYZ();
+      theNumCircles++;
+      aCircles[theNumCircles] = anAdaptor.Circle();
+    }
+    else if (anAdaptor.GetType() != GeomAbs_Line || aLinesNb > 4)
+    {
+      theNumCircles = 0;
+      return NCollection_Array1<gp_Circ>();
+    }
+    if (theNumCircles == 2)
+    {
+      break;
     }
   }
 
-  return isCylinder;
+  return aCircles;
 }
 
 //=======================================================================
@@ -658,29 +644,33 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
     }
     else if (Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (aSurf))
     {
-      gp_Dir aDummyDir;
-      if (isCylinderOrCone (theFace, gp_Pnt(), aDummyDir))
+      Standard_Size aNumCircles;
+      NCollection_Array1<gp_Circ> aCircles = getCylinderCircles (theFace, aNumCircles);
+      if (aNumCircles > 0 && aNumCircles < 3)
       {
         const gp_Cone aCone = BRepAdaptor_Surface (theFace).Cone();
-        const Standard_Real aRad1 = aCone.RefRadius();
-        const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
 
         gp_Trsf aTrsf;
-        aTrsf.SetTransformation (aCone.Position(), gp::XOY());
-
+        Standard_Real aRad1;
         Standard_Real aRad2;
-        if (aRad1 == 0.0)
+        Standard_Real aHeight;
+        if (aNumCircles == 1)
         {
-          aRad2 = Tan (aCone.SemiAngle()) * aHeight;
+          aRad1 = 0.0;
+          aRad2 = aCircles.First().Radius();
+          aHeight = aRad2 * Tan (aCone.SemiAngle());
+          aTrsf.SetTransformation (aCone.Position(), gp::XOY());
         }
         else
         {
-          const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
-            ? aRad1 / Tan (aCone.SemiAngle())
-            : aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
-          aRad2 = (aCone.SemiAngle() > 0.0)
-            ? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
-            : aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
+          aRad1 = aCircles.First().Radius();
+          aRad2 = aCircles.Last().Radius();
+          aHeight = aCircles.First().Location().Distance (aCircles.Last().Location());
+
+          const gp_Pnt aPos = aCircles.First().Location();
+          const gp_Dir aDirection (aCircles.Last().Location().XYZ() - aPos.XYZ());
+
+          aTrsf.SetTransformation (gp_Ax3(aPos, aDirection), gp::XOY());
         }
 
         Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf, true);
@@ -690,18 +680,19 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
     }
     else if (Handle(Geom_CylindricalSurface) aGeomCyl = Handle(Geom_CylindricalSurface)::DownCast (aSurf))
     {
-      const gp_Cylinder aCyl = BRepAdaptor_Surface (theFace).Cylinder();
-      gp_Ax3 aPos = aCyl.Position();
-      gp_Dir aDirection = aPos.Direction();
-
-      if (isCylinderOrCone (theFace, aPos.Location(), aDirection))
+      Standard_Size aNumCircles;
+      NCollection_Array1<gp_Circ> aCircles = getCylinderCircles (theFace, aNumCircles);
+      if (aNumCircles == 2)
       {
+        const gp_Cylinder aCyl = BRepAdaptor_Surface (theFace).Cylinder();
+
         const Standard_Real aRad = aCyl.Radius();
-        const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
+        const gp_Pnt aPos = aCircles.First().Location();
+        const gp_Dir aDirection (aCircles.Last().Location().XYZ() - aPos.XYZ());
+        const Standard_Real aHeight = aPos.Distance (aCircles.Last().Location());
 
         gp_Trsf aTrsf;
-        aPos.SetDirection (aDirection);
-        aTrsf.SetTransformation (aPos, gp::XOY());
+        aTrsf.SetTransformation (gp_Ax3 (aPos, aDirection), gp::XOY());
 
         Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf, true);
         theSensitiveList.Append (aSensSCyl);
diff --git a/tests/v3d/bugs/bug33664_1 b/tests/v3d/bugs/bug33664_1
new file mode 100644 (file)
index 0000000..445cc69
--- /dev/null
@@ -0,0 +1,21 @@
+puts "============"
+puts "0033664: Visualization - Selection does not work for simple shape"
+puts "============"
+puts ""
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+
+restore [locate_data_file cylinder_surface.brep] b
+vdisplay -dispMode 1 b
+vfit
+vsensdis
+
+vselect 200 200
+if {[vnbselected] != "1"} {
+  puts "ERROR: wrong sensitive area"
+}
+
+vselect 0 0
+vdump $::imagedir/${::casename}_cylinder.png
diff --git a/tests/v3d/bugs/bug33664_2 b/tests/v3d/bugs/bug33664_2
new file mode 100644 (file)
index 0000000..ed1cbf6
--- /dev/null
@@ -0,0 +1,36 @@
+puts "============"
+puts "0033664: Visualization - Selection does not work for simple shape"
+puts "============"
+puts ""
+
+pload MODELING VISUALIZATION
+vclear
+vinit View1
+
+pcone c1 50 100 100
+ttranslate c1 100 0 100
+explode c1
+explode c1_1
+
+pcone c2 100 50 100
+ttranslate c2 -100 0 100
+explode c2
+explode c2_1
+
+pcone c3 0 100 100
+ttranslate c3 100 0 -100
+explode c3
+explode c3_1
+
+pcone c4 100 0 100
+ttranslate c4 -100 0 -100
+explode c4
+explode c4_1
+
+vdisplay c1_1_1 c2_1_1 c3_1_1 c4_1_1 -dispmode 1
+vsensdis
+
+vfront
+vfit
+
+vdump $::imagedir/${::casename}_cone.png