]> OCCT Git - occt.git/commitdiff
0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow...
authormzernova <mzernova@opencascade.com>
Thu, 18 Aug 2022 14:12:03 +0000 (17:12 +0300)
committersmoskvin <smoskvin@opencascade.com>
Fri, 26 Aug 2022 14:38:19 +0000 (17:38 +0300)
Select3D_SensitiveCircle now inherits directly from Select3D_SensitiveEntity.
The sensitive circle sector is created using the Select3D_SensitivePoly class directly.

Added appropriate methods for selecting sensitive circles.
Added parameter myIsHollow to Select3D_SensitiveCylinder class.
It allows you to search for intersections with cylinders without covers.

The Draw vcircle command has been extended with UStart and UEnd parameters
to create a sector of a circle.

Added tests: vselect/cone_cylinder/circle_sector
             vselect/cone_cylinder/circle_wire
             vselect/cone_cylinder/filled_circle
             vselect/cone_cylinder/transformed
             vselect/cone_cylinder/hollow_cone_cyl

38 files changed:
src/AIS/AIS_Circle.cxx
src/AIS/AIS_Manipulator.cxx
src/PrsDim/PrsDim_ConcentricRelation.cxx
src/PrsDim/PrsDim_EqualDistanceRelation.cxx
src/Select3D/Select3D_SensitiveCircle.cxx
src/Select3D/Select3D_SensitiveCircle.hxx
src/Select3D/Select3D_SensitiveCylinder.cxx
src/Select3D/Select3D_SensitiveCylinder.hxx
src/Select3D/Select3D_SensitivePoly.cxx
src/Select3D/Select3D_SensitivePoly.hxx
src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr.cxx
src/SelectMgr/SelectMgr_AxisIntersector.cxx
src/SelectMgr/SelectMgr_AxisIntersector.hxx
src/SelectMgr/SelectMgr_BaseIntersector.cxx
src/SelectMgr/SelectMgr_BaseIntersector.hxx
src/SelectMgr/SelectMgr_Frustum.hxx
src/SelectMgr/SelectMgr_Frustum.lxx
src/SelectMgr/SelectMgr_RectangularFrustum.cxx
src/SelectMgr/SelectMgr_RectangularFrustum.hxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx
src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx
src/SelectMgr/SelectMgr_TriangularFrustum.cxx
src/SelectMgr/SelectMgr_TriangularFrustum.hxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx
src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx
src/StdSelect/StdSelect_BRepSelectionTool.cxx
src/StdSelect/StdSelect_BRepSelectionTool.hxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/v3d/manipulator/rotate
tests/vselect/bugs/bug27477
tests/vselect/cone_cylinder/circle_sector [new file with mode: 0644]
tests/vselect/cone_cylinder/circle_wire [new file with mode: 0644]
tests/vselect/cone_cylinder/filled_circle [new file with mode: 0644]
tests/vselect/cone_cylinder/hollow_cone_cyl [new file with mode: 0644]
tests/vselect/cone_cylinder/transformed_circle [new file with mode: 0644]
tests/vselect/cone_cylinder/trsf_cone
tests/vselect/cone_cylinder/trsf_cyl

index 70c7e7957e9c536ee2a52b0fa883e1dcec2b5c54..ef85e9b0ceeb1558852d4c035d791f90b7be7b88 100644 (file)
@@ -27,6 +27,7 @@
 #include <Prs3d_Presentation.hxx>
 #include <Quantity_Color.hxx>
 #include <Select3D_SensitiveCircle.hxx>
+#include <Select3D_SensitivePoly.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <SelectMgr_Selection.hxx>
 #include <Standard_Type.hxx>
@@ -41,9 +42,9 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_Circle,AIS_InteractiveObject)
 AIS_Circle::AIS_Circle(const Handle(Geom_Circle)& aComponent):
 AIS_InteractiveObject(PrsMgr_TOP_AllView),
 myComponent(aComponent),
-myUStart(0.),
-myUEnd(2*M_PI),
-myCircleIsArc(Standard_False),
+myUStart (0.0),
+myUEnd (2.0 * M_PI),
+myCircleIsArc (Standard_False),
 myIsFilledCircleSens (Standard_False)
 {
 }
@@ -60,7 +61,7 @@ AIS_Circle::AIS_Circle(const Handle(Geom_Circle)& theComponent,
   myComponent (theComponent),
   myUStart (theUStart),
   myUEnd (theUEnd),
-  myCircleIsArc (Standard_True),
+  myCircleIsArc (Abs (Abs (theUEnd - theUStart) - 2.0 * M_PI) > gp::Resolution()),
   myIsFilledCircleSens (theIsFilledCircleSens)
 {
 }
@@ -207,14 +208,14 @@ void AIS_Circle::UnsetWidth()
 //function : ComputeCircle
 //purpose  : 
 //=======================================================================
-void AIS_Circle::ComputeCircle( const Handle(Prs3d_Presentation)& aPresentation)
+void AIS_Circle::ComputeCircle (const Handle(Prs3d_Presentation)& thePresentation)
 {
 
   GeomAdaptor_Curve curv(myComponent);
   Standard_Real prevdev = myDrawer->DeviationCoefficient();
-  myDrawer->SetDeviationCoefficient(1.e-5);
-  StdPrs_DeflectionCurve::Add(aPresentation,curv,myDrawer);
-  myDrawer->SetDeviationCoefficient(prevdev);
+  myDrawer->SetDeviationCoefficient (1.e-5);
+  StdPrs_DeflectionCurve::Add (thePresentation, curv, myDrawer);
+  myDrawer->SetDeviationCoefficient (prevdev);
 
 }
 
@@ -223,13 +224,13 @@ void AIS_Circle::ComputeCircle( const Handle(Prs3d_Presentation)& aPresentation)
 
 //purpose  : 
 //=======================================================================
-void AIS_Circle::ComputeArc( const Handle(Prs3d_Presentation)& aPresentation)
+void AIS_Circle::ComputeArc (const Handle(Prs3d_Presentation)& thePresentation)
 {
-  GeomAdaptor_Curve curv(myComponent,myUStart,myUEnd);
+  GeomAdaptor_Curve curv(myComponent, myUStart, myUEnd);
   Standard_Real prevdev = myDrawer->DeviationCoefficient();
-  myDrawer->SetDeviationCoefficient(1.e-5);
-  StdPrs_DeflectionCurve::Add(aPresentation,curv,myDrawer);
-  myDrawer->SetDeviationCoefficient(prevdev);
+  myDrawer->SetDeviationCoefficient (1.e-5);
+  StdPrs_DeflectionCurve::Add (thePresentation, curv, myDrawer);
+  myDrawer->SetDeviationCoefficient (prevdev);
 }
 
 //=======================================================================
@@ -237,27 +238,25 @@ void AIS_Circle::ComputeArc( const Handle(Prs3d_Presentation)& aPresentation)
 //purpose  : 
 //=======================================================================
 
-void AIS_Circle::ComputeCircleSelection(const Handle(SelectMgr_Selection)& aSelection)
+void AIS_Circle::ComputeCircleSelection (const Handle(SelectMgr_Selection)& theSelection)
 {
-  Handle(SelectMgr_EntityOwner) eown = new SelectMgr_EntityOwner(this);
-  Handle(Select3D_SensitiveCircle) seg = new Select3D_SensitiveCircle (eown,
-                                                                       myComponent->Circ(),
-                                                                       myIsFilledCircleSens);
-  aSelection->Add(seg);
+  Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner(this);
+  Handle(Select3D_SensitiveCircle) aCirc = new Select3D_SensitiveCircle (anOwner,
+                                                                         myComponent->Circ(),
+                                                                         myIsFilledCircleSens);
+  theSelection->Add (aCirc);
 }
 //=======================================================================
 //function : ComputeArcSelection
 //purpose  : 
 //=======================================================================
 
-void AIS_Circle::ComputeArcSelection(const Handle(SelectMgr_Selection)& aSelection)
+void AIS_Circle::ComputeArcSelection (const Handle(SelectMgr_Selection)& theSelection)
 {
-
-
-  Handle(SelectMgr_EntityOwner) eown = new SelectMgr_EntityOwner(this);
-  Handle(Select3D_SensitiveCircle) seg = new Select3D_SensitiveCircle (eown,
-                                                                       myComponent->Circ(),
-                                                                       myUStart, myUEnd,
-                                                                       myIsFilledCircleSens);
-  aSelection->Add(seg);
+  Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner(this);
+  Handle(Select3D_SensitivePoly) aSeg = new Select3D_SensitivePoly (anOwner,
+                                                                    myComponent->Circ(),
+                                                                    myUStart, myUEnd,
+                                                                    myIsFilledCircleSens);
+  theSelection->Add (aSeg);
 }
index 43da955306944c2a47ed47b0bd758c7fada5684c..a6f739bdb0ac2b1bfa854dd5c96272415fe08988 100644 (file)
@@ -84,9 +84,8 @@ namespace
   public:
     //! Main constructor.
     ManipSensCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                     const gp_Circ& theCircle,
-                     const Standard_Integer theNbPnts)
-    : Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False, theNbPnts),
+                     const gp_Circ& theCircle)
+    : Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False),
       ManipSensRotation (theCircle.Position().Direction()) {}
 
     //! Checks whether the circle overlaps current selecting volume
@@ -1168,7 +1167,7 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
       }
       // 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, anAxis.FacettesNumber());
+      Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle);
       aCircle->SetSensitivityFactor (15);
       theSelection->Add (aCircle);
       // enlarge sensitivity by triangulation
