mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-09 18:50:54 +03:00
- initial transformation of triangulation is now applied to selecting frustum; - switched from NCollection_Vec3 to gp collections to avoid conversions and usage of macros; - calculation of frustum was refactored to reduce its build time; - double pixel tolerances for selection were replaced by integer ones; - switched to splitting along the main axis only in SelectMgr BVH selection primitive sets.
307 lines
11 KiB
C++
307 lines
11 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 <gp_Pnt.hxx>
|
|
#include <TopLoc_Location.hxx>
|
|
|
|
#include <Select3D_Pnt.hxx>
|
|
|
|
#include <Select3D_SensitivePoly.hxx>
|
|
|
|
|
|
//==================================================
|
|
// Function: Select3D_SensitivePoly
|
|
// Purpose :
|
|
//==================================================
|
|
Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_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(SelectBasics_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(SelectBasics_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;
|
|
return;
|
|
}
|
|
|
|
//==================================================
|
|
// Function: overlapsElement
|
|
// Purpose : Checks whether the segment with index
|
|
// theIdx overlaps the current selecting
|
|
// volume
|
|
//==================================================
|
|
Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
|
|
Standard_Integer theElemIdx,
|
|
Standard_Real& theMatchDepth)
|
|
{
|
|
if (mySegmentIndexes.IsNull())
|
|
return Standard_False;
|
|
|
|
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, theMatchDepth);
|
|
}
|
|
|
|
//==================================================
|
|
// Function : elementIsInside
|
|
// Purpose :
|
|
//==================================================
|
|
Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
|
|
const Standard_Integer theElemIdx)
|
|
{
|
|
const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
|
|
|
|
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()
|
|
{
|
|
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;
|
|
}
|