From 114b7bf18f6ef074558884f5871e77160251b7d1 Mon Sep 17 00:00:00 2001 From: vpa Date: Wed, 2 Mar 2016 20:27:42 +0300 Subject: [PATCH] 0027180: Visualization - improve selection logic of MeshVS_Mesh MeshVS_Mesh selection logic in MeshVS_SMF_Mesh mode (entire mesh) has been optimized. MeshVS_Mesh::ComputeSelection() now creates single sensitive entity MeshVS_CommonSensitiveEntity (new class) instead of small sensitive entity on each element. MeshVS_SensitiveQuad (new class) and Select3D_SensitiveTriangle are used instead of Select3D_SensitiveFace for local selection to reduce memory consumption when possible. --- src/MeshVS/FILES | 4 + src/MeshVS/MeshVS_Buffer.hxx | 7 + src/MeshVS/MeshVS_CommonSensitiveEntity.cxx | 323 ++++++++++++++++++ src/MeshVS/MeshVS_CommonSensitiveEntity.hxx | 94 +++++ src/MeshVS/MeshVS_Mesh.cxx | 266 +++++++++------ src/MeshVS/MeshVS_Mesh.hxx | 10 + src/MeshVS/MeshVS_SensitiveQuad.cxx | 126 +++++++ src/MeshVS/MeshVS_SensitiveQuad.hxx | 68 ++++ .../SelectBasics_SelectingVolumeManager.hxx | 6 + src/SelectMgr/SelectMgr_BaseFrustum.cxx | 2 +- src/SelectMgr/SelectMgr_BaseFrustum.hxx | 2 +- src/SelectMgr/SelectMgr_Frustum.hxx | 2 +- src/SelectMgr/SelectMgr_Frustum.lxx | 22 +- .../SelectMgr_RectangularFrustum.cxx | 22 +- .../SelectMgr_RectangularFrustum.hxx | 2 +- .../SelectMgr_SelectingVolumeManager.cxx | 19 ++ .../SelectMgr_SelectingVolumeManager.hxx | 7 + src/SelectMgr/SelectMgr_TriangularFrustum.cxx | 20 +- src/SelectMgr/SelectMgr_TriangularFrustum.hxx | 2 +- .../SelectMgr_TriangularFrustumSet.cxx | 2 +- .../SelectMgr_TriangularFrustumSet.hxx | 2 +- src/StdSelect/StdSelect_BRepSelectionTool.cxx | 6 +- src/StdSelect/StdSelect_BRepSelectionTool.hxx | 11 +- 23 files changed, 859 insertions(+), 166 deletions(-) create mode 100644 src/MeshVS/MeshVS_CommonSensitiveEntity.cxx create mode 100644 src/MeshVS/MeshVS_CommonSensitiveEntity.hxx create mode 100644 src/MeshVS/MeshVS_SensitiveQuad.cxx create mode 100644 src/MeshVS/MeshVS_SensitiveQuad.hxx diff --git a/src/MeshVS/FILES b/src/MeshVS/FILES index 03957f44b9..40672f91fb 100755 --- a/src/MeshVS/FILES +++ b/src/MeshVS/FILES @@ -3,6 +3,8 @@ MeshVS_Buffer.hxx MeshVS_BuilderPriority.hxx MeshVS_ColorHasher.cxx MeshVS_ColorHasher.hxx +MeshVS_CommonSensitiveEntity.hxx +MeshVS_CommonSensitiveEntity.cxx MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger.hxx MeshVS_DataMapIteratorOfDataMapOfHArray1OfSequenceOfInteger.hxx MeshVS_DataMapIteratorOfDataMapOfIntegerAsciiString.hxx @@ -67,6 +69,8 @@ MeshVS_SensitivePolyhedron.cxx MeshVS_SensitivePolyhedron.hxx MeshVS_SensitiveSegment.cxx MeshVS_SensitiveSegment.hxx +MeshVS_SensitiveQuad.hxx +MeshVS_SensitiveQuad.cxx MeshVS_SequenceOfPrsBuilder.hxx MeshVS_SymmetricPairHasher.hxx MeshVS_TextPrsBuilder.cxx diff --git a/src/MeshVS/MeshVS_Buffer.hxx b/src/MeshVS/MeshVS_Buffer.hxx index 51ab75d70d..47a83706a4 100644 --- a/src/MeshVS/MeshVS_Buffer.hxx +++ b/src/MeshVS/MeshVS_Buffer.hxx @@ -17,6 +17,7 @@ #define MeshVS_Buffer_HeaderFile #include +#include /** * General purpose buffer that is allocated on the stack with a @@ -68,6 +69,12 @@ public: return * (myDynData ? (Standard_Integer*) myDynData : (Standard_Integer*) myAutoData); } + //! Interpret the buffer as a reference to gp_Pnt + operator gp_Pnt& () + { + return * (myDynData ? (gp_Pnt*) myDynData : (gp_Pnt*) myAutoData); + } + private: //! Deprecate copy constructor MeshVS_Buffer(const MeshVS_Buffer&) {} diff --git a/src/MeshVS/MeshVS_CommonSensitiveEntity.cxx b/src/MeshVS/MeshVS_CommonSensitiveEntity.cxx new file mode 100644 index 0000000000..9438498af0 --- /dev/null +++ b/src/MeshVS/MeshVS_CommonSensitiveEntity.cxx @@ -0,0 +1,323 @@ +// Created on: 2016-02-18 +// Created by: Varvara POSKONINA +// Copyright (c) 2016 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 + +#include +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT (MeshVS_CommonSensitiveEntity, Select3D_SensitiveSet) + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwner, + const Handle(MeshVS_Mesh)& theParentMesh, + const MeshVS_MeshSelectionMethod theSelMethod) +: Select3D_SensitiveSet (theOwner), + myDataSource (theParentMesh->GetDataSource()), + mySelMethod (theSelMethod) +{ + theParentMesh->GetDrawer()->GetInteger (MeshVS_DA_MaxFaceNodes, myMaxFaceNodes); + Standard_ASSERT_RAISE (myMaxFaceNodes > 0, + "The maximal amount of nodes in a face must be greater than zero to create sensitive entity"); + gp_XYZ aCenter (0.0, 0.0, 0.0); + + if (mySelMethod == MeshVS_MSM_NODES) + { + Standard_Integer aNbSelectableNodes = 0; + const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes(); + for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter (anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) + { + const Standard_Integer aNodeIdx = aNodesIter.Key(); + if (theParentMesh->IsSelectableNode (aNodeIdx)) + { + const gp_Pnt aVertex = getVertexByIndex (aNodeIdx); + aCenter += aVertex.XYZ(); + myBndBox.Add (SelectMgr_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z())); + ++aNbSelectableNodes; + myItemIndexes.Append (aNodeIdx); + } + } + + // increase sensitivity for vertices detection + SetSensitivityFactor (8); + myCOG = aCenter / aNbSelectableNodes; + } + else if (mySelMethod == MeshVS_MSM_PRECISE) + { + const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes(); + for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter (anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) + { + const Standard_Integer aNodeIdx = aNodesIter.Key(); + const gp_Pnt aVertex = getVertexByIndex (aNodeIdx); + aCenter += aVertex.XYZ(); + myBndBox.Add (SelectMgr_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z())); + } + myCOG = aCenter / anAllNodesMap.Extent(); + + const TColStd_PackedMapOfInteger& anAllElementsMap = myDataSource->GetAllElements(); + MeshVS_EntityType aType; + for (TColStd_MapIteratorOfPackedMapOfInteger anElemIter (anAllElementsMap); anElemIter.More(); anElemIter.Next()) + { + const Standard_Integer anElemIdx = anElemIter.Key(); + if (theParentMesh->IsSelectableElem (anElemIdx) + && myDataSource->GetGeomType (anElemIdx, Standard_True, aType) + && aType == MeshVS_ET_Face) + { + myItemIndexes.Append (anElemIdx); + } + } + } +} + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +MeshVS_CommonSensitiveEntity::~MeshVS_CommonSensitiveEntity() +{ + myDataSource.Nullify(); + myItemIndexes.Clear(); +} + +//======================================================================= +//function : NbSubElements +//purpose : +//======================================================================= +Standard_Integer MeshVS_CommonSensitiveEntity::NbSubElements() +{ + return myItemIndexes.Size(); +} + +//======================================================================= +//function : Size +//purpose : +//======================================================================= +Standard_Integer MeshVS_CommonSensitiveEntity::Size() const +{ + return myItemIndexes.Size(); +} + +//======================================================================= +//function : getVertexByIndex +//purpose : +//======================================================================= +gp_Pnt MeshVS_CommonSensitiveEntity::getVertexByIndex (const Standard_Integer theNodeIdx) const +{ + Standard_Real aCoordsBuf[3]; + TColStd_Array1OfReal aCoords (aCoordsBuf[0], 1, 3); + Standard_Integer aNbNodes; + MeshVS_EntityType aType; + if (!myDataSource->GetGeom (theNodeIdx, Standard_False, aCoords, aNbNodes, aType)) + { + return gp_Pnt(); + } + return gp_Pnt (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3)); +} + +//======================================================================= +//function : Box +//purpose : +//======================================================================= +Select3D_BndBox3d MeshVS_CommonSensitiveEntity::Box (const Standard_Integer theIdx) const +{ + const Standard_Integer anItemIdx = myItemIndexes.Value (theIdx); + Select3D_BndBox3d aBox; + if (mySelMethod == MeshVS_MSM_PRECISE) + { + MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); + TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); + Standard_Integer aNbNodes; + MeshVS_EntityType aType; + if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) + || aNbNodes == 0) + { + return aBox; + } + + MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); + TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); + if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) + { + return aBox; + } + + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++) + { + const SelectMgr_Vec3 aPnt (aCoords (3 * aNodeIdx - 2), + aCoords (3 * aNodeIdx - 1), + aCoords (3 * aNodeIdx)); + aBox.Add (aPnt); + } + } + else if (mySelMethod == MeshVS_MSM_NODES) + { + const gp_Pnt aVert = getVertexByIndex (anItemIdx); + aBox.Add (SelectMgr_Vec3 (aVert.X(), aVert.Y(), aVert.Z())); + } + + return aBox; +} + +//======================================================================= +//function : Center +//purpose : +//======================================================================= +Standard_Real MeshVS_CommonSensitiveEntity::Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const +{ + const Select3D_BndBox3d& aBox = Box (theIdx); + SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5; + + return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z()); +} + +//======================================================================= +//function : Swap +//purpose : +//======================================================================= +void MeshVS_CommonSensitiveEntity::Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) +{ + const Standard_Integer anItem1 = myItemIndexes.Value (theIdx1); + const Standard_Integer anItem2 = myItemIndexes.Value (theIdx2); + myItemIndexes.ChangeValue (theIdx1) = anItem2; + myItemIndexes.ChangeValue (theIdx2) = anItem1; +} + +//======================================================================= +//function : overlapsElement +//purpose : +//======================================================================= +Standard_Boolean MeshVS_CommonSensitiveEntity::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr, + Standard_Integer theElemIdx, + Standard_Real& theMatchDepth) +{ + const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx); + if (mySelMethod == MeshVS_MSM_PRECISE) + { + MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); + TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); + Standard_Integer aNbNodes; + MeshVS_EntityType aType; + if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) + || aNbNodes == 0) + { + return Standard_False; + } + + MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); + TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); + if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) + { + return Standard_False; + } + if (aNbNodes == 3) + { + return theMgr.Overlaps (gp_Pnt (aCoords (1), aCoords (2), aCoords (3)), + gp_Pnt (aCoords (4), aCoords (5), aCoords (6)), + gp_Pnt (aCoords (7), aCoords (8), aCoords (9)), + Select3D_TOS_INTERIOR, theMatchDepth); + } + + MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real)); + TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes); + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++) + { + aFacePnts.SetValue (aNodeIdx, gp_Pnt (aCoords (3 * aNodeIdx - 2), + aCoords (3 * aNodeIdx - 1), + aCoords (3 * aNodeIdx))); + } + return theMgr.Overlaps (aFacePnts, Select3D_TOS_INTERIOR, theMatchDepth); + } + else if (mySelMethod == MeshVS_MSM_NODES) + { + const gp_Pnt aVert = getVertexByIndex (anItemIdx); + return theMgr.Overlaps (aVert, theMatchDepth); + } + return Standard_False; +} + +//======================================================================= +//function : elementIsInside +//purpose : +//======================================================================= +Standard_Boolean MeshVS_CommonSensitiveEntity::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, + const Standard_Integer theElemIdx) +{ + const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx); + if (mySelMethod == MeshVS_MSM_PRECISE) + { + MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); + TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); + Standard_Integer aNbNodes; + MeshVS_EntityType aType; + if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) + || aNbNodes == 0) + { + return Standard_False; + } + + MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); + TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); + if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) + { + return Standard_False; + } + + MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real)); + TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes); + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; ++aNodeIdx) + { + const gp_Pnt aPnt (aCoords (3 * aNodeIdx - 2), + aCoords (3 * aNodeIdx - 1), + aCoords (3 * aNodeIdx)); + if (!theMgr.Overlaps (aPnt)) + { + return Standard_False; + } + } + return Standard_True; + } + else if (mySelMethod == MeshVS_MSM_NODES) + { + const gp_Pnt aVert = getVertexByIndex (anItemIdx); + return theMgr.Overlaps (aVert); + } + return Standard_False; +} + +//======================================================================= +//function : distanceToCOG +//purpose : +//======================================================================= +Standard_Real MeshVS_CommonSensitiveEntity::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) +{ + return theMgr.DistToGeometryCenter (myCOG); +} + +//======================================================================= +//function : BoundingBox +//purpose : +//======================================================================= +Select3D_BndBox3d MeshVS_CommonSensitiveEntity::BoundingBox() +{ + return myBndBox; +} diff --git a/src/MeshVS/MeshVS_CommonSensitiveEntity.hxx b/src/MeshVS/MeshVS_CommonSensitiveEntity.hxx new file mode 100644 index 0000000000..90bf524234 --- /dev/null +++ b/src/MeshVS/MeshVS_CommonSensitiveEntity.hxx @@ -0,0 +1,94 @@ +// Created on: 2016-02-18 +// Created by: Varvara POSKONINA +// Copyright (c) 2016 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. + +#ifndef _MeshVS_CommonSensitiveEntity_Header +#define _MeshVS_CommonSensitiveEntity_Header + +#include +#include +#include +#include + +//! Sensitive entity covering entire mesh for global selection. +class MeshVS_CommonSensitiveEntity : public Select3D_SensitiveSet +{ +public: + + //! Default constructor. + Standard_EXPORT MeshVS_CommonSensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwner, + const Handle(MeshVS_Mesh)& theParentMesh, + const MeshVS_MeshSelectionMethod theSelMethod); + + //! Destructor. + Standard_EXPORT virtual ~MeshVS_CommonSensitiveEntity(); + + //! Number of elements. + Standard_EXPORT virtual Standard_Integer NbSubElements() Standard_OVERRIDE; + + //! Returns the amount of sub-entities of the complex entity + Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; + + //! Returns bounding box of sub-entity with index theIdx in sub-entity list + Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE; + + //! Returns geometry center of sensitive entity index theIdx along the given axis theAxis + Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIdx, + const Standard_Integer theAxis) const Standard_OVERRIDE; + + //! Swaps items with indexes theIdx1 and theIdx2 + Standard_EXPORT virtual void Swap (const Standard_Integer theIdx1, + const Standard_Integer theIdx2) Standard_OVERRIDE; + + //! Returns bounding box of the triangulation. If location + //! transformation is set, it will be applied + Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE; + +public: + + DEFINE_STANDARD_RTTIEXT (MeshVS_CommonSensitiveEntity, Select3D_SensitiveSet) + +protected: + + //! Checks whether the entity with index theIdx overlaps the current selecting volume + Standard_EXPORT virtual Standard_Boolean overlapsElement (SelectBasics_SelectingVolumeManager& theMgr, + Standard_Integer theElemIdx, + Standard_Real& theMatchDepth) Standard_OVERRIDE; + + //! Checks whether the entity with index theIdx is inside the current selecting volume + Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, + const Standard_Integer theElemIdx) Standard_OVERRIDE; + + //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry + Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE; + +private: + + //! Return point for specified index. + gp_Pnt getVertexByIndex (const Standard_Integer theNodeIdx) const; + +private: + + Handle(MeshVS_DataSource) myDataSource; //!< mesh data source + NCollection_Vector myItemIndexes; //!< indices for BVH tree reordering + MeshVS_MeshSelectionMethod mySelMethod; //!< selection mode + Standard_Integer myMaxFaceNodes; //!< maximum nodes within the element in mesh + gp_Pnt myCOG; //!< center of gravity + Select3D_BndBox3d myBndBox; //!< bounding box + +}; + +DEFINE_STANDARD_HANDLE (MeshVS_CommonSensitiveEntity, Select3D_SensitiveSet) + +#endif // _MeshVS_CommonSensitiveEntity_Header diff --git a/src/MeshVS/MeshVS_Mesh.cxx b/src/MeshVS/MeshVS_Mesh.cxx index 1027721d4b..e8fb5be733 100644 --- a/src/MeshVS/MeshVS_Mesh.cxx +++ b/src/MeshVS/MeshVS_Mesh.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -47,11 +49,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -194,6 +198,46 @@ void MeshVS_Mesh::Compute ( const Handle(PrsMgr_PresentationManager3d)& thePrsMg } } +//================================================================ +// Function : scanFacesForSharedNodes +// Purpose : +//================================================================ +void MeshVS_Mesh::scanFacesForSharedNodes (const TColStd_PackedMapOfInteger& theAllElements, + const Standard_Integer theNbMaxFaceNodes, + TColStd_PackedMapOfInteger& theSharedNodes) const +{ + theSharedNodes.Clear(); + MeshVS_EntityType aType; + Standard_Integer aNbNodes; + MeshVS_Buffer aCoordsBuf (3 * theNbMaxFaceNodes * sizeof (Standard_Real)); + TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * theNbMaxFaceNodes); + for (TColStd_MapIteratorOfPackedMapOfInteger aFaceIter (theAllElements); aFaceIter.More(); aFaceIter.Next()) + { + const Standard_Integer aFaceIdx = aFaceIter.Key(); + + if (IsSelectableElem (aFaceIdx) && + myDataSource->GetGeomType (aFaceIdx, Standard_True, aType) && + aType == MeshVS_ET_Face) + { + myDataSource->GetGeom (aFaceIdx, Standard_True, aCoords, aNbNodes, aType ); + if (aNbNodes == 0) + continue; + + MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); + TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); + if (!myDataSource->GetNodesByElement (aFaceIdx, aElemNodes, aNbNodes)) + continue; + + MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real)); + TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes); + for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; ++aNodeIdx) + { + theSharedNodes.Add (aElemNodes (aNodeIdx)); + } + } + } +} + //================================================================ // Function : ComputeSelection // Purpose : @@ -296,116 +340,86 @@ void MeshVS_Mesh::ComputeSelection ( const Handle(SelectMgr_Selection)& theSelec if( myWholeMeshOwner.IsNull() ) myWholeMeshOwner = new SelectMgr_EntityOwner( this ); - - switch( mySelectionMethod ) + + switch (mySelectionMethod) { case MeshVS_MSM_BOX: - { - Bnd_Box box; - TColStd_MapIteratorOfPackedMapOfInteger anIterN( anAllNodesMap ); - for( ; anIterN.More(); anIterN.Next() ) - { - if( myDataSource->GetGeom( anIterN.Key(), Standard_False, aCoords, NbNodes, aType ) ) { - box.Add (gp_Pnt (aCoords(1), aCoords(2), aCoords(3))); - } - } - if (!box.IsVoid()) - theSelection->Add (new Select3D_SensitiveBox (myWholeMeshOwner, box)); - } - break; - - case MeshVS_MSM_NODES: - { - TColStd_MapIteratorOfPackedMapOfInteger anIterN( anAllNodesMap ); - for( ; anIterN.More(); anIterN.Next() ) - if( myDataSource->GetGeom( anIterN.Key(), Standard_False, aCoords, NbNodes, aType ) && - IsSelectableNode( anIterN.Key() ) ) - theSelection->Add( new Select3D_SensitivePoint( myWholeMeshOwner, gp_Pnt ( aCoords(1), aCoords(2), aCoords(3) ) ) ); - } - break; - - case MeshVS_MSM_PRECISE: - { - Handle( Select3D_SensitiveEntity ) anEnt; - TColStd_MapIteratorOfPackedMapOfInteger anIterMV( anAllElementsMap ); - - TColStd_PackedMapOfInteger aSharedNodes; - for( ; anIterMV.More(); anIterMV.Next() ) - { - Standard_Integer aKey = anIterMV.Key(); - - if( IsSelectableElem( aKey ) && - myDataSource->GetGeomType( aKey, Standard_True, aType ) && - aType==MeshVS_ET_Face ) - { - myDataSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ); - if( NbNodes==0 ) - continue; - - MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer)); - TColStd_Array1OfInteger aElemNodes(aNodesBuf, 1, NbNodes); - if ( !myDataSource->GetNodesByElement ( aKey, aElemNodes, NbNodes ) ) - continue; - - TColgp_Array1OfPnt Points( 1, NbNodes ); - for ( Standard_Integer i=1; i<=NbNodes; i++ ) - { - Points (i) = gp_Pnt ( aCoords (3*i-2), aCoords (3*i-1), aCoords (3*i) ); - aSharedNodes.Add( aElemNodes( i ) ); - } - - anEnt = new Select3D_SensitiveFace( myWholeMeshOwner, Points, Select3D_TOS_INTERIOR); - theSelection->Add( anEnt ); - } - } - for( anIterMV.Initialize( anAllElementsMap ); anIterMV.More(); anIterMV.Next() ) - { - Standard_Integer aKey = anIterMV.Key(); - - if( IsSelectableElem( aKey ) && - myDataSource->GetGeomType( aKey, Standard_True, aType ) && - aType==MeshVS_ET_Link ) - { - myDataSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ); - if( NbNodes==0 ) - continue; - - MeshVS_Buffer aNodesBuf (NbNodes*sizeof(Standard_Integer)); - TColStd_Array1OfInteger aElemNodes(aNodesBuf, 1, NbNodes); - if ( !myDataSource->GetNodesByElement ( aKey, aElemNodes, NbNodes ) ) - continue; - - TColgp_Array1OfPnt Points( 1, NbNodes ); - Standard_Boolean all_shared = Standard_True; - for ( Standard_Integer i=1; i<=NbNodes; i++ ) - { - Points (i) = gp_Pnt ( aCoords (3*i-2), aCoords (3*i-1), aCoords (3*i) ); - all_shared = all_shared && aSharedNodes.Contains( aElemNodes( i ) ); - aSharedNodes.Add( aElemNodes( i ) ); - } - - if( !all_shared ) - { - anEnt = new Select3D_SensitiveSegment( myWholeMeshOwner, Points.Value( 1 ), Points.Value( 2 ) ); - theSelection->Add( anEnt ); - } - } - } - for( anIterMV.Initialize( anAllNodesMap ); anIterMV.More(); anIterMV.Next() ) - { - Standard_Integer aKey = anIterMV.Key(); - if( IsSelectableElem( aKey ) && - myDataSource->GetGeom ( aKey, Standard_False, aCoords, NbNodes, aType ) && - !aSharedNodes.Contains( aKey ) ) - { - anEnt = new Select3D_SensitivePoint( myWholeMeshOwner, gp_Pnt ( aCoords(1), aCoords(2), aCoords(3) ) ) ; - theSelection->Add( anEnt ); - } - } - } - break; + { + Bnd_Box aBndBox; + BoundingBox (aBndBox); + if (!aBndBox.IsVoid()) + theSelection->Add (new Select3D_SensitiveBox (myWholeMeshOwner, aBndBox)); } break; + case MeshVS_MSM_NODES: + { + theSelection->Add (new MeshVS_CommonSensitiveEntity (myWholeMeshOwner, this, MeshVS_MSM_NODES)); + } + break; + case MeshVS_MSM_PRECISE: + { + theSelection->Add (new MeshVS_CommonSensitiveEntity (myWholeMeshOwner, this, MeshVS_MSM_PRECISE)); + + // since MeshVS_Mesh objects can contain free edges and vertices, it is necessary to create + // separate sensitive entity for each of them + TColStd_PackedMapOfInteger aSharedNodes; + scanFacesForSharedNodes (anAllElementsMap, aMaxFaceNodes, aSharedNodes); + + // create sensitive entities for free edges, if there are any + for (TColStd_MapIteratorOfPackedMapOfInteger anElemIter (anAllElementsMap); anElemIter.More(); anElemIter.Next()) + { + const Standard_Integer anElemIdx = anElemIter.Key(); + + if (IsSelectableElem (anElemIdx) && + myDataSource->GetGeomType (anElemIdx, Standard_True, aType) && + aType == MeshVS_ET_Link) + { + myDataSource->GetGeom (anElemIdx, Standard_True, aCoords, NbNodes, aType); + if (NbNodes == 0) + continue; + + MeshVS_Buffer aNodesBuf (NbNodes * sizeof (Standard_Integer)); + TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, NbNodes); + if (!myDataSource->GetNodesByElement (anElemIdx, aElemNodes, NbNodes)) + continue; + + MeshVS_Buffer aPntsBuf (NbNodes * 3 * sizeof (Standard_Real)); + TColgp_Array1OfPnt aLinkPnts (aPntsBuf, 1, NbNodes); + Standard_Boolean isVertsShared = Standard_True; + for (Standard_Integer aPntIdx = 1; aPntIdx <= NbNodes; ++aPntIdx) + { + aLinkPnts (aPntIdx) = gp_Pnt (aCoords (3 * aPntIdx - 2), + aCoords (3 * aPntIdx - 1), + aCoords (3 * aPntIdx)); + isVertsShared = isVertsShared && aSharedNodes.Contains (aElemNodes (aPntIdx)); + aSharedNodes.Add (aElemNodes (aPntIdx)); + } + + if (!isVertsShared) + { + Handle(Select3D_SensitiveEntity) aLinkEnt + = new Select3D_SensitiveSegment (myWholeMeshOwner, aLinkPnts.Value (1), aLinkPnts.Value (2)); + theSelection->Add (aLinkEnt); + } + } + } + + // create sensitive entities for free nodes, if there are any + for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter (anAllNodesMap); aNodesIter.More(); aNodesIter.Next()) + { + const Standard_Integer aNodeIdx = aNodesIter.Key(); + if (IsSelectableNode (aNodeIdx) && + myDataSource->GetGeom (aNodeIdx, Standard_False, aCoords, NbNodes, aType) && + !aSharedNodes.Contains (aNodeIdx)) + { + Handle(Select3D_SensitiveEntity) aNodeEnt + = new Select3D_SensitivePoint (myWholeMeshOwner, gp_Pnt ( aCoords(1), aCoords(2), aCoords(3))); + theSelection->Add (aNodeEnt); + } + } + } + break; + } case MeshVS_SMF_Group: { @@ -471,9 +485,22 @@ void MeshVS_Mesh::ComputeSelection ( const Handle(SelectMgr_Selection)& theSelec if ( aType == MeshVS_ET_Face && NbNodes > 0 ) // Faces: 2D-elements { - Handle (MeshVS_SensitiveFace) aFace = - new MeshVS_SensitiveFace( anOwner, anArr ); - theSelection->Add ( aFace ); + Handle(Select3D_SensitiveEntity) aSensFace; + if (NbNodes == 3) + { + aSensFace = new Select3D_SensitiveTriangle (anOwner, + anArr.Value (1), anArr.Value (2), anArr.Value (3), + Select3D_TOS_INTERIOR); + } + else if (NbNodes == 4) + { + aSensFace = new MeshVS_SensitiveQuad (anOwner, anArr); + } + else + { + aSensFace = new MeshVS_SensitiveFace (anOwner, anArr); + } + theSelection->Add (aSensFace); added = Standard_True; } else if ( aType == MeshVS_ET_Link && NbNodes > 0 ) // Links: 1D-elements @@ -562,9 +589,22 @@ void MeshVS_Mesh::ComputeSelection ( const Handle(SelectMgr_Selection)& theSelec if ( aType == MeshVS_ET_Face && NbNodes > 0 ) // Faces: 2D-elements { - Handle (MeshVS_SensitiveFace) aFace = - new MeshVS_SensitiveFace( anOwner, anArr ); - theSelection->Add ( aFace ); + Handle(Select3D_SensitiveEntity) aSensFace; + if (NbNodes == 3) + { + aSensFace = new Select3D_SensitiveTriangle (anOwner, + anArr.Value (1), anArr.Value (2), anArr.Value (3), + Select3D_TOS_INTERIOR); + } + else if (NbNodes == 4) + { + aSensFace = new MeshVS_SensitiveQuad (anOwner, anArr); + } + else + { + aSensFace = new MeshVS_SensitiveFace (anOwner, anArr); + } + theSelection->Add (aSensFace); } else if ( aType == MeshVS_ET_Link && NbNodes > 0 ) // Links: 1D-elements { @@ -595,6 +635,8 @@ void MeshVS_Mesh::ComputeSelection ( const Handle(SelectMgr_Selection)& theSelec } } + StdSelect_BRepSelectionTool::PreBuildBVH (theSelection); + if ( ShowComputeSelectionTime ) { Standard_Real sec, cpu; diff --git a/src/MeshVS/MeshVS_Mesh.hxx b/src/MeshVS/MeshVS_Mesh.hxx index 2561ccf717..d15c562833 100644 --- a/src/MeshVS/MeshVS_Mesh.hxx +++ b/src/MeshVS/MeshVS_Mesh.hxx @@ -183,6 +183,16 @@ friend class MeshVS_PrsBuilder; DEFINE_STANDARD_RTTIEXT(MeshVS_Mesh,AIS_InteractiveObject) +protected: + + //! Stores all vertices that belong to one of the faces to the given map + //! @param theAllElements [in] the map of all mesh elements + //! @param theNbMaxFaceNodes [in] the maximum amount of nodes per face, retrieved from drawer + //! @param theSharedNodes [out] the result map of all vertices that belong to one face at least + Standard_EXPORT void scanFacesForSharedNodes (const TColStd_PackedMapOfInteger& theAllElements, + const Standard_Integer theNbMaxFaceNodes, + TColStd_PackedMapOfInteger& theSharedNodes) const; + protected: diff --git a/src/MeshVS/MeshVS_SensitiveQuad.cxx b/src/MeshVS/MeshVS_SensitiveQuad.cxx new file mode 100644 index 0000000000..5f0825dcaa --- /dev/null +++ b/src/MeshVS/MeshVS_SensitiveQuad.cxx @@ -0,0 +1,126 @@ +// Created on: 2016-03-02 +// Created by: Varvara POSKONINA +// Copyright (c) 2016 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 + +IMPLEMENT_STANDARD_RTTIEXT (MeshVS_SensitiveQuad, Select3D_SensitiveEntity) + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeshVS_SensitiveQuad::MeshVS_SensitiveQuad (const Handle(SelectMgr_EntityOwner)& theOwner, + const TColgp_Array1OfPnt& theQuadVerts) +: Select3D_SensitiveEntity (theOwner) +{ + const Standard_Integer aLowerIdx = theQuadVerts.Lower(); + for (Standard_Integer aVertIdx = 0; aVertIdx < 4; ++aVertIdx) + { + myVertices[aVertIdx] = theQuadVerts.Value (aLowerIdx + aVertIdx); + } +} + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeshVS_SensitiveQuad::MeshVS_SensitiveQuad (const Handle(SelectMgr_EntityOwner)& theOwner, + const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const gp_Pnt& thePnt3, + const gp_Pnt& thePnt4) +: Select3D_SensitiveEntity (theOwner) +{ + myVertices[0] = thePnt1; + myVertices[1] = thePnt2; + myVertices[2] = thePnt3; + myVertices[3] = thePnt4; +} + +//======================================================================= +// function : GetConnected +// purpose : +//======================================================================= +Handle(Select3D_SensitiveEntity) MeshVS_SensitiveQuad::GetConnected() +{ + return new MeshVS_SensitiveQuad (Handle(SelectMgr_EntityOwner)::DownCast (OwnerId()), + myVertices[0], myVertices[1], myVertices[2], myVertices[3]); +} + +//======================================================================= +// function : Matches +// purpose : Checks whether the box overlaps current selecting volume +//======================================================================= +Standard_Boolean MeshVS_SensitiveQuad::Matches (SelectBasics_SelectingVolumeManager& theMgr, + SelectBasics_PickResult& thePickResult) +{ + thePickResult = SelectBasics_PickResult (RealLast(), RealLast()); + + if (!theMgr.IsOverlapAllowed()) // check for inclusion + { + for (Standard_Integer aPntIdx = 0; aPntIdx < 4; ++aPntIdx) + { + if (!theMgr.Overlaps (myVertices[aPntIdx])) + return Standard_False; + } + + return Standard_True; + } + + // check for overlap + Standard_Real aDepth1 = std::numeric_limits::max(); + Standard_Real aDepth2 = std::numeric_limits::max(); + if (!theMgr.Overlaps (myVertices[0], myVertices[1], myVertices[2], Select3D_TOS_INTERIOR, aDepth1) + && !theMgr.Overlaps (myVertices[0], myVertices[2], myVertices[3], Select3D_TOS_INTERIOR, aDepth2)) + { + return Standard_False; + } + + thePickResult = SelectBasics_PickResult (Min (aDepth1, aDepth2), theMgr.DistToGeometryCenter (CenterOfGeometry())); + + return Standard_True; +} + +//======================================================================= +// function : CenterOfGeometry +// purpose : +//======================================================================= +gp_Pnt MeshVS_SensitiveQuad::CenterOfGeometry() const +{ + gp_XYZ aSum (0.0, 0.0, 0.0); + for (Standard_Integer aPntIdx = 0; aPntIdx < 4; ++aPntIdx) + { + aSum += myVertices[aPntIdx].XYZ(); + } + + return aSum / 4.0; +} + +//======================================================================= +// function : BoundingBox +// purpose : +//======================================================================= +Select3D_BndBox3d MeshVS_SensitiveQuad::BoundingBox() +{ + Select3D_BndBox3d aBox; + for (Standard_Integer aPntIdx = 0; aPntIdx < 4; ++aPntIdx) + { + aBox.Add (SelectMgr_Vec3 (myVertices[aPntIdx].X(), + myVertices[aPntIdx].Y(), + myVertices[aPntIdx].Z())); + } + + return aBox; +} diff --git a/src/MeshVS/MeshVS_SensitiveQuad.hxx b/src/MeshVS/MeshVS_SensitiveQuad.hxx new file mode 100644 index 0000000000..416e29c78c --- /dev/null +++ b/src/MeshVS/MeshVS_SensitiveQuad.hxx @@ -0,0 +1,68 @@ +// Created on: 2016-03-02 +// Created by: Varvara POSKONINA +// Copyright (c) 2016 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. + +#ifndef _MeshVS_SensitiveQuad_HeaderFile +#define _MeshVS_SensitiveQuad_HeaderFile + +#include +#include + +#include + +//! This class contains description of planar quadrangle and defines methods +//! for its detection by OCCT BVH selection mechanism +class MeshVS_SensitiveQuad : public Select3D_SensitiveEntity +{ +public: + + //! Creates a new instance and initializes quadrangle vertices with the given points + Standard_EXPORT MeshVS_SensitiveQuad (const Handle(SelectMgr_EntityOwner)& theOwner, const TColgp_Array1OfPnt& theQuadVerts); + + //! Creates a new instance and initializes quadrangle vertices with the given points + Standard_EXPORT MeshVS_SensitiveQuad (const Handle(SelectMgr_EntityOwner)& theOwner, + const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const gp_Pnt& thePnt3, + const gp_Pnt& thePnt4); + + //! Returns the amount of sub-entities in sensitive + Standard_EXPORT virtual Standard_Integer NbSubElements() Standard_OVERRIDE + { + return 1; + }; + + //! Returns a copy of this sensitive quadrangle + Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE; + + //! Checks whether the box overlaps current selecting volume + Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr, + SelectBasics_PickResult& thePickResult) Standard_OVERRIDE; + + //! Returns center of the box + Standard_EXPORT virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE; + + //! Returns coordinates of the box + Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT (MeshVS_SensitiveQuad, Select3D_SensitiveEntity) + +private: + + gp_Pnt myVertices[4]; //!< 3d coordinates of quad's corners +}; + +DEFINE_STANDARD_HANDLE (MeshVS_SensitiveQuad, Select3D_SensitiveEntity) + +#endif // _MeshVS_SensitiveQuad_HeaderFile diff --git a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx index bb17a15e06..d4d40ea982 100644 --- a/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx +++ b/src/SelectBasics/SelectBasics_SelectingVolumeManager.hxx @@ -68,6 +68,12 @@ public: Standard_Integer theSensType, Standard_Real& theDepth) = 0; + //! Returns true if selecting volume is overlapped by planar convex polygon, which points + //! are stored in theArrayOfPts, taking into account sensitivity type theSensType + virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPts, + Standard_Integer theSensType, + Standard_Real& theDepth) = 0; + //! Returns true if selecting volume is overlapped by line segment with start point at thePt1 //! and end point at thePt2 virtual Standard_Boolean Overlaps (const gp_Pnt& thePt1, diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index aecd3ad365..3508da72b1 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -176,7 +176,7 @@ Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const gp_Pnt& /*thePnt*/) // may be considered of interior part or boundary line defined // by segments depending on given sensitivity type //======================================================================= -Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& /*theArrayOfPnts*/, +Standard_Boolean SelectMgr_BaseFrustum::Overlaps (const TColgp_Array1OfPnt& /*theArrayOfPnts*/, Select3D_TypeOfSensitivity /*theSensType*/, Standard_Real& /*theDepth*/) { diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index c4adf95080..225b835445 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -129,7 +129,7 @@ public: //! SAT intersection test between defined volume and given ordered set of points, //! representing line segments. The test may be considered of interior part or //! boundary line defined by segments depending on given sensitivity type - Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth); diff --git a/src/SelectMgr/SelectMgr_Frustum.hxx b/src/SelectMgr/SelectMgr_Frustum.hxx index e73aef8fbf..e03bed36a4 100644 --- a/src/SelectMgr/SelectMgr_Frustum.hxx +++ b/src/SelectMgr/SelectMgr_Frustum.hxx @@ -76,7 +76,7 @@ protected: const gp_Pnt& thePnt2); //! SAT intersection test between frustum given and planar convex polygon represented as ordered point set - Standard_EXPORT Standard_Boolean hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, + Standard_EXPORT Standard_Boolean hasOverlap (const TColgp_Array1OfPnt& theArrayOfPnts, gp_Vec& theNormal); //! SAT intersection test between defined volume and given triangle diff --git a/src/SelectMgr/SelectMgr_Frustum.lxx b/src/SelectMgr/SelectMgr_Frustum.lxx index cc7e134c95..1562d3e04e 100644 --- a/src/SelectMgr/SelectMgr_Frustum.lxx +++ b/src/SelectMgr/SelectMgr_Frustum.lxx @@ -308,15 +308,15 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const gp_Pnt& theStartPnt, // polygon represented as ordered point set // ======================================================================= template -Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, +Standard_Boolean SelectMgr_Frustum::hasOverlap (const TColgp_Array1OfPnt& theArrayOfPnts, gp_Vec& theNormal) { - Standard_Integer aStartIdx = theArrayOfPnts->Lower(); - Standard_Integer anEndIdx = theArrayOfPnts->Upper(); + Standard_Integer aStartIdx = theArrayOfPnts.Lower(); + Standard_Integer anEndIdx = theArrayOfPnts.Upper(); - const gp_XYZ& aPnt1 = theArrayOfPnts->Value (aStartIdx).XYZ(); - const gp_XYZ& aPnt2 = theArrayOfPnts->Value (aStartIdx + 1).XYZ(); - const gp_XYZ& aPnt3 = theArrayOfPnts->Value (aStartIdx + 2).XYZ(); + const gp_XYZ& aPnt1 = theArrayOfPnts.Value (aStartIdx).XYZ(); + const gp_XYZ& aPnt2 = theArrayOfPnts.Value (aStartIdx + 1).XYZ(); + const gp_XYZ& aPnt3 = theArrayOfPnts.Value (aStartIdx + 2).XYZ(); const gp_XYZ aVec1 = aPnt1 - aPnt2; const gp_XYZ aVec2 = aPnt3 - aPnt2; theNormal = aVec2.Crossed (aVec1); @@ -347,7 +347,7 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1Of const gp_XYZ& aPlane = myPlanes[aPlaneIdx].XYZ(); for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter) { - Standard_Real aProjection = aPlane.Dot (theArrayOfPnts->Value (aPntIter).XYZ()); + Standard_Real aProjection = aPlane.Dot (theArrayOfPnts.Value (aPntIter).XYZ()); aMaxPolyg = Max (aMaxPolyg, aProjection); aMinPolyg = Min (aMinPolyg, aProjection); } @@ -361,10 +361,10 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1Of } Standard_Integer aDirectionsNb = myIsOrthographic ? 4 : 6; - for (Standard_Integer aPntsIter = 0, aLastIdx = anEndIdx - aStartIdx, aLen = theArrayOfPnts->Length(); aPntsIter <= aLastIdx; ++aPntsIter) + for (Standard_Integer aPntsIter = 0, aLastIdx = anEndIdx - aStartIdx, aLen = theArrayOfPnts.Length(); aPntsIter <= aLastIdx; ++aPntsIter) { - const gp_XYZ aSegmDir = theArrayOfPnts->Value ((aPntsIter + 1) % aLen + aStartIdx).XYZ() - - theArrayOfPnts->Value (aPntsIter + aStartIdx).XYZ(); + const gp_XYZ aSegmDir = theArrayOfPnts.Value ((aPntsIter + 1) % aLen + aStartIdx).XYZ() + - theArrayOfPnts.Value (aPntsIter + aStartIdx).XYZ(); for (Standard_Integer aVolDir = 0; aVolDir < aDirectionsNb; ++aVolDir) { Standard_Real aMaxPolyg = RealFirst(); @@ -375,7 +375,7 @@ Standard_Boolean SelectMgr_Frustum::hasOverlap (const Handle(TColgp_HArray1Of for (Standard_Integer aPntIter = aStartIdx; aPntIter <= anEndIdx; ++aPntIter) { - Standard_Real aProjection = aTestDir.Dot (theArrayOfPnts->Value (aPntIter).XYZ()); + Standard_Real aProjection = aTestDir.Dot (theArrayOfPnts.Value (aPntIter).XYZ()); aMaxPolyg = Max (aMaxPolyg, aProjection); aMinPolyg = Min (aMinPolyg, aProjection); } diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index ff65aa7cb3..664d3d4387 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -491,7 +491,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, // may be considered of interior part or boundary line defined // by segments depending on given sensitivity type // ======================================================================= -Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, +Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) { @@ -499,15 +499,12 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr { Standard_Integer aMatchingSegmentsNb = -1; theDepth = DBL_MAX; - Standard_Integer aLower = theArrayOfPnts->Lower(); - Standard_Integer anUpper = theArrayOfPnts->Upper(); - + const Standard_Integer aLower = theArrayOfPnts.Lower(); + const Standard_Integer anUpper = theArrayOfPnts.Upper(); for (Standard_Integer aPntIter = aLower; aPntIter <= anUpper; ++aPntIter) { - const gp_Pnt& aStartPnt = theArrayOfPnts->Value (aPntIter); - const gp_Pnt& aEndPnt = aPntIter == anUpper ? theArrayOfPnts->Value (aLower) - : theArrayOfPnts->Value (aPntIter + 1); - + const gp_Pnt& aStartPnt = theArrayOfPnts.Value (aPntIter); + const gp_Pnt& aEndPnt = theArrayOfPnts.Value (aPntIter == anUpper ? aLower : (aPntIter + 1)); if (hasOverlap (aStartPnt, aEndPnt)) { aMatchingSegmentsNb++; @@ -527,7 +524,7 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const Handle(TColgp_HAr return Standard_False; segmentPlaneIntersection (aPolyNorm, - theArrayOfPnts->Value (theArrayOfPnts->Lower()), + theArrayOfPnts.Value (theArrayOfPnts.Lower()), theDepth); } @@ -549,11 +546,8 @@ Standard_Boolean SelectMgr_RectangularFrustum::Overlaps (const gp_Pnt& thePnt1, { if (theSensType == Select3D_TOS_BOUNDARY) { - Handle(TColgp_HArray1OfPnt) aPntsArray = new TColgp_HArray1OfPnt(1, 4); - aPntsArray->SetValue (1, thePnt1); - aPntsArray->SetValue (2, thePnt2); - aPntsArray->SetValue (3, thePnt3); - aPntsArray->SetValue (4, thePnt1); + const gp_Pnt aPntsArrayBuf[4] = { thePnt1, thePnt2, thePnt3, thePnt1 }; + const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 4); return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theDepth); } else if (theSensType == Select3D_TOS_INTERIOR) diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index c1d4ca79bd..9cf9c12173 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -77,7 +77,7 @@ public: //! SAT intersection test between defined volume and given ordered set of points, //! representing line segments. The test may be considered of interior part or //! boundary line defined by segments depending on given sensitivity type - Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) Standard_OVERRIDE; diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index 69a7ca4c28..658900ed6f 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -284,6 +284,25 @@ Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const Handle(TColgp if (myActiveSelectionType == Unknown) return Standard_False; + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts->Array1(), + (Select3D_TypeOfSensitivity)theSensType, + theDepth); +} + +//======================================================================= +// function : Overlaps +// purpose : SAT intersection test between defined volume and given +// ordered set of points, representing line segments. The test +// may be considered of interior part or boundary line defined +// by segments depending on given sensitivity type +//======================================================================= +Standard_Boolean SelectMgr_SelectingVolumeManager::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, + Standard_Integer theSensType, + Standard_Real& theDepth) +{ + if (myActiveSelectionType == Unknown) + return Standard_False; + return mySelectingVolumes[myActiveSelectionType / 2]->Overlaps (theArrayOfPnts, (Select3D_TypeOfSensitivity)theSensType, theDepth); diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index ec63b43e1b..12f89014d4 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -120,6 +120,13 @@ public: Standard_Integer theSensType, Standard_Real& theDepth) Standard_OVERRIDE; + //! SAT intersection test between defined volume and given ordered set of points, + //! representing line segments. The test may be considered of interior part or + //! boundary line defined by segments depending on given sensitivity type + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPts, + Standard_Integer theSensType, + Standard_Real& theDepth) Standard_OVERRIDE; + //! Checks if line segment overlaps selecting frustum Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt1, const gp_Pnt& thePnt2, diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx index ca0e6756eb..79b02a1fc6 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx @@ -210,20 +210,18 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt, // may be considered of interior part or boundary line defined // by segments depending on given sensitivity type // ======================================================================= -Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, +Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& /*theDepth*/) { if (theSensType == Select3D_TOS_BOUNDARY) { - Standard_Integer aLower = theArrayOfPnts->Lower(); - Standard_Integer anUpper = theArrayOfPnts->Upper(); - + const Standard_Integer aLower = theArrayOfPnts.Lower(); + const Standard_Integer anUpper = theArrayOfPnts.Upper(); for (Standard_Integer aPtIdx = aLower; aPtIdx <= anUpper; ++aPtIdx) { - const gp_Pnt& aStartPt = theArrayOfPnts->Value (aPtIdx); - const gp_Pnt& aEndPt = aPtIdx == anUpper ? theArrayOfPnts->Value (aLower) : theArrayOfPnts->Value (aPtIdx + 1); - + const gp_Pnt& aStartPt = theArrayOfPnts.Value (aPtIdx); + const gp_Pnt& aEndPt = theArrayOfPnts.Value (aPtIdx == anUpper ? aLower : (aPtIdx + 1)); if (!hasOverlap (aStartPt, aEndPt)) { return Standard_False; @@ -265,11 +263,9 @@ Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt1, { if (theSensType == Select3D_TOS_BOUNDARY) { - Handle(TColgp_HArray1OfPnt) aPtsArray = new TColgp_HArray1OfPnt(1, 4); - aPtsArray->SetValue (1, thePnt1); - aPtsArray->SetValue (2, thePnt2); - aPtsArray->SetValue (3, thePnt3); - return Overlaps (aPtsArray, Select3D_TOS_BOUNDARY, theDepth); + const gp_Pnt aPntsArrayBuf[3] = { thePnt1, thePnt2, thePnt3 }; + const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 3); + return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theDepth); } else if (theSensType == Select3D_TOS_INTERIOR) { diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx index b829de846d..ceb104f378 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx @@ -63,7 +63,7 @@ public: //! SAT intersection test between defined volume and given ordered set of points, //! representing line segments. The test may be considered of interior part or //! boundary line defined by segments depending on given sensitivity type - Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) Standard_OVERRIDE; diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index b22152470b..c5d8c9fb9d 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -175,7 +175,7 @@ Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const gp_Pnt& thePnt, // function : Overlaps // purpose : // ======================================================================= -Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPts, +Standard_Boolean SelectMgr_TriangularFrustumSet::Overlaps (const TColgp_Array1OfPnt& theArrayOfPts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) { diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index 71f0b36449..baad601daf 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -61,7 +61,7 @@ public: Standard_EXPORT virtual Standard_Boolean Overlaps (const gp_Pnt& thePnt, Standard_Real& theDepth) Standard_OVERRIDE; - Standard_EXPORT virtual Standard_Boolean Overlaps (const Handle(TColgp_HArray1OfPnt)& theArrayOfPnts, + Standard_EXPORT virtual Standard_Boolean Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, Select3D_TypeOfSensitivity theSensType, Standard_Real& theDepth) Standard_OVERRIDE; diff --git a/src/StdSelect/StdSelect_BRepSelectionTool.cxx b/src/StdSelect/StdSelect_BRepSelectionTool.cxx index 3726615426..9b83721973 100644 --- a/src/StdSelect/StdSelect_BRepSelectionTool.cxx +++ b/src/StdSelect/StdSelect_BRepSelectionTool.cxx @@ -66,12 +66,12 @@ #define BVH_PRIMITIVE_LIMIT 800000 //================================================== -// function: preBuildBVH +// function: PreBuildBVH // purpose : Pre-builds BVH tree for heavyweight // sensitive entities with sub-elements // amount more than BVH_PRIMITIVE_LIMIT //================================================== -void StdSelect_BRepSelectionTool::preBuildBVH (const Handle(SelectMgr_Selection)& theSelection) +void StdSelect_BRepSelectionTool::PreBuildBVH (const Handle(SelectMgr_Selection)& theSelection) { for (theSelection->Init(); theSelection->More(); theSelection->Next()) { @@ -196,7 +196,7 @@ void StdSelect_BRepSelectionTool anOwner->Set (theSelectableObj); } - preBuildBVH (theSelection); + PreBuildBVH (theSelection); } //================================================== diff --git a/src/StdSelect/StdSelect_BRepSelectionTool.hxx b/src/StdSelect/StdSelect_BRepSelectionTool.hxx index 4d5e997a75..289d4edb3c 100644 --- a/src/StdSelect/StdSelect_BRepSelectionTool.hxx +++ b/src/StdSelect/StdSelect_BRepSelectionTool.hxx @@ -118,7 +118,10 @@ public: //! if = False the face will be sensitive only on its boundary Standard_EXPORT static Standard_Boolean GetSensitiveForFace (const TopoDS_Face& aFace, const Handle(StdSelect_BRepOwner)& anOwner, Select3D_EntitySequence& OutList, const Standard_Boolean AutoTriangulation = Standard_True, const Standard_Integer NbPOnEdge = 9, const Standard_Real MaxiParam = 500, const Standard_Boolean InteriorFlag = Standard_True); - + //! Traverses the selection given and pre-builds BVH trees for heavyweight + //! sensitive entities containing more than BVH_PRIMITIVE_LIMIT (defined in .cxx file) + //! sub-elements + Standard_EXPORT static void PreBuildBVH (const Handle(SelectMgr_Selection)& theSelection); protected: @@ -129,12 +132,6 @@ protected: private: - - //! Traverses the selection given and pre-builds BVH trees for heavyweight - //! sensitive entities containing more than BVH_PRIMITIVE_LIMIT (defined in .cxx file) - //! sub-elements - Standard_EXPORT static void preBuildBVH (const Handle(SelectMgr_Selection)& theSelection); - Standard_EXPORT static void GetEdgeSensitive (const TopoDS_Shape& aShape, const Handle(StdSelect_BRepOwner)& anOwner, const Handle(SelectMgr_Selection)& aSelection, const Standard_Real theDeflection, const Standard_Real theDeflectionAngle, const Standard_Integer NbPOnEdge, const Standard_Real MaximalParameter, Handle(Select3D_SensitiveEntity)& aSensitive);