index 807b6cd366ae3a6cd8fef768aaa5226e0f773bd8..6f283e13e167b60fddf1fa7253d6bd16c9de649d 100644 (file)
@@ -213,37 +213,39 @@ void PrsDim_ConcentricRelation::ComputeTwoEdgesConcentric(const Handle(Prs3d_Pre
 //purpose  : 
 //=======================================================================
 
-void PrsDim_ConcentricRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection, 
-                                             const Standard_Integer)
+void PrsDim_ConcentricRelation::ComputeSelection (const Handle(SelectMgr_Selection)& aSelection,
+                                                  const Standard_Integer)
 {
-  Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
+  Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner(this,7);
   
   //Creation of 2 sensitive circles
-     // the greater
-  gp_Ax2 ax(myCenter, myDir);
-  gp_Circ aCirc (ax, myRad);
-  Handle(Select3D_SensitiveCircle) sensit = new Select3D_SensitiveCircle (own, aCirc);
-  aSelection->Add(sensit);
-     // the smaller
-  aCirc.SetRadius(myRad/2);
-  sensit = new Select3D_SensitiveCircle (own, aCirc);
-  aSelection->Add(sensit);
+
+  // the greater
+  gp_Ax2 anAx (myCenter, myDir);
+  gp_Circ aCirc (anAx, myRad);
+  Handle(Select3D_SensitiveCircle) sensit = new Select3D_SensitiveCircle (anOwner, aCirc);
+  aSelection->Add (sensit);
+
+  // the smaller
+  aCirc.SetRadius (myRad / 2);
+  sensit = new Select3D_SensitiveCircle (anOwner, aCirc);
+  aSelection->Add (sensit);
 
   //Creation of 2 segments sensitive for the cross
   Handle(Select3D_SensitiveSegment) seg;
   gp_Pnt otherPnt = myPnt.Mirrored(myCenter);
-  seg = new Select3D_SensitiveSegment(own,
-                                     otherPnt,
-                                     myPnt);
-  aSelection->Add(seg);
+  seg = new Select3D_SensitiveSegment(anOwner,
+                                      otherPnt,
+                                      myPnt);
+  aSelection->Add (seg);
 
   gp_Ax1 RotateAxis(myCenter, myDir);
-  gp_Pnt FPnt = myCenter.Rotated(RotateAxis, M_PI/2);
-  gp_Pnt SPnt = myCenter.Rotated(RotateAxis, -M_PI/2);
-  seg = new Select3D_SensitiveSegment(own,
-                                     FPnt,
-                                     SPnt);
-  aSelection->Add(seg);
+  gp_Pnt FPnt = myCenter.Rotated (RotateAxis, M_PI_2);
+  gp_Pnt SPnt = myCenter.Rotated (RotateAxis, -M_PI_2);
+  seg = new Select3D_SensitiveSegment(anOwner,
+                                      FPnt,
+                                      SPnt);
+  aSelection->Add (seg);
 
 }
 
index 830edbb9ba2e33df1af6350c0732f070b2313dfb..cea28b70a9ddf5fce1625d55964aee6915ad746f 100644 (file)
@@ -36,7 +36,7 @@
 #include <Prs3d_Drawer.hxx>
 #include <Prs3d_Presentation.hxx>
 #include <Select3D_SensitiveBox.hxx>
-#include <Select3D_SensitiveCircle.hxx>
+#include <Select3D_SensitivePoly.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 #include <TopoDS_Edge.hxx>
@@ -202,124 +202,141 @@ void PrsDim_EqualDistanceRelation::Compute (const Handle(PrsMgr_PresentationMana
 
 //=======================================================================
 //function : ComputeSelection
-//purpose  : 
+//purpose  :
 //=======================================================================
 
-void PrsDim_EqualDistanceRelation::ComputeSelectionconst Handle( SelectMgr_Selection )& aSelection,
-                                                 const Standard_Integer ) 
+void PrsDim_EqualDistanceRelation::ComputeSelection (const Handle( SelectMgr_Selection )& aSelection,
+                                                     const Standard_Integer)
 {
   Handle( SelectMgr_EntityOwner ) own = new SelectMgr_EntityOwner( this, 7 );
   Handle( Select3D_SensitiveSegment ) seg;
 
   seg = new Select3D_SensitiveSegment( own, myPoint1, myPoint2 );
-  aSelection->Add( seg );
+  aSelection->Add (seg);
 
   seg = new Select3D_SensitiveSegment( own, myPoint3, myPoint4 );
-  aSelection->Add( seg );
+  aSelection->Add (seg);
 
   // Line between two middles
-  gp_Pnt Middle12( (myPoint1.XYZ() + myPoint2.XYZ()) * 0.5 ), 
+  gp_Pnt Middle12( (myPoint1.XYZ() + myPoint2.XYZ()) * 0.5 ),
          Middle34( (myPoint3.XYZ() + myPoint4.XYZ()) *0.5 );
   seg = new Select3D_SensitiveSegment( own, Middle12, Middle34 );
-  aSelection->Add( seg );
+  aSelection->Add (seg);
 
   gp_Pnt Middle((Middle12.XYZ() +  Middle34.XYZ())*0.5);
   Standard_Real SmallDist = .001;
-  Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox( own,
-                                                                 Middle.X() - SmallDist,
-                                                                 Middle.Y() - SmallDist,
-                                                                 Middle.Z() - SmallDist,
-                                                                 Middle.X() + SmallDist,
-                                                                 Middle.Y() + SmallDist,
-                                                                 Middle.Z() + SmallDist );
-  aSelection->Add(box);
-
-  if (myFShape.ShapeType() == TopAbs_EDGE){
+  Handle( Select3D_SensitiveBox ) box = new Select3D_SensitiveBox(own,
+                                                                  Middle.X() - SmallDist,
+                                                                  Middle.Y() - SmallDist,
+                                                                  Middle.Z() - SmallDist,
+                                                                  Middle.X() + SmallDist,
+                                                                  Middle.Y() + SmallDist,
+                                                                  Middle.Z() + SmallDist);
+  aSelection->Add (box);
+
+  if (myFShape.ShapeType() == TopAbs_EDGE)
+  {
     BRepAdaptor_Curve aCurve(TopoDS::Edge(myFShape));
-    if (aCurve.GetType() == GeomAbs_Line){
-       //add sensetive element - line
+    if (aCurve.GetType() == GeomAbs_Line)
+    {
+      //add sensetive element - line
       seg = new Select3D_SensitiveSegment( own, myAttachPoint1, myPoint1);
-      aSelection->Add( seg );
+      aSelection->Add (seg);
     }
-    else if (aCurve.GetType() == GeomAbs_Circle){
+    else if (aCurve.GetType() == GeomAbs_Circle)
+    {
       Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve.Curve().Curve());
       Standard_Real FirstPar = ElCLib::Parameter(aCircle->Circ(), myAttachPoint1),
                     LastPar  = ElCLib::Parameter(aCircle->Circ(), myPoint1);
-      if (LastPar < FirstPar ) LastPar+=M_PI*2;
-      Handle(Select3D_SensitiveCircle) circ = new Select3D_SensitiveCircle (own, aCircle->Circ(), FirstPar, LastPar);
-      aSelection->Add( circ );
+      if (LastPar < FirstPar ) LastPar += M_PI * 2;
+      Handle(Select3D_SensitivePoly) circ = new Select3D_SensitivePoly (own, aCircle->Circ(), FirstPar, LastPar);
+      aSelection->Add (circ);
     }
   }
-  else {
+  else
+  {
       seg = new Select3D_SensitiveSegment( own, myAttachPoint1, myPoint1);
-      aSelection->Add( seg );
-    }
-  
-  if (mySShape.ShapeType() == TopAbs_EDGE){
+      aSelection->Add (seg);
+  }
+
+  if (mySShape.ShapeType() == TopAbs_EDGE)
+  {
     BRepAdaptor_Curve aCurve(TopoDS::Edge(mySShape));
-    if (aCurve.GetType() == GeomAbs_Line) {
+    if (aCurve.GetType() == GeomAbs_Line)
+    {
       //add sensetive element - line
       seg = new Select3D_SensitiveSegment( own, myAttachPoint2, myPoint2);
-      aSelection->Add( seg );
+      aSelection->Add (seg);
     }
-    else if (aCurve.GetType() == GeomAbs_Circle){
+    else if (aCurve.GetType() == GeomAbs_Circle)
+    {
       Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve.Curve().Curve());
       Standard_Real FirstPar = ElCLib::Parameter(aCircle->Circ(), myAttachPoint2),
       LastPar  = ElCLib::Parameter(aCircle->Circ(), myPoint2);
-      if (LastPar < FirstPar ) LastPar+=M_PI*2;
-      Handle(Select3D_SensitiveCircle) circ = new Select3D_SensitiveCircle (own, aCircle->Circ(), FirstPar, LastPar);
-      aSelection->Add( circ );
+      if (LastPar < FirstPar) LastPar += M_PI * 2;
+      Handle(Select3D_SensitivePoly) circ = new Select3D_SensitivePoly (own, aCircle->Circ(), FirstPar, LastPar);
+      aSelection->Add (circ);
     }
   }
-  else {
+  else
+  {
     seg = new Select3D_SensitiveSegment( own, myAttachPoint2, myPoint2);
-    aSelection->Add( seg );
+    aSelection->Add (seg);
   }
     
-  if (myShape3.ShapeType() == TopAbs_EDGE){
+  if (myShape3.ShapeType() == TopAbs_EDGE)
+  {
     BRepAdaptor_Curve aCurve(TopoDS::Edge(myShape3));
-    if (aCurve.GetType() == GeomAbs_Line) {
+    if (aCurve.GetType() == GeomAbs_Line)
+    {
       //add sensetive element - line
       seg = new Select3D_SensitiveSegment( own, myAttachPoint3, myPoint3);
-      aSelection->Add( seg );
+      aSelection->Add (seg);
     }
-    else if (aCurve.GetType() == GeomAbs_Circle){
+    else if (aCurve.GetType() == GeomAbs_Circle)
+    {
       Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve.Curve().Curve());
       Standard_Real FirstPar = ElCLib::Parameter(aCircle->Circ(), myAttachPoint3),
       LastPar  = ElCLib::Parameter(aCircle->Circ(), myPoint3);
-      if (LastPar < FirstPar ) LastPar+=M_PI*2;
-      Handle(Select3D_SensitiveCircle) circ = new Select3D_SensitiveCircle (own, aCircle->Circ(), FirstPar, LastPar);
-      aSelection->Add( circ );
+      if (LastPar < FirstPar) LastPar += M_PI * 2;
+      Handle(Select3D_SensitivePoly) circ = new Select3D_SensitivePoly (own, aCircle->Circ(), FirstPar, LastPar);
+      aSelection->Add (circ);
     }
-    else {
+    else
+    {
       seg = new Select3D_SensitiveSegment( own, myAttachPoint3, myPoint3);
-      aSelection->Add( seg );
+      aSelection->Add (seg);
     }
   }
-  else {
+  else
+  {
     seg = new Select3D_SensitiveSegment( own, myAttachPoint3, myPoint3);
-    aSelection->Add( seg );
+    aSelection->Add (seg);
   }
 
-  if (myShape4.ShapeType() == TopAbs_EDGE){
+  if (myShape4.ShapeType() == TopAbs_EDGE)
+  {
     BRepAdaptor_Curve aCurve(TopoDS::Edge(myShape4));
-    if (aCurve.GetType() == GeomAbs_Line) {
+    if (aCurve.GetType() == GeomAbs_Line)
+    {
       //add sensetive element - line
       seg = new Select3D_SensitiveSegment( own, myAttachPoint4, myPoint4);
-      aSelection->Add( seg );
+      aSelection->Add (seg);
     }
-    else if (aCurve.GetType() == GeomAbs_Circle){
+    else if (aCurve.GetType() == GeomAbs_Circle)
+    {
       Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve.Curve().Curve());
       Standard_Real FirstPar = ElCLib::Parameter(aCircle->Circ(), myAttachPoint4),
       LastPar  = ElCLib::Parameter(aCircle->Circ(), myPoint4);
-      if (LastPar < FirstPar ) LastPar+=M_PI*2;
-      Handle(Select3D_SensitiveCircle) circ = new Select3D_SensitiveCircle (own, aCircle->Circ(), FirstPar, LastPar);
+      if (LastPar < FirstPar) LastPar += M_PI * 2;
+      Handle(Select3D_SensitivePoly) circ = new Select3D_SensitivePoly (own, aCircle->Circ(), FirstPar, LastPar);
       aSelection->Add( circ );
     }
   }
-  else {
+  else
+  {
     seg = new Select3D_SensitiveSegment( own, myAttachPoint4, myPoint4);
-    aSelection->Add( seg );
+    aSelection->Add (seg);
   }
 }
 
index 6a4864c7dd27725b995bfc37b636af7fa9c40b43..1e24dd8ba77fbcfb52af1148f341507da9cfdbc7 100644 (file)
 
 #include <Select3D_SensitiveCircle.hxx>
 
-#include <ElCLib.hxx>
-#include <Precision.hxx>
-#include <Select3D_SensitiveTriangle.hxx>
+#include <gp_Ax3.hxx>
 
-IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveCircle,Select3D_SensitivePoly)
-
-namespace
-{
-  static Standard_Integer GetCircleNbPoints (const gp_Circ& theCircle,
-                                             const Standard_Integer theNbPnts)
-  {
-    // Check if number of points is invalid.
-    // In this case myPolyg raises Standard_ConstructionError
-    // exception (see constructor below).
-    if (theNbPnts <= 0)
-      return 0;
-
-    if (theCircle.Radius() > Precision::Confusion())
-      return 2 * theNbPnts + 1;
-
-    // The radius is too small and circle degenerates into point
-    return 1;
-  }
-
-  //! Definition of circle polyline
-  static void initCircle (Select3D_PointData& thePolygon,
-                          const gp_Circ& theCircle,
-                          const Standard_Real theU1,
-                          const Standard_Real theU2,
-                          const Standard_Integer theNbPnts)
-  {
-    const Standard_Real aStep = (theU2 - theU1) / theNbPnts;
-    const Standard_Real aRadius = theCircle.Radius();
-    Standard_Integer aPntIdx = 0;
-    Standard_Real aCurU = theU1;
-    gp_Pnt aP1;
-    gp_Vec aV1;
-    for (Standard_Integer anIndex = 1; anIndex <= theNbPnts; ++anIndex, aCurU += aStep)
-    {
-      ElCLib::CircleD1 (aCurU, theCircle.Position(), theCircle.Radius(), aP1, aV1);
-      thePolygon.SetPnt (aPntIdx++, aP1);
-
-      aV1.Normalize();
-      const gp_Pnt aP2 = aP1.XYZ() + aV1.XYZ() * Tan (aStep * 0.5) * aRadius;
-      thePolygon.SetPnt (aPntIdx++, aP2);
-    }
-    aP1 = ElCLib::CircleValue (theU2, theCircle.Position(), theCircle.Radius());
-    thePolygon.SetPnt (theNbPnts * 2, aP1);
-  }
-}
+IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveCircle, Select3D_SensitiveEntity)
 
 //=======================================================================
 //function : Select3D_SensitiveCircle (constructor)
 //purpose  : Definition of a sensitive circle
 //=======================================================================
-Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                                   const gp_Circ& theCircle,
-                                                   const Standard_Boolean theIsFilled,
-                                                   const Standard_Integer theNbPnts)
-: Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts)),
-  myCircle (theCircle),
-  myStart (0.0),
-  myEnd (2.0 * M_PI)
-{
-  mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
-  myCenter3D = theCircle.Position().Location();
-  if (myPolyg.Size() != 1)
-  {
-    initCircle (myPolyg, theCircle, myStart, myEnd, theNbPnts);
-  }
-  // Radius = 0.0
-  else
-  {
-    myPolyg.SetPnt (0, theCircle.Position().Location());
-  }
-
-  if (mySensType == Select3D_TOS_BOUNDARY)
-  {
-    SetSensitivityFactor (6);
-  }
-}
-
-//=======================================================================
-//function : Select3D_SensitiveCircle (constructor)
-//purpose  : Definition of a sensitive arc
-//=======================================================================
 Select3D_SensitiveCircle::Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
                                                     const gp_Circ& theCircle,
-                                                    const Standard_Real theU1,
-                                                    const Standard_Real theU2,
-                                                    const Standard_Boolean theIsFilled,
-                                                    const Standard_Integer theNbPnts)
-: Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts)),
-  myCircle (theCircle),
-  myStart (Min (theU1, theU2)),
-  myEnd (Max (theU1, theU2))
+                                                    const Standard_Boolean theIsFilled)
+: Select3D_SensitiveEntity (theOwnerId)
 {
-  mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
-  myCenter3D = theCircle.Position().Location();
-  if (myPolyg.Size() != 1)
-  {
-    initCircle (myPolyg, theCircle, myStart, myEnd, theNbPnts);
-  }
-  else
-  {
-    myPolyg.SetPnt (0, theCircle.Position().Location());
-  }
+  myRadius = theCircle.Radius();
+  myTrsf.SetTransformation (theCircle.Position(), gp::XOY());
 
-  if (mySensType == Select3D_TOS_BOUNDARY)
-  {
-    SetSensitivityFactor (6);
-  }
-}
-
-//=======================================================================
-//function : Select3D_SensitiveCircle
-//purpose  :
-//=======================================================================
-Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                                   const Handle(TColgp_HArray1OfPnt)& thePnts3d,
-                                                   const Standard_Boolean theIsFilled)
-: Select3D_SensitivePoly (theOwnerId, thePnts3d, static_cast<Standard_Boolean> (!theIsFilled)),
-  myStart (0),
-  myEnd (0)
-{
   mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
-
-  if (myPolyg.Size() != 1)
-    computeCenter3D();
-  else
-    myCenter3D = myPolyg.Pnt (0);
-
-  if (mySensType == Select3D_TOS_BOUNDARY)
-  {
-    SetSensitivityFactor (6);
-  }
-}
-
-//=======================================================================
-//function : Select3D_SensitiveCircle
-//purpose  :
-//=======================================================================
-
-Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                                   const TColgp_Array1OfPnt& thePnts3d,
-                                                   const Standard_Boolean theIsFilled)
-: Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled),
-  myStart (0),
-  myEnd (0)
-{
-  mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
-
-  if (myPolyg.Size() != 1)
-    computeCenter3D();
-  else
-    myCenter3D = myPolyg.Pnt (0);
-
   if (mySensType == Select3D_TOS_BOUNDARY)
   {
     SetSensitivityFactor (6);
   }
 }
 
-//=======================================================================
-// function : BVH
-// purpose  : Builds BVH tree for a circle's edge segments if needed
-//=======================================================================
-void Select3D_SensitiveCircle::BVH()
-{
-  if (mySensType == Select3D_TOS_BOUNDARY)
-  {
-    Select3D_SensitivePoly::BVH();
-  }
-}
-
-//=======================================================================
-// function : ToBuildBVH
-// purpose  : 
-//=======================================================================
-Standard_Boolean Select3D_SensitiveCircle::ToBuildBVH() const
-{
-  if (mySensType != Select3D_TOS_BOUNDARY)
-  {
-    return Standard_False;
-  }
-
-  return Select3D_SensitivePoly::ToBuildBVH();
-}
-
 //=======================================================================
 // function : Matches
 // purpose  : Checks whether the circle overlaps current selecting volume
@@ -212,41 +46,27 @@ Standard_Boolean Select3D_SensitiveCircle::ToBuildBVH() const
 Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                     SelectBasics_PickResult& thePickResult)
 {
-  if (mySensType == Select3D_TOS_BOUNDARY)
-  {
-    if (!Select3D_SensitivePoly::Matches (theMgr, thePickResult))
-    {
-      return Standard_False;
-    }
-  }
-  else if (mySensType == Select3D_TOS_INTERIOR)
+  const Standard_Boolean aIsFilled = mySensType == Select3D_TOS_INTERIOR;
+
+  if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
   {
-    Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
-    Points3D (anArrayOfPnt);
     if (!theMgr.IsOverlapAllowed())
     {
-      if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
-      {
-        SelectBasics_PickResult aDummy;
-        return theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), mySensType, aDummy);
-      }
-      for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
-      {
-        if (!theMgr.OverlapsPoint (anArrayOfPnt->Value(aPntIdx)))
-        {
-          return Standard_False;
-        }
-      }
-      return Standard_True;
+      bool isInside = true;
+      return theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, &isInside) && isInside;
     }
-
-    if (!theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), Select3D_TOS_INTERIOR, thePickResult))
+    else
     {
-      return Standard_False;
+      return theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, NULL);
     }
-    thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
+  }
+  if (!theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, thePickResult))
+  {
+    return false;
   }
 
+  thePickResult.SetDistToGeomCenter (theMgr.DistToGeometryCenter (CenterOfGeometry()));
+
   return Standard_True;
 }
 
@@ -254,81 +74,36 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
 //function : GetConnected
 //purpose  :
 //=======================================================================
-
 Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected()
 {
-  Standard_Boolean isFilled = mySensType == Select3D_TOS_INTERIOR;
-  // Create a copy of this
-  Handle(Select3D_SensitiveEntity) aNewEntity;
-  // this was constructed using Handle(Geom_Circle)
-  if (!Precision::IsInfinite (myCircle.Radius()))
-  {
-    if ((myEnd - myStart) > Precision::Confusion())
-    {
-      // Arc
-      aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, myStart, myEnd, isFilled);
-    }
-    else
-    {
-      // Circle
-      aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, isFilled);
-    }
-  }
-  // this was constructed using TColgp_Array1OfPnt
-  else
-  {
-    Standard_Integer aSize = myPolyg.Size();
-    TColgp_Array1OfPnt aPolyg (1, aSize);
-    for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
-    {
-      aPolyg.SetValue(anIndex, myPolyg.Pnt (anIndex-1));
-    }
-    aNewEntity = new Select3D_SensitiveCircle (myOwnerId, aPolyg, isFilled);
-  }
-
+  Standard_Boolean anIsFilled = mySensType == Select3D_TOS_INTERIOR;
+  Handle(Select3D_SensitiveEntity) aNewEntity = new Select3D_SensitiveCircle (myOwnerId,
+                                                                              Circle(),
+                                                                              anIsFilled);
   return aNewEntity;
 }
 
-//=======================================================================
-//function : computeCenter3D
-//purpose  :
-//=======================================================================
-void Select3D_SensitiveCircle::computeCenter3D()
+//==================================================
+// Function: BoundingBox
+// Purpose :
+//==================================================
+Select3D_BndBox3d Select3D_SensitiveCircle::BoundingBox()
 {
-  gp_XYZ aCenter;
-  Standard_Integer aNbPnts = myPolyg.Size();
-  if (aNbPnts != 1)
-  {
-    // The mass of points system
-    Standard_Integer aMass = aNbPnts - 1;
-    // Find the circle barycenter
-    for (Standard_Integer anIndex = 0; anIndex < aNbPnts - 1; ++anIndex)
-    {
-      aCenter += myPolyg.Pnt(anIndex);
-    }
-    myCenter3D = aCenter / aMass;
-  }
-  else
-  {
-    myCenter3D = myPolyg.Pnt(0);
-  }
-}
+  Graphic3d_Mat4d aTrsf;
+  myTrsf.GetMat4 (aTrsf);
 
-//=======================================================================
-// function : CenterOfGeometry
-// purpose  : Returns center of the circle. If location transformation
-//            is set, it will be applied
-//=======================================================================
-gp_Pnt Select3D_SensitiveCircle::CenterOfGeometry() const
-{
-  return myCenter3D;
+  Select3D_BndBox3d aBox (SelectMgr_Vec3 (-myRadius, -myRadius, 0),
+                          SelectMgr_Vec3 (myRadius, myRadius, 0));
+  aBox.Transform (aTrsf);
+
+  return aBox;
 }
 
-//=======================================================================
-// function : distanceToCOG
-// purpose  :
-//=======================================================================
-Standard_Real Select3D_SensitiveCircle::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
+//==================================================
+// Function: CenterOfGeometry
+// Purpose :
+//==================================================
+gp_Pnt Select3D_SensitiveCircle::CenterOfGeometry() const
 {
-  return theMgr.DistToGeometryCenter (myCenter3D);
+  return gp_Pnt (myTrsf.TranslationPart());
 }
index 075c2658cff9c8693288b83d89eeb6856a27a655..ce0e103d4a0a8a237173a388798e1cc1515f82f6 100644 (file)
 #ifndef _Select3D_SensitiveCircle_HeaderFile
 #define _Select3D_SensitiveCircle_HeaderFile
 
+#include <Select3D_SensitiveEntity.hxx>
+
 #include <gp_Circ.hxx>
-#include <Select3D_SensitivePoly.hxx>
-#include <Select3D_TypeOfSensitivity.hxx>
-#include <SelectMgr_SelectingVolumeManager.hxx>
-#include <TColgp_HArray1OfPnt.hxx>
-
-//! A framework to define sensitive 3D arcs and circles.
-//! In some cases this class can raise Standard_ConstructionError and
-//! Standard_OutOfRange exceptions. For more details see Select3D_SensitivePoly.
-class Select3D_SensitiveCircle : public Select3D_SensitivePoly
+
+//! A framework to define sensitive 3D circles.
+class Select3D_SensitiveCircle : public Select3D_SensitiveEntity
 {
-  DEFINE_STANDARD_RTTIEXT(Select3D_SensitiveCircle, Select3D_SensitivePoly)
+  DEFINE_STANDARD_RTTIEXT(Select3D_SensitiveCircle, Select3D_SensitiveEntity)
 public:
 
   //! Constructs the sensitive circle object defined by the
-  //! owner theOwnerId, the circle theCircle, the boolean
-  //! theIsFilled and the number of points theNbPnts.
+  //! owner theOwnerId, the circle theCircle and the boolean theIsFilled.
   Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
                                             const gp_Circ& theCircle,
-                                            const Standard_Boolean theIsFilled = Standard_False,
-                                            const Standard_Integer theNbPnts = 12);
-
-  //! Constructs the sensitive arc object defined by the
-  //! owner theOwnerId, the circle theCircle, the parameters theU1
-  //! and theU2, the boolean theIsFilled and the number of points theNbPnts.
-  //! theU1 and theU2 define the first and last points of the arc on theCircle.
-  Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                            const gp_Circ& theCircle,
-                                            const Standard_Real theU1,
-                                            const Standard_Real theU2,
-                                            const Standard_Boolean theIsFilled = Standard_False,
-                                            const Standard_Integer theNbPnts = 12);
-
-  //! Constructs the sensitive circle object defined by the
-  //! owner theOwnerId, the array of triangles thePnts3d, and the boolean theIsFilled.
-  //! thePnts3d is an array of consecutive triangles on the
-  //! circle. The triangle i+1 lies on the intersection of the
-  //! tangents to the circle of i and i+2. Note, that the first point of thePnts3d
-  //! must be equal to the last point of thePnts3d.
-  Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                            const Handle(TColgp_HArray1OfPnt)& thePnts3d,
                                             const Standard_Boolean theIsFilled = Standard_False);
 
   //! Constructs the sensitive circle object defined by the
-  //! owner theOwnerId, the array of points thePnts3d, and the boolean theIsFilled.
-  //! If the length of thePnts3d is more then 1, the first point of thePnts3d
-  //! must be equal to the last point of thePnts3d.
-  Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
-                                            const TColgp_Array1OfPnt& thePnts3d,
-                                            const Standard_Boolean theIsFilled = Standard_False);
+  //! owner theOwnerId, the circle theCircle, the boolean
+  //! theIsFilled and the number of points theNbPnts.
+  Standard_DEPRECATED("Deprecated constructor, theNbPnts parameter will be ignored")
+  Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
+                            const gp_Circ& theCircle,
+                            const Standard_Boolean theIsFilled,
+                            const Standard_Integer /*theNbPnts*/)
+  : Select3D_SensitiveCircle (theOwnerId, theCircle, theIsFilled)
+  { }
 
   //! Checks whether the circle overlaps current selecting volume
   Standard_EXPORT  virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                      SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
 
+  //! Returns a copy of this sensitive circle
   Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE;
 
-  //! Returns center of the circle. If location
-  //! transformation is set, it will be applied
-  Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE;
+  //! Returns bounding box of the circle.
+  //! If location transformation is set, it will be applied
+  Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
 
-  //! Builds BVH tree for a circle's edge segments if needed
-  Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+  //! Always returns Standard_False
+  virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
 
-  //! Returns TRUE if BVH tree is in invalidated state
-  Standard_EXPORT virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE;
+  //! Returns the amount of points
+  virtual Standard_Integer NbSubElements() const Standard_OVERRIDE { return 1; }
 
-protected:
+  //! Returns center of the circle with transformation applied
+  Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE;
 
-  //! Calculates distance from the 3d projection of used-picked screen point
-  //! to center of the geometry
-  Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
+  //! The transformation for gp::XOY() with center in gp::Origin(),
+  //! it specifies the position and orientation of the circle.
+  const gp_Trsf& Transformation() const { return myTrsf; }
 
-private:
+  //! Returns circle
+  gp_Circ Circle() const { return gp_Circ (gp::XOY().Transformed (myTrsf), myRadius); }
 
-  //! Computes myCenter3D as the barycenter of points from mypolyg3d
-  void computeCenter3D();
+  //! Returns circle radius
+  Standard_Real Radius() const { return myRadius; }
 
 private:
 
