mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-06-04 11:36:52 +08:00
A special mode for the selecting by polygon is added to select only completely overlapping objects. In order to track the sensitives that were included completely by defined polygon, the boundary points of the polygonal frustrum are stored in the variable myBoundaryPoints. If an sensitive intersects with at least one of the frustrums from myFrustums, then checking whether this object intersects with borders using the isIntersectBoundary method; if not, then the sensitive were included completely by defined polygon. Because the polygon can be concave, then to check the sensitive were included completely by defined polygon, it is not enough to check of all its points, it is necessary that the edges of the sensitive do not intersect polygonal frustrum. To do this, for polygonal selection, a call to the Overlaps method for a point was replaced by a call to a segment where necessary. bugs/vis/bug31440: test case added
331 lines
12 KiB
C++
331 lines
12 KiB
C++
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <Select3D_SensitivePoly.hxx>
|
|
|
|
IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePoly,Select3D_SensitiveSet)
|
|
|
|
//==================================================
|
|
// Function: Select3D_SensitivePoly
|
|
// Purpose :
|
|
//==================================================
|
|
Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
|
|
const TColgp_Array1OfPnt& thePoints,
|
|
const Standard_Boolean theIsBVHEnabled)
|
|
: Select3D_SensitiveSet (theOwnerId),
|
|
myPolyg (thePoints.Upper() - thePoints.Lower() + 1)
|
|
{
|
|
Standard_Integer aLowerIdx = thePoints.Lower();
|
|
Standard_Integer anUpperIdx = thePoints.Upper();
|
|
gp_XYZ aPntSum (0.0, 0.0, 0.0);
|
|
|
|
Select3D_BndBox3d aBndBox;
|
|
for (Standard_Integer aIdx = aLowerIdx; aIdx <= anUpperIdx; ++aIdx)
|
|
{
|
|
aPntSum += thePoints.Value (aIdx).XYZ();
|
|
const SelectMgr_Vec3 aPnt (thePoints.Value (aIdx).X(),
|
|
thePoints.Value (aIdx).Y(),
|
|
thePoints.Value (aIdx).Z());
|
|
aBndBox.Add (aPnt);
|
|
myPolyg.SetPnt (aIdx - aLowerIdx, thePoints.Value (aIdx));
|
|
}
|
|
|
|
myBndBox = aBndBox;
|
|
myCOG = aPntSum / myPolyg.Size();
|
|
|
|
if (theIsBVHEnabled)
|
|
{
|
|
const Standard_Integer aPntsNum = myPolyg.Size();
|
|
mySegmentIndexes = new TColStd_HArray1OfInteger (0, aPntsNum - 2);
|
|
for (Standard_Integer aSegmIter = 0; aSegmIter < aPntsNum - 1; ++aSegmIter)
|
|
{
|
|
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
|
|
}
|
|
}
|
|
|
|
myIsComputed = Standard_True;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Select3D_SensitivePoly
|
|
// Purpose :
|
|
//==================================================
|
|
Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
|
|
const Handle(TColgp_HArray1OfPnt)& thePoints,
|
|
const Standard_Boolean theIsBVHEnabled)
|
|
: Select3D_SensitiveSet (theOwnerId),
|
|
myPolyg (thePoints->Upper() - thePoints->Lower() + 1)
|
|
{
|
|
Standard_Integer aLowerIdx = thePoints->Lower();
|
|
Standard_Integer anUpperIdx = thePoints->Upper();
|
|
gp_XYZ aPntSum (0.0, 0.0, 0.0);
|
|
|
|
Select3D_BndBox3d aBndBox;
|
|
for (Standard_Integer aIdx = aLowerIdx; aIdx <= anUpperIdx; ++aIdx)
|
|
{
|
|
aPntSum += thePoints->Value (aIdx).XYZ();
|
|
const SelectMgr_Vec3 aPnt (thePoints->Value (aIdx).X(),
|
|
thePoints->Value (aIdx).Y(),
|
|
thePoints->Value (aIdx).Z());
|
|
aBndBox.Add (aPnt);
|
|
myPolyg.SetPnt (aIdx - aLowerIdx, thePoints->Value (aIdx));
|
|
}
|
|
|
|
myBndBox = aBndBox;
|
|
myCOG = aPntSum / myPolyg.Size();
|
|
|
|
if (theIsBVHEnabled)
|
|
{
|
|
const Standard_Integer aPntsNum = myPolyg.Size();
|
|
mySegmentIndexes = new TColStd_HArray1OfInteger (0, aPntsNum - 2);
|
|
for (Standard_Integer aSegmIter = 0; aSegmIter < aPntsNum - 1; ++aSegmIter)
|
|
{
|
|
mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
|
|
}
|
|
}
|
|
|
|
myIsComputed = Standard_True;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Creation
|
|
// Purpose :
|
|
//==================================================
|
|
Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectMgr_EntityOwner)& theOwnerId,
|
|
const Standard_Boolean theIsBVHEnabled,
|
|
const Standard_Integer theNbPnts)
|
|
: Select3D_SensitiveSet (theOwnerId),
|
|
myPolyg (theNbPnts)
|
|
{
|
|
if (theIsBVHEnabled)
|
|
{
|
|
mySegmentIndexes = new TColStd_HArray1OfInteger (0, theNbPnts - 2);
|
|
for (Standard_Integer aIdx = 0; aIdx < theNbPnts - 1; ++aIdx)
|
|
{
|
|
mySegmentIndexes->SetValue (aIdx, aIdx);
|
|
}
|
|
}
|
|
myCOG = gp_Pnt (RealLast(), RealLast(), RealLast());
|
|
myIsComputed = Standard_False;
|
|
}
|
|
|
|
//==================================================
|
|
// function : BoundingBox
|
|
// purpose : Returns bounding box of a polygon. If location
|
|
// transformation is set, it will be applied
|
|
//==================================================
|
|
Select3D_BndBox3d Select3D_SensitivePoly::BoundingBox()
|
|
{
|
|
if (myBndBox.IsValid())
|
|
return myBndBox;
|
|
|
|
Select3D_BndBox3d aBndBox;
|
|
for (Standard_Integer aPntIter = 0; aPntIter < myPolyg.Size(); ++aPntIter)
|
|
{
|
|
SelectMgr_Vec3 aPnt (myPolyg.Pnt (aPntIter).x,
|
|
myPolyg.Pnt (aPntIter).y,
|
|
myPolyg.Pnt (aPntIter).z);
|
|
aBndBox.Add (aPnt);
|
|
}
|
|
|
|
myBndBox = aBndBox;
|
|
|
|
return myBndBox;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Size
|
|
// Purpose : Returns the amount of segments of
|
|
// the poly
|
|
//==================================================
|
|
Standard_Integer Select3D_SensitivePoly::Size() const
|
|
{
|
|
if (!mySegmentIndexes.IsNull())
|
|
return mySegmentIndexes->Length();
|
|
|
|
return -1;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Box
|
|
// Purpose : Returns bounding box of segment with
|
|
// index theIdx
|
|
//==================================================
|
|
Select3D_BndBox3d Select3D_SensitivePoly::Box (const Standard_Integer theIdx) const
|
|
{
|
|
if (mySegmentIndexes.IsNull())
|
|
return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()));
|
|
|
|
const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theIdx);
|
|
gp_Pnt aPnt1 = myPolyg.Pnt3d (aSegmentIdx);
|
|
gp_Pnt aPnt2 = myPolyg.Pnt3d (aSegmentIdx + 1);
|
|
|
|
const SelectMgr_Vec3 aMinPnt (Min (aPnt1.X(), aPnt2.X()),
|
|
Min (aPnt1.Y(), aPnt2.Y()),
|
|
Min (aPnt1.Z(), aPnt2.Z()));
|
|
const SelectMgr_Vec3 aMaxPnt (Max (aPnt1.X(), aPnt2.X()),
|
|
Max (aPnt1.Y(), aPnt2.Y()),
|
|
Max (aPnt1.Z(), aPnt2.Z()));
|
|
|
|
return Select3D_BndBox3d (aMinPnt, aMaxPnt);
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Center
|
|
// Purpose : Returns geometry center of sensitive
|
|
// entity index theIdx in the vector along
|
|
// the given axis theAxis
|
|
//==================================================
|
|
Standard_Real Select3D_SensitivePoly::Center (const Standard_Integer theIdx,
|
|
const Standard_Integer theAxis) const
|
|
{
|
|
if (mySegmentIndexes.IsNull())
|
|
return RealLast();
|
|
|
|
const Select3D_BndBox3d aBndBox = Box (theIdx);
|
|
const SelectMgr_Vec3 aCenter = (aBndBox.CornerMin() + aBndBox.CornerMax()) * 0.5;
|
|
return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
|
|
}
|
|
|
|
//==================================================
|
|
// Function: Swap
|
|
// Purpose : Swaps items with indexes theIdx1 and
|
|
// theIdx2 in the vector
|
|
//==================================================
|
|
void Select3D_SensitivePoly::Swap (const Standard_Integer theIdx1,
|
|
const Standard_Integer theIdx2)
|
|
{
|
|
if (mySegmentIndexes.IsNull())
|
|
return;
|
|
|
|
const Standard_Integer aSegmentIdx1 = mySegmentIndexes->Value (theIdx1);
|
|
const Standard_Integer aSegmentIdx2 = mySegmentIndexes->Value (theIdx2);
|
|
mySegmentIndexes->ChangeValue (theIdx1) = aSegmentIdx2;
|
|
mySegmentIndexes->ChangeValue (theIdx2) = aSegmentIdx1;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: overlapsElement
|
|
// Purpose : Checks whether the segment with index
|
|
// theIdx overlaps the current selecting
|
|
// volume
|
|
//==================================================
|
|
Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_PickResult& thePickResult,
|
|
SelectBasics_SelectingVolumeManager& theMgr,
|
|
Standard_Integer theElemIdx,
|
|
Standard_Boolean theIsFullInside)
|
|
{
|
|
if (mySegmentIndexes.IsNull())
|
|
{
|
|
return Standard_False;
|
|
}
|
|
else if (theIsFullInside)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
|
|
const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
|
|
gp_Pnt aPnt1 = myPolyg.Pnt3d (aSegmentIdx);
|
|
gp_Pnt aPnt2 = myPolyg.Pnt3d (aSegmentIdx + 1);
|
|
return theMgr.Overlaps (aPnt1, aPnt2, thePickResult);
|
|
}
|
|
|
|
//==================================================
|
|
// Function : elementIsInside
|
|
// Purpose :
|
|
//==================================================
|
|
Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
|
|
Standard_Integer theElemIdx,
|
|
Standard_Boolean theIsFullInside)
|
|
{
|
|
if (theIsFullInside)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
|
|
const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
|
|
if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
|
|
{
|
|
SelectBasics_PickResult aDummy;
|
|
return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0), myPolyg.Pnt3d (aSegmentIdx + 1), aDummy);
|
|
}
|
|
return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0))
|
|
&& theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1));
|
|
}
|
|
|
|
//==================================================
|
|
// Function: distanceToCOG
|
|
// Purpose : Calculates distance from the 3d
|
|
// projection of used-picked screen point
|
|
// to center of the geometry
|
|
//==================================================
|
|
Standard_Real Select3D_SensitivePoly::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
|
|
{
|
|
if (!myIsComputed)
|
|
{
|
|
gp_XYZ aCenter (0.0, 0.0, 0.0);
|
|
for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
|
|
{
|
|
aCenter += myPolyg.Pnt (aIdx);
|
|
}
|
|
myCOG = aCenter / myPolyg.Size();
|
|
myIsComputed = Standard_True;
|
|
}
|
|
|
|
return theMgr.DistToGeometryCenter (myCOG);
|
|
}
|
|
|
|
//==================================================
|
|
// Function: NbSubElements
|
|
// Purpose : Returns the amount of segments in poly
|
|
//==================================================
|
|
Standard_Integer Select3D_SensitivePoly::NbSubElements() const
|
|
{
|
|
return myPolyg.Size();
|
|
}
|
|
|
|
//==================================================
|
|
// Function: CenterOfGeometry
|
|
// Purpose : Returns center of the point set. If
|
|
// location transformation is set, it will
|
|
// be applied
|
|
//==================================================
|
|
gp_Pnt Select3D_SensitivePoly::CenterOfGeometry() const
|
|
{
|
|
if (!myIsComputed)
|
|
{
|
|
gp_XYZ aCenter (0.0, 0.0, 0.0);
|
|
for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
|
|
{
|
|
aCenter += myPolyg.Pnt (aIdx);
|
|
}
|
|
myCOG = aCenter / myPolyg.Size();
|
|
myIsComputed = Standard_True;
|
|
}
|
|
|
|
return myCOG;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : DumpJson
|
|
// purpose :
|
|
// =======================================================================
|
|
void Select3D_SensitivePoly::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
|
|
{
|
|
OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
|
|
OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveSet)
|
|
|
|
OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)
|
|
OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsComputed)
|
|
}
|