1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder

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
This commit is contained in:
mzernova 2022-08-18 17:12:03 +03:00 committed by smoskvin
parent da76ea432b
commit 7aaed2ce3b
38 changed files with 2117 additions and 784 deletions

View File

@ -27,6 +27,7 @@
#include <Prs3d_Presentation.hxx>
#include <Quantity_Color.hxx>
#include <Select3D_SensitiveCircle.hxx>
#include <Select3D_SensitivePoly.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_Selection.hxx>
#include <Standard_Type.hxx>
@ -41,9 +42,9 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_Circle,AIS_InteractiveObject)
AIS_Circle::AIS_Circle(const Handle(Geom_Circle)& aComponent):
AIS_InteractiveObject(PrsMgr_TOP_AllView),
myComponent(aComponent),
myUStart(0.),
myUEnd(2*M_PI),
myCircleIsArc(Standard_False),
myUStart (0.0),
myUEnd (2.0 * M_PI),
myCircleIsArc (Standard_False),
myIsFilledCircleSens (Standard_False)
{
}
@ -60,7 +61,7 @@ AIS_Circle::AIS_Circle(const Handle(Geom_Circle)& theComponent,
myComponent (theComponent),
myUStart (theUStart),
myUEnd (theUEnd),
myCircleIsArc (Standard_True),
myCircleIsArc (Abs (Abs (theUEnd - theUStart) - 2.0 * M_PI) > gp::Resolution()),
myIsFilledCircleSens (theIsFilledCircleSens)
{
}
@ -207,14 +208,14 @@ void AIS_Circle::UnsetWidth()
//function : ComputeCircle
//purpose :
//=======================================================================
void AIS_Circle::ComputeCircle( const Handle(Prs3d_Presentation)& aPresentation)
void AIS_Circle::ComputeCircle (const Handle(Prs3d_Presentation)& thePresentation)
{
GeomAdaptor_Curve curv(myComponent);
Standard_Real prevdev = myDrawer->DeviationCoefficient();
myDrawer->SetDeviationCoefficient(1.e-5);
StdPrs_DeflectionCurve::Add(aPresentation,curv,myDrawer);
myDrawer->SetDeviationCoefficient(prevdev);
myDrawer->SetDeviationCoefficient (1.e-5);
StdPrs_DeflectionCurve::Add (thePresentation, curv, myDrawer);
myDrawer->SetDeviationCoefficient (prevdev);
}
@ -223,13 +224,13 @@ void AIS_Circle::ComputeCircle( const Handle(Prs3d_Presentation)& aPresentation)
//purpose :
//=======================================================================
void AIS_Circle::ComputeArc( const Handle(Prs3d_Presentation)& aPresentation)
void AIS_Circle::ComputeArc (const Handle(Prs3d_Presentation)& thePresentation)
{
GeomAdaptor_Curve curv(myComponent,myUStart,myUEnd);
GeomAdaptor_Curve curv(myComponent, myUStart, myUEnd);
Standard_Real prevdev = myDrawer->DeviationCoefficient();
myDrawer->SetDeviationCoefficient(1.e-5);
StdPrs_DeflectionCurve::Add(aPresentation,curv,myDrawer);
myDrawer->SetDeviationCoefficient(prevdev);
myDrawer->SetDeviationCoefficient (1.e-5);
StdPrs_DeflectionCurve::Add (thePresentation, curv, myDrawer);
myDrawer->SetDeviationCoefficient (prevdev);
}
//=======================================================================
@ -237,27 +238,25 @@ void AIS_Circle::ComputeArc( const Handle(Prs3d_Presentation)& aPresentation)
//purpose :
//=======================================================================
void AIS_Circle::ComputeCircleSelection(const Handle(SelectMgr_Selection)& aSelection)
void AIS_Circle::ComputeCircleSelection (const Handle(SelectMgr_Selection)& theSelection)
{
Handle(SelectMgr_EntityOwner) eown = new SelectMgr_EntityOwner(this);
Handle(Select3D_SensitiveCircle) seg = new Select3D_SensitiveCircle (eown,
Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner(this);
Handle(Select3D_SensitiveCircle) aCirc = new Select3D_SensitiveCircle (anOwner,
myComponent->Circ(),
myIsFilledCircleSens);
aSelection->Add(seg);
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,
Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner(this);
Handle(Select3D_SensitivePoly) aSeg = new Select3D_SensitivePoly (anOwner,
myComponent->Circ(),
myUStart, myUEnd,
myIsFilledCircleSens);
aSelection->Add(seg);
theSelection->Add (aSeg);
}

View File

@ -84,9 +84,8 @@ namespace
public:
//! Main constructor.
ManipSensCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
const gp_Circ& theCircle,
const Standard_Integer theNbPnts)
: Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False, theNbPnts),
const gp_Circ& theCircle)
: Select3D_SensitiveCircle (theOwnerId, theCircle, Standard_False),
ManipSensRotation (theCircle.Position().Direction()) {}
//! Checks whether the circle overlaps current selecting volume
@ -1168,7 +1167,7 @@ void AIS_Manipulator::ComputeSelection (const Handle(SelectMgr_Selection)& theSe
}
// define sensitivity by circle
const gp_Circ aGeomCircle (gp_Ax2 (gp::Origin(), anAxis.ReferenceAxis().Direction()), anAxis.RotatorDiskRadius());
Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle, anAxis.FacettesNumber());
Handle(Select3D_SensitiveCircle) aCircle = new ManipSensCircle (anOwner, aGeomCircle);
aCircle->SetSensitivityFactor (15);
theSelection->Add (aCircle);
// enlarge sensitivity by triangulation

View File

@ -213,37 +213,39 @@ void PrsDim_ConcentricRelation::ComputeTwoEdgesConcentric(const Handle(Prs3d_Pre
//purpose :
//=======================================================================
void PrsDim_ConcentricRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
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);
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 (own, aCirc);
aSelection->Add(sensit);
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,
seg = new Select3D_SensitiveSegment(anOwner,
otherPnt,
myPnt);
aSelection->Add(seg);
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,
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);
aSelection->Add (seg);
}

View File

@ -36,7 +36,7 @@
#include <Prs3d_Drawer.hxx>
#include <Prs3d_Presentation.hxx>
#include <Select3D_SensitiveBox.hxx>
#include <Select3D_SensitiveCircle.hxx>
#include <Select3D_SensitivePoly.hxx>
#include <Select3D_SensitiveSegment.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <TopoDS_Edge.hxx>
@ -205,121 +205,138 @@ void PrsDim_EqualDistanceRelation::Compute (const Handle(PrsMgr_PresentationMana
//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 ),
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,
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);
Middle.Z() + SmallDist);
aSelection->Add (box);
if (myFShape.ShapeType() == TopAbs_EDGE){
if (myFShape.ShapeType() == TopAbs_EDGE)
{
BRepAdaptor_Curve aCurve(TopoDS::Edge(myFShape));
if (aCurve.GetType() == GeomAbs_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 );
aSelection->Add (seg);
}
if (mySShape.ShapeType() == TopAbs_EDGE){
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);
}
}

View File

@ -16,195 +16,29 @@
#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))
{
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());
}
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)
: Select3D_SensitiveEntity (theOwnerId)
{
myRadius = theCircle.Radius();
myTrsf.SetTransformation (theCircle.Position(), gp::XOY());
mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
if (myPolyg.Size() != 1)
computeCenter3D();
else
myCenter3D = myPolyg.Pnt (0);
if (mySensType == Select3D_TOS_BOUNDARY)
{
SetSensitivityFactor (6);
}
}
//=======================================================================
//function : Select3D_SensitiveCircle
//purpose :
//=======================================================================
Select3D_SensitiveCircle::Select3D_SensitiveCircle(const Handle(SelectMgr_EntityOwner)& theOwnerId,
const TColgp_Array1OfPnt& thePnts3d,
const Standard_Boolean theIsFilled)
: Select3D_SensitivePoly (theOwnerId, thePnts3d, !theIsFilled),
myStart (0),
myEnd (0)
{
mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
if (myPolyg.Size() != 1)
computeCenter3D();
else
myCenter3D = myPolyg.Pnt (0);
if (mySensType == Select3D_TOS_BOUNDARY)
{
SetSensitivityFactor (6);
}
}
//=======================================================================
// function : BVH
// purpose : Builds BVH tree for a circle's edge segments if needed
//=======================================================================
void Select3D_SensitiveCircle::BVH()
{
if (mySensType == Select3D_TOS_BOUNDARY)
{
Select3D_SensitivePoly::BVH();
}
}
//=======================================================================
// function : ToBuildBVH
// purpose :
//=======================================================================
Standard_Boolean Select3D_SensitiveCircle::ToBuildBVH() const
{
if (mySensType != Select3D_TOS_BOUNDARY)
{
return Standard_False;
}
return Select3D_SensitivePoly::ToBuildBVH();
}
//=======================================================================
// function : Matches
// purpose : Checks whether the circle overlaps current selecting volume
@ -212,40 +46,26 @@ Standard_Boolean Select3D_SensitiveCircle::ToBuildBVH() const
Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
if (mySensType == Select3D_TOS_BOUNDARY)
const Standard_Boolean aIsFilled = mySensType == Select3D_TOS_INTERIOR;
if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
{
if (!Select3D_SensitivePoly::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);
bool isInside = true;
return theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, &isInside) && isInside;
}
for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
else
{
if (!theMgr.OverlapsPoint (anArrayOfPnt->Value(aPntIdx)))
{
return Standard_False;
return theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, NULL);
}
}
return Standard_True;
if (!theMgr.OverlapsCircle (myRadius, myTrsf, aIsFilled, thePickResult))
{
return false;
}
if (!theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), Select3D_TOS_INTERIOR, thePickResult))
{
return Standard_False;
}
thePickResult.SetDistToGeomCenter(distanceToCOG(theMgr));
}
thePickResult.SetDistToGeomCenter (theMgr.DistToGeometryCenter (CenterOfGeometry()));
return Standard_True;
}
@ -254,81 +74,36 @@ Standard_Boolean Select3D_SensitiveCircle::Matches (SelectBasics_SelectingVolume
//function : GetConnected
//purpose :
//=======================================================================
Handle(Select3D_SensitiveEntity) Select3D_SensitiveCircle::GetConnected()
{
Standard_Boolean isFilled = mySensType == Select3D_TOS_INTERIOR;
// Create a copy of this
Handle(Select3D_SensitiveEntity) aNewEntity;
// this was constructed using Handle(Geom_Circle)
if (!Precision::IsInfinite (myCircle.Radius()))
{
if ((myEnd - myStart) > Precision::Confusion())
{
// Arc
aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, myStart, myEnd, isFilled);
}
else
{
// Circle
aNewEntity = new Select3D_SensitiveCircle (myOwnerId, myCircle, isFilled);
}
}
// this was constructed using TColgp_Array1OfPnt
else
{
Standard_Integer aSize = myPolyg.Size();
TColgp_Array1OfPnt aPolyg (1, aSize);
for(Standard_Integer anIndex = 1; anIndex <= aSize; ++anIndex)
{
aPolyg.SetValue(anIndex, myPolyg.Pnt (anIndex-1));
}
aNewEntity = new Select3D_SensitiveCircle (myOwnerId, aPolyg, isFilled);
}
Standard_Boolean anIsFilled = mySensType == Select3D_TOS_INTERIOR;
Handle(Select3D_SensitiveEntity) aNewEntity = new Select3D_SensitiveCircle (myOwnerId,
Circle(),
anIsFilled);
return aNewEntity;
}
//=======================================================================
//function : computeCenter3D
//purpose :
//=======================================================================
void Select3D_SensitiveCircle::computeCenter3D()
//==================================================
// Function: BoundingBox
// Purpose :
//==================================================
Select3D_BndBox3d Select3D_SensitiveCircle::BoundingBox()
{
gp_XYZ aCenter;
Standard_Integer aNbPnts = myPolyg.Size();
if (aNbPnts != 1)
{
// The mass of points system
Standard_Integer aMass = aNbPnts - 1;
// Find the circle barycenter
for (Standard_Integer anIndex = 0; anIndex < aNbPnts - 1; ++anIndex)
{
aCenter += myPolyg.Pnt(anIndex);
}
myCenter3D = aCenter / aMass;
}
else
{
myCenter3D = myPolyg.Pnt(0);
}
Graphic3d_Mat4d aTrsf;
myTrsf.GetMat4 (aTrsf);
Select3D_BndBox3d aBox (SelectMgr_Vec3 (-myRadius, -myRadius, 0),
SelectMgr_Vec3 (myRadius, myRadius, 0));
aBox.Transform (aTrsf);
return aBox;
}
//=======================================================================
// function : CenterOfGeometry
// purpose : Returns center of the circle. If location transformation
// is set, it will be applied
//=======================================================================
//==================================================
// Function: CenterOfGeometry
// Purpose :
//==================================================
gp_Pnt Select3D_SensitiveCircle::CenterOfGeometry() const
{
return myCenter3D;
}
//=======================================================================
// function : distanceToCOG
// purpose :
//=======================================================================
Standard_Real Select3D_SensitiveCircle::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
{
return theMgr.DistToGeometryCenter (myCenter3D);
return gp_Pnt (myTrsf.TranslationPart());
}