-  Select3D_TypeOfSensitivity mySensType; //!< True if type of selection is interior, false otherwise
-  gp_Pnt                     myCenter3D; //!< Center of a circle
-  gp_Circ                    myCircle;   //!< Points of the circle
-  Standard_Real              myStart;    //!< Sensitive arc parameter
-  Standard_Real              myEnd;      //!< Sensitive arc parameter
+  Select3D_TypeOfSensitivity mySensType; //!< Type of sensitivity: boundary or interior
+  gp_Trsf                    myTrsf;     //!< Circle transformation to apply
+  Standard_Real              myRadius;   //!< Circle radius
 };
 
-DEFINE_STANDARD_HANDLE(Select3D_SensitiveCircle, Select3D_SensitivePoly)
+DEFINE_STANDARD_HANDLE(Select3D_SensitiveCircle, Select3D_SensitiveEntity)
 
 #endif // _Select3D_SensitiveCircle_HeaderFile
index 6c2ebf181e72bd6c04e30ad8bc8aedb583a3e3ab..288795d0cb121f12e4e223b7ad5cad6adad3eefd 100644 (file)
@@ -25,12 +25,14 @@ Select3D_SensitiveCylinder::Select3D_SensitiveCylinder (const Handle(SelectMgr_E
                                                         const Standard_Real theBottomRad,
                                                         const Standard_Real theTopRad,
                                                         const Standard_Real    theHeight,
-                                                        const gp_Trsf& theTrsf)
+                                                        const gp_Trsf& theTrsf,
+                                                        const Standard_Boolean theIsHollow)
 : Select3D_SensitiveEntity (theOwnerId),
   myTrsf (theTrsf),
   myBottomRadius (theBottomRad),
   myTopRadius (theTopRad),
-  myHeight (theHeight)
+  myHeight (theHeight),
+  myIsHollow (theIsHollow)
 {
 }
 
@@ -46,14 +48,14 @@ Standard_Boolean Select3D_SensitiveCylinder::Matches (SelectBasics_SelectingVolu
     if (!theMgr.IsOverlapAllowed())
     {
       bool isInside = true;
-      return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, &isInside) && isInside;
+      return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, &isInside) && isInside;
     }
     else
     {
-      return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, NULL);
+      return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, NULL);
     }
   }
-  if (!theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, thePickResult))
+  if (!theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, thePickResult))
   {
     return false;
   }
index 7a963e224aee1e51b6b32104ffbcfb5115fcf63b..30f789197cb29684067727ad3cec95d0480b3a6a 100644 (file)
@@ -32,7 +32,8 @@ public:
                                               const Standard_Real theBottomRad,
                                               const Standard_Real theTopRad,
                                               const Standard_Real theHeight,
-                                              const gp_Trsf& theTrsf);
+                                              const gp_Trsf& theTrsf,
+                                              const Standard_Boolean theIsHollow = Standard_False);
 
   //! Checks whether the cylinder overlaps current selecting volume
   Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
@@ -66,11 +67,15 @@ public:
   //! Returns cylinder height
   Standard_Real Height() const { return myHeight; }
 
+  //! Returns true if the cylinder is empty inside
+  Standard_Boolean IsHollow() const { return myIsHollow; }
+
 protected:
-  gp_Trsf       myTrsf;         //!< cylinder transformation to apply
-  Standard_Real myBottomRadius; //!< cylinder bottom radius
-  Standard_Real myTopRadius;    //!< cylinder top radius
-  Standard_Real myHeight;       //!< cylinder height
+  gp_Trsf          myTrsf;         //!< cylinder transformation to apply
+  Standard_Real    myBottomRadius; //!< cylinder bottom radius
+  Standard_Real    myTopRadius;    //!< cylinder top radius
+  Standard_Real    myHeight;       //!< cylinder height
+  Standard_Boolean myIsHollow;     //!< true if the cylinder is empty inside
 };
 
 #endif // _Select3D_SensitiveSphere_HeaderFile
index 33e733b1eabe23ec441eea6264782a7bc002e1d8..162af349ff8e6b32453cd10b95be0f8e0f7e0b74 100644 (file)
 
 #include <Select3D_SensitivePoly.hxx>
 
+#include <ElCLib.hxx>
+
 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePoly,Select3D_SensitiveSet)
 
+namespace
+{
+  static Standard_Integer GetCircleNbPoints (const gp_Circ& theCircle,
+                                             const Standard_Integer theNbPnts,
+                                             const Standard_Real theU1,
+                                             const Standard_Real theU2,
+                                             const Standard_Boolean theIsFilled)
+  {
+    // Check if number of points is invalid.
+    // In this case myPolyg raises Standard_ConstructionError
+    // exception (see constructor below).
+    if (theNbPnts <= 0)
+    {
+      return 0;
+    }
+
+    if (theCircle.Radius() > Precision::Confusion())
+    {
+      const Standard_Boolean isSector = theIsFilled && Abs (Abs (theU2 - theU1) - 2.0 * M_PI) > gp::Resolution();
+      return 2 * theNbPnts + 1 + (isSector ? 2 : 0);
+    }
+
+    // The radius is too small and circle degenerates into point
+    return 1;
+  }
+
+  //! Definition of circle polyline
+  static void initCircle (Select3D_PointData& thePolygon,
+                          const gp_Circ&      theCircle,
+                          const Standard_Real theU1,
+                          const Standard_Real theU2,
+                          const Standard_Boolean theIsFilled,
+                          const Standard_Integer theNbPnts)
+  {
+    const Standard_Real aStep = (theU2 - theU1) / theNbPnts;
+    const Standard_Real aRadius = theCircle.Radius();
+    Standard_Integer aPntIdx = 0;
+    Standard_Real aCurU = theU1;
+    gp_Pnt aP1;
+    gp_Vec aV1;
+
+    const Standard_Boolean isSector = Abs (theU2 - theU1 - 2.0 * M_PI) > gp::Resolution();
+
+    if (isSector && theIsFilled) { thePolygon.SetPnt (aPntIdx++, theCircle.Location()); }
+
+    for (Standard_Integer anIndex = 1; anIndex <= theNbPnts; ++anIndex, aCurU += aStep)
+    {
+      ElCLib::CircleD1 (aCurU, theCircle.Position(), theCircle.Radius(), aP1, aV1);
+      thePolygon.SetPnt (aPntIdx++, aP1);
+
+      aV1.Normalize();
+      const gp_Pnt aP2 = aP1.XYZ() + aV1.XYZ() * Tan (aStep * 0.5) * aRadius;
+      thePolygon.SetPnt (aPntIdx++, aP2);
+    }
+    aP1 = ElCLib::CircleValue (theU2, theCircle.Position(), theCircle.Radius());
+    thePolygon.SetPnt (aPntIdx++, aP1);
+
+    if (isSector && theIsFilled) { thePolygon.SetPnt (aPntIdx++, theCircle.Location()); }
+  }
+}
+
 //==================================================
 // Function: Select3D_SensitivePoly
 // Purpose :
@@ -23,7 +86,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
                                                 const TColgp_Array1OfPnt& thePoints,
                                                 const Standard_Boolean theIsBVHEnabled)
 : Select3D_SensitiveSet (theOwnerId),
-  myPolyg (thePoints.Upper() - thePoints.Lower() + 1)
+  myPolyg (thePoints.Upper() - thePoints.Lower() + 1),
+  mySensType (Select3D_TOS_BOUNDARY)
 {
   Standard_Integer aLowerIdx = thePoints.Lower();
   Standard_Integer anUpperIdx = thePoints.Upper();
@@ -64,7 +128,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
                                                 const Handle(TColgp_HArray1OfPnt)& thePoints,
                                                 const Standard_Boolean theIsBVHEnabled)
 : Select3D_SensitiveSet (theOwnerId),
-  myPolyg (thePoints->Upper() - thePoints->Lower() + 1)
+  myPolyg (thePoints->Upper() - thePoints->Lower() + 1),
+  mySensType (Select3D_TOS_BOUNDARY)
 {
   Standard_Integer aLowerIdx = thePoints->Lower();
   Standard_Integer anUpperIdx = thePoints->Upper();
@@ -105,7 +170,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
                                                 const Standard_Boolean theIsBVHEnabled,
                                                 const Standard_Integer theNbPnts)
 : Select3D_SensitiveSet (theOwnerId),
-  myPolyg (theNbPnts)
+  myPolyg (theNbPnts),
+  mySensType (Select3D_TOS_BOUNDARY)
 {
   if (theIsBVHEnabled)
   {
@@ -119,6 +185,80 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
   myIsComputed = Standard_False;
 }
 
+//==================================================
+// Function: Creation
+// Purpose :
+//==================================================
+Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
+                                                const gp_Circ& theCircle,
+                                                const Standard_Real theU1,
+                                                const Standard_Real theU2,
+                                                const Standard_Boolean theIsFilled,
+                                                const Standard_Integer theNbPnts)
+: Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts, theU1, theU2, theIsFilled))
+{
+  mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
+
+  if (myPolyg.Size() != 1)
+  {
+    initCircle (myPolyg, theCircle, Min (theU1, theU2), Max (theU1, theU2), theIsFilled, theNbPnts);
+  }
+  else
+  {
+    myPolyg.SetPnt (0, theCircle.Position().Location());
+  }
+
+  if (!theIsFilled)
+  {
+    SetSensitivityFactor (6);
+  }
+}
+
+//=======================================================================
+// function : Matches
+// purpose  :
+//=======================================================================
+Standard_Boolean Select3D_SensitivePoly::Matches (SelectBasics_SelectingVolumeManager& theMgr,
+                                                  SelectBasics_PickResult& thePickResult)
+{
+  if (mySensType == Select3D_TOS_BOUNDARY)
+  {
+    if (!Select3D_SensitiveSet::Matches (theMgr, thePickResult))
+    {
+      return Standard_False;
+    }
+  }
+  else if (mySensType == Select3D_TOS_INTERIOR)
+  {
+    Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
+    Points3D (anArrayOfPnt);
+    if (!theMgr.IsOverlapAllowed())
+    {
+      if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
+      {
+        SelectBasics_PickResult aDummy;
+        return theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), mySensType, aDummy);
+      }
+      for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
+      {
+        if (!theMgr.OverlapsPoint (anArrayOfPnt->Value(aPntIdx)))
+        {
+          return Standard_False;
+        }
+      }
+      return Standard_True;
+    }
+
+    if (!theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), Select3D_TOS_INTERIOR, thePickResult))
+    {
+      return Standard_False;
+    }
+    thePickResult.SetDistToGeomCenter (distanceToCOG(theMgr));
+  }
+
+  return Standard_True;
+}
+
 //==================================================
 // function : BoundingBox
 // purpose  : Returns bounding box of a polygon. If location
index fa96f412bd8e21b32b9a0e0b508e2c4b8eb38f29..77ead4bc7d50942ed96e269768266786bc8b1984 100644 (file)
 #ifndef _Select3D_SensitivePoly_HeaderFile
 #define _Select3D_SensitivePoly_HeaderFile
 
+#include <gp_Circ.hxx>
 #include <Select3D_PointData.hxx>
 #include <Select3D_SensitiveSet.hxx>
 #include <Select3D_TypeOfSensitivity.hxx>
 #include <TColStd_HArray1OfInteger.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
 
-
 //! Sensitive Entity to make a face selectable.
 //! In some cases this class can raise Standard_ConstructionError and
 //! Standard_OutOfRange exceptions from its member Select3D_PointData
@@ -46,13 +46,28 @@ public:
                                           const Handle(TColgp_HArray1OfPnt)& thePoints,
                                           const Standard_Boolean theIsBVHEnabled);
 
-  //! Constructs the sensitive circle object defined by the
-  //! owner OwnerId, the circle Circle, the Boolean
-  //! FilledCircle and the number of points NbOfPoints.
+  //! Constructs the sensitive arc object defined by the
+  //! owner theOwnerId, the circle theCircle, the parameters theU1
+  //! and theU2, the boolean theIsFilled and the number of points theNbPnts.
+  //! theU1 and theU2 define the first and last points of the arc on theCircle.
+  Standard_EXPORT Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
+                                          const gp_Circ& theCircle,
+                                          const Standard_Real theU1,
+                                          const Standard_Real theU2,
+                                          const Standard_Boolean theIsFilled = Standard_False,
+                                          const Standard_Integer theNbPnts = 12);
+
+  //! Constructs a sensitive curve or arc object defined by the
+  //! owner theOwnerId, the theIsBVHEnabled flag, and the
+  //! maximum number of points on the curve: theNbPnts.
   Standard_EXPORT Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
                                           const Standard_Boolean theIsBVHEnabled,
                                           const Standard_Integer theNbPnts = 6);
 
+  //! Checks whether the poly overlaps current selecting volume
+  Standard_EXPORT  virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
+                                                     SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
+
   //! Returns the amount of segments in poly
   Standard_EXPORT virtual Standard_Integer NbSubElements() const Standard_OVERRIDE;
 
@@ -128,11 +143,12 @@ protected:
 
 protected:
 
-  Select3D_PointData              myPolyg;              //!< Points of the poly
-  mutable gp_Pnt                  myCOG;                //!< Center of the poly
-  Handle(TColStd_HArray1OfInteger) mySegmentIndexes;     //!< Segment indexes for BVH tree build
-  Select3D_BndBox3d               myBndBox;             //!< Bounding box of the poly
-  mutable Standard_Boolean        myIsComputed;         //!< Is true if all the points and data structures of polygon are initialized
+  Select3D_PointData               myPolyg;          //!< Points of the poly
+  mutable gp_Pnt                   myCOG;            //!< Center of the poly
+  Handle(TColStd_HArray1OfInteger) mySegmentIndexes; //!< Segment indexes for BVH tree build
+  Select3D_BndBox3d                myBndBox;         //!< Bounding box of the poly
+  Select3D_TypeOfSensitivity       mySensType;       //!< Type of sensitivity: boundary or interior
+  mutable Standard_Boolean         myIsComputed;     //!< Is true if all the points and data structures of polygon are initialized
 };
 
 DEFINE_STANDARD_HANDLE(Select3D_SensitivePoly, Select3D_SensitiveSet)
index 5fa66b04f4ae81946e2ccd90a32643e4da8f83cb..88009fca9a056b2ddde1597a5be0d4ae64d60913 100644 (file)
@@ -96,21 +96,41 @@ public:
                                            Standard_Boolean* theInside = NULL) const = 0;
 
   //! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
-  //! and theTopRad, height theHeight and transformation to apply theTrsf.
+  //! and theTopRad, height theHeight, the boolean theIsHollow and transformation to apply theTrsf.
   virtual Standard_Boolean OverlapsCylinder (const Standard_Real theBottomRad,
                                              const Standard_Real theTopRad,
                                              const Standard_Real theHeight,
                                              const gp_Trsf& theTrsf,
+                                             const Standard_Boolean theIsHollow,
                                              SelectBasics_PickResult& thePickResult) const = 0;
 
   //! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
-  //! and theTopRad, height theHeight and transformation to apply theTrsf.
+  //! and theTopRad, height theHeight, the boolean theIsHollow and transformation to apply theTrsf.
   virtual Standard_Boolean OverlapsCylinder (const Standard_Real theBottomRad,
                                              const Standard_Real theTopRad,
                                              const Standard_Real theHeight,
                                              const gp_Trsf& theTrsf,
+                                             const Standard_Boolean theIsHollow,
                                              Standard_Boolean* theInside = NULL) const = 0;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! the boolean theIsFilled, and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                           const gp_Trsf& theTrsf,
+                                           const Standard_Boolean theIsFilled,
+                                           SelectBasics_PickResult& thePickResult) const = 0;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! the boolean theIsFilled, and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                           const gp_Trsf& theTrsf,
+                                           const Standard_Boolean theIsFilled,
+                                           Standard_Boolean* theInside = NULL) const = 0;
+
 public:
 
   //! Calculates distance from 3d projection of user-defined selection point
index b0999fae331353c2a61c90c77a2d677815362e9b..1f647b3d282ba1b4d59cb5005b57bc59bc073e0f 100644 (file)
@@ -23,6 +23,7 @@
 #include <TColgp_HArray1OfPnt.hxx>
 #include <TColgp_SequenceOfPnt.hxx>
 #include <Select3D_SensitiveBox.hxx>
+#include <Select3D_SensitiveCircle.hxx>
 #include <Select3D_SensitiveCylinder.hxx>
 #include <Select3D_SensitiveEntity.hxx>
 #include <Select3D_SensitiveFace.hxx>
@@ -133,41 +134,56 @@ namespace
     }
   }
 
+  //! Fill in circle polylines.
+  static void addCircle (Prs3d_NListOfSequenceOfPnt& theSeqLines,
+                         const Standard_Real theRadius,
+                         const gp_Trsf& theTrsf,
+                         const Standard_Real theHeight = 0)
+  {
+    const Standard_Real anUStep = 0.1;
+    gp_XYZ aVec (0, 0, theHeight);
+
+    Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
+    Geom_Circle aGeom (gp_Ax2(), theRadius);
+    for (Standard_Real anU = 0.0f; anU < (2.0 * M_PI + anUStep); anU += anUStep)
+    {
+      gp_Pnt aCircPnt = aGeom.Value (anU).Coord() + aVec;
+      aCircPnt.Transform (theTrsf);
+      aPoints->Append (aCircPnt);
+    }
+    theSeqLines.Append (aPoints);
+  }
+
   //! Fill in cylinder polylines.
   static void addCylinder (Prs3d_NListOfSequenceOfPnt& theSeqLines,
-                           const Handle(Select3D_SensitiveCylinder)& theSensCyl)
+                           const Handle(Select3D_SensitiveCylinder)& theSensCyl,
+                           const gp_Trsf& theLoc)
   {
-    Handle(TColgp_HSequenceOfPnt) aVertLines[2];
-    aVertLines[0] = new TColgp_HSequenceOfPnt();
-    aVertLines[1] = new TColgp_HSequenceOfPnt();
-    const gp_Trsf& aTrsf = theSensCyl->Transformation();
+    Handle(TColgp_HSequenceOfPnt) aVertLine1 = new TColgp_HSequenceOfPnt();
+    Handle(TColgp_HSequenceOfPnt) aVertLine2 = new TColgp_HSequenceOfPnt();
+
+    const gp_Trsf& aTrsf = theLoc.Multiplied (theSensCyl->Transformation());
     const Standard_Real aHeight = theSensCyl->Height();
-    const Standard_Real anUStep = 0.1;
 
     for (int aCircNum = 0; aCircNum < 3; aCircNum++)
     {
       Standard_Real aRadius = 0.5 * (2 - aCircNum) * theSensCyl->BottomRadius()
                             + 0.5 * aCircNum * theSensCyl->TopRadius();
-      Geom_Circle aGeom (gp_Ax2(), aRadius);
-      Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
-      gp_XYZ aVec (0, 0, aHeight * 0.5 * aCircNum);
+      const gp_XYZ aVec (0, 0, aHeight * 0.5 * aCircNum);
 
       if (aCircNum != 1)
       {
-        aVertLines[0]->Append (gp_Pnt(aGeom.Value (0).Coord() + aVec).Transformed (aTrsf));
-        aVertLines[1]->Append (gp_Pnt(aGeom.Value (M_PI).Coord() + aVec).Transformed (aTrsf));
+        aVertLine1->Append (gp_Pnt (gp_XYZ (aRadius, 0, 0) + aVec).Transformed (aTrsf));
+        aVertLine2->Append (gp_Pnt (gp_XYZ (-aRadius, 0, 0) + aVec).Transformed (aTrsf));
       }
 
-      for (Standard_Real anU = 0.0f; anU < (2.0 * M_PI + anUStep); anU += anUStep)
+      if (aRadius > Precision::Confusion())
       {
-        gp_Pnt aCircPnt = aGeom.Value (anU).Coord() + aVec;
-        aCircPnt.Transform (aTrsf);
-        aPoints->Append (aCircPnt);
+        addCircle (theSeqLines, aRadius, aTrsf, aVec.Z());
       }
-      theSeqLines.Append (aPoints);
     }
-    theSeqLines.Append (aVertLines[0]);
-    theSeqLines.Append (aVertLines[1]);
+    theSeqLines.Append (aVertLine1);
+    theSeqLines.Append (aVertLine2);
   }
 }
 
