1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-09 18:50:54 +03:00
occt/src/Select3D/Select3D_SensitivePoly.cxx
vpa 3bf9a45f7a 0026195: Visualization - optimize selection algorithms
- 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.
2015-09-10 15:00:04 +03:00

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