mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +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:
@@ -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))
|
||||
{
|
||||
|
@@ -227,7 +227,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
|
||||
|
||||
(void )theInside;
|
||||
Standard_Real aTimeEnter, aTimeLeave;
|
||||
@@ -252,7 +252,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsBox (const SelectMgr_Vec3& t
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsBox() should be called after selection axis initialization");
|
||||
|
||||
Standard_Real aTimeEnter, aTimeLeave;
|
||||
if (!hasIntersection (theBoxMin, theBoxMax, aTimeEnter, aTimeLeave))
|
||||
@@ -283,7 +283,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
|
||||
|
||||
Standard_Real aDepth = 0.0;
|
||||
if (!hasIntersection (thePnt, aDepth))
|
||||
@@ -304,7 +304,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt,
|
||||
Standard_Boolean SelectMgr_AxisIntersector::OverlapsPoint (const gp_Pnt& thePnt) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsPoint() should be called after selection axis initialization");
|
||||
|
||||
Standard_Real aDepth = 0.0;
|
||||
return hasIntersection (thePnt, aDepth);
|
||||
@@ -320,7 +320,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSegment (const gp_Pnt& thePn
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsSegment() should be called after selection axis initialization");
|
||||
|
||||
if (!raySegmentDistance (thePnt1, thePnt2, thePickResult))
|
||||
{
|
||||
@@ -340,7 +340,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsPolygon (const TColgp_Array1
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsPolygon() should be called after selection axis initialization");
|
||||
|
||||
if (theSensType == Select3D_TOS_BOUNDARY)
|
||||
{
|
||||
@@ -400,7 +400,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsTriangle (const gp_Pnt& theP
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE(mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsTriangle() should be called after selection axis initialization");
|
||||
|
||||
if (theSensType == Select3D_TOS_BOUNDARY)
|
||||
{
|
||||
@@ -503,7 +503,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
|
||||
(void )theInside;
|
||||
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
|
||||
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
|
||||
@@ -527,7 +527,7 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsSphere (const gp_Pnt& theCen
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsSphere() should be called after selection axis initialization");
|
||||
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
|
||||
if (!RaySphereIntersection (theCenter, theRadius, myAxis.Location(), myAxis.Direction(), aTimeEnter, aTimeLeave))
|
||||
{
|
||||
@@ -558,22 +558,24 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
|
||||
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
|
||||
gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
|
||||
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
|
||||
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
|
||||
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
|
||||
theIsHollow, aTimeEnter, aTimeLeave))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Standard_Real aDepth = 0.0;
|
||||
Bnd_Range aRange (Max (aTimeEnter, 0.0), aTimeLeave);
|
||||
Bnd_Range aRange (Max (aTimeEnter, 0.0), Max (aTimeEnter, aTimeLeave));
|
||||
aRange.GetMin (aDepth);
|
||||
if (!theClipRange.GetNearestDepth (aRange, aDepth))
|
||||
{
|
||||
@@ -606,15 +608,17 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
Standard_Boolean* theInside) const
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::Overlaps() should be called after selection axis initialization");
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsCylinder() should be called after selection axis initialization");
|
||||
Standard_Real aTimeEnter = 0.0, aTimeLeave = 0.0;
|
||||
gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
gp_Pnt aLoc = myAxis.Location() .Transformed (aTrsfInv);
|
||||
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
|
||||
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir, aTimeEnter, aTimeLeave))
|
||||
if (!RayCylinderIntersection (theBottomRad, theTopRad, theHeight, aLoc, aRayDir,
|
||||
theIsHollow, aTimeEnter, aTimeLeave))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -625,6 +629,74 @@ Standard_Boolean SelectMgr_AxisIntersector::OverlapsCylinder (const Standard_Rea
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : OverlapsCircle
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
|
||||
Standard_Real aTime = 0.0;
|
||||
gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
gp_Pnt aLoc = myAxis.Location().Transformed (aTrsfInv);
|
||||
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
|
||||
if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Standard_Real aDepth = Max (aTime, 0.0);
|
||||
if (theClipRange.IsClipped (aDepth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gp_Pnt aPntOnCylinder = aLoc.XYZ() + aRayDir.XYZ() * aDepth;
|
||||
thePickResult.SetDepth (aDepth);
|
||||
thePickResult.SetPickedPoint (aPntOnCylinder.Transformed (theTrsf));
|
||||
if (Abs (aPntOnCylinder.Z()) < Precision::Confusion())
|
||||
{
|
||||
thePickResult.SetSurfaceNormal (-gp::DZ().Transformed (theTrsf));
|
||||
}
|
||||
else
|
||||
{
|
||||
thePickResult.SetSurfaceNormal (gp_Vec (aPntOnCylinder.X(), aPntOnCylinder.Y(), 0.0).Transformed (theTrsf));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : OverlapsCircle
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean SelectMgr_AxisIntersector::OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
Standard_ASSERT_RAISE (mySelectionType == SelectMgr_SelectionType_Point,
|
||||
"Error! SelectMgr_AxisIntersector::OverlapsCircle() should be called after selection axis initialization");
|
||||
Standard_Real aTime = 0.0;
|
||||
gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
gp_Pnt aLoc = myAxis.Location().Transformed (aTrsfInv);
|
||||
gp_Dir aRayDir = myAxis.Direction().Transformed (aTrsfInv);
|
||||
if (!RayCircleIntersection (theRadius, aLoc, aRayDir, theIsFilled, aTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (theInside != NULL)
|
||||
{
|
||||
*theInside &= (aTime >= 0.0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : GetNearPnt
|
||||
// purpose :
|
||||
|
@@ -117,6 +117,7 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
@@ -126,8 +127,28 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
public:
|
||||
|
||||
//! Measures distance between start axis point and given point theCOG.
|
||||
|
@@ -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 :
|
||||
|
@@ -187,6 +187,7 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const = 0;
|
||||
|
||||
@@ -196,8 +197,28 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const = 0;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const = 0;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const = 0;
|
||||
|
||||
public:
|
||||
|
||||
//! Measures distance between 3d projection of user-picked
|
||||
@@ -224,15 +245,37 @@ public:
|
||||
Standard_Real& theTimeLeave) const;
|
||||
|
||||
//! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
|
||||
//! with the cylinder (or cone) with radiuses theBottomRad and theTopRad and height theHeights
|
||||
//! with the hollow cylinder (or cone)
|
||||
//! @param[in] theBottomRadius the bottom cylinder radius
|
||||
//! @param[in] theTopRadius the top cylinder radius
|
||||
//! @param[in] theHeight the cylinder height
|
||||
//! @param[in] theLoc the location of the ray
|
||||
//! @param[in] theRayDir the ray direction
|
||||
//! @param[in] theIsHollow true if the cylinder is hollow
|
||||
//! @param[out] theTimeEnter the entering the intersection
|
||||
//! @param[out] theTimeLeave the leaving the intersection
|
||||
Standard_EXPORT virtual Standard_Boolean RayCylinderIntersection (const Standard_Real theBottomRadius,
|
||||
const Standard_Real theTopRadius,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Pnt& theLoc,
|
||||
const gp_Dir& theRayDir,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Real& theTimeEnter,
|
||||
Standard_Real& theTimeLeave) const;
|
||||
|
||||
//! Checks whether the ray that starts at the point theLoc and directs with the direction theRayDir intersects
|
||||
//! with the circle
|
||||
//! @param[in] theRadius the circle radius
|
||||
//! @param[in] theLoc the location of the ray
|
||||
//! @param[in] theRayDir the ray direction
|
||||
//! @param[in] theIsFilled true if it's a circle, false if it's a circle outline
|
||||
//! @param[out] theTime the intersection
|
||||
Standard_EXPORT virtual Standard_Boolean RayCircleIntersection (const Standard_Real theRadius,
|
||||
const gp_Pnt& theLoc,
|
||||
const gp_Dir& theRayDir,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Real& theTime) const;
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(SelectMgr_BaseIntersector,Standard_Transient)
|
||||
|
||||
protected:
|
||||
|
@@ -98,11 +98,25 @@ protected:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const;
|
||||
|
||||
//! Intersection test between defined volume and given circle.
|
||||
Standard_Boolean hasCircleOverlap (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const;
|
||||
|
||||
//! Returns True if all vertices (theVertices) are inside the top and bottom sides of the cylinder.
|
||||
Standard_Boolean isInsideCylinderEndFace (const Standard_Real theBottomRad,
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const;
|
||||
|
||||
//! Checking whether the point thePnt is inside the shape with borders theVertices.
|
||||
//! thePnt and theVertices lie in the same plane.
|
||||
Standard_Boolean IsDotInside (const gp_Pnt& thePnt,
|
||||
Standard_Boolean isDotInside (const gp_Pnt& thePnt,
|
||||
const TColgp_Array1OfPnt& theVertices) const;
|
||||
|
||||
private:
|
||||
@@ -116,10 +130,10 @@ private:
|
||||
|
||||
//! Checking whether the borders theVertices of the shape intersect
|
||||
//! the cylinder (or cone) end face with the center theCenter and radius theRadius
|
||||
Standard_Boolean isIntersectCylinderEndFace (const Standard_Real theRad,
|
||||
const gp_Pnt& theCenter,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const;
|
||||
Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
|
||||
const gp_Pnt& theCenter,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const;
|
||||
|
||||
//! Checks if AABB and frustum are separated along the given axis
|
||||
Standard_Boolean isSeparated (const SelectMgr_Vec3& theBoxMin,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Created on: 2015-03-16
|
||||
// Created on: 2015-03-16
|
||||
// Created by: Varvara POSKONINA
|
||||
// Copyright (c) 2005-2014 OPEN CASCADE SAS
|
||||
//
|
||||
@@ -520,7 +520,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasSphereOverlap (const gp_Pnt& thePnt,
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<int N>
|
||||
Standard_Boolean SelectMgr_Frustum<N>::IsDotInside (const gp_Pnt& thePnt,
|
||||
Standard_Boolean SelectMgr_Frustum<N>::isDotInside (const gp_Pnt& thePnt,
|
||||
const TColgp_Array1OfPnt& theVertices) const
|
||||
{
|
||||
Standard_Real anAngle = 0.0;
|
||||
@@ -598,14 +598,14 @@ Standard_Boolean SelectMgr_Frustum<N>::isSegmentsIntersect (const gp_Pnt& thePnt
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : isIntersectCylinderEndFace
|
||||
// function : isIntersectCircle
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<int N>
|
||||
Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standard_Real theRad,
|
||||
const gp_Pnt& theCenter,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const
|
||||
Standard_Boolean SelectMgr_Frustum<N>::isIntersectCircle (const Standard_Real theRadius,
|
||||
const gp_Pnt& theCenter,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const
|
||||
{
|
||||
const gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
const gp_Dir aRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]).Transformed (aTrsfInv);
|
||||
@@ -633,7 +633,7 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
|
||||
// Solving quadratic equation anA * T^2 + 2 * aK * T + aC = 0
|
||||
const Standard_Real anA = (aX1 - aX2) * (aX1 - aX2) + (anY1 - anY2) * (anY1 - anY2);
|
||||
const Standard_Real aK = aX1 * (aX2 - aX1) + anY1 * (anY2 - anY1);
|
||||
const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRad * theRad;
|
||||
const Standard_Real aC = aX1 * aX1 + anY1 * anY1 - theRadius * theRadius;
|
||||
|
||||
const Standard_Real aDiscr = aK * aK - anA * aC;
|
||||
if (aDiscr >= 0.0)
|
||||
@@ -649,6 +649,47 @@ Standard_Boolean SelectMgr_Frustum<N>::isIntersectCylinderEndFace (const Standar
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : isInsideCylinderEndFace
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<int N>
|
||||
Standard_Boolean SelectMgr_Frustum<N>::isInsideCylinderEndFace (const Standard_Real theBottomRad,
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const
|
||||
{
|
||||
const gp_Trsf aTrsfInv = theTrsf.Inverted();
|
||||
const gp_Dir aRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]).Transformed (aTrsfInv);
|
||||
if (aRayDir.Z() == 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Standard_Integer anIdx = theVertices.Lower(); anIdx <= theVertices.Upper(); anIdx++)
|
||||
{
|
||||
const gp_Pnt aLoc = theVertices.Value (anIdx).Transformed (aTrsfInv);
|
||||
|
||||
const Standard_Real aTime1 = (0 - aLoc.Z()) / aRayDir.Z();
|
||||
const Standard_Real aX1 = aLoc.X() + aRayDir.X() * aTime1;
|
||||
const Standard_Real anY1 = aLoc.Y() + aRayDir.Y() * aTime1;
|
||||
|
||||
const Standard_Real aTime2 = (theHeight - aLoc.Z()) / aRayDir.Z();
|
||||
const Standard_Real aX2 = aLoc.X() + aRayDir.X() * aTime2;
|
||||
const Standard_Real anY2 = aLoc.Y() + aRayDir.Y() * aTime2;
|
||||
|
||||
if (aX1 * aX1 + anY1 * anY1 <= theBottomRad * theBottomRad
|
||||
&& aX2 * aX2 + anY2 * anY2 <= theTopRad * theTopRad)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : hasCylinderOverlap
|
||||
// purpose :
|
||||
@@ -658,8 +699,37 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
gp_Pnt aVerticesBuf[N];
|
||||
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
|
||||
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
|
||||
if (anIncFactor == 2)
|
||||
{
|
||||
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (theIsHollow && isInsideCylinderEndFace (theBottomRad, theTopRad, theHeight, theTrsf, aVertices))
|
||||
{
|
||||
if (theInside != NULL)
|
||||
{
|
||||
*theInside = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const gp_Dir aCylNorm (gp::DZ().Transformed (theTrsf));
|
||||
const gp_Pnt aBottomCenter (gp::Origin().Transformed (theTrsf));
|
||||
const gp_Pnt aTopCenter = aBottomCenter.XYZ() + aCylNorm.XYZ() * theHeight;
|
||||
@@ -698,29 +768,11 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
|
||||
aPoints[5] = aBottomCenterProject.XYZ() - aDirEndFaces.XYZ() * theBottomRad;
|
||||
const TColgp_Array1OfPnt aPointsArr (aPoints[0], 0, 5);
|
||||
|
||||
gp_Pnt aVerticesBuf[N];
|
||||
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
|
||||
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
|
||||
if (anIncFactor == 2)
|
||||
{
|
||||
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIdx]);
|
||||
}
|
||||
}
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
if ((aCylNormProject.Dot (aCylNormProject) == 0.0
|
||||
&& aVertices.Value (anIdx).Distance (aPoints[0]) <= Max (theTopRad, theBottomRad))
|
||||
|| IsDotInside (aVertices.Value (anIdx), aPointsArr))
|
||||
|| isDotInside (aVertices.Value (anIdx), aPointsArr))
|
||||
{
|
||||
if (theInside != NULL)
|
||||
{
|
||||
@@ -747,8 +799,9 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntersectCylinderEndFace (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
|
||||
|| isIntersectCylinderEndFace (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices))
|
||||
if (!theIsHollow
|
||||
&& (isIntersectCircle (theBottomRad, gp_Pnt (0, 0, 0), theTrsf, aVertices)
|
||||
|| isIntersectCircle (theTopRad, gp_Pnt (0, 0, theHeight), theTrsf, aVertices)))
|
||||
{
|
||||
if (theInside != NULL)
|
||||
{
|
||||
@@ -759,7 +812,7 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
|
||||
bool isCylInsideRec = true;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
isCylInsideRec &= IsDotInside (aPoints[i], aVertices);
|
||||
isCylInsideRec &= isDotInside (aPoints[i], aVertices);
|
||||
}
|
||||
if (theInside != NULL)
|
||||
{
|
||||
@@ -768,6 +821,82 @@ Standard_Boolean SelectMgr_Frustum<N>::hasCylinderOverlap (const Standard_Real t
|
||||
return isCylInsideRec;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : hasCircleOverlap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<int N>
|
||||
Standard_Boolean SelectMgr_Frustum<N>::hasCircleOverlap (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside) const
|
||||
{
|
||||
gp_Pnt aVerticesBuf[N];
|
||||
TColgp_Array1OfPnt aVertices (aVerticesBuf[0], 0, N - 1);
|
||||
const Standard_Integer anIncFactor = (Camera()->IsOrthographic() && N == 4) ? 2 : 1;
|
||||
if (anIncFactor == 2)
|
||||
{
|
||||
const Standard_Integer anIndices[] = { 0, 2, 6, 4 };
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIndices[anIdx]]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Standard_Integer anIdx = 0; anIdx < N; anIdx++)
|
||||
{
|
||||
aVertices.SetValue (anIdx, myVertices[anIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntersectCircle (theRadius, gp_Pnt (0, 0, 0), theTrsf, aVertices))
|
||||
{
|
||||
if (theInside != NULL)
|
||||
{
|
||||
*theInside = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
gp_Pnt aCircCenter = gp::Origin();//.Transformed (theTrsf);
|
||||
const gp_Dir aViewRayDir = gp_Dir (myEdgeDirs[N == 4 ? 4 : 0]);
|
||||
const gp_Pln aPln (myVertices[0], aViewRayDir);
|
||||
Standard_Real aCoefA, aCoefB, aCoefC, aCoefD;
|
||||
aPln.Coefficients (aCoefA, aCoefB, aCoefC, aCoefD);
|
||||
|
||||
const Standard_Real aTCenter = -(aCircCenter.XYZ().Dot (aViewRayDir.XYZ()) + aCoefD);
|
||||
const gp_Pnt aCenterProject (aCoefA * aTCenter,
|
||||
aCoefB * aTCenter,
|
||||
aCoefC * aTCenter);
|
||||
if (isDotInside (aCenterProject, aVertices))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Standard_Boolean isInside = true;
|
||||
for (Standard_Integer anIdx = aVertices.Lower(); anIdx <= aVertices.Upper(); anIdx++)
|
||||
{
|
||||
if (aVertices.Value (anIdx).Distance (aCenterProject) > theRadius)
|
||||
{
|
||||
isInside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theInside != NULL)
|
||||
{
|
||||
*theInside = false;
|
||||
}
|
||||
|
||||
if (!theIsFilled && isInside)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return isInside;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : DumpJson
|
||||
//purpose :
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@@ -66,6 +66,18 @@ public:
|
||||
Standard_EXPORT void Init (const gp_Pnt2d& theMinPnt,
|
||||
const gp_Pnt2d& theMaxPnt);
|
||||
|
||||
//! Returns True if Frustum (theVertices) intersects the circle.
|
||||
Standard_EXPORT Standard_Boolean isIntersectCircle (const Standard_Real theRadius,
|
||||
const gp_Pnt& theCenter,
|
||||
const gp_Trsf& theTrsf,
|
||||
const TColgp_Array1OfPnt& theVertices) const;
|
||||
|
||||
//! Returns True if Seg1 (thePnt1Seg1, thePnt2Seg1) and Seg2 (thePnt1Seg2, thePnt2Seg2) intersect.
|
||||
Standard_EXPORT Standard_Boolean isSegmentsIntersect (const gp_Pnt& thePnt1Seg1,
|
||||
const gp_Pnt& thePnt2Seg1,
|
||||
const gp_Pnt& thePnt1Seg2,
|
||||
const gp_Pnt& thePnt2Seg2) const;
|
||||
|
||||
//! Builds volume according to internal parameters.
|
||||
//! NOTE: it should be called after Init() method
|
||||
Standard_EXPORT virtual void Build() Standard_OVERRIDE;
|
||||
@@ -150,6 +162,7 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
@@ -159,8 +172,28 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Measures distance between 3d projection of user-picked
|
||||
//! screen point and given point theCOG.
|
||||
//! It makes sense only for frustums built on a single point.
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -168,6 +168,7 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
|
||||
@@ -176,8 +177,27 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Measures distance between 3d projection of user-picked
|
||||
//! screen point and given point theCOG
|
||||
Standard_EXPORT virtual Standard_Real DistToGeometryCenter (const gp_Pnt& theCOG) const Standard_OVERRIDE;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@@ -123,6 +123,7 @@ public: //! @name SAT Tests for different objects
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
@@ -132,8 +133,28 @@ public: //! @name SAT Tests for different objects
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by circle with radius theRadius,
|
||||
//! boolean theIsFilled and transformation to apply theTrsf.
|
||||
//! The position and orientation of the circle are specified
|
||||
//! via theTrsf transformation for gp::XOY() with center in gp::Origin().
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
public:
|
||||
|
||||
//! Nullifies the handle to corresponding builder instance to prevent memory leaks
|
||||
|
@@ -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;
|
||||
|
@@ -124,6 +124,7 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
@@ -133,8 +134,24 @@ public:
|
||||
const Standard_Real theTopRad,
|
||||
const Standard_Real theHeight,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsHollow,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
|
||||
//! and theTopRad, height theHeight and transformation to apply theTrsf.
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
const SelectMgr_ViewClipRange& theClipRange,
|
||||
SelectBasics_PickResult& thePickResult) const Standard_OVERRIDE;
|
||||
|
||||
//! Returns true if selecting volume is overlapped by cylinder (or cone) with radiuses theBottomRad
|
||||
//! and theTopRad, height theHeight and transformation to apply theTrsf.
|
||||
Standard_EXPORT virtual Standard_Boolean OverlapsCircle (const Standard_Real theBottomRad,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled,
|
||||
Standard_Boolean* theInside = NULL) const Standard_OVERRIDE;
|
||||
|
||||
//! Stores plane equation coefficients (in the following form:
|
||||
//! Ax + By + Cz + D = 0) to the given vector
|
||||
Standard_EXPORT virtual void GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const Standard_OVERRIDE;
|
||||
@@ -151,15 +168,34 @@ private:
|
||||
//! Checks whether the segment intersects with the boundary of the current volume selection
|
||||
Standard_EXPORT Standard_Boolean isIntersectBoundary (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2) const;
|
||||
|
||||
//! Checks whether the circle intersects with the boundary of the current volume selection
|
||||
Standard_EXPORT Standard_Boolean isIntersectBoundary (const Standard_Real theRadius,
|
||||
const gp_Trsf& theTrsf,
|
||||
const Standard_Boolean theIsFilled) const;
|
||||
|
||||
//! Checks whether the triangle intersects with a segment
|
||||
Standard_EXPORT Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
|
||||
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3) const;
|
||||
Standard_EXPORT static Standard_Boolean segmentTriangleIntersection (const gp_Pnt &theOrig, const gp_Vec& theDir,
|
||||
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
|
||||
|
||||
Standard_EXPORT static Standard_Boolean segmentSegmentIntersection (const gp_Pnt& theStartPnt1,
|
||||
const gp_Pnt& theEndPnt1,
|
||||
const gp_Pnt& theStartPnt2,
|
||||
const gp_Pnt& theEndPnt2);
|
||||
|
||||
Standard_EXPORT static Standard_Boolean pointInTriangle (const gp_Pnt& thePnt,
|
||||
const gp_Pnt& theV1, const gp_Pnt& theV2, const gp_Pnt& theV3);
|
||||
|
||||
private:
|
||||
|
||||
SelectMgr_TriangFrustums myFrustums; //!< set of triangular frustums
|
||||
SelectionPolyline mySelPolyline; //!< parameters of selection polyline (it is used to build triangle frustum set)
|
||||
TColgp_Array1OfPnt myBoundaryPoints; //!< boundary points
|
||||
//! 1_____2
|
||||
//! /| |\ .
|
||||
//! 4/_|_____|_\3
|
||||
//! | 5|_____|6 |
|
||||
//! | / \ |
|
||||
//! 8|/_________\|7
|
||||
Standard_Boolean myToAllowOverlap; //!< flag to detect only fully included sensitives or not
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user