@@ -193,7 +209,11 @@ void SelectMgr::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& thePrs,
     }
     else if (Handle(Select3D_SensitiveCylinder) aSensCyl = Handle(Select3D_SensitiveCylinder)::DownCast (anEnt))
     {
-      addCylinder (aSeqLines, aSensCyl);
+      addCylinder (aSeqLines, aSensCyl, theLoc);
+    }
+    else if (Handle(Select3D_SensitiveCircle) aSensCircle = Handle(Select3D_SensitiveCircle)::DownCast (anEnt))
+    {
+      addCircle (aSeqLines, aSensCircle->Radius(), theLoc.Multiplied (aSensCircle->Transformation()));
     }
     else if (Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(anEnt))
     {
index c4cbf1fa740be037ea76bab7466dc985ca241908..44ff25b75231d91eae4e53f376a90ee3f74acbdb 100644 (file)
@@ -227,7 +227,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
                                                          Standard_Boolean*     theInside) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
 
   (void )theInside;
   Standard_Real aTimeEnter, aTimeLeave;
@@ -252,7 +252,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
                                                          SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
 
   Standard_Real aTimeEnter, aTimeLeave;
   if (!hasIntersection (theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
@@ -283,7 +283,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
                                                            SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
 
   Standard_Real aDepth = 0.0;
   if (!hasIntersection (thePnt, aDepth))
@@ -304,7 +304,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
 Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
 
   Standard_Real aDepth = 0.0;
   return hasIntersection (thePnt, aDepth);
@@ -320,7 +320,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSegment (const gp_Pnt& thePn
                                                              SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsSegment() should be called after selection axis initialization");
 
   if (!raySegmentDistance (thePnt1, thePnt2, thePickResult))
   {
@@ -340,7 +340,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPolygon (const TColgp_Array1
                                                              SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsPolygon() should be called after selection axis initialization");
 
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
@@ -400,7 +400,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
                                                               SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsTriangle() should be called after selection axis initialization");
 
   if (theSensType == Select3D_TOS_BOUNDARY)
   {
@@ -503,7 +503,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
                                                             Standard_Boolean* theInside) const
 {
   Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
   (void )theInside;
   Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
   if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
@@ -527,7 +527,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
                                                             SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
   Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
   if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
   {
@@ -558,22 +558,24 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
                                                               const Standard_Real theTopRad,
                                                               const Standard_Real theHeight,
                                                               const gp_Trsf& theTrsf,
+                                                              const Standard_Boolean theIsHollow,
                                                               const SelectMgr_ViewClipRange& theClipRange,
                                                               SelectBasics_PickResult& thePickResult) const
 {
   Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
   Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
   gp_Trsf aTrsfInv = theTrsf.Inverted();
   gp_Pnt  aLoc     = myAxis.Location() .Transformed (aTrsfInv);
   gp_Dir  aRayDir  = myAxis.Direction().Transformed (aTrsfInv);
-  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
+  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
+                                theIsHollow, aTimeEnter, aTimeLeave))
   {
     return false;
   }
 
   Standard_Real aDepth = 0.0;
-  Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
+  Bnd_Range aRange (Max (aTimeEnter, 0.0), Max (aTimeEnter, aTimeLeave));
   aRange.GetMin (aDepth);
   if (!theClipRange.GetNearestDepth (aRange, aDepth))
   {
@@ -606,15 +608,17 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
                                                               const Standard_Real theTopRad,
                                                               const Standard_Real theHeight,
                                                               const gp_Trsf& theTrsf,
-                                                              Standard_Boolean* theInside)  const
+                                                              const Standard_Boolean theIsHollow,
+                                                              Standard_Boolean* theInside) const
 {
   Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
-    "Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
+    "Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
   Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
   gp_Trsf aTrsfInv = theTrsf.Inverted();
   gp_Pnt  aLoc     = myAxis.Location() .Transformed (aTrsfInv);
   gp_Dir  aRayDir  = myAxis.Direction().Transformed (aTrsfInv);
-  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
+  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
+                                theIsHollow, aTimeEnter, aTimeLeave))
   {
     return false;
   }
@@ -625,6 +629,74 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
   return true;
 }
 
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
+                                                            const gp_Trsf& theTrsf,
+                                                            const Standard_Boolean theIsFilled,
+                                                            const SelectMgr_ViewClipRange& theClipRange,
+                                                            SelectBasics_PickResult& thePickResult) const
+{
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
+    "Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
+  Standard_Real aTime = 0.0;
+  gp_Trsf aTrsfInv = theTrsf.Inverted();
+  gp_Pnt  aLoc = myAxis.Location().Transformed (aTrsfInv);
+  gp_Dir  aRayDir = myAxis.Direction().Transformed (aTrsfInv);
+  if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
+  {
+    return false;
+  }
+
+  Standard_Real aDepth = Max (aTime, 0.0);
+  if (theClipRange.IsClipped (aDepth))
+  {
+    return false;
+  }
+
+  const gp_Pnt aPntOnCylinder = aLoc.XYZ() + aRayDir.XYZ() * aDepth;
+  thePickResult.SetDepth (aDepth);
+  thePickResult.SetPickedPoint (aPntOnCylinder.Transformed (theTrsf));
+  if (Abs (aPntOnCylinder.Z()) < Precision::Confusion())
+  {
+    thePickResult.SetSurfaceNormal (-gp::DZ().Transformed (theTrsf));
+  }
+  else
+  {
+    thePickResult.SetSurfaceNormal (gp_Vec (aPntOnCylinder.X(), aPntOnCylinder.Y(), 0.0).Transformed (theTrsf));
+  }
+
+  return true;
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
+                                                            const gp_Trsf& theTrsf,
+                                                            const Standard_Boolean theIsFilled,
+                                                            Standard_Boolean* theInside) const
+{
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
+    "Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
+  Standard_Real aTime = 0.0;
+  gp_Trsf aTrsfInv = theTrsf.Inverted();
+  gp_Pnt  aLoc = myAxis.Location().Transformed (aTrsfInv);
+  gp_Dir  aRayDir = myAxis.Direction().Transformed (aTrsfInv);
+  if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
+  {
+    return false;
+  }
+  if (theInside != NULL)
+  {
+    *theInside &= (aTime >= 0.0);
+  }
+  return true;
+}
+
 //=======================================================================
 // function : GetNearPnt
 // purpose  :
index 543c4e61757050453adb80b73617892cc902d444..6a6b60bc09c8b94d45bd2cef8287dc589e562871 100644 (file)
@@ -117,6 +117,7 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              const SelectMgr_ViewClipRange& theClipRange,
                                                              SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
@@ -126,8 +127,28 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           const SelectMgr_ViewClipRange& theClipRange,
+                                                           SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
+
 public:
 
   //! Measures distance between start axis point and given point theCOG.
index 2ce3de812377288e8fde51864e6c3535e56d186e..bc3d93e45e84d51c19e29926decc7e71dabcbc17 100644 (file)
@@ -176,15 +176,15 @@ Standard_Boolean SelectMgr_BaseIntersector::RayCylinderIntersection (const Stand
                                                                      const Standard_Real theHeight,
                                                                      const gp_Pnt& theLoc,
                                                                      const gp_Dir& theRayDir,
+                                                                     const Standard_Boolean theIsHollow,
                                                                      Standard_Real& theTimeEnter,
                                                                      Standard_Real& theTimeLeave) const
 {
   Standard_Integer aNbIntersections = 0;
   Standard_Real anIntersections[4] = { RealLast(), RealLast(), RealLast(), RealLast() };
-  //NCollection_Vector<Standard_Real> anIntersections; // vector for all intersections
   // Check intersections with end faces
   // point of intersection theRayDir and z = 0
-  if (theRayDir.Z() != 0)
+  if (!theIsHollow && theRayDir.Z() != 0)
   {
     const Standard_Real aTime1 = (0 - theLoc.Z()) / theRayDir.Z();
     const Standard_Real aX1 = theLoc.X() + theRayDir.X() * aTime1;
@@ -293,6 +293,33 @@ Standard_Boolean SelectMgr_BaseIntersector::RayCylinderIntersection (const Stand
   return true;
 }
 
+//=======================================================================
+// function : RayCircleIntersection
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_BaseIntersector::RayCircleIntersection (const Standard_Real theRadius,
+                                                                   const gp_Pnt& theLoc,
+                                                                   const gp_Dir& theRayDir,
+                                                                   const Standard_Boolean theIsFilled,
+                                                                   Standard_Real& theTime) const
+{
+  if (theRayDir.Z() != 0)
+  {
+    const Standard_Real aTime = (0 - theLoc.Z()) / theRayDir.Z();
+    const Standard_Real aX1 = theLoc.X() + theRayDir.X() * aTime;
+    const Standard_Real anY1 = theLoc.Y() + theRayDir.Y() * aTime;
+
+    const Standard_Real aK = aX1 * aX1 + anY1 * anY1;
+    if ((theIsFilled && aK <= theRadius * theRadius)
+     || (!theIsFilled && Abs (sqrt (aK) - theRadius) <= Precision::Confusion()))
+    {
+      theTime = aTime;
+      return true;
+    }
+  }
+  return false;
+}
+
 //=======================================================================
 // function : DistToGeometryCenter
 // purpose  :
index 5ab38e9ea9253e333c266638487799469f8ee6c5..e9bd50edfc8c53ad1d7130ead958f669f63e464e 100644 (file)
@@ -187,6 +187,7 @@ public:
                                              const Standard_Real theTopRad,
                                              const Standard_Real theHeight,
                                              const gp_Trsf& theTrsf,
+                                             const Standard_Boolean theIsHollow,
                                              const SelectMgr_ViewClipRange& theClipRange,
                                              SelectBasics_PickResult& thePickResult) const = 0;
 
@@ -196,8 +197,28 @@ public:
                                              const Standard_Real theTopRad,
                                              const Standard_Real theHeight,
                                              const gp_Trsf& theTrsf,
+                                             const Standard_Boolean theIsHollow,
                                              Standard_Boolean* theInside = NULL) const = 0;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                           const gp_Trsf& theTrsf,
+                                           const Standard_Boolean theIsFilled,
+                                           const SelectMgr_ViewClipRange& theClipRange,
+                                           SelectBasics_PickResult& thePickResult) const = 0;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                           const gp_Trsf& theTrsf,
+                                           const Standard_Boolean theIsFilled,
+                                           Standard_Boolean* theInside = NULL) const = 0;
+
 public:
 
   //! Measures distance between 3d projection of user-picked
@@ -224,15 +245,37 @@ public:
                                                                   Standard_Real& theTimeLeave) const;
 
   //! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
-  //! with the cylinder (or cone) with radiuses theBottomRad and theTopRad and height theHeights
+  //! with the hollow cylinder (or cone)
+  //! @param[in]  theBottomRadius the bottom cylinder radius
+  //! @param[in]  theTopRadius    the top cylinder radius
+  //! @param[in]  theHeight       the cylinder height
+  //! @param[in]  theLoc          the location of the ray
+  //! @param[in]  theRayDir       the ray direction
+  //! @param[in]  theIsHollow     true if the cylinder is hollow
+  //! @param[out] theTimeEnter    the entering the intersection
+  //! @param[out] theTimeLeave    the leaving the intersection
   Standard_EXPORT virtual Standard_Boolean RayCylinderIntersection (const Standard_Real theBottomRadius,
                                                                     const Standard_Real theTopRadius,
                                                                     const Standard_Real theHeight,
                                                                     const gp_Pnt& theLoc,
                                                                     const gp_Dir& theRayDir,
+                                                                    const Standard_Boolean theIsHollow,
                                                                     Standard_Real& theTimeEnter,
                                                                     Standard_Real& theTimeLeave) const;
 
+  //! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
+  //! with the circle
+  //! @param[in]  theRadius   the circle radius
+  //! @param[in]  theLoc      the location of the ray
+  //! @param[in]  theRayDir   the ray direction
+  //! @param[in]  theIsFilled true if it's a circle, false if it's a circle outline
+  //! @param[out] theTime     the intersection
+  Standard_EXPORT virtual Standard_Boolean RayCircleIntersection (const Standard_Real theRadius,
+                                                                  const gp_Pnt& theLoc,
+                                                                  const gp_Dir& theRayDir,
+                                                                  const Standard_Boolean theIsFilled,
+                                                                  Standard_Real& theTime) const;
+
   DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient)
 
 protected:
index 35f214780814893e54499fa6ce580da31eca2fcb..8a77af6b391689efbe198c87a9518a620104a550 100644 (file)
@@ -98,11 +98,25 @@ protected:
                                        const Standard_Real theTopRad,
                                        const Standard_Real theHeight,
                                        const gp_Trsf& theTrsf,
+                                       const Standard_Boolean theIsHollow,
                                        Standard_Boolean* theInside = NULL) const;
 
+  //! Intersection test between defined volume and given circle.
+  Standard_Boolean hasCircleOverlap (const Standard_Real theRadius,
+                                     const gp_Trsf& theTrsf,
+                                     const Standard_Boolean theIsFilled,
+                                     Standard_Boolean* theInside = NULL) const;
+
+  //! Returns True if all vertices (theVertices) are inside the top and bottom sides of the cylinder.
+  Standard_Boolean isInsideCylinderEndFace (const Standard_Real theBottomRad,
+                                            const Standard_Real theTopRad,
+                                            const Standard_Real theHeight,
+                                            const gp_Trsf& theTrsf,
+                                            const TColgp_Array1OfPnt& theVertices) const;
+
   //! Checking whether the point thePnt is inside the shape with borders theVertices.
   //! thePnt and theVertices lie in the same plane.
-  Standard_Boolean IsDotInside (const gp_Pnt& thePnt,
+  Standard_Boolean isDotInside (const gp_Pnt& thePnt,
                                 const TColgp_Array1OfPnt& theVertices) const;
 
 private:
@@ -116,10 +130,10 @@ private:
 
   //! Checking whether the borders theVertices of the shape intersect
   //! the cylinder (or cone) end face with the center theCenter and radius theRadius
-  Standard_Boolean isIntersectCylinderEndFace (const Standard_Real theRad,
-                                               const gp_Pnt& theCenter,
-                                               const gp_Trsf& theTrsf,
-                                               const TColgp_Array1OfPnt& theVertices) const;
+  Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
+                                      const gp_Pnt& theCenter,
+                                      const gp_Trsf& theTrsf,
+                                      const TColgp_Array1OfPnt& theVertices) const;
 
   //! Checks if AABB and frustum are separated along the given axis
   Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin,
index 07be0d8d99c817f7f3e4b05b33dad44555f89ffe..c01e50b6bfb617e04e8f24edcaa6872fe9f4ba38 100644 (file)
@@ -1,4 +1,4 @@
-// Created on: 2015-03-16
+// Created on: 2015-03-16
 // Created by: Varvara POSKONINA
 // Copyright (c) 2005-2014 OPEN CASCADE SAS
 //
@@ -520,7 +520,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasSphereOverlap (const gp_Pnt& thePnt,
 // purpose  :
 // =======================================================================
 template<int N>
-Standard_Boolean SelectMgr_Frustum<N>::IsDotInside (const gp_Pnt& thePnt,
+Standard_Boolean SelectMgr_Frustum<N>::isDotInside (const gp_Pnt& thePnt,
                                                     const TColgp_Array1OfPnt& theVertices) const
 {
   Standard_Real anAngle = 0.0;
@@ -598,14 +598,14 @@ Standard_Boolean SelectMgr_Frustum<N>::isSegmentsIntersect (const gp_Pnt& thePnt
 }
 
 // =======================================================================
-// function : isIntersectCylinderEndFace
+// function : isIntersectCircle
 // purpose  :
 // =======================================================================
 template<int N>
-Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standard_Real theRad,
-                                                                   const gp_Pnt& theCenter,
-                                                                   const gp_Trsf& theTrsf,
-                                                                   const TColgp_Array1OfPnt& theVertices) const
+Standard_Boolean SelectMgr_Frustum<N>::isIntersectCircle (const Standard_Real theRadius,
+                                                          const gp_Pnt& theCenter,
+                                                          const gp_Trsf& theTrsf,
+                                                          const TColgp_Array1OfPnt& theVertices) const
 {
   const gp_Trsf aTrsfInv = theTrsf.Inverted();
   const gp_Dir aRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]).Transformed (aTrsfInv);
@@ -633,7 +633,7 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
     // Solving quadratic equation anA * T^2 + 2 * aK * T + aC = 0
     const Standard_Real anA = (aX1 - aX2) * (aX1 - aX2) + (anY1 - anY2) * (anY1 - anY2);
     const Standard_Real aK = aX1 * (aX2 - aX1) + anY1 * (anY2 - anY1);
-    const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRad * theRad;
+    const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRadius * theRadius;
 
     const Standard_Real aDiscr = aK * aK - anA * aC;
     if (aDiscr >= 0.0)
@@ -649,6 +649,47 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
   return false;
 }
 
+// =======================================================================
+// function : isInsideCylinderEndFace
+// purpose  :
+// =======================================================================
+template<int N>
+Standard_Boolean SelectMgr_Frustum<N>::isInsideCylinderEndFace (const Standard_Real theBottomRad,
+                                                                const Standard_Real theTopRad,
+                                                                const Standard_Real theHeight,
+                                                                const gp_Trsf& theTrsf,
+                                                                const TColgp_Array1OfPnt& theVertices) const
+{
+  const gp_Trsf aTrsfInv = theTrsf.Inverted();
+  const gp_Dir aRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]).Transformed (aTrsfInv);
+  if (aRayDir.Z() == 0.0)
+  {
+    return false;
+  }
+
+  for (Standard_Integer anIdx = theVertices.Lower(); anIdx <= theVertices.Upper(); anIdx++)
+  {
+    const gp_Pnt aLoc = theVertices.Value (anIdx).Transformed (aTrsfInv);
+
+    const Standard_Real aTime1 = (0 - aLoc.Z()) / aRayDir.Z();
+    const Standard_Real aX1 = aLoc.X() + aRayDir.X() * aTime1;
+    const Standard_Real anY1 = aLoc.Y() + aRayDir.Y() * aTime1;
+
+    const Standard_Real aTime2 = (theHeight - aLoc.Z()) / aRayDir.Z();
+    const Standard_Real aX2 = aLoc.X() + aRayDir.X() * aTime2;
+    const Standard_Real anY2 = aLoc.Y() + aRayDir.Y() * aTime2;
+
+    if (aX1 * aX1 + anY1 * anY1 <= theBottomRad * theBottomRad
+     && aX2 * aX2 + anY2 * anY2 <= theTopRad * theTopRad)
+    {
+      continue;
+    }
+
+    return false;
+  }
+  return true;
+}
+
 // =======================================================================
 // function : hasCylinderOverlap
 // purpose  :