View File

@ -17,93 +17,70 @@
#ifndef _Select3D_SensitiveCircle_HeaderFile
#define _Select3D_SensitiveCircle_HeaderFile
#include <gp_Circ.hxx>
#include <Select3D_SensitivePoly.hxx>
#include <Select3D_TypeOfSensitivity.hxx>
#include <SelectMgr_SelectingVolumeManager.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <Select3D_SensitiveEntity.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
#include <gp_Circ.hxx>
//! 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 and the boolean theIsFilled.
Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
const gp_Circ& theCircle,
const Standard_Boolean theIsFilled = Standard_False);
//! Constructs the sensitive circle object defined by the
//! owner theOwnerId, the circle theCircle, the boolean
//! theIsFilled and the number of points theNbPnts.
Standard_EXPORT Select3D_SensitiveCircle (const Handle(SelectMgr_EntityOwner)& theOwnerId,
Standard_DEPRECATED("Deprecated constructor, theNbPnts parameter will be ignored")
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);
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
//! Returns bounding box of the circle.
//! If location transformation is set, it will be applied
Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
//! Always returns Standard_False
virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE { return Standard_False; }
//! Returns the amount of points
virtual Standard_Integer NbSubElements() const Standard_OVERRIDE { return 1; }
//! Returns center of the circle with transformation applied
Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE;
//! Builds BVH tree for a circle's edge segments if needed
Standard_EXPORT virtual void BVH() 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; }
//! Returns TRUE if BVH tree is in invalidated state
Standard_EXPORT virtual Standard_Boolean ToBuildBVH() const Standard_OVERRIDE;
//! Returns circle
gp_Circ Circle() const { return gp_Circ (gp::XOY().Transformed (myTrsf), myRadius); }
protected:
//! 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;
//! Returns circle radius
Standard_Real Radius() const { return myRadius; }
private:
//! Computes myCenter3D as the barycenter of points from mypolyg3d
void computeCenter3D();
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

View File

@ -25,12 +25,14 @@ Select3D_SensitiveCylinder::Select3D_SensitiveCylinder (const Handle(SelectMgr_E
const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf)
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow)
: Select3D_SensitiveEntity (theOwnerId),
myTrsf (theTrsf),
myBottomRadius (theBottomRad),
myTopRadius (theTopRad),
myHeight (theHeight)
myHeight (theHeight),
myIsHollow (theIsHollow)
{
}
@ -46,14 +48,14 @@ Standard_Boolean Select3D_SensitiveCylinder::Matches (SelectBasics_SelectingVolu
if (!theMgr.IsOverlapAllowed())
{
bool isInside = true;
return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, &isInside) && isInside;
return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, &isInside) && isInside;
}
else
{
return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, NULL);
return theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, NULL);
}
}
if (!theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, thePickResult))
if (!theMgr.OverlapsCylinder (myBottomRadius, myTopRadius, myHeight, myTrsf, myIsHollow, thePickResult))
{
return false;
}

View File

@ -32,7 +32,8 @@ public:
const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf);
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow = Standard_False);
//! Checks whether the cylinder overlaps current selecting volume
Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
@ -66,11 +67,15 @@ public:
//! Returns cylinder height
Standard_Real Height() const { return myHeight; }
//! Returns true if the cylinder is empty inside
Standard_Boolean IsHollow() const { return myIsHollow; }
protected:
gp_Trsf myTrsf; //!< cylinder transformation to apply
Standard_Real myBottomRadius; //!< cylinder bottom radius
Standard_Real myTopRadius; //!< cylinder top radius
Standard_Real myHeight; //!< cylinder height
Standard_Boolean myIsHollow; //!< true if the cylinder is empty inside
};
#endif // _Select3D_SensitiveSphere_HeaderFile

View File

@ -13,8 +13,71 @@
#include <Select3D_SensitivePoly.hxx>
#include <ElCLib.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePoly,Select3D_SensitiveSet)
namespace
{
static Standard_Integer GetCircleNbPoints (const gp_Circ& theCircle,
const Standard_Integer theNbPnts,
const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Boolean theIsFilled)
{
// Check if number of points is invalid.
// In this case myPolyg raises Standard_ConstructionError
// exception (see constructor below).
if (theNbPnts <= 0)
{
return 0;
}
if (theCircle.Radius() > Precision::Confusion())
{
const Standard_Boolean isSector = theIsFilled && Abs (Abs (theU2 - theU1) - 2.0 * M_PI) > gp::Resolution();
return 2 * theNbPnts + 1 + (isSector ? 2 : 0);
}
// The radius is too small and circle degenerates into point
return 1;
}
//! Definition of circle polyline
static void initCircle (Select3D_PointData& thePolygon,
const gp_Circ& theCircle,
const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Boolean theIsFilled,
const Standard_Integer theNbPnts)
{
const Standard_Real aStep = (theU2 - theU1) / theNbPnts;
const Standard_Real aRadius = theCircle.Radius();
Standard_Integer aPntIdx = 0;
Standard_Real aCurU = theU1;
gp_Pnt aP1;
gp_Vec aV1;
const Standard_Boolean isSector = Abs (theU2 - theU1 - 2.0 * M_PI) > gp::Resolution();
if (isSector && theIsFilled) { thePolygon.SetPnt (aPntIdx++, theCircle.Location()); }
for (Standard_Integer anIndex = 1; anIndex <= theNbPnts; ++anIndex, aCurU += aStep)
{
ElCLib::CircleD1 (aCurU, theCircle.Position(), theCircle.Radius(), aP1, aV1);
thePolygon.SetPnt (aPntIdx++, aP1);
aV1.Normalize();
const gp_Pnt aP2 = aP1.XYZ() + aV1.XYZ() * Tan (aStep * 0.5) * aRadius;
thePolygon.SetPnt (aPntIdx++, aP2);
}
aP1 = ElCLib::CircleValue (theU2, theCircle.Position(), theCircle.Radius());
thePolygon.SetPnt (aPntIdx++, aP1);
if (isSector && theIsFilled) { thePolygon.SetPnt (aPntIdx++, theCircle.Location()); }
}
}
//==================================================
// Function: Select3D_SensitivePoly
// Purpose :
@ -23,7 +86,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
const TColgp_Array1OfPnt& thePoints,
const Standard_Boolean theIsBVHEnabled)
: Select3D_SensitiveSet (theOwnerId),
myPolyg (thePoints.Upper() - thePoints.Lower() + 1)
myPolyg (thePoints.Upper() - thePoints.Lower() + 1),
mySensType (Select3D_TOS_BOUNDARY)
{
Standard_Integer aLowerIdx = thePoints.Lower();
Standard_Integer anUpperIdx = thePoints.Upper();
@ -64,7 +128,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
const Handle(TColgp_HArray1OfPnt)& thePoints,
const Standard_Boolean theIsBVHEnabled)
: Select3D_SensitiveSet (theOwnerId),
myPolyg (thePoints->Upper() - thePoints->Lower() + 1)
myPolyg (thePoints->Upper() - thePoints->Lower() + 1),
mySensType (Select3D_TOS_BOUNDARY)
{
Standard_Integer aLowerIdx = thePoints->Lower();
Standard_Integer anUpperIdx = thePoints->Upper();
@ -105,7 +170,8 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
const Standard_Boolean theIsBVHEnabled,
const Standard_Integer theNbPnts)
: Select3D_SensitiveSet (theOwnerId),
myPolyg (theNbPnts)
myPolyg (theNbPnts),
mySensType (Select3D_TOS_BOUNDARY)
{
if (theIsBVHEnabled)
{
@ -119,6 +185,80 @@ Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwn
myIsComputed = Standard_False;
}
//==================================================
// Function: Creation
// Purpose :
//==================================================
Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
const gp_Circ& theCircle,
const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Boolean theIsFilled,
const Standard_Integer theNbPnts)
: Select3D_SensitivePoly (theOwnerId, !theIsFilled, GetCircleNbPoints (theCircle, theNbPnts, theU1, theU2, theIsFilled))
{
mySensType = theIsFilled ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
if (myPolyg.Size() != 1)
{
initCircle (myPolyg, theCircle, Min (theU1, theU2), Max (theU1, theU2), theIsFilled, theNbPnts);
}
else
{
myPolyg.SetPnt (0, theCircle.Position().Location());
}
if (!theIsFilled)
{
SetSensitivityFactor (6);
}
}
//=======================================================================
// function : Matches
// purpose :
//=======================================================================
Standard_Boolean Select3D_SensitivePoly::Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult)
{
if (mySensType == Select3D_TOS_BOUNDARY)
{
if (!Select3D_SensitiveSet::Matches (theMgr, thePickResult))
{
return Standard_False;
}
}
else if (mySensType == Select3D_TOS_INTERIOR)
{
Handle(TColgp_HArray1OfPnt) anArrayOfPnt;
Points3D (anArrayOfPnt);
if (!theMgr.IsOverlapAllowed())
{
if (theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Polyline)
{
SelectBasics_PickResult aDummy;
return theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), mySensType, aDummy);
}
for (Standard_Integer aPntIdx = anArrayOfPnt->Lower(); aPntIdx <= anArrayOfPnt->Upper(); ++aPntIdx)
{
if (!theMgr.OverlapsPoint (anArrayOfPnt->Value(aPntIdx)))
{
return Standard_False;
}
}
return Standard_True;
}
if (!theMgr.OverlapsPolygon (anArrayOfPnt->Array1(), Select3D_TOS_INTERIOR, thePickResult))
{
return Standard_False;
}
thePickResult.SetDistToGeomCenter (distanceToCOG(theMgr));
}
return Standard_True;
}
//==================================================
// function : BoundingBox
// purpose : Returns bounding box of a polygon. If location

View File

@ -14,13 +14,13 @@
#ifndef _Select3D_SensitivePoly_HeaderFile
#define _Select3D_SensitivePoly_HeaderFile
#include <gp_Circ.hxx>
#include <Select3D_PointData.hxx>
#include <Select3D_SensitiveSet.hxx>
#include <Select3D_TypeOfSensitivity.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#include <TColgp_HArray1OfPnt.hxx>
//! Sensitive Entity to make a face selectable.
//! In some cases this class can raise Standard_ConstructionError and
//! Standard_OutOfRange exceptions from its member Select3D_PointData
@ -46,13 +46,28 @@ public:
const Handle(TColgp_HArray1OfPnt)& thePoints,
const Standard_Boolean theIsBVHEnabled);
//! Constructs the sensitive circle object defined by the
//! owner OwnerId, the circle Circle, the Boolean
//! FilledCircle and the number of points NbOfPoints.
//! Constructs the sensitive arc object defined by the
//! owner theOwnerId, the circle theCircle, the parameters theU1
//! and theU2, the boolean theIsFilled and the number of points theNbPnts.
//! theU1 and theU2 define the first and last points of the arc on theCircle.
Standard_EXPORT Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
const gp_Circ& theCircle,
const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Boolean theIsFilled = Standard_False,
const Standard_Integer theNbPnts = 12);
//! Constructs a sensitive curve or arc object defined by the
//! owner theOwnerId, the theIsBVHEnabled flag, and the
//! maximum number of points on the curve: theNbPnts.
Standard_EXPORT Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
const Standard_Boolean theIsBVHEnabled,
const Standard_Integer theNbPnts = 6);
//! Checks whether the poly overlaps current selecting volume
Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
//! Returns the amount of segments in poly
Standard_EXPORT virtual Standard_Integer NbSubElements() const Standard_OVERRIDE;
@ -132,6 +147,7 @@ protected:
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
};

View File

@ -96,19 +96,39 @@ public:
Standard_Boolean* theInside = NULL) const = 0;
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
//! and theTopRad, height theHeight and transformation to apply theTrsf.
//! and theTopRad, height theHeight, the boolean theIsHollow and transformation to apply theTrsf.
virtual Standard_Boolean OverlapsCylinder (const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
SelectBasics_PickResult& thePickResult) const = 0;
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
//! and theTopRad, height theHeight and transformation to apply theTrsf.
//! and theTopRad, height theHeight, the boolean theIsHollow and transformation to apply theTrsf.
virtual Standard_Boolean OverlapsCylinder (const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const = 0;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! the boolean theIsFilled, and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
SelectBasics_PickResult& thePickResult) const = 0;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! the boolean theIsFilled, and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const = 0;
public:

View File

@ -23,6 +23,7 @@
#include <TColgp_HArray1OfPnt.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include <Select3D_SensitiveBox.hxx>
#include <Select3D_SensitiveCircle.hxx>
#include <Select3D_SensitiveCylinder.hxx>
#include <Select3D_SensitiveEntity.hxx>
#include <Select3D_SensitiveFace.hxx>
@ -133,41 +134,56 @@ namespace
}
}
//! Fill in circle polylines.
static void addCircle (Prs3d_NListOfSequenceOfPnt& theSeqLines,
const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Real theHeight = 0)
{
const Standard_Real anUStep = 0.1;
gp_XYZ aVec (0, 0, theHeight);
Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
Geom_Circle aGeom (gp_Ax2(), theRadius);
for (Standard_Real anU = 0.0f; anU < (2.0 * M_PI + anUStep); anU += anUStep)
{
gp_Pnt aCircPnt = aGeom.Value (anU).Coord() + aVec;
aCircPnt.Transform (theTrsf);
aPoints->Append (aCircPnt);
}
theSeqLines.Append (aPoints);
}
//! Fill in cylinder polylines.
static void addCylinder (Prs3d_NListOfSequenceOfPnt& theSeqLines,
const Handle(Select3D_SensitiveCylinder)& theSensCyl)
const Handle(Select3D_SensitiveCylinder)& theSensCyl,
const gp_Trsf& theLoc)
{
Handle(TColgp_HSequenceOfPnt) aVertLines[2];
aVertLines[0] = new TColgp_HSequenceOfPnt();
aVertLines[1] = new TColgp_HSequenceOfPnt();
const gp_Trsf& aTrsf = theSensCyl->Transformation();
Handle(TColgp_HSequenceOfPnt) aVertLine1 = new TColgp_HSequenceOfPnt();
Handle(TColgp_HSequenceOfPnt) aVertLine2 = new TColgp_HSequenceOfPnt();
const gp_Trsf& aTrsf = theLoc.Multiplied (theSensCyl->Transformation());
const Standard_Real aHeight = theSensCyl->Height();
const Standard_Real anUStep = 0.1;
for (int aCircNum = 0; aCircNum < 3; aCircNum++)
{
Standard_Real aRadius = 0.5 * (2 - aCircNum) * theSensCyl->BottomRadius()
+ 0.5 * aCircNum * theSensCyl->TopRadius();
Geom_Circle aGeom (gp_Ax2(), aRadius);
Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
gp_XYZ aVec (0, 0, aHeight * 0.5 * aCircNum);
const gp_XYZ aVec (0, 0, aHeight * 0.5 * aCircNum);
if (aCircNum != 1)
{
aVertLines[0]->Append (gp_Pnt(aGeom.Value (0).Coord() + aVec).Transformed (aTrsf));
aVertLines[1]->Append (gp_Pnt(aGeom.Value (M_PI).Coord() + aVec).Transformed (aTrsf));
aVertLine1->Append (gp_Pnt (gp_XYZ (aRadius, 0, 0) + aVec).Transformed (aTrsf));
aVertLine2->Append (gp_Pnt (gp_XYZ (-aRadius, 0, 0) + aVec).Transformed (aTrsf));
}
for (Standard_Real anU = 0.0f; anU < (2.0 * M_PI + anUStep); anU += anUStep)
if (aRadius > Precision::Confusion())
{
gp_Pnt aCircPnt = aGeom.Value (anU).Coord() + aVec;
aCircPnt.Transform (aTrsf);
aPoints->Append (aCircPnt);
addCircle (theSeqLines, aRadius, aTrsf, aVec.Z());
}
theSeqLines.Append (aPoints);
}
theSeqLines.Append (aVertLines[0]);
theSeqLines.Append (aVertLines[1]);
theSeqLines.Append (aVertLine1);
theSeqLines.Append (aVertLine2);
}
}
@ -193,7 +209,11 @@ void SelectMgr::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& thePrs,
}
else if (Handle(Select3D_SensitiveCylinder) aSensCyl = Handle(Select3D_SensitiveCylinder)::DownCast (anEnt))
{
addCylinder (aSeqLines, aSensCyl);
addCylinder (aSeqLines, aSensCyl, theLoc);
}
else if (Handle(Select3D_SensitiveCircle) aSensCircle = Handle(Select3D_SensitiveCircle)::DownCast (anEnt))
{
addCircle (aSeqLines, aSensCircle->Radius(), theLoc.Multiplied (aSensCircle->Transformation()));
}
else if (Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(anEnt))
{

View File

@ -227,7 +227,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
(void )theInside;
Standard_Real aTimeEnter, aTimeLeave;
@ -252,7 +252,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
Standard_Real aTimeEnter, aTimeLeave;
if (!hasIntersection (theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
@ -283,7 +283,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
Standard_Real aDepth = 0.0;
if (!hasIntersection (thePnt, aDepth))
@ -304,7 +304,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
Standard_Real aDepth = 0.0;
return hasIntersection (thePnt, aDepth);
@ -320,7 +320,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSegment (const gp_Pnt& thePn
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsSegment() should be called after selection axis initialization");
if (!raySegmentDistance (thePnt1, thePnt2, thePickResult))
{
@ -340,7 +340,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPolygon (const TColgp_Array1
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsPolygon() should be called after selection axis initialization");
if (theSensType == Select3D_TOS_BOUNDARY)
{
@ -400,7 +400,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsTriangle() should be called after selection axis initialization");
if (theSensType == Select3D_TOS_BOUNDARY)
{
@ -503,7 +503,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
(void )theInside;
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
@ -527,7 +527,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
{
@ -558,22 +558,24 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
gp_Trsf aTrsfInv = theTrsf.Inverted();
gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
theIsHollow, aTimeEnter, aTimeLeave))
{
return false;
}
Standard_Real aDepth = 0.0;
Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
Bnd_Range aRange (Max (aTimeEnter, 0.0), Max (aTimeEnter, aTimeLeave));
aRange.GetMin (aDepth);
if (!theClipRange.GetNearestDepth (aRange, aDepth))
{
@ -606,15 +608,17 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
"Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
gp_Trsf aTrsfInv = theTrsf.Inverted();
gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
theIsHollow, aTimeEnter, aTimeLeave))
{
return false;
}
@ -625,6 +629,74 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
return true;
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
Standard_Real aTime = 0.0;
gp_Trsf aTrsfInv = theTrsf.Inverted();
gp_Pnt aLoc = myAxis.Location().Transformed (aTrsfInv);
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
{
return false;
}
Standard_Real aDepth = Max (aTime, 0.0);
if (theClipRange.IsClipped (aDepth))
{
return false;
}
const gp_Pnt aPntOnCylinder = aLoc.XYZ() + aRayDir.XYZ() * aDepth;
thePickResult.SetDepth (aDepth);
thePickResult.SetPickedPoint (aPntOnCylinder.Transformed (theTrsf));
if (Abs (aPntOnCylinder.Z()) < Precision::Confusion())
{
thePickResult.SetSurfaceNormal (-gp::DZ().Transformed (theTrsf));
}
else
{
thePickResult.SetSurfaceNormal (gp_Vec (aPntOnCylinder.X(), aPntOnCylinder.Y(), 0.0).Transformed (theTrsf));
}
return true;
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
"Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
Standard_Real aTime = 0.0;
gp_Trsf aTrsfInv = theTrsf.Inverted();
gp_Pnt aLoc = myAxis.Location().Transformed (aTrsfInv);
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
{
return false;
}
if (theInside != NULL)
{
*theInside &= (aTime >= 0.0);
}
return true;
}
//=======================================================================
// function : GetNearPnt
// purpose :

View File

@ -117,6 +117,7 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
@ -126,6 +127,26 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
public:

View File

@ -176,15 +176,15 @@ Standard_Boolean SelectMgr_BaseIntersector::RayCylinderIntersection (const Stand
const Standard_Real theHeight,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
const Standard_Boolean theIsHollow,
Standard_Real& theTimeEnter,
Standard_Real& theTimeLeave) const
{
Standard_Integer aNbIntersections = 0;
Standard_Real anIntersections[4] = { RealLast(), RealLast(), RealLast(), RealLast() };
//NCollection_Vector<Standard_Real> anIntersections; // vector for all intersections
// Check intersections with end faces
// point of intersection theRayDir and z = 0
if (theRayDir.Z() != 0)
if (!theIsHollow && theRayDir.Z() != 0)
{
const Standard_Real aTime1 = (0 - theLoc.Z()) / theRayDir.Z();
const Standard_Real aX1 = theLoc.X() + theRayDir.X() * aTime1;
@ -293,6 +293,33 @@ Standard_Boolean SelectMgr_BaseIntersector::RayCylinderIntersection (const Stand
return true;
}
//=======================================================================
// function : RayCircleIntersection
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_BaseIntersector::RayCircleIntersection (const Standard_Real theRadius,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
const Standard_Boolean theIsFilled,
Standard_Real& theTime) const
{
if (theRayDir.Z() != 0)
{
const Standard_Real aTime = (0 - theLoc.Z()) / theRayDir.Z();
const Standard_Real aX1 = theLoc.X() + theRayDir.X() * aTime;
const Standard_Real anY1 = theLoc.Y() + theRayDir.Y() * aTime;
const Standard_Real aK = aX1 * aX1 + anY1 * anY1;
if ((theIsFilled && aK <= theRadius * theRadius)
|| (!theIsFilled && Abs (sqrt (aK) - theRadius) <= Precision::Confusion()))
{
theTime = aTime;
return true;
}
}
return false;
}
//=======================================================================
// function : DistToGeometryCenter
// purpose :

View File

@ -187,6 +187,7 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const = 0;
@ -196,6 +197,26 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const = 0;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const = 0;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const = 0;
public:
@ -224,15 +245,37 @@ public:
Standard_Real& theTimeLeave) const;
//! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
//! with the cylinder (or cone) with radiuses theBottomRad and theTopRad and height theHeights
//! with the hollow cylinder (or cone)
//! @param[in] theBottomRadius the bottom cylinder radius
//! @param[in] theTopRadius the top cylinder radius
//! @param[in] theHeight the cylinder height
//! @param[in] theLoc the location of the ray
//! @param[in] theRayDir the ray direction
//! @param[in] theIsHollow true if the cylinder is hollow
//! @param[out] theTimeEnter the entering the intersection
//! @param[out] theTimeLeave the leaving the intersection
Standard_EXPORT virtual Standard_Boolean RayCylinderIntersection (const Standard_Real theBottomRadius,
const Standard_Real theTopRadius,
const Standard_Real theHeight,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
const Standard_Boolean theIsHollow,
Standard_Real& theTimeEnter,
Standard_Real& theTimeLeave) const;
//! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
//! with the circle
//! @param[in] theRadius the circle radius
//! @param[in] theLoc the location of the ray
//! @param[in] theRayDir the ray direction
//! @param[in] theIsFilled true if it's a circle, false if it's a circle outline
//! @param[out] theTime the intersection
Standard_EXPORT virtual Standard_Boolean RayCircleIntersection (const Standard_Real theRadius,
const gp_Pnt& theLoc,
const gp_Dir& theRayDir,
const Standard_Boolean theIsFilled,
Standard_Real& theTime) const;
DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient)
protected:

View File

@ -98,11 +98,25 @@ protected:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const;
//! Intersection test between defined volume and given circle.
Standard_Boolean hasCircleOverlap (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const;
//! Returns True if all vertices (theVertices) are inside the top and bottom sides of the cylinder.
Standard_Boolean isInsideCylinderEndFace (const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const;
//! Checking whether the point thePnt is inside the shape with borders theVertices.
//! thePnt and theVertices lie in the same plane.
Standard_Boolean IsDotInside (const gp_Pnt& thePnt,
Standard_Boolean isDotInside (const gp_Pnt& thePnt,
const TColgp_Array1OfPnt& theVertices) const;
private:
@ -116,7 +130,7 @@ 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,
Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
const gp_Pnt& theCenter,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const;

View File

@ -1,4 +1,4 @@
// Created on: 2015-03-16
// Created on: 2015-03-16
// Created by: Varvara POSKONINA
// Copyright (c) 2005-2014 OPEN CASCADE SAS
//
@ -520,7 +520,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasSphereOverlap (const gp_Pnt& thePnt,
// purpose :
// =======================================================================
template<int N>
Standard_Boolean SelectMgr_Frustum<N>::IsDotInside (const gp_Pnt& thePnt,
Standard_Boolean SelectMgr_Frustum<N>::isDotInside (const gp_Pnt& thePnt,
const TColgp_Array1OfPnt& theVertices) const
{
Standard_Real anAngle = 0.0;
@ -598,11 +598,11 @@ Standard_Boolean SelectMgr_Frustum<N>::isSegmentsIntersect (const gp_Pnt& thePnt
}
// =======================================================================
// function : isIntersectCylinderEndFace
// function : isIntersectCircle
// purpose :
// =======================================================================
template<int N>
Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standard_Real theRad,
Standard_Boolean SelectMgr_Frustum<N>::isIntersectCircle (const Standard_Real theRadius,
const gp_Pnt& theCenter,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const
@ -633,7 +633,7 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
// Solving quadratic equation anA * T^2 + 2 * aK * T + aC = 0
const Standard_Real anA = (aX1 - aX2) * (aX1 - aX2) + (anY1 - anY2) * (anY1 - anY2);
const Standard_Real aK = aX1 * (aX2 - aX1) + anY1 * (anY2 - anY1);
const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRad * theRad;
const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRadius * theRadius;
const Standard_Real aDiscr = aK * aK - anA * aC;
if (aDiscr >= 0.0)
@ -649,6 +649,47 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
return false;
}
// =======================================================================
// function : isInsideCylinderEndFace
// purpose :
// =======================================================================
template<int N>
Standard_Boolean SelectMgr_Frustum<N>::isInsideCylinderEndFace (const Standard_Real theBottomRad,
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const
{
const gp_Trsf aTrsfInv = theTrsf.Inverted();
const gp_Dir aRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]).Transformed (aTrsfInv);
if (aRayDir.Z() == 0.0)
{
return false;
}
for (Standard_Integer anIdx = theVertices.Lower(); anIdx <= theVertices.Upper(); anIdx++)
{
const gp_Pnt aLoc = theVertices.Value (anIdx).Transformed (aTrsfInv);
const Standard_Real aTime1 = (0 - aLoc.Z()) / aRayDir.Z();
const Standard_Real aX1 = aLoc.X() + aRayDir.X() * aTime1;
const Standard_Real anY1 = aLoc.Y() + aRayDir.Y() * aTime1;
const Standard_Real aTime2 = (theHeight - aLoc.Z()) / aRayDir.Z();
const Standard_Real aX2 = aLoc.X() + aRayDir.X() * aTime2;
const Standard_Real anY2 = aLoc.Y() + aRayDir.Y() * aTime2;
if (aX1 * aX1 + anY1 * anY1 <= theBottomRad * theBottomRad
&& aX2 * aX2 + anY2 * anY2 <= theTopRad * theTopRad)
{
continue;
}
return false;
}
return true;
}
// =======================================================================
// function : hasCylinderOverlap
// purpose :
@ -658,8 +699,37 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
gp_Pnt aVerticesBuf[N];
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
if (anIncFactor == 2)
{
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
}
}
else
{
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIdx]);
}
}
if (theIsHollow && isInsideCylinderEndFace (theBottomRad, theTopRad, theHeight, theTrsf, aVertices))
{
if (theInside != NULL)
{
*theInside = false;
}
return false;
}
const gp_Dir aCylNorm (gp::DZ().Transformed (theTrsf));
const gp_Pnt aBottomCenter (gp::Origin().Transformed (theTrsf));
const gp_Pnt aTopCenter = aBottomCenter.XYZ() + aCylNorm.XYZ() * theHeight;
@ -698,29 +768,11 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
aPoints[5] = aBottomCenterProject.XYZ() - aDirEndFaces.XYZ() * theBottomRad;
const TColgp_Array1OfPnt aPointsArr (aPoints[0], 0, 5);
gp_Pnt aVerticesBuf[N];
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
if (anIncFactor == 2)
{
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
}
}
else
{
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIdx]);
}
}
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
if ((aCylNormProject.Dot (aCylNormProject) == 0.0
&& aVertices.Value (anIdx).Distance (aPoints[0]) <= Max (theTopRad, theBottomRad))
|| IsDotInside (aVertices.Value (anIdx), aPointsArr))
|| isDotInside (aVertices.Value (anIdx), aPointsArr))
{
if (theInside != NULL)
{
@ -747,8 +799,9 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
}
}
if (isIntersectCylinderEndFace (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
|| isIntersectCylinderEndFace (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices))
if (!theIsHollow
&& (isIntersectCircle (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
|| isIntersectCircle (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices)))
{
if (theInside != NULL)
{
@ -759,7 +812,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
bool isCylInsideRec = true;
for (int i = 0; i < 6; ++i)
{
isCylInsideRec &= IsDotInside (aPoints[i], aVertices);
isCylInsideRec &= isDotInside (aPoints[i], aVertices);
}
if (theInside != NULL)
{
@ -768,6 +821,82 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
return isCylInsideRec;
}
// =======================================================================
// function : hasCircleOverlap
// purpose :
// =======================================================================
template<int N>
Standard_Boolean SelectMgr_Frustum<N>::hasCircleOverlap (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
gp_Pnt aVerticesBuf[N];
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
if (anIncFactor == 2)
{
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
}
}
else
{
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
{
aVertices.SetValue (anIdx, myVertices[anIdx]);
}
}
if (isIntersectCircle (theRadius, gp_Pnt (0, 0, 0), theTrsf, aVertices))
{
if (theInside != NULL)
{
*theInside = false;
}
return true;
}
gp_Pnt aCircCenter = gp::Origin();//.Transformed (theTrsf);
const gp_Dir aViewRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]);
const gp_Pln aPln (myVertices[0], aViewRayDir);
Standard_Real aCoefA, aCoefB, aCoefC, aCoefD;
aPln.Coefficients (aCoefA, aCoefB, aCoefC, aCoefD);
const Standard_Real aTCenter = -(aCircCenter.XYZ().Dot (aViewRayDir.XYZ()) + aCoefD);
const gp_Pnt aCenterProject (aCoefA * aTCenter,
aCoefB * aTCenter,
aCoefC * aTCenter);
if (isDotInside (aCenterProject, aVertices))
{
return true;
}
Standard_Boolean isInside = true;
for (Standard_Integer anIdx = aVertices.Lower(); anIdx <= aVertices.Upper(); anIdx++)
{
if (aVertices.Value (anIdx).Distance (aCenterProject) > theRadius)
{
isInside = false;
break;
}
}
if (theInside != NULL)
{
*theInside = false;
}
if (!theIsFilled && isInside)
{
return false;
}
return isInside;
}
//=======================================================================
//function : DumpJson
//purpose :

View File

@ -748,6 +748,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
@ -757,7 +758,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
const gp_Trsf aTrsfInv = theTrsf.Inverted();
const gp_Pnt aLoc = myNearPickedPnt.Transformed (aTrsfInv);
const gp_Dir aRayDir = myViewRayDir .Transformed (aTrsfInv);
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimes[0], aTimes[1]))
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, theIsHollow, aTimes[0], aTimes[1]))
{
return Standard_False;
}
@ -787,6 +788,165 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
return !theClipRange.IsClipped (thePickResult.Depth());
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
Standard_Real aTime = 0.0;
const gp_Trsf aTrsfInv = theTrsf.Inverted();
const gp_Pnt aLoc = myNearPickedPnt.Transformed (aTrsfInv);
const gp_Dir aRayDir = myViewRayDir.Transformed (aTrsfInv);
if (!theIsFilled)
{
if (!hasCircleOverlap (theRadius, theTrsf, theIsFilled, NULL))
{
return Standard_False;
}
if (aRayDir.Z() != 0)
{
aTime = (0 - aLoc.Z()) / aRayDir.Z();
}
}
else if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
{
return Standard_False;
}
thePickResult.SetDepth (aTime * myScale);
if (theClipRange.IsClipped (thePickResult.Depth()))
{
thePickResult.SetDepth (aTime * myScale);
}
const gp_Pnt aPntOnCircle = aLoc.XYZ() + aRayDir.XYZ() * aTime;
if (Abs (aPntOnCircle.Z()) < Precision::Confusion())
{
thePickResult.SetSurfaceNormal (-gp::DZ().Transformed (theTrsf));
}
else
{
thePickResult.SetSurfaceNormal (gp_Vec (aPntOnCircle.X(), aPntOnCircle.Y(), 0.0).Transformed (theTrsf));
}
thePickResult.SetPickedPoint (aPntOnCircle.Transformed (theTrsf));
return !theClipRange.IsClipped (thePickResult.Depth());
}
//=======================================================================
// function : isIntersectCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::isIntersectCircle (const Standard_Real theRadius,
const gp_Pnt& theCenter,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const
{
const gp_Trsf aTrsfInv = theTrsf.Inverted();
const gp_Dir aRayDir = gp_Dir (myEdgeDirs[4 == 4 ? 4 : 0]).Transformed (aTrsfInv);
if (aRayDir.Z() == 0.0)
{
return false;
}
for (Standard_Integer anIdx = theVertices.Lower(); anIdx <= theVertices.Upper(); anIdx++)
{
const gp_Pnt aPntStart = theVertices.Value (anIdx).Transformed (aTrsfInv);
const gp_Pnt aPntFinish = anIdx == theVertices.Upper()
? theVertices.Value (theVertices.Lower()).Transformed (aTrsfInv)
: theVertices.Value (anIdx + 1).Transformed (aTrsfInv);
// Project points on the end face plane
const Standard_Real aParam1 = (theCenter.Z() - aPntStart.Z()) / aRayDir.Z();
const Standard_Real aX1 = aPntStart.X() + aRayDir.X() * aParam1;
const Standard_Real anY1 = aPntStart.Y() + aRayDir.Y() * aParam1;
const Standard_Real aParam2 = (theCenter.Z() - aPntFinish.Z()) / aRayDir.Z();
const Standard_Real aX2 = aPntFinish.X() + aRayDir.X() * aParam2;
const Standard_Real anY2 = aPntFinish.Y() + aRayDir.Y() * aParam2;
// Solving quadratic equation anA * T^2 + 2 * aK * T + aC = 0
const Standard_Real anA = (aX1 - aX2) * (aX1 - aX2) + (anY1 - anY2) * (anY1 - anY2);
const Standard_Real aK = aX1 * (aX2 - aX1) + anY1 * (anY2 - anY1);
const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRadius * theRadius;
const Standard_Real aDiscr = aK * aK - anA * aC;
if (aDiscr >= 0.0)
{
const Standard_Real aT1 = (-aK + Sqrt (aDiscr)) / anA;
const Standard_Real aT2 = (-aK - Sqrt (aDiscr)) / anA;
if ((aT1 >= 0 && aT1 <= 1) || (aT2 >= 0 && aT2 <= 1))
{
return true;
}
}
}
return false;
}
//=======================================================================
// function : isSegmentsIntersect
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::isSegmentsIntersect (const gp_Pnt& thePnt1Seg1,
const gp_Pnt& thePnt2Seg1,
const gp_Pnt& thePnt1Seg2,
const gp_Pnt& thePnt2Seg2) const
{
const gp_Mat aMatPln (thePnt2Seg1.X() - thePnt1Seg1.X(), thePnt2Seg1.Y() - thePnt1Seg1.Y(), thePnt2Seg1.Z() - thePnt1Seg1.Z(),
thePnt1Seg2.X() - thePnt1Seg1.X(), thePnt1Seg2.Y() - thePnt1Seg1.Y(), thePnt1Seg2.Z() - thePnt1Seg1.Z(),
thePnt2Seg2.X() - thePnt1Seg1.X(), thePnt2Seg2.Y() - thePnt1Seg1.Y(), thePnt2Seg2.Z() - thePnt1Seg1.Z());
if (Abs (aMatPln.Determinant()) > Precision::Confusion())
{
return false;
}
Standard_Real aFst[4] = { thePnt1Seg1.X(), thePnt2Seg1.X(), thePnt1Seg2.X(), thePnt2Seg2.X() };
Standard_Real aSnd[4] = { thePnt1Seg1.Y(), thePnt2Seg1.Y(), thePnt1Seg2.Y(), thePnt2Seg2.Y() };
if (aFst[0] == aFst[2] && aFst[1] == aFst[3])
{
aFst[0] = thePnt1Seg1.Z();
aFst[1] = thePnt2Seg1.Z();
aFst[2] = thePnt1Seg2.Z();
aFst[3] = thePnt2Seg2.Z();
}
if (aSnd[0] == aSnd[2]
&& aSnd[1] == aSnd[3])
{
aSnd[0] = thePnt1Seg1.Z();
aSnd[1] = thePnt2Seg1.Z();
aSnd[2] = thePnt1Seg2.Z();
aSnd[3] = thePnt2Seg2.Z();
}
const gp_Mat2d aMat (gp_XY (aFst[0] - aFst[1], aSnd[0] - aSnd[1]),
gp_XY (aFst[3] - aFst[2], aSnd[3] - aSnd[2]));
const gp_Mat2d aMatU (gp_XY (aFst[0] - aFst[2], aSnd[0] - aSnd[2]),
gp_XY (aFst[3] - aFst[2], aSnd[3] - aSnd[2]));
const gp_Mat2d aMatV (gp_XY (aFst[0] - aFst[1], aSnd[0] - aSnd[1]),
gp_XY (aFst[0] - aFst[2], aSnd[0] - aSnd[2]));
if (aMat.Determinant() == 0.0)
{
return false;
}
const Standard_Real anU = aMatU.Determinant() / aMat.Determinant();
const Standard_Real aV = aMatV.Determinant() / aMat.Determinant();
if (anU >= 0.0 && anU <= 1.0
&& aV >= 0.0 && aV <= 1.0)
{
return true;
}
return false;
}
//=======================================================================
// function : OverlapsCylinder
// purpose :
@ -795,12 +955,28 @@ Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCylinder (const Standard_
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theInside);
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow, theInside);
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point || mySelectionType == SelectMgr_SelectionType_Box,
"Error! SelectMgr_RectangularFrustum::Overlaps() should be called after selection frustum initialization");
return hasCircleOverlap (theRadius, theTrsf, theIsFilled, theInside);
}
// =======================================================================

