1
0
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:
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

@@ -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,
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 :

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,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.

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,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:

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,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,

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,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 :

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,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.

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,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;

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,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

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,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
};