@@ -658,8 +699,37 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
                                                            const Standard_Real theTopRad,
                                                            const Standard_Real theHeight,
                                                            const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsHollow,
                                                            Standard_Boolean* theInside) const
 {
+  gp_Pnt aVerticesBuf[N];
+  TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
+  const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
+  if (anIncFactor == 2)
+  {
+    const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
+    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
+    {
+      aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
+    }
+  }
+  else
+  {
+    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
+    {
+      aVertices.SetValue (anIdx, myVertices[anIdx]);
+    }
+  }
+
+  if (theIsHollow && isInsideCylinderEndFace (theBottomRad, theTopRad, theHeight, theTrsf, aVertices))
+  {
+    if (theInside != NULL)
+    {
+      *theInside = false;
+    }
+    return false;
+  }
+
   const gp_Dir aCylNorm (gp::DZ().Transformed (theTrsf));
   const gp_Pnt aBottomCenter (gp::Origin().Transformed (theTrsf));
   const gp_Pnt aTopCenter = aBottomCenter.XYZ() + aCylNorm.XYZ() * theHeight;
@@ -698,29 +768,11 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
   aPoints[5] = aBottomCenterProject.XYZ() - aDirEndFaces.XYZ() * theBottomRad;
   const TColgp_Array1OfPnt aPointsArr (aPoints[0], 0, 5);
 
-  gp_Pnt aVerticesBuf[N];
-  TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
-  const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
-  if (anIncFactor == 2)
-  {
-    const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
-    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
-    {
-      aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
-    }
-  }
-  else
-  {
-    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
-    {
-      aVertices.SetValue (anIdx, myVertices[anIdx]);
-    }
-  }
   for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
   {
     if ((aCylNormProject.Dot (aCylNormProject) == 0.0
      && aVertices.Value (anIdx).Distance (aPoints[0]) <= Max (theTopRad, theBottomRad))
-     || IsDotInside (aVertices.Value (anIdx), aPointsArr))
+     || isDotInside (aVertices.Value (anIdx), aPointsArr))
     {
       if (theInside != NULL)
       {
@@ -747,8 +799,9 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
     }
   }
 
-  if (isIntersectCylinderEndFace (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
-   || isIntersectCylinderEndFace (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices))
+  if (!theIsHollow
+   && (isIntersectCircle (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
+    || isIntersectCircle (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices)))
   {
     if (theInside != NULL)
     {
@@ -759,7 +812,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
   bool isCylInsideRec = true;
   for (int i = 0; i < 6; ++i)
   {
-    isCylInsideRec &= IsDotInside (aPoints[i], aVertices);
+    isCylInsideRec &= isDotInside (aPoints[i], aVertices);
   }
   if (theInside != NULL)
   {
@@ -768,6 +821,82 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
   return isCylInsideRec;
 }
 
+// =======================================================================
+// function : hasCircleOverlap
+// purpose  :
+// =======================================================================
+template<int N>
+Standard_Boolean SelectMgr_Frustum<N>::hasCircleOverlap (const Standard_Real theRadius,
+                                                         const gp_Trsf& theTrsf,
+                                                         const Standard_Boolean theIsFilled,
+                                                         Standard_Boolean* theInside) const
+{
+  gp_Pnt aVerticesBuf[N];
+  TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
+  const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
+  if (anIncFactor == 2)
+  {
+    const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
+    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
+    {
+      aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
+    }
+  }
+  else
+  {
+    for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
+    {
+      aVertices.SetValue (anIdx, myVertices[anIdx]);
+    }
+  }
+
+  if (isIntersectCircle (theRadius, gp_Pnt (0, 0, 0), theTrsf, aVertices))
+  {
+    if (theInside != NULL)
+    {
+      *theInside = false;
+    }
+    return true;
+  }
+
+  gp_Pnt aCircCenter = gp::Origin();//.Transformed (theTrsf);
+  const gp_Dir aViewRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]);
+  const gp_Pln aPln (myVertices[0], aViewRayDir);
+  Standard_Real aCoefA, aCoefB, aCoefC, aCoefD;
+  aPln.Coefficients (aCoefA, aCoefB, aCoefC, aCoefD);
+
+  const Standard_Real aTCenter = -(aCircCenter.XYZ().Dot (aViewRayDir.XYZ()) + aCoefD);
+  const gp_Pnt aCenterProject (aCoefA * aTCenter,
+                               aCoefB * aTCenter,
+                               aCoefC * aTCenter);
+  if (isDotInside (aCenterProject, aVertices))
+  {
+    return true;
+  }
+
+  Standard_Boolean isInside = true;
+  for (Standard_Integer anIdx = aVertices.Lower(); anIdx <= aVertices.Upper(); anIdx++)
+  {
+    if (aVertices.Value (anIdx).Distance (aCenterProject) > theRadius)
+    {
+      isInside = false;
+      break;
+    }
+  }
+
+  if (theInside != NULL)
+  {
+    *theInside = false;
+  }
+
+  if (!theIsFilled && isInside)
+  {
+    return false;
+  }
+
+  return isInside;
+}
+
 //=======================================================================
 //function : DumpJson
 //purpose  : 
index 12f45aac66eca621add45fb871f3b0bc24005891..0031c5f2756598ef82f52e123067468b503946bf 100644 (file)
@@ -748,6 +748,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
                                                                  const Standard_Real theTopRad,
                                                                  const Standard_Real theHeight,
                                                                  const gp_Trsf& theTrsf,
+                                                                 const Standard_Boolean theIsHollow,
                                                                  const SelectMgr_ViewClipRange& theClipRange,
                                                                  SelectBasics_PickResult& thePickResult) const
 {
@@ -757,7 +758,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
   const gp_Trsf aTrsfInv = theTrsf.Inverted();
   const gp_Pnt  aLoc     = myNearPickedPnt.Transformed (aTrsfInv);
   const gp_Dir  aRayDir  = myViewRayDir   .Transformed (aTrsfInv);
-  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimes[0], aTimes[1]))
+  if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, theIsHollow, aTimes[0], aTimes[1]))
   {
     return Standard_False;
   }
@@ -787,6 +788,165 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
   return !theClipRange.IsClipped (thePickResult.Depth());
 }
 
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCircle (const Standard_Real theRadius,
+                                                               const gp_Trsf& theTrsf,
+                                                               const Standard_Boolean theIsFilled,
+                                                               const SelectMgr_ViewClipRange& theClipRange,
+                                                               SelectBasics_PickResult& thePickResult) const
+{
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+  Standard_Real aTime = 0.0;
+  const gp_Trsf aTrsfInv = theTrsf.Inverted();
+  const gp_Pnt  aLoc = myNearPickedPnt.Transformed (aTrsfInv);
+  const gp_Dir  aRayDir = myViewRayDir.Transformed (aTrsfInv);
+  if (!theIsFilled)
+  {
+    if (!hasCircleOverlap (theRadius, theTrsf, theIsFilled, NULL))
+    {
+      return Standard_False;
+    }
+    if (aRayDir.Z() != 0)
+    {
+      aTime = (0 - aLoc.Z()) / aRayDir.Z();
+    }
+  }
+  else if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
+  {
+    return Standard_False;
+  }
+
+  thePickResult.SetDepth (aTime * myScale);
+  if (theClipRange.IsClipped (thePickResult.Depth()))
+  {
+    thePickResult.SetDepth (aTime * myScale);
+  }
+
+  const gp_Pnt aPntOnCircle = aLoc.XYZ() + aRayDir.XYZ() * aTime;
+  if (Abs (aPntOnCircle.Z()) < Precision::Confusion())
+  {
+    thePickResult.SetSurfaceNormal (-gp::DZ().Transformed (theTrsf));
+  }
+  else
+  {
+    thePickResult.SetSurfaceNormal (gp_Vec (aPntOnCircle.X(), aPntOnCircle.Y(), 0.0).Transformed (theTrsf));
+  }
+  thePickResult.SetPickedPoint (aPntOnCircle.Transformed (theTrsf));
+  return !theClipRange.IsClipped (thePickResult.Depth());
+}
+
+//=======================================================================
+// function : isIntersectCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::isIntersectCircle (const Standard_Real theRadius,
+                                                                  const gp_Pnt& theCenter,
+                                                                  const gp_Trsf& theTrsf,
+                                                                  const TColgp_Array1OfPnt& theVertices) const
+{
+  const gp_Trsf aTrsfInv = theTrsf.Inverted();
+  const gp_Dir aRayDir = gp_Dir (myEdgeDirs[4 == 4 ? 4 : 0]).Transformed (aTrsfInv);
+  if (aRayDir.Z() == 0.0)
+  {
+    return false;
+  }
+
+  for (Standard_Integer anIdx = theVertices.Lower(); anIdx <= theVertices.Upper(); anIdx++)
+  {
+    const gp_Pnt aPntStart = theVertices.Value (anIdx).Transformed (aTrsfInv);
+    const gp_Pnt aPntFinish = anIdx == theVertices.Upper()
+      ? theVertices.Value (theVertices.Lower()).Transformed (aTrsfInv)
+      : theVertices.Value (anIdx + 1).Transformed (aTrsfInv);
+
+    // Project points on the end face plane
+    const Standard_Real aParam1 = (theCenter.Z() - aPntStart.Z()) / aRayDir.Z();
+    const Standard_Real aX1 = aPntStart.X() + aRayDir.X() * aParam1;
+    const Standard_Real anY1 = aPntStart.Y() + aRayDir.Y() * aParam1;
+
+    const Standard_Real aParam2 = (theCenter.Z() - aPntFinish.Z()) / aRayDir.Z();
+    const Standard_Real aX2 = aPntFinish.X() + aRayDir.X() * aParam2;
+    const Standard_Real anY2 = aPntFinish.Y() + aRayDir.Y() * aParam2;
+
+    // Solving quadratic equation anA * T^2 + 2 * aK * T + aC = 0
+    const Standard_Real anA = (aX1 - aX2) * (aX1 - aX2) + (anY1 - anY2) * (anY1 - anY2);
+    const Standard_Real aK = aX1 * (aX2 - aX1) + anY1 * (anY2 - anY1);
+    const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRadius * theRadius;
+
+    const Standard_Real aDiscr = aK * aK - anA * aC;
+    if (aDiscr >= 0.0)
+    {
+      const Standard_Real aT1 = (-aK + Sqrt (aDiscr)) / anA;
+      const Standard_Real aT2 = (-aK - Sqrt (aDiscr)) / anA;
+      if ((aT1 >= 0 && aT1 <= 1) || (aT2 >= 0 && aT2 <= 1))
+      {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+//=======================================================================
+// function : isSegmentsIntersect
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::isSegmentsIntersect (const gp_Pnt& thePnt1Seg1,
+                                                                    const gp_Pnt& thePnt2Seg1,
+                                                                    const gp_Pnt& thePnt1Seg2,
+                                                                    const gp_Pnt& thePnt2Seg2) const
+{
+  const gp_Mat aMatPln (thePnt2Seg1.X() - thePnt1Seg1.X(), thePnt2Seg1.Y() - thePnt1Seg1.Y(), thePnt2Seg1.Z() - thePnt1Seg1.Z(),
+                        thePnt1Seg2.X() - thePnt1Seg1.X(), thePnt1Seg2.Y() - thePnt1Seg1.Y(), thePnt1Seg2.Z() - thePnt1Seg1.Z(),
+                        thePnt2Seg2.X() - thePnt1Seg1.X(), thePnt2Seg2.Y() - thePnt1Seg1.Y(), thePnt2Seg2.Z() - thePnt1Seg1.Z());
+  if (Abs (aMatPln.Determinant()) > Precision::Confusion())
+  {
+    return false;
+  }
+
+  Standard_Real aFst[4] = { thePnt1Seg1.X(), thePnt2Seg1.X(), thePnt1Seg2.X(), thePnt2Seg2.X() };
+  Standard_Real aSnd[4] = { thePnt1Seg1.Y(), thePnt2Seg1.Y(), thePnt1Seg2.Y(), thePnt2Seg2.Y() };
+  if (aFst[0] == aFst[2] && aFst[1] == aFst[3])
+  {
+    aFst[0] = thePnt1Seg1.Z();
+    aFst[1] = thePnt2Seg1.Z();
+    aFst[2] = thePnt1Seg2.Z();
+    aFst[3] = thePnt2Seg2.Z();
+  }
+  if (aSnd[0] == aSnd[2]
+   && aSnd[1] == aSnd[3])
+  {
+    aSnd[0] = thePnt1Seg1.Z();
+    aSnd[1] = thePnt2Seg1.Z();
+    aSnd[2] = thePnt1Seg2.Z();
+    aSnd[3] = thePnt2Seg2.Z();
+  }
+  const gp_Mat2d aMat (gp_XY (aFst[0] - aFst[1], aSnd[0] - aSnd[1]),
+                       gp_XY (aFst[3] - aFst[2], aSnd[3] - aSnd[2]));
+
+  const gp_Mat2d aMatU (gp_XY (aFst[0] - aFst[2], aSnd[0] - aSnd[2]),
+                        gp_XY (aFst[3] - aFst[2], aSnd[3] - aSnd[2]));
+
+  const gp_Mat2d aMatV (gp_XY (aFst[0] - aFst[1], aSnd[0] - aSnd[1]),
+                        gp_XY (aFst[0] - aFst[2], aSnd[0] - aSnd[2]));
+  if (aMat.Determinant() == 0.0)
+  {
+    return false;
+  }
+
+  const Standard_Real anU = aMatU.Determinant() / aMat.Determinant();
+  const Standard_Real aV = aMatV.Determinant() / aMat.Determinant();
+  if (anU >= 0.0 && anU <= 1.0
+   && aV >= 0.0 && aV <= 1.0)
+  {
+    return true;
+  }
+  return false;
+}
+
 //=======================================================================
 // function : OverlapsCylinder
 // purpose  :
@@ -795,12 +955,28 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
                                                                  const Standard_Real theTopRad,
                                                                  const Standard_Real theHeight,
                                                                  const gp_Trsf& theTrsf,
+                                                                 const Standard_Boolean theIsHollow,
                                                                  Standard_Boolean* theInside) const
 {
   Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
     "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
 
-  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theInside);
+  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow, theInside);
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCircle (const Standard_Real theRadius,
+                                                               const gp_Trsf& theTrsf,
+                                                               const Standard_Boolean theIsFilled,
+                                                               Standard_Boolean* theInside) const
+{
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
+    "Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
+
+  return hasCircleOverlap (theRadius, theTrsf, theIsFilled, theInside);
 }
 
 // =======================================================================
index 8788a4af51bf472cfd1afa622bfd14c18148041d..bcebbb626bfc65a3a9352ec08adcf6b23c306c1e 100644 (file)
@@ -66,6 +66,18 @@ public:
   Standard_EXPORT void Init (const gp_Pnt2d& theMinPnt,
                              const gp_Pnt2d& theMaxPnt);
 
+  //! Returns True if Frustum (theVertices) intersects the circle.
+  Standard_EXPORT Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
+                                                      const gp_Pnt& theCenter,
+                                                      const gp_Trsf& theTrsf,
+                                                      const TColgp_Array1OfPnt& theVertices) const;
+
+  //! Returns True if Seg1 (thePnt1Seg1, thePnt2Seg1) and Seg2 (thePnt1Seg2, thePnt2Seg2) intersect.
+  Standard_EXPORT Standard_Boolean isSegmentsIntersect (const gp_Pnt& thePnt1Seg1,
+                                                        const gp_Pnt& thePnt2Seg1,
+                                                        const gp_Pnt& thePnt1Seg2,
+                                                        const gp_Pnt& thePnt2Seg2) const;
+
   //! Builds volume according to internal parameters.
   //! NOTE: it should be called after Init() method
   Standard_EXPORT virtual void Build() Standard_OVERRIDE;
@@ -150,6 +162,7 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              const SelectMgr_ViewClipRange& theClipRange,
                                                              SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
@@ -159,8 +172,28 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           const SelectMgr_ViewClipRange& theClipRange,
+                                                           SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
+
   //! Measures distance between 3d projection of user-picked
   //! screen point and given point theCOG.
   //! It makes sense only for frustums built on a single point.
index d4eee16aecc04a133ea27a78176517b856d84ff7..df3159d98fddd4084d6528c433529ac87a6b8856 100644 (file)
@@ -426,13 +426,15 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCylinder (const Stand
                                                                      const Standard_Real theTopRad,
                                                                      const Standard_Real theHeight,
                                                                      const gp_Trsf& theTrsf,
+                                                                     const Standard_Boolean theIsHollow,
                                                                      SelectBasics_PickResult& thePickResult) const
 {
   if (myActiveSelectingVolume.IsNull())
   {
     return false;
   }
-  return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, myViewClipRange, thePickResult);
+  return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf,
+                                                    theIsHollow, myViewClipRange, thePickResult);
 }
 
 //=======================================================================
@@ -443,13 +445,47 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCylinder (const Stand
                                                                      const Standard_Real theTopRad,
                                                                      const Standard_Real theHeight,
                                                                      const gp_Trsf& theTrsf,
+                                                                     const Standard_Boolean theIsHollow,
                                                                      Standard_Boolean* theInside) const
 {
   if (myActiveSelectingVolume.IsNull())
   {
     return false;
   }
-  return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theInside);
+  return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight,
+                                                    theTrsf, theIsHollow, theInside);
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCircle (const Standard_Real theRadius,
+                                                                   const gp_Trsf& theTrsf,
+                                                                   const Standard_Boolean theIsFilled,
+                                                                   SelectBasics_PickResult& thePickResult) const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return false;
+  }
+  return myActiveSelectingVolume->OverlapsCircle (theRadius, theTrsf, theIsFilled, myViewClipRange, thePickResult);
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCircle (const Standard_Real theRadius,
+                                                                   const gp_Trsf& theTrsf,
+                                                                   const Standard_Boolean theIsFilled,
+                                                                   Standard_Boolean* theInside) const
+{
+  if (myActiveSelectingVolume.IsNull())
+  {
+    return false;
+  }
+  return myActiveSelectingVolume->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside);
 }
 
 //=======================================================================
index 580e206cdae0774390e699170d640cd8f1cf14ce..708e7a885f234826e383add7cb96a4260d0123db 100644 (file)
@@ -168,6 +168,7 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
   //! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
@@ -176,8 +177,27 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
+
   //! Measures distance between 3d projection of user-picked
   //! screen point and given point theCOG
   Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const Standard_OVERRIDE;
index 44e8dac76d445b1041830405e3def1a6ae1134bb..efaf686e28710a9a4d3367a24534a236a8dca3ae 100644 (file)
@@ -337,12 +337,13 @@ Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCylinder (const Standard_R
                                                                 const Standard_Real theTopRad,
                                                                 const Standard_Real theHeight,
                                                                 const gp_Trsf& theTrsf,
+                                                                const Standard_Boolean theIsHollow,
                                                                 const SelectMgr_ViewClipRange& theClipRange,
                                                                 SelectBasics_PickResult& thePickResult) const
 {
   (void)theClipRange;
   (void)thePickResult;
-  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf);
+  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow);
 }
 
 //=======================================================================