View File

@ -66,6 +66,18 @@ public:
Standard_EXPORT void Init (const gp_Pnt2d& theMinPnt,
const gp_Pnt2d& theMaxPnt);
//! Returns True if Frustum (theVertices) intersects the circle.
Standard_EXPORT Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
const gp_Pnt& theCenter,
const gp_Trsf& theTrsf,
const TColgp_Array1OfPnt& theVertices) const;
//! Returns True if Seg1 (thePnt1Seg1, thePnt2Seg1) and Seg2 (thePnt1Seg2, thePnt2Seg2) intersect.
Standard_EXPORT Standard_Boolean isSegmentsIntersect (const gp_Pnt& thePnt1Seg1,
const gp_Pnt& thePnt2Seg1,
const gp_Pnt& thePnt1Seg2,
const gp_Pnt& thePnt2Seg2) const;
//! Builds volume according to internal parameters.
//! NOTE: it should be called after Init() method
Standard_EXPORT virtual void Build() Standard_OVERRIDE;
@ -150,6 +162,7 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
@ -159,6 +172,26 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Measures distance between 3d projection of user-picked

View File

@ -426,13 +426,15 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCylinder (const Stand
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
SelectBasics_PickResult& thePickResult) const
{
if (myActiveSelectingVolume.IsNull())
{
return false;
}
return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, myViewClipRange, thePickResult);
return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf,
theIsHollow, myViewClipRange, thePickResult);
}
//=======================================================================
@ -443,13 +445,47 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCylinder (const Stand
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
if (myActiveSelectingVolume.IsNull())
{
return false;
}
return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theInside);
return myActiveSelectingVolume->OverlapsCylinder (theBottomRad, theTopRad, theHeight,
theTrsf, theIsHollow, theInside);
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
SelectBasics_PickResult& thePickResult) const
{
if (myActiveSelectingVolume.IsNull())
{
return false;
}
return myActiveSelectingVolume->OverlapsCircle (theRadius, theTrsf, theIsFilled, myViewClipRange, thePickResult);
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_SelectingVolumeManager::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
if (myActiveSelectingVolume.IsNull())
{
return false;
}
return myActiveSelectingVolume->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside);
}
//=======================================================================

