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
#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>
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)
{
}
myComponent (theComponent),
myUStart (theUStart),
myUEnd (theUEnd),
- myCircleIsArc (Standard_True),
+ myCircleIsArc (Abs (Abs (theUEnd - theUStart) - 2.0 * M_PI) > gp::Resolution()),
myIsFilledCircleSens (theIsFilledCircleSens)
{
}
//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);
}
//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);
}
//=======================================================================
//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);
}
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
}
// 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
//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);
}
#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>
//=======================================================================
//function : ComputeSelection
-//purpose :
+//purpose :
//=======================================================================
-void PrsDim_EqualDistanceRelation::ComputeSelection( const 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);
}
}
#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
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;
}
//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());
}
#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
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)
{
}
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;
}
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,
//! 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
#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 :
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();
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();
const Standard_Boolean theIsBVHEnabled,
const Standard_Integer theNbPnts)
: Select3D_SensitiveSet (theOwnerId),
- myPolyg (theNbPnts)
+ myPolyg (theNbPnts),
+ mySensType (Select3D_TOS_BOUNDARY)
{
if (theIsBVHEnabled)
{
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
#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
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;
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)
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
#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>
}
}
+ //! 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);
}
}
}
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))
{
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;
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))
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))
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);
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))
{
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)
{
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)
{
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))
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))
{
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))
{
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;
}
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 :
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;
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.
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;
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 :
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;
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
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:
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:
//! 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,
-// Created on: 2015-03-16
+// Created on: 2015-03-16
// Created by: Varvara POSKONINA
// Copyright (c) 2005-2014 OPEN CASCADE SAS
//
// 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;
}
// =======================================================================
-// 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);
// 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)
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 :
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;
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)
{
}
}
- 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)
{
bool isCylInsideRec = true;
for (int i = 0; i < 6; ++i)
{
- isCylInsideRec &= IsDotInside (aPoints[i], aVertices);
+ isCylInsideRec &= isDotInside (aPoints[i], aVertices);
}
if (theInside != NULL)
{
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 :
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
+ const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
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;
}
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 :
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);
}
// =======================================================================
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;
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;
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.
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);
}
//=======================================================================
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);
}
//=======================================================================
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
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;
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);
}
//=======================================================================
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);
}
// =======================================================================
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;
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
#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>
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
+ const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
"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;
}
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));
{
aVertices[anIdx] = anIter.Value()->myVertices[anIdx];
}
- if (anIter.Value()->IsDotInside (aPoints[i], aVertices))
+ if (anIter.Value()->isDotInside (aPoints[i], aVertices))
{
isInside = true;
break;
}
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;
}
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 :
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 :
// 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;
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;
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;
//! 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
};
#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>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
#define BVH_PRIMITIVE_LIMIT 800000
case TopAbs_FACE:
{
const TopoDS_Face& aFace = TopoDS::Face (theShape);
+
Select3D_EntitySequence aSensitiveList;
GetSensitiveForFace (aFace, theOwner,
aSensitiveList,
{
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;
}
}
else
{
- theSensitive = new Select3D_SensitiveCircle (theOwner, aCircle,
- aParamFirst, aParamLast, Standard_False, 16);
+ theSensitive = new Select3D_SensitivePoly (theOwner, aCircle, aParamFirst, aParamLast, Standard_False);
}
break;
}
}
}
+//=======================================================================
+//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 :
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;
}
else
{
- theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag, 16));
+ theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag));
}
}
}
}
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;
+}
#include <Select3D_SensitiveEntity.hxx>
#include <Select3D_EntitySequence.hxx>
#include <StdSelect_BRepOwner.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
class SelectMgr_SelectableObject;
class TopoDS_Face;
}
//! 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,
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,
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,
#include <Select3D_SensitiveSegment.hxx>
#include <Select3D_SensitivePrimitiveArray.hxx>
#include <Select3D_SensitivePoint.hxx>
+#include <Select3D_SensitivePoly.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <StdPrs_Curve.hxx>
// 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();
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;
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);
}
//==============================================================================
//==============================================================================
//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;
return 1;
}
- DisplayCircle (aGeomCircle, aName, isFilled);
+ DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
// Arguments: AIS_Plane AIS_Point Real
return 1;
}
- DisplayCircle (aGeomCircle, aName, isFilled);
+ DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else
{
return 1;
}
- DisplayCircle (aGeomCircle, aName, isFilled);
+ DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else if (aShapeA.ShapeType() == TopAbs_FACE)
{
return 1;
}
- DisplayCircle (aGeomCircle, aName, isFilled);
+ DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else
{
)" /* [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] */);
# 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
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
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
}
--- /dev/null
+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" }
--- /dev/null
+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" }
--- /dev/null
+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" }
--- /dev/null
+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" }
--- /dev/null
+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
vinit View1
-# check Select3D_SensitiveTriangulation
+# check Select3D_SensitiveCircle
vclear
vaxo
compound {*}[explode c Sh] cc
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
vinit View1
-# check Select3D_SensitiveTriangulation
+# check Select3D_SensitiveCircle
vclear
vaxo
compound {*}[explode c Sh] cc
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