@@ -353,10 +354,39 @@ Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCylinder (const Standard_R
                                                                 const Standard_Real theTopRad,
                                                                 const Standard_Real theHeight,
                                                                 const gp_Trsf& theTrsf,
+                                                                const Standard_Boolean theIsHollow,
                                                                 Standard_Boolean* theInside) const
 {
   (void) theInside;
-  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf);
+  return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow);
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCircle (const Standard_Real theRadius,
+                                                              const gp_Trsf& theTrsf,
+                                                              const Standard_Boolean theIsFilled,
+                                                              const SelectMgr_ViewClipRange& theClipRange,
+                                                              SelectBasics_PickResult& thePickResult) const
+{
+  (void)theClipRange;
+  (void)thePickResult;
+  return hasCircleOverlap (theRadius, theTrsf, theIsFilled);
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCircle (const Standard_Real theRadius,
+                                                              const gp_Trsf& theTrsf,
+                                                              const Standard_Boolean theIsFilled,
+                                                              Standard_Boolean* theInside) const
+{
+  (void)theInside;
+  return hasCircleOverlap (theRadius, theTrsf, theIsFilled);
 }
 
 // =======================================================================
index a5c7d0857637e8ef2fbc3dacb801320c48feae30..a13067b03356a6c4e6e50fa92d4602c6959a0dc4 100644 (file)
@@ -123,6 +123,7 @@ public: //! @name SAT Tests for different objects
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              const SelectMgr_ViewClipRange& theClipRange,
                                                              SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
@@ -132,8 +133,28 @@ public: //! @name SAT Tests for different objects
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
 
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           const SelectMgr_ViewClipRange& theClipRange,
+                                                           SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
+
+  //! Returns true if selecting volume is overlapped by circle with radius theRadius,
+  //! boolean theIsFilled and transformation to apply theTrsf.
+  //! The position and orientation of the circle are specified
+  //! via theTrsf transformation for gp::XOY() with center in gp::Origin().
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
+
 public:
 
   //! Nullifies the handle to corresponding builder instance to prevent memory leaks
index 31cc5e69f48335f618ec7cc6c53561376e3516d9..907a85406179dbcc2a15a8ed5d50069d63332653 100644 (file)
 
 #include <BRepMesh_DataStructureOfDelaun.hxx>
 #include <BRepMesh_Delaun.hxx>
+#include <Geom_Plane.hxx>
+#include <GeomInt_IntSS.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Line.hxx>
 #include <NCollection_IncAllocator.hxx>
 #include <SelectMgr_FrustumBuilder.hxx>
 
@@ -506,6 +510,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
                                                                    const Standard_Real theTopRad,
                                                                    const Standard_Real theHeight,
                                                                    const gp_Trsf& theTrsf,
+                                                                   const Standard_Boolean theIsHollow,
                                                                    const SelectMgr_ViewClipRange& theClipRange,
                                                                    SelectBasics_PickResult& thePickResult) const
 {
@@ -513,7 +518,8 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
     "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
   for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theClipRange, thePickResult))
+    if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf,
+                                          theIsHollow, theClipRange, thePickResult))
     {
       return true;
     }
@@ -529,6 +535,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
                                                                    const Standard_Real theTopRad,
                                                                    const Standard_Real theHeight,
                                                                    const gp_Trsf& theTrsf,
+                                                                   const Standard_Boolean theIsHollow,
                                                                    Standard_Boolean* theInside) const
 {
   const gp_Dir aCylNorm (gp::DZ().Transformed (theTrsf));
@@ -589,7 +596,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
       {
         aVertices[anIdx] = anIter.Value()->myVertices[anIdx];
       }
-      if (anIter.Value()->IsDotInside (aPoints[i], aVertices))
+      if (anIter.Value()->isDotInside (aPoints[i], aVertices))
       {
         isInside = true;
         break;
@@ -607,7 +614,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
   }
   for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
   {
-    if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theInside))
+    if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow, theInside))
     {
       return true;
     }
@@ -615,6 +622,109 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
   return false;
 }
 
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCircle (const Standard_Real theRadius,
+                                                                 const gp_Trsf& theTrsf,
+                                                                 const Standard_Boolean theIsFilled,
+                                                                 const SelectMgr_ViewClipRange& theClipRange,
+                                                                 SelectBasics_PickResult& thePickResult) const
+{
+  Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline,
+    "Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
+  for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
+  {
+    if (anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theClipRange, thePickResult))
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+//=======================================================================
+// function : OverlapsCircle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCircle (const Standard_Real theRadius,
+                                                                 const gp_Trsf& theTrsf,
+                                                                 const Standard_Boolean theIsFilled,
+                                                                 Standard_Boolean* theInside) const
+{
+  const gp_Pnt aCenter (gp::Origin().Transformed (theTrsf));
+  const gp_Vec aVecPlane1 (myFrustums.First()->myVertices[0], myFrustums.First()->myVertices[1]);
+  const gp_Vec aVecPlane2 (myFrustums.First()->myVertices[0], myFrustums.First()->myVertices[2]);
+
+  const gp_Dir aDirNorm (aVecPlane1.Crossed (aVecPlane2));
+  const gp_Pln aPln (myFrustums.First()->myVertices[0], aDirNorm);
+  Standard_Real aCoefA, aCoefB, aCoefC, aCoefD;
+  aPln.Coefficients (aCoefA, aCoefB, aCoefC, aCoefD);
+
+  const Standard_Real aT = -(aCenter.XYZ().Dot (aDirNorm.XYZ()) + aCoefD) / aDirNorm.Dot (aDirNorm);
+  const gp_Pnt aCenterProject (aCoefA * aT + aCenter.X(),
+                               aCoefB * aT + aCenter.Y(),
+                               aCoefC * aT + aCenter.Z());
+
+  gp_Pnt aVerticesBuf[3];
+  TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, 2);
+
+  if (!theIsFilled)
+  {
+    for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
+    {
+      if (!anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside))
+      {
+        continue;
+      }
+
+      if (myToAllowOverlap)
+      {
+        return Standard_True;
+      }
+
+      if (isIntersectBoundary (theRadius, theTrsf, theIsFilled))
+      {
+        if (theInside != NULL)
+        {
+          *theInside &= Standard_False;
+        }
+        return Standard_False;
+      }
+      return Standard_True;
+    }
+  }
+  else
+  {
+    for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
+    {
+      if (!anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside))
+      {
+        continue;
+      }
+
+      if (myToAllowOverlap)
+      {
+        return Standard_True;
+      }
+
+      if (isIntersectBoundary (theRadius, theTrsf, theIsFilled))
+      {
+        return Standard_False;
+      }
+      return Standard_True;
+    }
+  }
+
+  if (theInside != NULL)
+  {
+    *theInside &= Standard_False;
+  }
+
+  return Standard_False;
+}
+
 // =======================================================================
 // function : GetPlanes
 // purpose  :
@@ -638,6 +748,127 @@ void SelectMgr_TriangularFrustumSet::SetAllowOverlapDetection (const Standard_Bo
   myToAllowOverlap = theIsToAllow;
 }
 
+//=======================================================================
+// function : PointInTriangle
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::pointInTriangle (const gp_Pnt& thePnt,
+                                                                  const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3)
+{
+  gp_Vec a = theV1.XYZ() - thePnt.XYZ();
+  gp_Vec b = theV2.XYZ() - thePnt.XYZ();
+  gp_Vec c = theV3.XYZ() - thePnt.XYZ();
+
+  gp_Vec u = b.Crossed (c);
+  gp_Vec v = c.Crossed (a);
+  gp_Vec w = a.Crossed (b);
+
+  if (u.Dot (v) < 0.0 || u.Dot (w) < 0.0) {
+    return false;
+  }
+
+  return true;
+}
+
+//=======================================================================
+// function : segmentSegmentIntersection
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::segmentSegmentIntersection (const gp_Pnt& theStartPnt1,
+                                                                             const gp_Pnt& theEndPnt1,
+                                                                             const gp_Pnt& theStartPnt2,
+                                                                             const gp_Pnt& theEndPnt2)
+{
+  gp_XYZ aVec1 = theEndPnt1.XYZ() - theStartPnt1.XYZ();
+  gp_XYZ aVec2 = theEndPnt2.XYZ() - theStartPnt2.XYZ();
+  gp_XYZ aVec21 = theStartPnt2.XYZ() - theStartPnt1.XYZ();
+  gp_XYZ aVec12 = theStartPnt1.XYZ() - theStartPnt2.XYZ();
+  if (Abs (aVec21.DotCross (aVec1, aVec2)) > Precision::Confusion() ||
+      Abs (aVec12.DotCross (aVec2, aVec1)) > Precision::Confusion())
+  {
+    // lines are not coplanar
+    return false;
+  }
+
+  double aValue1 = aVec21.Crossed (aVec2).Dot (aVec1.Crossed (aVec2)) / aVec1.Crossed (aVec2).SquareModulus();
+  double aValue2 = aVec12.Crossed (aVec1).Dot (aVec2.Crossed (aVec1)) / aVec2.Crossed (aVec1).SquareModulus();
+  if (aValue1 < 0.0 || aValue1 > 1.0 || aValue2 < 0.0 || aValue2 > 1.0)
+  {
+    return false;
+  }
+  return true;
+}
+
+//=======================================================================
+// function : isIntersectBoundary
+// purpose  :
+//=======================================================================
+Standard_Boolean SelectMgr_TriangularFrustumSet::isIntersectBoundary (const Standard_Real theRadius,
+                                                                      const gp_Trsf& theTrsf,
+                                                                      const Standard_Boolean theIsFilled) const
+{
+  Standard_Integer aFacesNb = myBoundaryPoints.Size() / 2;
+
+  const gp_Pnt& aCircCenter = theTrsf.TranslationPart();
+  gp_Ax2 anAxis;
+  anAxis.Transform (theTrsf);
+  Handle(Geom_Circle) aCirc = new Geom_Circle (anAxis, theRadius);
+
+  gp_Dir aCircNorm = gp_Dir(0, 0, 1).Transformed (theTrsf);
+  Handle(Geom_Surface) aCircPlane = new Geom_Plane(aCircCenter, aCircNorm);
+
+  for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx < aFacesNb + myBoundaryPoints.Lower(); anIdx++)
+  {
+    gp_Pnt aFace[4] = { myBoundaryPoints.Value (anIdx),
+                        myBoundaryPoints.Value (anIdx + aFacesNb),
+                        myBoundaryPoints.Value (anIdx % aFacesNb + 1 + aFacesNb),
+                        myBoundaryPoints.Value (anIdx % aFacesNb + 1) };
+
+    gp_Dir aBndPlaneNorm = gp_Vec (aFace[0], aFace[1]).Crossed (gp_Vec(aFace[0], aFace[2]));
+    Handle(Geom_Surface) aBndPlane = new Geom_Plane(aFace[0], aBndPlaneNorm);
+
+    GeomInt_IntSS anInterSS (aCircPlane, aBndPlane, Precision::Confusion());
+    if (!anInterSS.IsDone() || anInterSS.NbLines() == 0)
+    {
+      continue;
+    }
+
+    const Handle(Geom_Line)& anInterLine = Handle(Geom_Line)::DownCast (anInterSS.Line(1));
+    Standard_Real aDistance = anInterLine->Lin().Distance (aCircCenter);
+    if (aDistance > theRadius)
+    {
+      continue;
+    }
+
+    gp_Lin aLine = anInterLine->Lin();
+    gp_Lin aNormalLine = aLine.Normal (aCircCenter);
+    gp_Pnt aCrossPoint = aCircCenter.Translated (aNormalLine.Direction().Reversed().XYZ() * aDistance);
+
+    Standard_Real anOffset = Sqrt (theRadius * theRadius - aDistance * aDistance);
+    // Line-circle intersection points
+    gp_Pnt aP1 = aCrossPoint.Translated (aLine.Direction().XYZ() * anOffset);
+    gp_Pnt aP2 = aCrossPoint.Translated (aLine.Direction().Reversed().XYZ() * anOffset);
+
+    if (pointInTriangle (aP1, aFace[0], aFace[1], aFace[2])
+     || pointInTriangle (aP1, aFace[0], aFace[2], aFace[3])
+     || pointInTriangle (aP2, aFace[0], aFace[1], aFace[2])
+     || pointInTriangle (aP2, aFace[0], aFace[2], aFace[3]))
+    {
+      return Standard_True;
+    }
+
+    if (theIsFilled
+     || segmentSegmentIntersection (aP1, aP2, aFace[0], aFace[1])
+     || segmentSegmentIntersection (aP1, aP2, aFace[1], aFace[2])
+     || segmentSegmentIntersection (aP1, aP2, aFace[2], aFace[3])
+     || segmentSegmentIntersection (aP1, aP2, aFace[0], aFace[3]))
+    {
+      return Standard_True;
+    }
+  }
+  return Standard_False;
+}
+
 //=======================================================================
 // function : isIntersectBoundary
 // purpose  :
@@ -669,7 +900,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::isIntersectBoundary (const gp_P
 // purpose  : Moller-Trumbore ray-triangle intersection test
 //=======================================================================
 Standard_Boolean SelectMgr_TriangularFrustumSet::segmentTriangleIntersection (const gp_Pnt& theOrig, const gp_Vec& theDir,
-                                                                              const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const
+                                                                              const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3)
 {
   gp_Vec        aPVec, aTVec, aQVec;
   Standard_Real aD, aInvD, anU, aV, aT;
index f5c51f31a0b2fe0b3e358ef610ef3a5ace33e518..694c3efc55e4f05e1615d2e5d59beb477815adba 100644 (file)
@@ -124,6 +124,7 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              const SelectMgr_ViewClipRange& theClipRange,
                                                              SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
 
@@ -133,8 +134,24 @@ public:
                                                              const Standard_Real theTopRad,
                                                              const Standard_Real theHeight,
                                                              const gp_Trsf& theTrsf,
+                                                             const Standard_Boolean theIsHollow,
                                                              Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
 
+  //! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
+  //! and theTopRad, height theHeight and transformation to apply theTrsf.
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           const SelectMgr_ViewClipRange& theClipRange,
+                                                           SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
+
+  //! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
+  //! and theTopRad, height theHeight and transformation to apply theTrsf.
+  Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
+                                                           const gp_Trsf& theTrsf,
+                                                           const Standard_Boolean theIsFilled,
+                                                           Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
+
   //! Stores plane equation coefficients (in the following form:
   //! Ax + By + Cz + D = 0) to the given vector
   Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;
@@ -151,15 +168,34 @@ private:
   //! Checks whether the segment intersects with the boundary of the current volume selection
   Standard_EXPORT Standard_Boolean isIntersectBoundary (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2) const;
 
+  //! Checks whether the circle intersects with the boundary of the current volume selection
+  Standard_EXPORT Standard_Boolean isIntersectBoundary (const Standard_Real theRadius,
+                                                        const gp_Trsf& theTrsf,
+                                                        const Standard_Boolean theIsFilled) const;
+
   //! Checks whether the triangle intersects with a segment
-  Standard_EXPORT Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
-                                                                const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const;
+  Standard_EXPORT static Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
+                                                                       const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
+
+  Standard_EXPORT static Standard_Boolean segmentSegmentIntersection (const gp_Pnt& theStartPnt1,
+                                                                      const gp_Pnt& theEndPnt1,
+                                                                      const gp_Pnt& theStartPnt2,
+                                                                      const gp_Pnt& theEndPnt2);
+
+  Standard_EXPORT static Standard_Boolean pointInTriangle (const gp_Pnt& thePnt,
+                                                           const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
 
 private:
 
   SelectMgr_TriangFrustums      myFrustums;          //!< set of triangular frustums
   SelectionPolyline             mySelPolyline;       //!< parameters of selection polyline (it is used to build triangle frustum set)
   TColgp_Array1OfPnt            myBoundaryPoints;    //!< boundary points
+                                                     //!       1_____2
+                                                     //!      /|     |\ .
+                                                     //!    4/_|_____|_\3
+                                                     //!    | 5|_____|6 |
+                                                     //!    | /       \ |
+                                                     //!   8|/_________\|7
   Standard_Boolean              myToAllowOverlap;    //!< flag to detect only fully included sensitives or not
 };
 
index 36e5ce9fca0c91929e6b655634cf5d13aea59bca..07b5a96543ffe528a78104206805823dd05f2094 100644 (file)
@@ -40,6 +40,7 @@
 #include <Select3D_SensitiveFace.hxx>
 #include <Select3D_SensitiveGroup.hxx>
 #include <Select3D_SensitivePoint.hxx>
+#include <Select3D_SensitivePoly.hxx>
 #include <Select3D_SensitiveSegment.hxx>
 #include <Select3D_SensitiveSphere.hxx>
 #include <Select3D_SensitiveTriangulation.hxx>
@@ -60,7 +61,6 @@
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Wire.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
 
 #define BVH_PRIMITIVE_LIMIT 800000
 
@@ -249,6 +249,7 @@ void StdSelect_BRepSelectionTool::ComputeSensitive (const TopoDS_Shape& theShape
     case TopAbs_FACE:
     {
       const TopoDS_Face& aFace = TopoDS::Face (theShape);
+
       Select3D_EntitySequence aSensitiveList;
       GetSensitiveForFace (aFace, theOwner,
                            aSensitiveList,
@@ -266,159 +267,15 @@ void StdSelect_BRepSelectionTool::ComputeSensitive (const TopoDS_Shape& theShape
     {
       TopTools_IndexedMapOfShape aSubfacesMap;
       TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
-      if (aSubfacesMap.Extent() == 2) // detect cone
-      {
-        const TopoDS_Face* aFaces[2] =
-        {
-          &TopoDS::Face (aSubfacesMap.FindKey (1)),
-          &TopoDS::Face (aSubfacesMap.FindKey (2))
-        };
-
-        TopLoc_Location aLocSurf[2];
-        const Handle(Geom_Surface)* aSurfaces[2] =
-        {
-          &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
-          &BRep_Tool::Surface (*aFaces[1], aLocSurf[1])
-        };
 
-        Standard_Integer aConIndex = 0;
-        Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[0]);
-        Handle(Geom_Plane) aGeomPln;
-        if (!aGeomCone.IsNull())
-        {
-          aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[1]);
-        }
-        else
-        {
-          aConIndex = 1;
-          aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[1]);
-          aGeomPln  = Handle(Geom_Plane)::DownCast (*aSurfaces[0]);
-        }
-        if (!aGeomCone.IsNull()
-         && !aGeomPln.IsNull()
-         &&  aGeomPln->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
-        {
-          const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
-          const Standard_Real aRad1 = aCone.RefRadius();
-          const Standard_Real aHeight = (aRad1 != 0.0)
-                                       ? aRad1 / Abs (Tan (aCone.SemiAngle()))
-                                       : aCone.Location().Distance (aGeomPln->Location().Transformed (aLocSurf[aConIndex == 0 ? 1 : 0]));
-          const Standard_Real aRad2 = (aRad1 != 0.0) ? 0.0 : Tan (aCone.SemiAngle()) * aHeight;
-          gp_Trsf aTrsf;
-          aTrsf.SetTransformation (aCone.Position(), gp_Ax3());
-          Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
-          theSelection->Add (aSensSCyl);
-          break;
-        }
-      }
-      if (aSubfacesMap.Extent() == 3) // detect cylinder or truncated cone
+      if (!GetSensitiveForCylinder (aSubfacesMap, theOwner, theSelection))
       {
-        const TopoDS_Face* aFaces[3] =
-        {
-          &TopoDS::Face (aSubfacesMap.FindKey (1)),
-          &TopoDS::Face (aSubfacesMap.FindKey (2)),
-          &TopoDS::Face (aSubfacesMap.FindKey (3))
-        };
-
-        TopLoc_Location aLocSurf[3];
-        const Handle(Geom_Surface)* aSurfaces[3] =
-        {
-          &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
-          &BRep_Tool::Surface (*aFaces[1], aLocSurf[1]),
-          &BRep_Tool::Surface (*aFaces[2], aLocSurf[2])
-        };
-
-        Standard_Integer aConIndex = -1, aNbPlanes = 0;
-        Handle(Geom_ConicalSurface) aGeomCone;
-        Handle(Geom_CylindricalSurface) aGeomCyl;
-        Handle(Geom_Plane) aGeomPlanes[2];
-        const TopLoc_Location* aGeomPlanesLoc[2];
-        for (Standard_Integer aSurfIter = 0; aSurfIter < 3; ++aSurfIter)
+        for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
         {
-          const Handle(Geom_Surface)& aSurf = *aSurfaces[aSurfIter];
-          if (aConIndex == -1)
-          {
-            aGeomCone = Handle (Geom_ConicalSurface)::DownCast (aSurf);
-            if (!aGeomCone.IsNull())
-            {
-              aConIndex = aSurfIter;
-              continue;
-            }
-            aGeomCyl = Handle (Geom_CylindricalSurface)::DownCast (aSurf);
-            if (!aGeomCyl.IsNull())
-            {
-              aConIndex = aSurfIter;
-              continue;
-            }
-          }
-          if (aNbPlanes < 2)
-          {
-            aGeomPlanes[aNbPlanes] = Handle(Geom_Plane)::DownCast (aSurf);
-            if (!aGeomPlanes[aNbPlanes].IsNull())
-            {
-              aGeomPlanesLoc[aNbPlanes] = &aLocSurf[aSurfIter];
-              ++aNbPlanes;
-            }
-          }
+          ComputeSensitive (aSubfacesMap.FindKey (aShIndex), theOwner,
+                            theSelection,
+                            theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
         }
-
-        if (!aGeomCone.IsNull())
-        {
-          if (!aGeomPlanes[0].IsNull()
-           && !aGeomPlanes[1].IsNull()
-           &&  aGeomPlanes[0]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular())
-           &&  aGeomPlanes[1]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
-          {
-            const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
-            const Standard_Real aRad1 = aCone.RefRadius();
-            const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
-                               .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
-            gp_Trsf aTrsf;
-            aTrsf.SetTransformation (aCone.Position(), gp_Ax3());
-            const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
-                                                ?  aRad1 / Tan (aCone.SemiAngle())
-                                                :  aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
-            const Standard_Real aRad2 = (aCone.SemiAngle() > 0.0)
-                                       ? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
-                                       : aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
-            Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
-            theSelection->Add (aSensSCyl);
-            break;
-          }
-        }
-        else if (!aGeomCyl.IsNull())
-        {
-          if (!aGeomPlanes[0].IsNull()
-           && !aGeomPlanes[1].IsNull()
-           &&  aGeomPlanes[0]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular())
-           &&  aGeomPlanes[1]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular()))
-          {
-            const gp_Cylinder aCyl = BRepAdaptor_Surface (*aFaces[aConIndex]).Cylinder();
-            const Standard_Real aRad = aCyl.Radius();
-            const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
-                               .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
-
-            gp_Trsf aTrsf;
-            gp_Ax3 aPos = aCyl.Position();
-            if (aGeomPlanes[0]->Position().IsCoplanar (aGeomPlanes[1]->Position(), Precision::Angular(), Precision::Angular()))
-            {
-              // cylinders created as a prism have an inverse vector of the cylindrical surface
-              aPos.SetDirection (aPos.Direction().Reversed());
-            }
-            aTrsf.SetTransformation (aPos, gp_Ax3());
-
-            Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf);
-            theSelection->Add (aSensSCyl);
-            break;
-          }
-        }
-      }
-
-      for (Standard_Integer aShIndex = 1; aShIndex <= aSubfacesMap.Extent(); ++aShIndex)
-      {
-        ComputeSensitive (aSubfacesMap.FindKey (aShIndex), theOwner,
-                          theSelection,
-                          theDeflection, theDeviationAngle, theNbPOnEdge, theMaxParam, isAutoTriangulation);
       }
       break;
     }
@@ -633,8 +490,7 @@ void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape
       }
       else
       {
-        theSensitive = new Select3D_SensitiveCircle (theOwner, aCircle,
-                                                     aParamFirst, aParamLast, Standard_False, 16);
+        theSensitive = new Select3D_SensitivePoly (theOwner, aCircle, aParamFirst, aParamLast, Standard_False);
       }
       break;
     }