View File

@ -168,6 +168,7 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
@ -176,6 +177,25 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Measures distance between 3d projection of user-picked

View File

@ -337,12 +337,13 @@ Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCylinder (const Standard_R
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
(void)theClipRange;
(void)thePickResult;
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf);
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow);
}
//=======================================================================
@ -353,10 +354,39 @@ Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCylinder (const Standard_R
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
(void) theInside;
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf);
return hasCylinderOverlap (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow);
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
(void)theClipRange;
(void)thePickResult;
return hasCircleOverlap (theRadius, theTrsf, theIsFilled);
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustum::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
(void)theInside;
return hasCircleOverlap (theRadius, theTrsf, theIsFilled);
}
// =======================================================================

View File

@ -123,6 +123,7 @@ public: //! @name SAT Tests for different objects
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
@ -132,6 +133,26 @@ public: //! @name SAT Tests for different objects
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
//! boolean theIsFilled and transformation to apply theTrsf.
//! The position and orientation of the circle are specified
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
public:

View File

@ -17,6 +17,10 @@
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_Delaun.hxx>
#include <Geom_Plane.hxx>
#include <GeomInt_IntSS.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Line.hxx>
#include <NCollection_IncAllocator.hxx>
#include <SelectMgr_FrustumBuilder.hxx>
@ -506,6 +510,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
@ -513,7 +518,8 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
"Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theClipRange, thePickResult))
if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf,
theIsHollow, theClipRange, thePickResult))
{
return true;
}
@ -529,6 +535,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside) const
{
const gp_Dir aCylNorm (gp::DZ().Transformed (theTrsf));
@ -589,7 +596,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
{
aVertices[anIdx] = anIter.Value()->myVertices[anIdx];
}
if (anIter.Value()->IsDotInside (aPoints[i], aVertices))
if (anIter.Value()->isDotInside (aPoints[i], aVertices))
{
isInside = true;
break;
@ -607,7 +614,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
}
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theInside))
if (anIter.Value()->OverlapsCylinder (theBottomRad, theTopRad, theHeight, theTrsf, theIsHollow, theInside))
{
return true;
}
@ -615,6 +622,109 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCylinder (const Standar
return false;
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const
{
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Polyline,
"Error! SelectMgr_TriangularFrustumSet::Overlaps() should be called after selection frustum initialization");
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theClipRange, thePickResult))
{
return true;
}
}
return false;
}
//=======================================================================
// function : OverlapsCircle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::OverlapsCircle (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside) const
{
const gp_Pnt aCenter (gp::Origin().Transformed (theTrsf));
const gp_Vec aVecPlane1 (myFrustums.First()->myVertices[0], myFrustums.First()->myVertices[1]);
const gp_Vec aVecPlane2 (myFrustums.First()->myVertices[0], myFrustums.First()->myVertices[2]);
const gp_Dir aDirNorm (aVecPlane1.Crossed (aVecPlane2));
const gp_Pln aPln (myFrustums.First()->myVertices[0], aDirNorm);
Standard_Real aCoefA, aCoefB, aCoefC, aCoefD;
aPln.Coefficients (aCoefA, aCoefB, aCoefC, aCoefD);
const Standard_Real aT = -(aCenter.XYZ().Dot (aDirNorm.XYZ()) + aCoefD) / aDirNorm.Dot (aDirNorm);
const gp_Pnt aCenterProject (aCoefA * aT + aCenter.X(),
aCoefB * aT + aCenter.Y(),
aCoefC * aT + aCenter.Z());
gp_Pnt aVerticesBuf[3];
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, 2);
if (!theIsFilled)
{
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (!anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside))
{
continue;
}
if (myToAllowOverlap)
{
return Standard_True;
}
if (isIntersectBoundary (theRadius, theTrsf, theIsFilled))
{
if (theInside != NULL)
{
*theInside &= Standard_False;
}
return Standard_False;
}
return Standard_True;
}
}
else
{
for (SelectMgr_TriangFrustums::Iterator anIter (myFrustums); anIter.More(); anIter.Next())
{
if (!anIter.Value()->OverlapsCircle (theRadius, theTrsf, theIsFilled, theInside))
{
continue;
}
if (myToAllowOverlap)
{
return Standard_True;
}
if (isIntersectBoundary (theRadius, theTrsf, theIsFilled))
{
return Standard_False;
}
return Standard_True;
}
}
if (theInside != NULL)
{
*theInside &= Standard_False;
}
return Standard_False;
}
// =======================================================================
// function : GetPlanes
// purpose :
@ -638,6 +748,127 @@ void SelectMgr_TriangularFrustumSet::SetAllowOverlapDetection (const Standard_Bo
myToAllowOverlap = theIsToAllow;
}
//=======================================================================
// function : PointInTriangle
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::pointInTriangle (const gp_Pnt& thePnt,
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3)
{
gp_Vec a = theV1.XYZ() - thePnt.XYZ();
gp_Vec b = theV2.XYZ() - thePnt.XYZ();
gp_Vec c = theV3.XYZ() - thePnt.XYZ();
gp_Vec u = b.Crossed (c);
gp_Vec v = c.Crossed (a);
gp_Vec w = a.Crossed (b);
if (u.Dot (v) < 0.0 || u.Dot (w) < 0.0) {
return false;
}
return true;
}
//=======================================================================
// function : segmentSegmentIntersection
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::segmentSegmentIntersection (const gp_Pnt& theStartPnt1,
const gp_Pnt& theEndPnt1,
const gp_Pnt& theStartPnt2,
const gp_Pnt& theEndPnt2)
{
gp_XYZ aVec1 = theEndPnt1.XYZ() - theStartPnt1.XYZ();
gp_XYZ aVec2 = theEndPnt2.XYZ() - theStartPnt2.XYZ();
gp_XYZ aVec21 = theStartPnt2.XYZ() - theStartPnt1.XYZ();
gp_XYZ aVec12 = theStartPnt1.XYZ() - theStartPnt2.XYZ();
if (Abs (aVec21.DotCross (aVec1, aVec2)) > Precision::Confusion() ||
Abs (aVec12.DotCross (aVec2, aVec1)) > Precision::Confusion())
{
// lines are not coplanar
return false;
}
double aValue1 = aVec21.Crossed (aVec2).Dot (aVec1.Crossed (aVec2)) / aVec1.Crossed (aVec2).SquareModulus();
double aValue2 = aVec12.Crossed (aVec1).Dot (aVec2.Crossed (aVec1)) / aVec2.Crossed (aVec1).SquareModulus();
if (aValue1 < 0.0 || aValue1 > 1.0 || aValue2 < 0.0 || aValue2 > 1.0)
{
return false;
}
return true;
}
//=======================================================================
// function : isIntersectBoundary
// purpose :
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::isIntersectBoundary (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled) const
{
Standard_Integer aFacesNb = myBoundaryPoints.Size() / 2;
const gp_Pnt& aCircCenter = theTrsf.TranslationPart();
gp_Ax2 anAxis;
anAxis.Transform (theTrsf);
Handle(Geom_Circle) aCirc = new Geom_Circle (anAxis, theRadius);
gp_Dir aCircNorm = gp_Dir(0, 0, 1).Transformed (theTrsf);
Handle(Geom_Surface) aCircPlane = new Geom_Plane(aCircCenter, aCircNorm);
for (Standard_Integer anIdx = myBoundaryPoints.Lower(); anIdx < aFacesNb + myBoundaryPoints.Lower(); anIdx++)
{
gp_Pnt aFace[4] = { myBoundaryPoints.Value (anIdx),
myBoundaryPoints.Value (anIdx + aFacesNb),
myBoundaryPoints.Value (anIdx % aFacesNb + 1 + aFacesNb),
myBoundaryPoints.Value (anIdx % aFacesNb + 1) };
gp_Dir aBndPlaneNorm = gp_Vec (aFace[0], aFace[1]).Crossed (gp_Vec(aFace[0], aFace[2]));
Handle(Geom_Surface) aBndPlane = new Geom_Plane(aFace[0], aBndPlaneNorm);
GeomInt_IntSS anInterSS (aCircPlane, aBndPlane, Precision::Confusion());
if (!anInterSS.IsDone() || anInterSS.NbLines() == 0)
{
continue;
}
const Handle(Geom_Line)& anInterLine = Handle(Geom_Line)::DownCast (anInterSS.Line(1));
Standard_Real aDistance = anInterLine->Lin().Distance (aCircCenter);
if (aDistance > theRadius)
{
continue;
}
gp_Lin aLine = anInterLine->Lin();
gp_Lin aNormalLine = aLine.Normal (aCircCenter);
gp_Pnt aCrossPoint = aCircCenter.Translated (aNormalLine.Direction().Reversed().XYZ() * aDistance);
Standard_Real anOffset = Sqrt (theRadius * theRadius - aDistance * aDistance);
// Line-circle intersection points
gp_Pnt aP1 = aCrossPoint.Translated (aLine.Direction().XYZ() * anOffset);
gp_Pnt aP2 = aCrossPoint.Translated (aLine.Direction().Reversed().XYZ() * anOffset);
if (pointInTriangle (aP1, aFace[0], aFace[1], aFace[2])
|| pointInTriangle (aP1, aFace[0], aFace[2], aFace[3])
|| pointInTriangle (aP2, aFace[0], aFace[1], aFace[2])
|| pointInTriangle (aP2, aFace[0], aFace[2], aFace[3]))
{
return Standard_True;
}
if (theIsFilled
|| segmentSegmentIntersection (aP1, aP2, aFace[0], aFace[1])
|| segmentSegmentIntersection (aP1, aP2, aFace[1], aFace[2])
|| segmentSegmentIntersection (aP1, aP2, aFace[2], aFace[3])
|| segmentSegmentIntersection (aP1, aP2, aFace[0], aFace[3]))
{
return Standard_True;
}
}
return Standard_False;
}
//=======================================================================
// function : isIntersectBoundary
// purpose :
@ -669,7 +900,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::isIntersectBoundary (const gp_P
// purpose : Moller-Trumbore ray-triangle intersection test
//=======================================================================
Standard_Boolean SelectMgr_TriangularFrustumSet::segmentTriangleIntersection (const gp_Pnt& theOrig, const gp_Vec& theDir,
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3)
{
gp_Vec aPVec, aTVec, aQVec;
Standard_Real aD, aInvD, anU, aV, aT;

View File

@ -124,6 +124,7 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
@ -133,6 +134,22 @@ public:
const Standard_Real theTopRad,
const Standard_Real theHeight,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsHollow,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
//! and theTopRad, height theHeight and transformation to apply theTrsf.
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
const SelectMgr_ViewClipRange& theClipRange,
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
//! and theTopRad, height theHeight and transformation to apply theTrsf.
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled,
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
//! Stores plane equation coefficients (in the following form:
@ -151,15 +168,34 @@ private:
//! Checks whether the segment intersects with the boundary of the current volume selection
Standard_EXPORT Standard_Boolean isIntersectBoundary (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2) const;
//! Checks whether the circle intersects with the boundary of the current volume selection
Standard_EXPORT Standard_Boolean isIntersectBoundary (const Standard_Real theRadius,
const gp_Trsf& theTrsf,
const Standard_Boolean theIsFilled) const;
//! Checks whether the triangle intersects with a segment
Standard_EXPORT Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const;
Standard_EXPORT static Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
Standard_EXPORT static Standard_Boolean segmentSegmentIntersection (const gp_Pnt& theStartPnt1,
const gp_Pnt& theEndPnt1,
const gp_Pnt& theStartPnt2,
const gp_Pnt& theEndPnt2);
Standard_EXPORT static Standard_Boolean pointInTriangle (const gp_Pnt& thePnt,
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
private:
SelectMgr_TriangFrustums myFrustums; //!< set of triangular frustums
SelectionPolyline mySelPolyline; //!< parameters of selection polyline (it is used to build triangle frustum set)
TColgp_Array1OfPnt myBoundaryPoints; //!< boundary points
//! 1_____2
//! /| |\ .
//! 4/_|_____|_\3
//! | 5|_____|6 |
//! | / \ |
//! 8|/_________\|7
Standard_Boolean myToAllowOverlap; //!< flag to detect only fully included sensitives or not
};

View File

@ -40,6 +40,7 @@
#include <Select3D_SensitiveFace.hxx>
#include <Select3D_SensitiveGroup.hxx>
#include <Select3D_SensitivePoint.hxx>
#include <Select3D_SensitivePoly.hxx>
#include <Select3D_SensitiveSegment.hxx>
#include <Select3D_SensitiveSphere.hxx>
#include <Select3D_SensitiveTriangulation.hxx>
@ -60,7 +61,6 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#define BVH_PRIMITIVE_LIMIT 800000
@ -249,6 +249,7 @@ void StdSelect_BRepSelectionTool::ComputeSensitive (const TopoDS_Shape& theShape
case TopAbs_FACE:
{
const TopoDS_Face& aFace = TopoDS::Face (theShape);
Select3D_EntitySequence aSensitiveList;
GetSensitiveForFace (aFace, theOwner,
aSensitiveList,
@ -266,160 +267,16 @@ void StdSelect_BRepSelectionTool::ComputeSensitive (const TopoDS_Shape& theShape
{
TopTools_IndexedMapOfShape aSubfacesMap;
TopExp::MapShapes (theShape, TopAbs_FACE, aSubfacesMap);
if (aSubfacesMap.Extent() == 2) // detect cone
{
const TopoDS_Face* aFaces[2] =
{
&TopoDS::Face (aSubfacesMap.FindKey (1)),
&TopoDS::Face (aSubfacesMap.FindKey (2))
};
TopLoc_Location aLocSurf[2];
const Handle(Geom_Surface)* aSurfaces[2] =
if (!GetSensitiveForCylinder (aSubfacesMap, theOwner, theSelection))
{
&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
{
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)
{
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_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;
}
case TopAbs_COMPOUND:
@ -633,8 +490,7 @@ void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape
}
else
{
theSensitive = new Select3D_SensitiveCircle (theOwner, aCircle,
aParamFirst, aParamLast, Standard_False, 16);
theSensitive = new Select3D_SensitivePoly (theOwner, aCircle, aParamFirst, aParamLast, Standard_False);
}
break;
}
@ -705,6 +561,57 @@ void StdSelect_BRepSelectionTool::GetEdgeSensitive (const TopoDS_Shape& theShape
}
}
//=======================================================================
//function : getCylinderHeight
//purpose :
//=======================================================================
static Standard_Real getCylinderHeight (const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLoc)
{
Bnd_Box aBox;
gp_Trsf aScaleTrsf;
aScaleTrsf.SetScaleFactor (theLoc.Transformation().ScaleFactor());
theTriangulation->MinMax (aBox, aScaleTrsf);
return aBox.CornerMax().Z() - aBox.CornerMin().Z();
}
//=======================================================================
//function : isCylinderOrCone
//purpose :
//=======================================================================
static Standard_Boolean isCylinderOrCone (const TopoDS_Face& theHollowCylinder, const gp_Pnt& theLocation, gp_Dir& theDirection)
{
Standard_Integer aCirclesNb = 0;
Standard_Boolean isCylinder = Standard_False;
gp_Pnt aPos;
TopExp_Explorer anEdgeExp;
for (anEdgeExp.Init (theHollowCylinder, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeExp.Current());
BRepAdaptor_Curve anAdaptor (anEdge);
if (anAdaptor.GetType() == GeomAbs_Circle
&& BRep_Tool::IsClosed (anEdge))
{
aCirclesNb++;
isCylinder = Standard_True;
if (aCirclesNb == 2)
{
// Reverse the direction of the cylinder, relevant if the cylinder was created as a prism
if (aPos.IsEqual (theLocation, Precision::Confusion()))
{
theDirection.Reverse();
}
return Standard_True;
}
aPos = anAdaptor.Circle().Location().XYZ();
}
}
return isCylinder;
}
//=======================================================================
//function : GetSensitiveEntityForFace
//purpose :
@ -749,6 +656,76 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
return Standard_True;
}
}
else if (Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (aSurf))
{
gp_Dir aDummyDir;
if (isCylinderOrCone (theFace, gp_Pnt(), aDummyDir))
{
const gp_Cone aCone = BRepAdaptor_Surface (theFace).Cone();
const Standard_Real aRad1 = aCone.RefRadius();
const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
gp_Trsf aTrsf;
aTrsf.SetTransformation (aCone.Position(), gp::XOY());
Standard_Real aRad2;
if (aRad1 == 0.0)
{
aRad2 = Tan (aCone.SemiAngle()) * aHeight;
}
else
{
const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
? aRad1 / Tan (aCone.SemiAngle())
: aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
aRad2 = (aCone.SemiAngle() > 0.0)
? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
: aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
}
Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf, true);
theSensitiveList.Append (aSensSCyl);
return Standard_True;
}
}
else if (Handle(Geom_CylindricalSurface) aGeomCyl = Handle(Geom_CylindricalSurface)::DownCast (aSurf))
{
const gp_Cylinder aCyl = BRepAdaptor_Surface (theFace).Cylinder();
gp_Ax3 aPos = aCyl.Position();
gp_Dir aDirection = aPos.Direction();
if (isCylinderOrCone (theFace, aPos.Location(), aDirection))
{
const Standard_Real aRad = aCyl.Radius();
const Standard_Real aHeight = getCylinderHeight (aTriangulation, aLoc);
gp_Trsf aTrsf;
aPos.SetDirection (aDirection);
aTrsf.SetTransformation (aPos, gp::XOY());
Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf, true);
theSensitiveList.Append (aSensSCyl);
return Standard_True;
}
}
else if (Handle(Geom_Plane) aGeomPlane = Handle(Geom_Plane)::DownCast (aSurf))
{
TopTools_IndexedMapOfShape aSubfacesMap;
TopExp::MapShapes (theFace, TopAbs_EDGE, aSubfacesMap);
if (aSubfacesMap.Extent() == 1)
{
const TopoDS_Edge& anEdge = TopoDS::Edge (aSubfacesMap.FindKey (1));
BRepAdaptor_Curve anAdaptor (anEdge);
if (anAdaptor.GetType() == GeomAbs_Circle
&& BRep_Tool::IsClosed (anEdge))
{
Handle(Select3D_SensitiveCircle) aSensSCyl = new Select3D_SensitiveCircle (theOwner, anAdaptor.Circle(), theInteriorFlag);
theSensitiveList.Append (aSensSCyl);
return Standard_True;
}
}
}
Handle(Select3D_SensitiveTriangulation) STG = new Select3D_SensitiveTriangulation (theOwner, aTriangulation, aLoc, theInteriorFlag);
theSensitiveList.Append (STG);
return Standard_True;
@ -877,7 +854,7 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
}
else
{
theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag, 16));
theSensitiveList.Append (new Select3D_SensitiveCircle (theOwner, cu3d.Circle(), theInteriorFlag));
}
}
}
@ -947,3 +924,163 @@ Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForFace (const TopoDS_
}
return Standard_True;
}
//=======================================================================
//function : GetSensitiveForCylinder
//purpose :
//=======================================================================
Standard_Boolean StdSelect_BRepSelectionTool::GetSensitiveForCylinder (const TopTools_IndexedMapOfShape& theSubfacesMap,
const Handle(SelectMgr_EntityOwner)& theOwner,
const Handle(SelectMgr_Selection)& theSelection)
{
if (theSubfacesMap.Extent() == 2) // detect cone
{
const TopoDS_Face* aFaces[2] =
{
&TopoDS::Face (theSubfacesMap.FindKey (1)),
&TopoDS::Face (theSubfacesMap.FindKey (2))
};
TopLoc_Location aLocSurf[2];
const Handle(Geom_Surface)* aSurfaces[2] =
{
&BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
&BRep_Tool::Surface (*aFaces[1], aLocSurf[1])
};
Standard_Integer aConIndex = 0;
Handle(Geom_ConicalSurface) aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[0]);
Handle(Geom_Plane) aGeomPln;
if (!aGeomCone.IsNull())
{
aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[1]);
}
else
{
aConIndex = 1;
aGeomCone = Handle(Geom_ConicalSurface)::DownCast (*aSurfaces[1]);
aGeomPln = Handle(Geom_Plane)::DownCast (*aSurfaces[0]);
}
if (!aGeomCone.IsNull()
&& !aGeomPln.IsNull()
&& aGeomPln->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
{
const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
const Standard_Real aRad1 = aCone.RefRadius();
const Standard_Real aHeight = (aRad1 != 0.0)
? aRad1 / Abs (Tan (aCone.SemiAngle()))
: aCone.Location().Distance (aGeomPln->Location().Transformed (aLocSurf[aConIndex == 0 ? 1 : 0]));
const Standard_Real aRad2 = (aRad1 != 0.0) ? 0.0 : Tan (aCone.SemiAngle()) * aHeight;
gp_Trsf aTrsf;
aTrsf.SetTransformation (aCone.Position(), gp::XOY());
Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
theSelection->Add (aSensSCyl);
return Standard_True;
}
}
if (theSubfacesMap.Extent() == 3) // detect cylinder or truncated cone
{
const TopoDS_Face* aFaces[3] =
{
&TopoDS::Face (theSubfacesMap.FindKey (1)),
&TopoDS::Face (theSubfacesMap.FindKey (2)),
&TopoDS::Face (theSubfacesMap.FindKey (3))
};
TopLoc_Location aLocSurf[3];
const Handle(Geom_Surface)* aSurfaces[3] =
{
&BRep_Tool::Surface (*aFaces[0], aLocSurf[0]),
&BRep_Tool::Surface (*aFaces[1], aLocSurf[1]),
&BRep_Tool::Surface (*aFaces[2], aLocSurf[2])
};
Standard_Integer aConIndex = -1, aNbPlanes = 0;
Handle(Geom_ConicalSurface) aGeomCone;
Handle(Geom_CylindricalSurface) aGeomCyl;
Handle(Geom_Plane) aGeomPlanes[2];
const TopLoc_Location* aGeomPlanesLoc[2];
for (Standard_Integer aSurfIter = 0; aSurfIter < 3; ++aSurfIter)
{
const Handle(Geom_Surface)& aSurf = *aSurfaces[aSurfIter];
if (aConIndex == -1)
{
aGeomCone = Handle (Geom_ConicalSurface)::DownCast (aSurf);
if (!aGeomCone.IsNull())
{
aConIndex = aSurfIter;
continue;
}
aGeomCyl = Handle (Geom_CylindricalSurface)::DownCast (aSurf);
if (!aGeomCyl.IsNull())
{
aConIndex = aSurfIter;
continue;
}
}
if (aNbPlanes < 2)
{
aGeomPlanes[aNbPlanes] = Handle(Geom_Plane)::DownCast (aSurf);
if (!aGeomPlanes[aNbPlanes].IsNull())
{
aGeomPlanesLoc[aNbPlanes] = &aLocSurf[aSurfIter];
++aNbPlanes;
}
}
}
if (!aGeomCone.IsNull())
{
if (!aGeomPlanes[0].IsNull()
&& !aGeomPlanes[1].IsNull()
&& aGeomPlanes[0]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular())
&& aGeomPlanes[1]->Position().Direction().IsEqual (aGeomCone->Position().Direction(), Precision::Angular()))
{
const gp_Cone aCone = BRepAdaptor_Surface (*aFaces[aConIndex]).Cone();
const Standard_Real aRad1 = aCone.RefRadius();
const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
.Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
gp_Trsf aTrsf;
aTrsf.SetTransformation (aCone.Position(), gp::XOY());
const Standard_Real aTriangleHeight = (aCone.SemiAngle() > 0.0)
? aRad1 / Tan (aCone.SemiAngle())
: aRad1 / Tan (Abs (aCone.SemiAngle())) - aHeight;
const Standard_Real aRad2 = (aCone.SemiAngle() > 0.0)
? aRad1 * (aTriangleHeight + aHeight) / aTriangleHeight
: aRad1 * aTriangleHeight / (aTriangleHeight + aHeight);
Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad1, aRad2, aHeight, aTrsf);
theSelection->Add (aSensSCyl);
return Standard_True;
}
}
else if (!aGeomCyl.IsNull())
{
if (!aGeomPlanes[0].IsNull()
&& !aGeomPlanes[1].IsNull()
&& aGeomPlanes[0]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular())
&& aGeomPlanes[1]->Position().Direction().IsParallel (aGeomCyl->Position().Direction(), Precision::Angular()))
{
const gp_Cylinder aCyl = BRepAdaptor_Surface (*aFaces[aConIndex]).Cylinder();
const Standard_Real aRad = aCyl.Radius();
const Standard_Real aHeight = aGeomPlanes[0]->Location().Transformed (*aGeomPlanesLoc[0])
.Distance (aGeomPlanes[1]->Location().Transformed (*aGeomPlanesLoc[1]));
gp_Trsf aTrsf;
gp_Ax3 aPos = aCyl.Position();
if (aGeomPlanes[0]->Position().IsCoplanar (aGeomPlanes[1]->Position(), Precision::Angular(), Precision::Angular()))
{
// cylinders created as a prism have an inverse vector of the cylindrical surface
aPos.SetDirection (aPos.Direction().Reversed());
}
aTrsf.SetTransformation (aPos, gp::XOY());
Handle(Select3D_SensitiveCylinder) aSensSCyl = new Select3D_SensitiveCylinder (theOwner, aRad, aRad, aHeight, aTrsf);
theSelection->Add (aSensSCyl);
return Standard_True;
}
}
}
return Standard_False;
}