@@ -705,6 +561,57 @@ void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape
   }
 }
 
+//=======================================================================
+//function : getCylinderHeight
+//purpose  :
+//=======================================================================
+static Standard_Real getCylinderHeight (const Handle(Poly_Triangulation)& theTriangulation,
+                                        const TopLoc_Location& theLoc)
+{
+  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;
+
+  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);
+
+    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();
+    }
+  }
+
+  return isCylinder;
+}
+
 //=======================================================================
 //function : GetSensitiveEntityForFace
 //purpose  :
@@ -749,6 +656,76 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
         return Standard_True;
       }
     }
+    else if (Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (aSurf))
+    {
+      gp_Dir aDummyDir;
+      if (isCylinderOrCone (theFace, gp_Pnt(), aDummyDir))
+      {
+        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 aRad2;
+        if (aRad1 == 0.0)
+        {
+          aRad2 = Tan (aCone.SemiAngle()) * aHeight;
+        }
+        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);
+        }
+
+        Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf, true);
+        theSensitiveList.Append (aSensSCyl);
+        return Standard_True;
+      }
+    }
+    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))
+      {
+        const Standard_Real aRad = aCyl.Radius();
+        const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
+
+        gp_Trsf aTrsf;
+        aPos.SetDirection (aDirection);
+        aTrsf.SetTransformation (aPos, gp::XOY());
+
+        Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf, true);
+        theSensitiveList.Append (aSensSCyl);
+        return Standard_True;
+      }
+    }
+    else if (Handle(Geom_Plane) aGeomPlane = Handle(Geom_Plane)::DownCast (aSurf))
+    {
+      TopTools_IndexedMapOfShape aSubfacesMap;
+      TopExp::MapShapes (theFace, TopAbs_EDGE, aSubfacesMap);
+      if (aSubfacesMap.Extent() == 1)
+      {
+        const TopoDS_Edge& anEdge = TopoDS::Edge (aSubfacesMap.FindKey (1));
+        BRepAdaptor_Curve anAdaptor (anEdge);
+        if (anAdaptor.GetType() == GeomAbs_Circle
+         && BRep_Tool::IsClosed (anEdge))
+        {
+          Handle(Select3D_SensitiveCircle) aSensSCyl = new Select3D_SensitiveCircle (theOwner, anAdaptor.Circle(), theInteriorFlag);
+          theSensitiveList.Append (aSensSCyl);
+          return Standard_True;
+        }
+      }
+    }
+
     Handle(Select3D_SensitiveTriangulation) STG = new Select3D_SensitiveTriangulation (theOwner, aTriangulation, aLoc, theInteriorFlag);
     theSensitiveList.Append (STG);
     return Standard_True;
@@ -877,7 +854,7 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
             }
             else
             {
-              theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag, 16));
+              theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag));
             }
           }
         }
@@ -947,3 +924,163 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
   }
   return Standard_True;
 }
+
+//=======================================================================
+//function : GetSensitiveForCylinder
+//purpose  :
+//=======================================================================
+Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForCylinder (const TopTools_IndexedMapOfShape& theSubfacesMap,
+                                                                       const Handle(SelectMgr_EntityOwner)& theOwner,
+                                                                       const Handle(SelectMgr_Selection)& theSelection)
+{
+  if (theSubfacesMap.Extent() == 2) // detect cone
+  {
+    const TopoDS_Face* aFaces[2] =
+    {
+      &TopoDS::Face (theSubfacesMap.FindKey (1)),
+      &TopoDS::Face (theSubfacesMap.FindKey (2))
+    };
+
+    TopLoc_Location aLocSurf[2];
+    const Handle(Geom_Surface)* aSurfaces[2] =
+    {
+      &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
+      &BRep_Tool::Surface (*aFaces[1], aLocSurf[1])
+    };
+
+    Standard_Integer aConIndex = 0;
+    Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[0]);
+    Handle(Geom_Plane) aGeomPln;
+    if (!aGeomCone.IsNull())
+    {
+      aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[1]);
+    }
+    else
+    {
+      aConIndex = 1;
+      aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[1]);
+      aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[0]);
+    }
+    if (!aGeomCone.IsNull()
+      && !aGeomPln.IsNull()
+      && aGeomPln->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
+    {
+      const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
+      const Standard_Real aRad1 = aCone.RefRadius();
+      const Standard_Real aHeight = (aRad1 != 0.0)
+        ? aRad1 / Abs (Tan (aCone.SemiAngle()))
+        : aCone.Location().Distance (aGeomPln->Location().Transformed (aLocSurf[aConIndex == 0 ? 1 : 0]));
+      const Standard_Real aRad2 = (aRad1 != 0.0) ? 0.0 : Tan (aCone.SemiAngle()) * aHeight;
+      gp_Trsf aTrsf;
+      aTrsf.SetTransformation (aCone.Position(), gp::XOY());
+      Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
+      theSelection->Add (aSensSCyl);
+      return Standard_True;
+    }
+  }
+  if (theSubfacesMap.Extent() == 3) // detect cylinder or truncated cone
+  {
+    const TopoDS_Face* aFaces[3] =
+    {
+      &TopoDS::Face (theSubfacesMap.FindKey (1)),
+      &TopoDS::Face (theSubfacesMap.FindKey (2)),
+      &TopoDS::Face (theSubfacesMap.FindKey (3))
+    };
+
+    TopLoc_Location aLocSurf[3];
+    const Handle(Geom_Surface)* aSurfaces[3] =
+    {
+      &BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
+      &BRep_Tool::Surface (*aFaces[1], aLocSurf[1]),
+      &BRep_Tool::Surface (*aFaces[2], aLocSurf[2])
+    };
+
+    Standard_Integer aConIndex = -1, aNbPlanes = 0;
+    Handle(Geom_ConicalSurface) aGeomCone;
+    Handle(Geom_CylindricalSurface) aGeomCyl;
+    Handle(Geom_Plane) aGeomPlanes[2];
+    const TopLoc_Location* aGeomPlanesLoc[2];
+    for (Standard_Integer aSurfIter = 0; aSurfIter < 3; ++aSurfIter)
+    {
+      const Handle(Geom_Surface)& aSurf = *aSurfaces[aSurfIter];
+      if (aConIndex == -1)
+      {
+        aGeomCone = Handle (Geom_ConicalSurface)::DownCast (aSurf);
+        if (!aGeomCone.IsNull())
+        {
+          aConIndex = aSurfIter;
+          continue;
+        }
+        aGeomCyl = Handle (Geom_CylindricalSurface)::DownCast (aSurf);
+        if (!aGeomCyl.IsNull())
+        {
+          aConIndex = aSurfIter;
+          continue;
+        }
+      }
+      if (aNbPlanes < 2)
+      {
+        aGeomPlanes[aNbPlanes] = Handle(Geom_Plane)::DownCast (aSurf);
+        if (!aGeomPlanes[aNbPlanes].IsNull())
+        {
+          aGeomPlanesLoc[aNbPlanes] = &aLocSurf[aSurfIter];
+          ++aNbPlanes;
+        }
+      }
+    }
+
+    if (!aGeomCone.IsNull())
+    {
+      if (!aGeomPlanes[0].IsNull()
+        && !aGeomPlanes[1].IsNull()
+        && aGeomPlanes[0]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular())
+        && aGeomPlanes[1]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
+      {
+        const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
+        const Standard_Real aRad1 = aCone.RefRadius();
+        const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
+          .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
+        gp_Trsf aTrsf;
+        aTrsf.SetTransformation (aCone.Position(), gp::XOY());
+        const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
+          ? aRad1 / Tan (aCone.SemiAngle())
+          : aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
+        const Standard_Real aRad2 = (aCone.SemiAngle() > 0.0)
+          ? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
+          : aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
+
+        Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
+        theSelection->Add (aSensSCyl);
+        return Standard_True;
+      }
+    }
+    else if (!aGeomCyl.IsNull())
+    {
+      if (!aGeomPlanes[0].IsNull()
+        && !aGeomPlanes[1].IsNull()
+        && aGeomPlanes[0]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular())
+        && aGeomPlanes[1]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular()))
+      {
+        const gp_Cylinder aCyl = BRepAdaptor_Surface (*aFaces[aConIndex]).Cylinder();
+        const Standard_Real aRad = aCyl.Radius();
+        const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
+          .Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
+
+        gp_Trsf aTrsf;
+        gp_Ax3 aPos = aCyl.Position();
+        if (aGeomPlanes[0]->Position().IsCoplanar (aGeomPlanes[1]->Position(), Precision::Angular(), Precision::Angular()))
+        {
+          // cylinders created as a prism have an inverse vector of the cylindrical surface
+          aPos.SetDirection (aPos.Direction().Reversed());
+        }
+        aTrsf.SetTransformation (aPos, gp::XOY());
+
+        Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf);
+        theSelection->Add (aSensSCyl);
+        return Standard_True;
+      }
+    }
+  }
+
+  return Standard_False;
+}
index 45dd97b5db8c6f1e69bfcfd42e82c64e096ad774..1c677fc3dabb5c5f1a468e2c828ce86207410b78 100644 (file)
@@ -28,6 +28,7 @@
 #include <Select3D_SensitiveEntity.hxx>
 #include <Select3D_EntitySequence.hxx>
 #include <StdSelect_BRepOwner.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 class SelectMgr_SelectableObject;
 class TopoDS_Face;
 
@@ -124,14 +125,14 @@ public:
   }
 
   //! Computes the sensitive primitives, stores them in the SelectMgr_Selection object, and returns this object.
-  //! @param theShape        shape to compute sensitive entities
-  //! @param theOwner        selectable owner object
-  //! @param theSelection    selection to append new sensitive entities
-  //! @param theDeflection   linear deflection
-  //! @param theDeflAngle    angular deflection
-  //! @param theNbPOnEdge    sensitivity parameters for edges and wires
-  //! @param theMaxiParam    sensitivity parameters for infinite objects (the default value is 500)
-  //! @param theAutoTriang   flag to compute triangulation for the faces which have none
+  //! @param[in] theShape        shape to compute sensitive entities
+  //! @param[in] theOwner        selectable owner object
+  //! @param[in] theSelection    selection to append new sensitive entities
+  //! @param[in] theDeflection   linear deflection
+  //! @param[in] theDeflAngle    angular deflection
+  //! @param[in] theNbPOnEdge    sensitivity parameters for edges and wires
+  //! @param[in] theMaxiParam    sensitivity parameters for infinite objects (the default value is 500)
+  //! @param[in] theAutoTriang   flag to compute triangulation for the faces which have none
   Standard_EXPORT static void ComputeSensitive (const TopoDS_Shape& theShape,
                                                 const Handle(SelectMgr_EntityOwner)& theOwner,
                                                 const Handle(SelectMgr_Selection)& theSelection,
@@ -142,13 +143,13 @@ public:
                                                 const Standard_Boolean theAutoTriang = Standard_True);
 
   //! Creates the 3D sensitive entities for Face selection.
-  //! @param theFace         face to compute sensitive entities
-  //! @param theOwner        selectable owner object
-  //! @param theOutList      output result list to append created entities
-  //! @param theAutoTriang   obsolete flag (has no effect)
-  //! @param theNbPOnEdge    sensitivity parameters
-  //! @param theMaxiParam    sensitivity parameters
-  //! @param theInteriorFlag flag indicating that face interior (TRUE) or face boundary (FALSE) should be selectable
+  //! @param[in]  theFace         face to compute sensitive entities
+  //! @param[in]  theOwner        selectable owner object
+  //! @param[out] theOutList     output result list to append created entities
+  //! @param[in]  theAutoTriang   obsolete flag (has no effect)
+  //! @param[in]  theNbPOnEdge    sensitivity parameters
+  //! @param[in]  theMaxiParam    sensitivity parameters
+  //! @param[in]  theInteriorFlag flag indicating that face interior (TRUE) or face boundary (FALSE) should be selectable
   Standard_EXPORT static Standard_Boolean GetSensitiveForFace (const TopoDS_Face& theFace,
                                                                const Handle(SelectMgr_EntityOwner)& theOwner,
                                                                Select3D_EntitySequence& theOutList,
@@ -157,14 +158,22 @@ public:
                                                                const Standard_Real theMaxiParam = 500,
                                                                const Standard_Boolean theInteriorFlag = Standard_True);
 
+  //! Creates a sensitive cylinder.
+  //! @param[in] theSubfacesMap map of cylinder faces
+  //! @param[in] theOwner       selectable owner object
+  //! @param[in] theSelection   selection to append new sensitive entities
+  Standard_EXPORT static Standard_Boolean GetSensitiveForCylinder (const TopTools_IndexedMapOfShape& theSubfacesMap,
+                                                                   const Handle(SelectMgr_EntityOwner)& theOwner,
+                                                                   const Handle(SelectMgr_Selection)& theSelection);
+
   //! Create a sensitive edge or sensitive wire.
-  //! @param theShape          either TopoDS_Edge or TopoDS_Wire to compute sensitive entities
-  //! @param theOwner          selectable owner object
-  //! @param theSelection      selection to append new sensitive entities
-  //! @param theDeflection     linear deflection
-  //! @param theDeviationAngle angular deflection
-  //! @param theNbPOnEdge      sensitivity parameters
-  //! @param theMaxiParam      sensitivity parameters
+  //! @param[in]  theShape          either TopoDS_Edge or TopoDS_Wire to compute sensitive entities
+  //! @param[in]  theOwner          selectable owner object
+  //! @param[in]  theSelection      selection to append new sensitive entities
+  //! @param[in]  theDeflection     linear deflection
+  //! @param[in]  theDeviationAngle angular deflection
+  //! @param[in]  theNbPOnEdge      sensitivity parameters
+  //! @param[out] theMaxiParam      sensitivity parameters
   Standard_EXPORT static void GetEdgeSensitive (const TopoDS_Shape& theShape,
                                                 const Handle(SelectMgr_EntityOwner)& theOwner,
                                                 const Handle(SelectMgr_Selection)& theSelection,
index 98ae2e622af82669b08bce9649ab6a4ac8504be0..69481addee3eb31736b377b3a304554df3ced7b9 100644 (file)
 #include <Select3D_SensitiveSegment.hxx>
 #include <Select3D_SensitivePrimitiveArray.hxx>
 #include <Select3D_SensitivePoint.hxx>
+#include <Select3D_SensitivePoly.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <StdPrs_Curve.hxx>
 
@@ -1965,8 +1966,14 @@ public:
   // CASCADE RTTI
   DEFINE_STANDARD_RTTI_INLINE(FilledCircle, AIS_InteractiveObject);
 
-  FilledCircle (const gp_Pnt& theCenter, Standard_Real theRadius);
-  FilledCircle (Handle(Geom_Circle) theCircle);
+  FilledCircle (const Handle(Geom_Circle)& theCircle,
+                const Standard_Real theUStart,
+                const Standard_Real theUEnd);
+
+  FilledCircle (const gp_Pnt& theCenter,
+                const Standard_Real theRadius,
+                const Standard_Real theUStart,
+                const Standard_Real theUEnd);
 
 private:
   TopoDS_Face ComputeFace();
@@ -1982,35 +1989,50 @@ private:
 protected:
 
   Handle(Geom_Circle) myCircle;
-  Standard_Boolean myFilledStatus;
+  Standard_Real       myUStart;
+  Standard_Real       myUEnd;
+  Standard_Boolean    myFilledStatus;
 
 }; 
 
-
-FilledCircle::FilledCircle(const gp_Pnt& theCenter, Standard_Real theRadius) 
-{
-  myCircle = CreateCircle(theCenter, theRadius);
-  myFilledStatus = Standard_True;
-}
-
-FilledCircle::FilledCircle(Handle(Geom_Circle) theCircle) 
-{
-  myCircle = theCircle;
-  myFilledStatus = Standard_True;
-}
-
-TopoDS_Face FilledCircle::ComputeFace() 
+FilledCircle::FilledCircle (const Handle(Geom_Circle)& theCircle,
+                            const Standard_Real theUStart,
+                            const Standard_Real theUEnd)
+: myCircle (theCircle),
+  myUStart (theUStart),
+  myUEnd (theUEnd),
+  myFilledStatus (Standard_True)
+{ }
+
+FilledCircle::FilledCircle (const gp_Pnt& theCenter,
+                            const Standard_Real theRadius,
+                            const Standard_Real theUStart,
+                            const Standard_Real theUEnd)
+: FilledCircle (CreateCircle (theCenter, theRadius), theUStart, theUEnd)
+{ }
+
+TopoDS_Face FilledCircle::ComputeFace()
 {
-  // Create edge from myCircle 
-  BRepBuilderAPI_MakeEdge anEdgeMaker(myCircle->Circ());
-  TopoDS_Edge anEdge = anEdgeMaker.Edge(); 
+  // Create edge from myCircle
+  BRepBuilderAPI_MakeEdge anEdgeMaker (myCircle->Circ(), myUStart, myUEnd);
+  TopoDS_Edge anEdge = anEdgeMaker.Edge();
 
-  // Create wire from anEdge 
-  BRepBuilderAPI_MakeWire aWireMaker(anEdge);
+  // Create wire from anEdge
+  BRepBuilderAPI_MakeWire aWireMaker;
+  if (Abs (Abs (myUEnd - myUStart) - 2.0 * M_PI) > gp::Resolution())
+  {
+    TopoDS_Edge anEndCenterEdge = BRepBuilderAPI_MakeEdge (myCircle->Value (myUEnd), myCircle->Location()).Edge();
+    TopoDS_Edge aStartCenterEdge = BRepBuilderAPI_MakeEdge (myCircle->Location(), myCircle->Value (myUStart)).Edge();
+    aWireMaker = BRepBuilderAPI_MakeWire (anEdge, anEndCenterEdge, aStartCenterEdge);
+  }
+  else
+  {
+    aWireMaker = BRepBuilderAPI_MakeWire (anEdge);
+  }
   TopoDS_Wire aWire = aWireMaker.Wire();
 
   // Create face from aWire
-  BRepBuilderAPI_MakeFace aFaceMaker(aWire);
+  BRepBuilderAPI_MakeFace aFaceMaker (aWire);
   TopoDS_Face aFace = aFaceMaker.Face();
 
   return aFace;
@@ -2030,12 +2052,22 @@ void FilledCircle::Compute (const Handle(PrsMgr_PresentationManager)& ,
   StdPrs_ShadedShape::Add (thePrs, aFace, myDrawer);
 }
 
-void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelection, 
-                                    const Standard_Integer /*theMode*/)
+void FilledCircle::ComputeSelection (const Handle(SelectMgr_Selection) &theSelection,
+                                     const Standard_Integer /*theMode*/)
 {
   Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
-  Handle(Select3D_SensitiveCircle) aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
-  theSelection->Add(aSensitiveCircle);
+  Handle(Select3D_SensitiveEntity) aSensitiveCircle;
+
+  if (Abs (Abs (myUEnd - myUStart) - 2.0 * M_PI) > gp::Resolution())
+  {
+    aSensitiveCircle = new Select3D_SensitivePoly (anEntityOwner, myCircle->Circ(), myUStart, myUEnd, myFilledStatus);
+  }
+  else
+  {
+    aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
+  }
+
+  theSelection->Add (aSensitiveCircle);
 }
 
 //==============================================================================
@@ -2046,51 +2078,63 @@ void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelect
 //==============================================================================
 //function : VCircleBuilder
 //purpose  : Build an AIS_Circle
-//Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled
-//                              PointName PointName PointName IsFilled
+//Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled UStart UEnd
+//                              PointName PointName PointName IsFilled UStart UEnd
 //==============================================================================
 
-void DisplayCircle (Handle (Geom_Circle) theGeomCircle,
-                    TCollection_AsciiString theName, 
-                    Standard_Boolean isFilled) 
+void DisplayCircle (const Handle(Geom_Circle)& theGeomCircle,
+                    const TCollection_AsciiString& theName,
+                    const Standard_Boolean isFilled,
+                    const Standard_Real theUStart,
+                    const Standard_Real theUEnd)
 {
   Handle(AIS_InteractiveObject) aCircle;
-  if (isFilled) 
+  if (isFilled)
   {
-    aCircle = new FilledCircle(theGeomCircle);
+    aCircle = new FilledCircle (theGeomCircle, theUStart, theUEnd);
   }
   else
   {
-    aCircle = new AIS_Circle(theGeomCircle);
-    Handle(AIS_Circle)::DownCast (aCircle)->SetFilledCircleSens (Standard_False);
+    aCircle = new AIS_Circle (theGeomCircle, theUStart, theUEnd, Standard_False);
   }
 
   // Check if there is an object with given name
   // and remove it from context
-  if (GetMapOfAIS().IsBound2(theName)) 
+  if (GetMapOfAIS().IsBound2(theName))
   {
-    Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2(theName);
-    TheAISContext()->Remove(anInterObj, Standard_False);
-    GetMapOfAIS().UnBind2(theName);
+    Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2 (theName);
+    TheAISContext()->Remove (anInterObj, Standard_False);
+    GetMapOfAIS().UnBind2 (theName);
    }
 
    // Bind the circle to its name
-   GetMapOfAIS().Bind(aCircle, theName);
+   GetMapOfAIS().Bind (aCircle, theName);
 
    // Display the circle
    TheAISContext()->Display (aCircle, Standard_True);
-  
 }
 
-static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
+static int VCircleBuilder (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
 {
-  if (argc > 6 || argc < 2)
-  { 
+  if (argc > 8 || argc < 2)
+  {
     Message::SendFail ("Syntax error: wrong number of arguments");
     return 1;
   }
 
-  if (argc == 6) 
+  Standard_Real anUStart = 0, anUEnd = M_PI * 2.0;
+  if (argc == 8)
+  {
+    anUStart = Draw::Atof (argv[6]) * M_PI / 180.0;
+    anUEnd  = Draw::Atof (argv[7]) * M_PI / 180.0;
+  }
+  else if (argc == 4)
+  {
+    anUStart = Draw::Atof (argv[2]) * M_PI / 180.0;
+    anUEnd  = Draw::Atof (argv[3]) * M_PI / 180.0;
+  }
+
+  if (argc == 6 || argc == 8)
   {
     TCollection_AsciiString aName (argv[1]);
     Standard_Boolean isFilled = Draw::Atoi(argv[5]) != 0;
@@ -2159,7 +2203,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
         return 1;
       }
 
-      DisplayCircle (aGeomCircle, aName, isFilled);
+      DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
     }
 
     // Arguments: AIS_Plane AIS_Point Real
@@ -2203,7 +2247,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
         return 1;
       }
 
-      DisplayCircle (aGeomCircle, aName, isFilled);
+      DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
     }
     else
     {
@@ -2263,7 +2307,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
         return 1;
       }
 
-      DisplayCircle (aGeomCircle, aName, isFilled);
+      DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
     }
     else if (aShapeA.ShapeType() == TopAbs_FACE)
     {
@@ -2307,7 +2351,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
         return 1;
       }
 
-      DisplayCircle (aGeomCircle, aName, isFilled);
+      DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
     }
     else
     {
@@ -6914,8 +6958,8 @@ Creates a line from coordinates, named or interactively selected vertices.
 )" /* [vline] */);
 
   addCmd ("vcircle", VCircleBuilder, /* [vcircle] */ R"(
-vcircle CircleName [PointName PointName PointName IsFilled]
-                   [PlaneName PointName Radius IsFilled]
+vcircle CircleName [PointName PointName PointName IsFilled] [UStart UEnd]
+                   [PlaneName PointName Radius IsFilled] [UStart UEnd]
 Creates a circle from named or interactively selected entities.
 Parameter IsFilled is defined as 0 or 1.
 )" /* [vcircle] */);
index b648749d73e17982fadb23b269f9abb9f83b9cda..4b87f97fb681b382c6537c45616a148e7d2c8514 100644 (file)
@@ -113,7 +113,7 @@ vmanipulator m -followRotation 0
 # test rotation around y axis (world reference frame)
 # ---------------------------------------------------
 
-set mouse_pick {211 087}
+set mouse_pick {205 087}
 set mouse_drag {232 127}
 
 vmoveto {*}$mouse_pick
index 7ce18aef2a951f9d811dabd6a1f75102d32e455d..5c0a69e228ab2794122dfaaf938f77dff4078755 100644 (file)
@@ -8,7 +8,7 @@ proc check_output {theInfo} {
   for {set i 0} {$i < $aSize} {incr i} {
     if {[string equal [lindex $theInfo $i] "Depth:"]} {
       set aDepth [lindex $theInfo [expr $i + 1]]
-      if {[string equal $aDepth "17.5691"]} {
+      if {[string equal $aDepth "17.4833"]} {
         return 1
       } else {
         return $aDepth
@@ -35,7 +35,7 @@ set aResult [check_output $anInfo]
 if {$aResult == 1} {
   puts "OK"
   } else {
-    puts "ERROR: the depth value is incorrect: should be 17.5691, but is equal to:"
+    puts "ERROR: the depth value is incorrect: should be 17.4833, but is equal to:"
     puts $aResult
   }
 
diff --git a/tests/vselect/cone_cylinder/circle_sector b/tests/vselect/cone_cylinder/circle_sector
new file mode 100644 (file)
index 0000000..00d6cfe
--- /dev/null
@@ -0,0 +1,46 @@
+puts "================================="
+puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
+puts ""
+puts "================================="
+
+pload VISUALIZATION OPENGL 
+vinit View1 
+
+# Filled circle sector
+vpoint C1P1 10 10 10
+vpoint C1P2 60 60 -10 
+vpoint C1P3 35 100 10 
+vcircle c1 C1P1 C1P2 C1P3 1 90 150
+
+# Circle arc
+vpoint C2P1 10 -10 -10 
+vpoint C2P2 60 -60 10 
+vpoint C2P3 35 -100 10 
+vcircle c2 C2P1 C2P2 C2P3 0 90 150
+
+# Filled circle
+vpoint C3P1 -80 -10 10 
+vpoint C3P2 -140 -50 -10 
+vpoint C3P3 -110 -100 -10 
+vcircle c3 C3P1 C3P2 C3P3 1 0 360
+
+# Circle wire
+vpoint C4P1 -80 10 10 
+vpoint C4P2 -140 60 10 
+vpoint C4P3 -110 100 -10 
+vcircle c4 C4P1 C4P2 C4P3 0 0 360
+
+vbottom
+vfit
+
+vselect 100 100
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: filled circle should be detected" }
+
+vselect 100 225
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle wire should be detected" }
+
+vselect 390 50
+if { ![string match "*Select3D_SensitivePoly*" [vstate -entities]] } { puts "Error: circle arc should be detected" }
+
+vselect 360 350
+if { ![string match "*Select3D_SensitivePoly*" [vstate -entities]] } { puts "Error: circle sector should be detected" }
diff --git a/tests/vselect/cone_cylinder/circle_wire b/tests/vselect/cone_cylinder/circle_wire
new file mode 100644 (file)
index 0000000..5b3b6ea
--- /dev/null
@@ -0,0 +1,67 @@
+puts "================================="
+puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
+puts ""
+puts "================================="
+
+pload VISUALIZATION OPENGL 
+vinit View1 
+
+vpoint radP1 0 0 0 
+vpoint radP2 50 50 0 
+vpoint radP3 100 0 0 
+vcircle circle radP1 radP2 radP3 0 
+vaxo
+vfit
+
+# Single click selection
+# point inside a circle
+vselect 200 200 
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
+
+# point on circle
+vselect 177 285 
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
+
+# point outside a circle
+vselect 360 360
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
+
+
+# Selection with polygon
+# circle inside a polygon
+vselect 50 300 360 300 360 100 50 100 
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a polygon should be detected" }
+
+# circle is partially covered by a polygon
+vselect 250 300 360 300 360 100 250 100 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should not be detected" }
+
+vselect 250 300 360 300 360 100 250 100 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should be detected" }
+
+# polygon inside a circle
+vselect 150 200 200 200 200 150 150 150 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
+
+vselect 150 200 200 200 200 150 150 150 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
+
+
+# Selection with rectangle
+# circle inside a rectangle
+vselect 50 300 360 100
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a rectangle should be detected" }
+
+# circle is partially covered by a rectangle
+vselect 250 300 360 100 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should not be detected" }
+
+vselect 250 300 360 100 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should be detected" }
+
+# rectangle inside a circle
+vselect 150 200 200 150 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }
+
+vselect 150 200 200 150 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }
diff --git a/tests/vselect/cone_cylinder/filled_circle b/tests/vselect/cone_cylinder/filled_circle
new file mode 100644 (file)
index 0000000..9d35f96
--- /dev/null
@@ -0,0 +1,67 @@
+puts "================================="
+puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
+puts ""
+puts "================================="
+
+pload VISUALIZATION OPENGL 
+vinit View1
+
+vpoint radP1 0 0 0 
+vpoint radP2 50 50 0 
+vpoint radP3 100 0 0 
+vcircle circle radP1 radP2 radP3 1 
+vaxo
+vfit
+
+# Single click selection
+# point inside a circle
+vselect 200 200 
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
+
+# point on circle
+vselect 177 279 
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
+
+# point outside a circle
+vselect 360 360
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
+
+
+# Selection with polygon
+# circle inside a polygon
+vselect 50 300 360 300 360 100 50 100 
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a polygon should be detected" }
+
+# circle is partially covered by a polygon
+vselect 250 300 360 300 360 100 250 100 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should not be detected" }
+
+vselect 250 300 360 300 360 100 250 100 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should be detected" }
+
+# polygon inside a circle
+vselect 150 200 200 200 200 150 150 150 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
+
+vselect 150 200 200 200 200 150 150 150 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should be detected" }
+
+
+# Selection with rectangle
+# circle inside a rectangle
+vselect 50 300 360 100
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a rectangle should be detected" }
+
+# circle is partially covered by a rectangle
+vselect 250 300 360 100 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should not be detected" }
+
+vselect 250 300 360 100 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should be detected" }
+
+# rectangle inside a circle
+vselect 150 200 200 150 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }
+
+vselect 150 200 200 150 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should be detected" }
diff --git a/tests/vselect/cone_cylinder/hollow_cone_cyl b/tests/vselect/cone_cylinder/hollow_cone_cyl
new file mode 100644 (file)
index 0000000..4e870ff
--- /dev/null
@@ -0,0 +1,61 @@
+puts "================================="
+puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
+puts " "
+puts "================================="
+
+pload MODELING VISUALIZATION
+pcone      cone 10 5 10
+trotate    cone 0 0 0 1 1 0 30
+ttranslate cone 15 15 0
+
+pcylinder cyl 7 7
+trotate   cyl 0 0 0 1 1 0 30
+
+explode cyl F 
+explode cone F 
+
+vdisplay -dispmode 1 cyl_1 cone_1
+
+vaxo
+vfit
+
+vselect 60 220 140 220 140 190 60 190 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
+
+vselect 60 220 140 220 140 190 60 190 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
+
+vselect 60 220 140 190 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
+
+vselect 60 220 140 190 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
+
+vselect 270 210 310 210 310 160 270 160 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
+
+vselect 270 210 310 210 310 160 270 160 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
+
+vselect 270 210 310 160 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
+
+vselect 270 210 310 160 -allowoverlap 1
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
+
+
+vselect 60 210 310 210 310 200 60 200 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]]} { puts "Error: cone should not be detected" }
+
+vselect 60 210 310 210 310 200 60 200 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCylinder*" [vstate -entities]]
+   && [string first "Select3D_SensitiveCylinder" [vstate -entities]]
+    != [string last "Select3D_SensitiveCylinder" [vstate -entities]]} { puts "Error: cone should be detected" }
+
+vselect 60 210 310 200 -allowoverlap 0
+if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
+
+vselect 60 210 310 200 -allowoverlap 1
+if { ![string match "*Select3D_SensitiveCylinder*" [vstate -entities]]
+   && [string first "Select3D_SensitiveCylinder" [vstate -entities]]
+    != [string last "Select3D_SensitiveCylinder" [vstate -entities]] } { puts "Error: cone should be detected" }
diff --git a/tests/vselect/cone_cylinder/transformed_circle b/tests/vselect/cone_cylinder/transformed_circle
new file mode 100644 (file)
index 0000000..c068dd4
--- /dev/null
@@ -0,0 +1,41 @@
+puts "================================="
+puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
+puts ""
+puts "================================="
+
+pload VISUALIZATION OPENGL 
+vinit View1
+
+vpoint C1P1 10 10 10
+vpoint C1P2 60 60 -10 
+vpoint C1P3 35 100 10 
+vcircle c1 C1P1 C1P2 C1P3 1 
+
+vpoint C2P1 10 -10 -10 
+vpoint C2P2 60 -60 10 
+vpoint C2P3 35 -100 10 
+vcircle c2 C2P1 C2P2 C2P3 1 
+
+vpoint C3P1 -80 -10 10 
+vpoint C3P2 -140 -50 -10 
+vpoint C3P3 -110 -100 -10 
+vcircle c3 C3P1 C3P2 C3P3 1 
+
+vpoint C4P1 -80 10 10 
+vpoint C4P2 -140 60 10 
+vpoint C4P3 -110 100 -10 
+vcircle c4 C4P1 C4P2 C4P3 1 
+
+vbottom
+vfit
+
+vmoveto 100 100
+if {[vreadpixel 100 100 rgb name] != "TURQUOISE"} { puts "ERROR: the circle should be highlighted" }
+
+vmoveto 200 200
+
+vseldump $imagedir/${casename}_selnorm.png -type surfNormal
+
+vsensdis
+
+vseldump $imagedir/${casename}.png
index a87ecd58d49f85a9e934ffee48bd12c7b78bfd9a..4b21f5575b69573fa5a378aa047109782d60772a 100644 (file)
@@ -11,7 +11,7 @@ ttranslate c 2500 3500 1000
 
 vinit View1
 
-# check Select3D_SensitiveTriangulation
+# check Select3D_SensitiveCircle
 vclear
 vaxo
 compound {*}[explode c Sh] cc
@@ -21,7 +21,7 @@ vselaxis 2500 3498 1001 0 1 0 -display a -showNormal
 set aPntTris [vmoveto 200 200]
 vpoint pp {*}$aPntTris
 checkpoint aPntTris_p $aPntTris {2500.42 3499.54 1000.81} 0.1
-if { ![string match "*Select3D_SensitiveTriangulation*" [vstate -entities]] } { puts "Error: triangulation should be detected" }
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
 vfit
 vdump $imagedir/${casename}_prs_tris.png
 vseldump $imagedir/${casename}_selnorm_tris.png -type surfNormal
index 6711eb260936ad0335e6d1cf49d7ef80de256ba1..48dd8373d763d4315a0ad69a6a43b2769c5c7619 100644 (file)
@@ -11,7 +11,7 @@ ttranslate c 2500 3500 1000
 
 vinit View1
 
-# check Select3D_SensitiveTriangulation
+# check Select3D_SensitiveCircle
 vclear
 vaxo
 compound {*}[explode c Sh] cc
@@ -21,7 +21,7 @@ vselaxis 2500 3498 1001 0 1 0 -display a -showNormal
 set aPntTris [vmoveto 200 200]
 vpoint pp {*}$aPntTris
 checkpoint aPntTris_p $aPntTris {2500.9 3499.0 1001.6} 0.1
-if { ![string match "*Select3D_SensitiveTriangulation*" [vstate -entities]] } { puts "Error: triangulation should be detected" }
+if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
 vfit
 vdump $imagedir/${casename}_prs_tris.png
 vseldump $imagedir/${casename}_selnorm_tris.png -type surfNormal