View File

@ -28,6 +28,7 @@
#include <Select3D_SensitiveEntity.hxx>
#include <Select3D_EntitySequence.hxx>
#include <StdSelect_BRepOwner.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
class SelectMgr_SelectableObject;
class TopoDS_Face;
@ -124,14 +125,14 @@ public:
}
//! Computes the sensitive primitives, stores them in the SelectMgr_Selection object, and returns this object.
//! @param theShape shape to compute sensitive entities
//! @param theOwner selectable owner object
//! @param theSelection selection to append new sensitive entities
//! @param theDeflection linear deflection
//! @param theDeflAngle angular deflection
//! @param theNbPOnEdge sensitivity parameters for edges and wires
//! @param theMaxiParam sensitivity parameters for infinite objects (the default value is 500)
//! @param theAutoTriang flag to compute triangulation for the faces which have none
//! @param[in] theShape shape to compute sensitive entities
//! @param[in] theOwner selectable owner object
//! @param[in] theSelection selection to append new sensitive entities
//! @param[in] theDeflection linear deflection
//! @param[in] theDeflAngle angular deflection
//! @param[in] theNbPOnEdge sensitivity parameters for edges and wires
//! @param[in] theMaxiParam sensitivity parameters for infinite objects (the default value is 500)
//! @param[in] theAutoTriang flag to compute triangulation for the faces which have none
Standard_EXPORT static void ComputeSensitive (const TopoDS_Shape& theShape,
const Handle(SelectMgr_EntityOwner)& theOwner,
const Handle(SelectMgr_Selection)& theSelection,
@ -142,13 +143,13 @@ public:
const Standard_Boolean theAutoTriang = Standard_True);
//! Creates the 3D sensitive entities for Face selection.
//! @param theFace face to compute sensitive entities
//! @param theOwner selectable owner object
//! @param theOutList output result list to append created entities
//! @param theAutoTriang obsolete flag (has no effect)
//! @param theNbPOnEdge sensitivity parameters
//! @param theMaxiParam sensitivity parameters
//! @param theInteriorFlag flag indicating that face interior (TRUE) or face boundary (FALSE) should be selectable
//! @param[in] theFace face to compute sensitive entities
//! @param[in] theOwner selectable owner object
//! @param[out] theOutList output result list to append created entities
//! @param[in] theAutoTriang obsolete flag (has no effect)
//! @param[in] theNbPOnEdge sensitivity parameters
//! @param[in] theMaxiParam sensitivity parameters
//! @param[in] theInteriorFlag flag indicating that face interior (TRUE) or face boundary (FALSE) should be selectable
Standard_EXPORT static Standard_Boolean GetSensitiveForFace (const TopoDS_Face& theFace,
const Handle(SelectMgr_EntityOwner)& theOwner,
Select3D_EntitySequence& theOutList,
@ -157,14 +158,22 @@ public:
const Standard_Real theMaxiParam = 500,
const Standard_Boolean theInteriorFlag = Standard_True);
//! Creates a sensitive cylinder.
//! @param[in] theSubfacesMap map of cylinder faces
//! @param[in] theOwner selectable owner object
//! @param[in] theSelection selection to append new sensitive entities
Standard_EXPORT static Standard_Boolean GetSensitiveForCylinder (const TopTools_IndexedMapOfShape& theSubfacesMap,
const Handle(SelectMgr_EntityOwner)& theOwner,
const Handle(SelectMgr_Selection)& theSelection);
//! Create a sensitive edge or sensitive wire.
//! @param theShape either TopoDS_Edge or TopoDS_Wire to compute sensitive entities
//! @param theOwner selectable owner object
//! @param theSelection selection to append new sensitive entities
//! @param theDeflection linear deflection
//! @param theDeviationAngle angular deflection
//! @param theNbPOnEdge sensitivity parameters
//! @param theMaxiParam sensitivity parameters
//! @param[in] theShape either TopoDS_Edge or TopoDS_Wire to compute sensitive entities
//! @param[in] theOwner selectable owner object
//! @param[in] theSelection selection to append new sensitive entities
//! @param[in] theDeflection linear deflection
//! @param[in] theDeviationAngle angular deflection
//! @param[in] theNbPOnEdge sensitivity parameters
//! @param[out] theMaxiParam sensitivity parameters
Standard_EXPORT static void GetEdgeSensitive (const TopoDS_Shape& theShape,
const Handle(SelectMgr_EntityOwner)& theOwner,
const Handle(SelectMgr_Selection)& theSelection,

View File

@ -132,6 +132,7 @@
#include <Select3D_SensitiveSegment.hxx>
#include <Select3D_SensitivePrimitiveArray.hxx>
#include <Select3D_SensitivePoint.hxx>
#include <Select3D_SensitivePoly.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <StdPrs_Curve.hxx>
@ -1965,8 +1966,14 @@ public:
// CASCADE RTTI
DEFINE_STANDARD_RTTI_INLINE(FilledCircle, AIS_InteractiveObject);
FilledCircle (const gp_Pnt& theCenter, Standard_Real theRadius);
FilledCircle (Handle(Geom_Circle) theCircle);
FilledCircle (const Handle(Geom_Circle)& theCircle,
const Standard_Real theUStart,
const Standard_Real theUEnd);
FilledCircle (const gp_Pnt& theCenter,
const Standard_Real theRadius,
const Standard_Real theUStart,
const Standard_Real theUEnd);
private:
TopoDS_Face ComputeFace();
@ -1982,35 +1989,50 @@ private:
protected:
Handle(Geom_Circle) myCircle;
Standard_Real myUStart;
Standard_Real myUEnd;
Standard_Boolean myFilledStatus;
};
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, Standard_Real theRadius)
{
myCircle = CreateCircle(theCenter, theRadius);
myFilledStatus = Standard_True;
}
FilledCircle::FilledCircle(Handle(Geom_Circle) theCircle)
{
myCircle = theCircle;
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());
BRepBuilderAPI_MakeEdge anEdgeMaker (myCircle->Circ(), myUStart, myUEnd);
TopoDS_Edge anEdge = anEdgeMaker.Edge();
// Create wire from anEdge
BRepBuilderAPI_MakeWire aWireMaker(anEdge);
BRepBuilderAPI_MakeWire aWireMaker;
if (Abs (Abs (myUEnd - myUStart) - 2.0 * M_PI) > gp::Resolution())
{
TopoDS_Edge anEndCenterEdge = BRepBuilderAPI_MakeEdge (myCircle->Value (myUEnd), myCircle->Location()).Edge();
TopoDS_Edge aStartCenterEdge = BRepBuilderAPI_MakeEdge (myCircle->Location(), myCircle->Value (myUStart)).Edge();
aWireMaker = BRepBuilderAPI_MakeWire (anEdge, anEndCenterEdge, aStartCenterEdge);
}
else
{
aWireMaker = BRepBuilderAPI_MakeWire (anEdge);
}
TopoDS_Wire aWire = aWireMaker.Wire();
// Create face from aWire
BRepBuilderAPI_MakeFace aFaceMaker(aWire);
BRepBuilderAPI_MakeFace aFaceMaker (aWire);
TopoDS_Face aFace = aFaceMaker.Face();
return aFace;
@ -2030,12 +2052,22 @@ void FilledCircle::Compute (const Handle(PrsMgr_PresentationManager)& ,
StdPrs_ShadedShape::Add (thePrs, aFace, myDrawer);
}
void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelection,
void FilledCircle::ComputeSelection (const Handle(SelectMgr_Selection) &theSelection,
const Standard_Integer /*theMode*/)
{
Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner(this);
Handle(Select3D_SensitiveCircle) aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
theSelection->Add(aSensitiveCircle);
Handle(Select3D_SensitiveEntity) aSensitiveCircle;
if (Abs (Abs (myUEnd - myUStart) - 2.0 * M_PI) > gp::Resolution())
{
aSensitiveCircle = new Select3D_SensitivePoly (anEntityOwner, myCircle->Circ(), myUStart, myUEnd, myFilledStatus);
}
else
{
aSensitiveCircle = new Select3D_SensitiveCircle (anEntityOwner, myCircle->Circ(), myFilledStatus);
}
theSelection->Add (aSensitiveCircle);
}
//==============================================================================
@ -2046,51 +2078,63 @@ void FilledCircle::ComputeSelection(const Handle(SelectMgr_Selection) &theSelect
//==============================================================================
//function : VCircleBuilder
//purpose : Build an AIS_Circle
//Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled
// PointName PointName PointName IsFilled
//Draw arg : vcircle CircleName PlaneName PointName Radius IsFilled UStart UEnd
// PointName PointName PointName IsFilled UStart UEnd
//==============================================================================
void DisplayCircle (Handle (Geom_Circle) theGeomCircle,
TCollection_AsciiString theName,
Standard_Boolean isFilled)
void DisplayCircle (const Handle(Geom_Circle)& theGeomCircle,
const TCollection_AsciiString& theName,
const Standard_Boolean isFilled,
const Standard_Real theUStart,
const Standard_Real theUEnd)
{
Handle(AIS_InteractiveObject) aCircle;
if (isFilled)
{
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))
{
Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2(theName);
TheAISContext()->Remove(anInterObj, Standard_False);
GetMapOfAIS().UnBind2(theName);
Handle(AIS_InteractiveObject) anInterObj = GetMapOfAIS().Find2 (theName);
TheAISContext()->Remove (anInterObj, Standard_False);
GetMapOfAIS().UnBind2 (theName);
}
// Bind the circle to its name
GetMapOfAIS().Bind(aCircle, theName);
GetMapOfAIS().Bind (aCircle, theName);
// Display the circle
TheAISContext()->Display (aCircle, Standard_True);
}
static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
static int VCircleBuilder (Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
{
if (argc > 6 || argc < 2)
if (argc > 8 || argc < 2)
{
Message::SendFail ("Syntax error: wrong number of arguments");
return 1;
}
if (argc == 6)
Standard_Real anUStart = 0, anUEnd = M_PI * 2.0;
if (argc == 8)
{
anUStart = Draw::Atof (argv[6]) * M_PI / 180.0;
anUEnd = Draw::Atof (argv[7]) * M_PI / 180.0;
}
else if (argc == 4)
{
anUStart = Draw::Atof (argv[2]) * M_PI / 180.0;
anUEnd = Draw::Atof (argv[3]) * M_PI / 180.0;
}
if (argc == 6 || argc == 8)
{
TCollection_AsciiString aName (argv[1]);
Standard_Boolean isFilled = Draw::Atoi(argv[5]) != 0;
@ -2159,7 +2203,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
return 1;
}
DisplayCircle (aGeomCircle, aName, isFilled);
DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
// Arguments: AIS_Plane AIS_Point Real
@ -2203,7 +2247,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
return 1;
}
DisplayCircle (aGeomCircle, aName, isFilled);
DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else
{
@ -2263,7 +2307,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
return 1;
}
DisplayCircle (aGeomCircle, aName, isFilled);
DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else if (aShapeA.ShapeType() == TopAbs_FACE)
{
@ -2307,7 +2351,7 @@ static int VCircleBuilder(Draw_Interpretor& /*di*/, Standard_Integer argc, const
return 1;
}
DisplayCircle (aGeomCircle, aName, isFilled);
DisplayCircle (aGeomCircle, aName, isFilled, anUStart, anUEnd);
}
else
{
@ -6914,8 +6958,8 @@ Creates a line from coordinates, named or interactively selected vertices.
)" /* [vline] */);
addCmd ("vcircle", VCircleBuilder, /* [vcircle] */ R"(
vcircle CircleName [PointName PointName PointName IsFilled]
[PlaneName PointName Radius IsFilled]
vcircle CircleName [PointName PointName PointName IsFilled] [UStart UEnd]
[PlaneName PointName Radius IsFilled] [UStart UEnd]
Creates a circle from named or interactively selected entities.
Parameter IsFilled is defined as 0 or 1.
)" /* [vcircle] */);

View File

@ -113,7 +113,7 @@ vmanipulator m -followRotation 0
# test rotation around y axis (world reference frame)
# ---------------------------------------------------
set mouse_pick {211 087}
set mouse_pick {205 087}
set mouse_drag {232 127}
vmoveto {*}$mouse_pick

View File

@ -8,7 +8,7 @@ proc check_output {theInfo} {
for {set i 0} {$i < $aSize} {incr i} {
if {[string equal [lindex $theInfo $i] "Depth:"]} {
set aDepth [lindex $theInfo [expr $i + 1]]
if {[string equal $aDepth "17.5691"]} {
if {[string equal $aDepth "17.4833"]} {
return 1
} else {
return $aDepth
@ -35,7 +35,7 @@ set aResult [check_output $anInfo]
if {$aResult == 1} {
puts "OK"
} else {
puts "ERROR: the depth value is incorrect: should be 17.5691, but is equal to:"
puts "ERROR: the depth value is incorrect: should be 17.4833, but is equal to:"
puts $aResult
}

View File

@ -0,0 +1,46 @@
puts "================================="
puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
puts ""
puts "================================="
pload VISUALIZATION OPENGL
vinit View1
# Filled circle sector
vpoint C1P1 10 10 10
vpoint C1P2 60 60 -10
vpoint C1P3 35 100 10
vcircle c1 C1P1 C1P2 C1P3 1 90 150
# Circle arc
vpoint C2P1 10 -10 -10
vpoint C2P2 60 -60 10
vpoint C2P3 35 -100 10
vcircle c2 C2P1 C2P2 C2P3 0 90 150
# Filled circle
vpoint C3P1 -80 -10 10
vpoint C3P2 -140 -50 -10
vpoint C3P3 -110 -100 -10
vcircle c3 C3P1 C3P2 C3P3 1 0 360
# Circle wire
vpoint C4P1 -80 10 10
vpoint C4P2 -140 60 10
vpoint C4P3 -110 100 -10
vcircle c4 C4P1 C4P2 C4P3 0 0 360
vbottom
vfit
vselect 100 100
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: filled circle should be detected" }
vselect 100 225
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle wire should be detected" }
vselect 390 50
if { ![string match "*Select3D_SensitivePoly*" [vstate -entities]] } { puts "Error: circle arc should be detected" }
vselect 360 350
if { ![string match "*Select3D_SensitivePoly*" [vstate -entities]] } { puts "Error: circle sector should be detected" }

View File

@ -0,0 +1,67 @@
puts "================================="
puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
puts ""
puts "================================="
pload VISUALIZATION OPENGL
vinit View1
vpoint radP1 0 0 0
vpoint radP2 50 50 0
vpoint radP3 100 0 0
vcircle circle radP1 radP2 radP3 0
vaxo
vfit
# Single click selection
# point inside a circle
vselect 200 200
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
# point on circle
vselect 177 285
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
# point outside a circle
vselect 360 360
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
# Selection with polygon
# circle inside a polygon
vselect 50 300 360 300 360 100 50 100
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a polygon should be detected" }
# circle is partially covered by a polygon
vselect 250 300 360 300 360 100 250 100 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should not be detected" }
vselect 250 300 360 300 360 100 250 100 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should be detected" }
# polygon inside a circle
vselect 150 200 200 200 200 150 150 150 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
vselect 150 200 200 200 200 150 150 150 -allowoverlap 1
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
# Selection with rectangle
# circle inside a rectangle
vselect 50 300 360 100
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a rectangle should be detected" }
# circle is partially covered by a rectangle
vselect 250 300 360 100 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should not be detected" }
vselect 250 300 360 100 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should be detected" }
# rectangle inside a circle
vselect 150 200 200 150 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }
vselect 150 200 200 150 -allowoverlap 1
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }

View File

@ -0,0 +1,67 @@
puts "================================="
puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
puts ""
puts "================================="
pload VISUALIZATION OPENGL
vinit View1
vpoint radP1 0 0 0
vpoint radP2 50 50 0
vpoint radP3 100 0 0
vcircle circle radP1 radP2 radP3 1
vaxo
vfit
# Single click selection
# point inside a circle
vselect 200 200
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
# point on circle
vselect 177 279
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
# point outside a circle
vselect 360 360
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should not be detected" }
# Selection with polygon
# circle inside a polygon
vselect 50 300 360 300 360 100 50 100
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a polygon should be detected" }
# circle is partially covered by a polygon
vselect 250 300 360 300 360 100 250 100 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should not be detected" }
vselect 250 300 360 300 360 100 250 100 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a polygon should be detected" }
# polygon inside a circle
vselect 150 200 200 200 200 150 150 150 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should not be detected" }
vselect 150 200 200 200 200 150 150 150 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the polygon should be detected" }
# Selection with rectangle
# circle inside a rectangle
vselect 50 300 360 100
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle inside a rectangle should be detected" }
# circle is partially covered by a rectangle
vselect 250 300 360 100 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should not be detected" }
vselect 250 300 360 100 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle partially covered by a rectangle should be detected" }
# rectangle inside a circle
vselect 150 200 200 150 -allowoverlap 0
if { [string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should not be detected" }
vselect 150 200 200 150 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle around the rectangle should be detected" }

View File

@ -0,0 +1,61 @@
puts "================================="
puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
puts " "
puts "================================="
pload MODELING VISUALIZATION
pcone cone 10 5 10
trotate cone 0 0 0 1 1 0 30
ttranslate cone 15 15 0
pcylinder cyl 7 7
trotate cyl 0 0 0 1 1 0 30
explode cyl F
explode cone F
vdisplay -dispmode 1 cyl_1 cone_1
vaxo
vfit
vselect 60 220 140 220 140 190 60 190 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
vselect 60 220 140 220 140 190 60 190 -allowoverlap 1
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
vselect 60 220 140 190 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
vselect 60 220 140 190 -allowoverlap 1
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cylinder should not be detected" }
vselect 270 210 310 210 310 160 270 160 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
vselect 270 210 310 210 310 160 270 160 -allowoverlap 1
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
vselect 270 210 310 160 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
vselect 270 210 310 160 -allowoverlap 1
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
vselect 60 210 310 210 310 200 60 200 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]]} { puts "Error: cone should not be detected" }
vselect 60 210 310 210 310 200 60 200 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCylinder*" [vstate -entities]]
&& [string first "Select3D_SensitiveCylinder" [vstate -entities]]
!= [string last "Select3D_SensitiveCylinder" [vstate -entities]]} { puts "Error: cone should be detected" }
vselect 60 210 310 200 -allowoverlap 0
if { [string match "*Select3D_SensitiveCylinder*" [vstate -entities]] } { puts "Error: cone should not be detected" }
vselect 60 210 310 200 -allowoverlap 1
if { ![string match "*Select3D_SensitiveCylinder*" [vstate -entities]]
&& [string first "Select3D_SensitiveCylinder" [vstate -entities]]
!= [string last "Select3D_SensitiveCylinder" [vstate -entities]] } { puts "Error: cone should be detected" }

View File

@ -0,0 +1,41 @@
puts "================================="
puts "0032547: Visualization, Select3D_SensitiveCylinder - implement picking of a hollow cylinder"
puts ""
puts "================================="
pload VISUALIZATION OPENGL
vinit View1
vpoint C1P1 10 10 10
vpoint C1P2 60 60 -10
vpoint C1P3 35 100 10
vcircle c1 C1P1 C1P2 C1P3 1
vpoint C2P1 10 -10 -10
vpoint C2P2 60 -60 10
vpoint C2P3 35 -100 10
vcircle c2 C2P1 C2P2 C2P3 1
vpoint C3P1 -80 -10 10
vpoint C3P2 -140 -50 -10
vpoint C3P3 -110 -100 -10
vcircle c3 C3P1 C3P2 C3P3 1
vpoint C4P1 -80 10 10
vpoint C4P2 -140 60 10
vpoint C4P3 -110 100 -10
vcircle c4 C4P1 C4P2 C4P3 1
vbottom
vfit
vmoveto 100 100
if {[vreadpixel 100 100 rgb name] != "TURQUOISE"} { puts "ERROR: the circle should be highlighted" }
vmoveto 200 200
vseldump $imagedir/${casename}_selnorm.png -type surfNormal
vsensdis
vseldump $imagedir/${casename}.png

View File

@ -11,7 +11,7 @@ ttranslate c 2500 3500 1000
vinit View1
# check Select3D_SensitiveTriangulation
# check Select3D_SensitiveCircle
vclear
vaxo
compound {*}[explode c Sh] cc
@ -21,7 +21,7 @@ vselaxis 2500 3498 1001 0 1 0 -display a -showNormal
set aPntTris [vmoveto 200 200]
vpoint pp {*}$aPntTris
checkpoint aPntTris_p $aPntTris {2500.42 3499.54 1000.81} 0.1
if { ![string match "*Select3D_SensitiveTriangulation*" [vstate -entities]] } { puts "Error: triangulation should be detected" }
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
vfit
vdump $imagedir/${casename}_prs_tris.png
vseldump $imagedir/${casename}_selnorm_tris.png -type surfNormal

View File

@ -11,7 +11,7 @@ ttranslate c 2500 3500 1000
vinit View1
# check Select3D_SensitiveTriangulation
# check Select3D_SensitiveCircle
vclear
vaxo
compound {*}[explode c Sh] cc
@ -21,7 +21,7 @@ vselaxis 2500 3498 1001 0 1 0 -display a -showNormal
set aPntTris [vmoveto 200 200]
vpoint pp {*}$aPntTris
checkpoint aPntTris_p $aPntTris {2500.9 3499.0 1001.6} 0.1
if { ![string match "*Select3D_SensitiveTriangulation*" [vstate -entities]] } { puts "Error: triangulation should be detected" }
if { ![string match "*Select3D_SensitiveCircle*" [vstate -entities]] } { puts "Error: circle should be detected" }
vfit
vdump $imagedir/${casename}_prs_tris.png
vseldump $imagedir/${casename}_selnorm_tris.png -type surfNormal