0028801: Visualization, Select3D_SensitivePrimitiveArray - add option to keep index...
authorkgv <kgv@opencascade.com>
Thu, 1 Jun 2017 12:30:57 +0000 (15:30 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 29 Jun 2017 11:22:58 +0000 (14:22 +0300)
Select3D_SensitiveGroup - added option to force overlap check for all entities in the group.
Added interface for accessing last detected entity in the group.

Select3D_SensitivePrimitiveArray - added option to keep index map of detected elements
and option to split array into groups for faster initialization of extra-large arrays.

BVH_Geometry, BVH_Object - added missing accessor ::IsDirty() for checking BVH tree state.

src/AIS/AIS_PointCloud.cxx
src/BVH/BVH_Geometry.hxx
src/BVH/BVH_Object.hxx
src/Select3D/Select3D_SensitiveGroup.cxx
src/Select3D/Select3D_SensitiveGroup.hxx
src/Select3D/Select3D_SensitivePrimitiveArray.cxx
src/Select3D/Select3D_SensitivePrimitiveArray.hxx
src/Select3D/Select3D_SensitiveSet.cxx

index a0df6dd..454dbc2 100644 (file)
@@ -437,9 +437,11 @@ void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSel
       if (!aPoints.IsNull()
        && !aPoints->Attributes().IsNull())
       {
+        // split large point clouds into several groups
+        const Standard_Integer aNbGroups = aPoints->Attributes()->NbElements > 500000 ? 8 : 1;
         Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
         aSensitive->SetSensitivityFactor (8);
-        aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location());
+        aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location(), true, aNbGroups);
         aSensitive->BVH();
         theSelection->Add (aSensitive);
         return;
index b7d8064..f84a8be 100644 (file)
@@ -57,6 +57,9 @@ public:
 
 public:
 
+  //! Returns TRUE if geometry state should be updated.
+  virtual Standard_Boolean IsDirty() const { return myIsDirty; }
+
   //! Marks geometry as outdated.
   virtual void MarkDirty() { myIsDirty = Standard_True; }
 
index 22b317f..82a9133 100644 (file)
@@ -32,6 +32,9 @@ public:
   //! Sets properties of the geometric object.
   virtual void SetProperties (const Handle(BVH_Properties)& theProperties) { myProperties = theProperties; }
 
+  //! Returns TRUE if object state should be updated.
+  virtual Standard_Boolean IsDirty() const { return myIsDirty; }
+
   //! Marks object state as outdated (needs BVH rebuilding).
   virtual void MarkDirty() { myIsDirty = Standard_True; }
 
index 5d91264..b4d5896 100644 (file)
@@ -28,6 +28,7 @@ Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_Enti
                                                   const Standard_Boolean theIsMustMatchAll)
 : Select3D_SensitiveSet (theOwnerId),
   myMustMatchAll (theIsMustMatchAll),
+  myToCheckOverlapAll (Standard_False),
   myCenter (0.0, 0.0, 0.0) {}
 
 //=======================================================================
@@ -38,10 +39,10 @@ Select3D_SensitiveGroup::Select3D_SensitiveGroup (const Handle(SelectBasics_Enti
                                                   Select3D_EntitySequence& theEntities,
                                                   const Standard_Boolean theIsMustMatchAll)
 : Select3D_SensitiveSet (theOwnerId),
-  myMustMatchAll (theIsMustMatchAll)
+  myMustMatchAll (theIsMustMatchAll),
+  myToCheckOverlapAll (Standard_False),
+  myCenter (0.0, 0.0, 0.0)
 {
-  myCenter = gp_Pnt (0.0, 0.0, 0.0);
-
   for (Select3D_EntitySequenceIter anIter (theEntities); anIter.More(); anIter.Next())
   {
     const Handle(Select3D_SensitiveEntity)& anEntity = anIter.Value();
@@ -187,29 +188,46 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitiveGroup::GetConnected()
 Standard_Boolean Select3D_SensitiveGroup::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                    SelectBasics_PickResult& thePickResult)
 {
-  if (!myMustMatchAll
-    || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point)
+  const Standard_Boolean toMatchAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+                                   && myMustMatchAll;
+  const Standard_Boolean toCheckAll = theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point
+                                   && myToCheckOverlapAll;
+  if (!toMatchAll && !toCheckAll)
+  {
     return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
+  }
 
   Standard_Real aDepth     = RealLast();
   Standard_Real aDistToCOG = RealLast();
-
+  Standard_Boolean isFailed = Standard_False;
   for (Select3D_EntitySequenceIter anIt (myEntities); anIt.More(); anIt.Next())
   {
     SelectBasics_PickResult aMatchResult;
     Handle(Select3D_SensitiveEntity)& aChild = anIt.ChangeValue();
     if (!aChild->Matches (theMgr, aMatchResult))
     {
-      aMatchResult = SelectBasics_PickResult (RealLast(), RealLast());
-      return Standard_False;
+      if (toMatchAll)
+      {
+        isFailed = Standard_True;
+        if (!toCheckAll)
+        {
+          break;
+        }
+      }
+    }
+    else
+    {
+      aDepth = Min (aMatchResult.Depth(), aDepth);
     }
-
-    aDepth = Min (aMatchResult.Depth(), aDepth);
+  }
+  if (isFailed)
+  {
+    thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+    return Standard_False;
   }
 
   aDistToCOG = theMgr.DistToGeometryCenter (CenterOfGeometry());
   thePickResult = SelectBasics_PickResult (aDepth, aDistToCOG);
-
   return Standard_True;
 }
 
index d3700a1..3781e2f 100644 (file)
@@ -47,6 +47,25 @@ public:
                                            Select3D_EntitySequence& theEntities,
                                            const Standard_Boolean theIsMustMatchAll = Standard_True);
 
+  //! Gets group content
+  const Select3D_EntitySequence& GetEntities() const { return myEntities; }
+
+  //! Access entity by index [1, NbSubElements()].
+  const Handle(Select3D_SensitiveEntity)& SubEntity (const Standard_Integer theIndex) const
+  {
+    return myEntities.Value (theIndex);
+  }
+
+  //! Return last detected entity.
+  Handle(Select3D_SensitiveEntity) LastDetectedEntity() const
+  {
+    const Standard_Integer anIndex = LastDetectedEntityIndex();
+    return anIndex != -1 ? myEntities.Value (anIndex) : Handle(Select3D_SensitiveEntity)();
+  }
+
+  //! Return index of last detected entity.
+  Standard_Integer LastDetectedEntityIndex() const { return myDetectedIdx != -1 ? myBVHPrimIndexes.Value (myDetectedIdx) : -1; }
+
   //! Adds the list of sensitive entities LL to the empty
   //! sensitive group object created at construction time.
   Standard_EXPORT void Add (Select3D_EntitySequence& theEntities);
@@ -74,6 +93,20 @@ public:
   //! at the time of construction, or added using the function Add must be matched.
   Standard_Boolean MustMatchAll() const { return myMustMatchAll; }
 
+  //! Returns TRUE if all sensitive entities should be checked within rectangular/polygonal selection, FALSE by default.
+  //! Can be useful for sensitive entities holding detection results as class property.
+  Standard_Boolean ToCheckOverlapAll() const
+  {
+    return myToCheckOverlapAll;
+  }
+
+  //! Returns TRUE if all sensitive entities should be checked within rectangular/polygonal selection, FALSE by default.
+  //! Can be useful for sensitive entities holding detection results as class property.
+  void SetCheckOverlapAll (Standard_Boolean theToCheckAll)
+  {
+    myToCheckOverlapAll = theToCheckAll;
+  }
+
   //! Checks whether the group overlaps current selecting volume
   Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                     SelectBasics_PickResult& thePickResult) Standard_OVERRIDE;
@@ -86,9 +119,6 @@ public:
   //! Sets the owner for all entities in group
   Standard_EXPORT void Set (const Handle(SelectBasics_EntityOwner)& theOwnerId) Standard_OVERRIDE;
 
-  //! Gets group content
-  const Select3D_EntitySequence& GetEntities() const { return myEntities; }
-
   //! Returns bounding box of the group. If location transformation
   //! is set, it will be applied
   Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
@@ -130,6 +160,7 @@ private:
 
   Select3D_EntitySequence              myEntities;           //!< Grouped sensitive entities
   Standard_Boolean                     myMustMatchAll;       //!< Determines whether all entities in the group should be overlapped or not
+  Standard_Boolean                     myToCheckOverlapAll;  //!< flag to check overlapping with all entities within rectangular/polygonal selection
   gp_Pnt                               myCenter;             //!< Center of geometry of the group
   mutable Select3D_BndBox3d            myBndBox;             //!< Bounding box of the group
   NCollection_Vector<Standard_Integer> myBVHPrimIndexes;     //!< Vector of sub-entities indexes for BVH tree build
index 6851cf8..bc32db0 100644 (file)
@@ -16,6 +16,7 @@
 #include <Select3D_SensitivePrimitiveArray.hxx>
 
 #include <NCollection_AlignedAllocator.hxx>
+#include <OSD_Parallel.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
 
@@ -71,6 +72,84 @@ namespace
 
 }
 
+//! Functor for initializing groups in parallel threads.
+struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_InitFunctor
+{
+  Select3D_SensitivePrimitiveArray_InitFunctor (Select3D_SensitivePrimitiveArray& thePrimArray,
+                                                Standard_Integer theDivStep,
+                                                Standard_Boolean theToEvalMinMax)
+  : myPrimArray (thePrimArray),
+    myDivStep (theDivStep),
+    myToEvalMinMax (theToEvalMinMax),
+    myToComputeBvh (Standard_True),
+    myNbFailures (0) {}
+  void operator()(const Standard_Integer& theIndex) const
+  {
+    Handle(Select3D_SensitivePrimitiveArray)& anEntity = myPrimArray.myGroups->ChangeValue (theIndex);
+    const Standard_Integer aLower  = myPrimArray.myIndexLower + theIndex * myDivStep;
+    const Standard_Integer anUpper = Min (aLower + myDivStep - 1, myPrimArray.myIndexUpper);
+    anEntity = new Select3D_SensitivePrimitiveArray (myPrimArray.myOwnerId);
+    anEntity->SetPatchSizeMax     (myPrimArray.myPatchSizeMax);
+    anEntity->SetPatchDistance    (myPrimArray.myPatchDistance);
+    anEntity->SetDetectElements   (myPrimArray.myToDetectElem);
+    anEntity->SetDetectElementMap (myPrimArray.ToDetectElementMap());
+    anEntity->SetDetectNodes      (myPrimArray.myToDetectNode);
+    anEntity->SetDetectNodeMap    (myPrimArray.ToDetectNodeMap());
+    anEntity->SetSensitivityFactor(myPrimArray.SensitivityFactor());
+    switch (myPrimArray.myPrimType)
+    {
+      case Graphic3d_TOPA_POINTS:
+      {
+        if (!anEntity->InitPoints (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
+        {
+          Standard_Atomic_Increment (&myNbFailures);
+          return;
+        }
+        break;
+      }
+      case Graphic3d_TOPA_TRIANGLES:
+      {
+        if (!anEntity->InitTriangulation (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
+        {
+          Standard_Atomic_Increment (&myNbFailures);
+          return;
+        }
+        break;
+      }
+      default:
+      {
+        Standard_Atomic_Increment (&myNbFailures);
+        return;
+      }
+    }
+
+    if (myToComputeBvh)
+    {
+      anEntity->BVH();
+    }
+  }
+  Standard_Boolean IsDone() const { return myNbFailures == 0; }
+private:
+  Select3D_SensitivePrimitiveArray_InitFunctor operator= (Select3D_SensitivePrimitiveArray_InitFunctor& );
+private:
+  Select3D_SensitivePrimitiveArray& myPrimArray;
+  Standard_Integer                  myDivStep;
+  Standard_Boolean                  myToEvalMinMax;
+  Standard_Boolean                  myToComputeBvh;
+  mutable volatile Standard_Integer myNbFailures;
+};
+
+//! Functor for computing BVH in parallel threads.
+struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_BVHFunctor
+{
+  Select3D_SensitivePrimitiveArray_BVHFunctor (NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& theGroups) : myGroups (theGroups) {}
+  void operator()(const Standard_Integer& theIndex) const { myGroups.ChangeValue (theIndex)->BVH(); }
+private:
+  Select3D_SensitivePrimitiveArray_BVHFunctor operator= (Select3D_SensitivePrimitiveArray_BVHFunctor& );
+private:
+  NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& myGroups;
+};
+
 // =======================================================================
 // function : Select3D_SensitivePrimitiveArray
 // purpose  :
@@ -100,6 +179,50 @@ Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle
 }
 
 // =======================================================================
+// function : SetDetectElementMap
+// purpose  :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::SetDetectElementMap (bool theToDetect)
+{
+  if (!theToDetect)
+  {
+    myDetectedElemMap.Nullify();
+    return;
+  }
+
+  if (myDetectedElemMap.IsNull())
+  {
+    myDetectedElemMap = new TColStd_HPackedMapOfInteger();
+  }
+  else
+  {
+    myDetectedElemMap->ChangeMap().Clear();
+  }
+}
+
+// =======================================================================
+// function : SetDetectNodeMap
+// purpose  :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::SetDetectNodeMap (bool theToDetect)
+{
+  if (!theToDetect)
+  {
+    myDetectedNodeMap.Nullify();
+    return;
+  }
+
+  if (myDetectedNodeMap.IsNull())
+  {
+    myDetectedNodeMap = new TColStd_HPackedMapOfInteger();
+  }
+  else
+  {
+    myDetectedNodeMap->ChangeMap().Clear();
+  }
+}
+
+// =======================================================================
 // function : InitTriangulation
 // purpose  :
 // =======================================================================
@@ -108,9 +231,11 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
                                                           const TopLoc_Location&               theInitLoc,
                                                           const Standard_Integer               theIndexLower,
                                                           const Standard_Integer               theIndexUpper,
-                                                          const bool                           theToEvalMinMax)
+                                                          const bool                           theToEvalMinMax,
+                                                          const Standard_Integer               theNbGroups)
 {
   MarkDirty();
+  myGroups.Nullify();
   myPrimType = Graphic3d_TOPA_TRIANGLES;
   myBndBox.Clear();
   myVerts.Nullify();
@@ -121,6 +246,7 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
   myBvhIndices.release();
   myIs3d = false;
   myInitLocation = theInitLoc;
+  myCDG3D.SetCoord (0.0, 0.0, 0.0);
   if (theVerts.IsNull()
    || theVerts->NbElements == 0)
   {
@@ -171,11 +297,12 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
 
   Standard_Integer aTriFrom = theIndexLower / 3;
   Standard_Integer aNbTris  = (theIndexUpper - theIndexLower + 1) / 3;
+  const bool hasGroups = (theNbGroups > 1) && (aNbTris / theNbGroups > 10);
   if (aNbTris < 1)
   {
     return false;
   }
-  if (!myBvhIndices.Init (aNbTris, myPatchSizeMax > 1))
+  if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbTris, !hasGroups && myPatchSizeMax > 1))
   {
     return false;
   }
@@ -185,6 +312,30 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
   myIndexLower = theIndexLower;
   myIndexUpper = theIndexUpper;
   myInvInitLocation = myInitLocation.Transformation().Inverted();
+  if (hasGroups)
+  {
+    myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
+    const Standard_Integer aDivStep = (aNbTris / theNbGroups) * 3;
+    Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
+    OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
+    if (!anInitFunctor.IsDone())
+    {
+      return false;
+    }
+    for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
+    {
+      Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
+      myBndBox.Combine (anEntity->BoundingBox());
+      myBvhIndices.SetIndex (aGroupIter, aGroupIter);
+      myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+    }
+    myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
+    if (theToEvalMinMax)
+    {
+      computeBoundingBox();
+    }
+    return true;
+  }
 
   Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
   Standard_Integer  aTriNodes1[3] = { -1, -1, -1 };
@@ -259,9 +410,11 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
                                                    const TopLoc_Location&               theInitLoc,
                                                    const Standard_Integer               theIndexLower,
                                                    const Standard_Integer               theIndexUpper,
-                                                   const bool                           theToEvalMinMax)
+                                                   const bool                           theToEvalMinMax,
+                                                   const Standard_Integer               theNbGroups)
 {
   MarkDirty();
+  myGroups.Nullify();
   myPrimType = Graphic3d_TOPA_POINTS;
   myBndBox.Clear();
   myVerts.Nullify();
@@ -320,12 +473,13 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
     }
   }
 
-  Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
+  const Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
+  const bool hasGroups = (theNbGroups > 1) && (aNbPoints / theNbGroups > 10);
   if (aNbPoints < 1)
   {
     return false;
   }
-  if (!myBvhIndices.Init (aNbPoints, myPatchSizeMax > 1))
+  if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbPoints, !hasGroups && myPatchSizeMax > 1))
   {
     return false;
   }
@@ -335,6 +489,30 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
   myIndexLower = theIndexLower;
   myIndexUpper = theIndexUpper;
   myInvInitLocation = myInitLocation.Transformation().Inverted();
+  if (hasGroups)
+  {
+    myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
+    const Standard_Integer aDivStep = aNbPoints / theNbGroups;
+    Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
+    OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
+    if (!anInitFunctor.IsDone())
+    {
+      return false;
+    }
+    for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
+    {
+      Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
+      myBndBox.Combine (anEntity->BoundingBox());
+      myBvhIndices.SetIndex (aGroupIter, aGroupIter);
+      myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
+    }
+    myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
+    if (theToEvalMinMax)
+    {
+      computeBoundingBox();
+    }
+    return true;
+  }
 
   Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
   Standard_Integer aPatchFrom = 0;
@@ -427,12 +605,12 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected(
   {
     case Graphic3d_TOPA_POINTS:
     {
-      aNewEntity->InitPoints        (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper);
+      aNewEntity->InitPoints        (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
       break;
     }
     case Graphic3d_TOPA_TRIANGLES:
     {
-      aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper);
+      aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
       break;
     }
     default: break;
@@ -440,6 +618,55 @@ Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected(
   return aNewEntity;
 }
 
+//=======================================================================
+//function : Set
+//purpose  :
+//=======================================================================
+void Select3D_SensitivePrimitiveArray::Set (const Handle(SelectBasics_EntityOwner)& theOwnerId)
+{
+  base_type::Set (theOwnerId);
+  if (!myGroups.IsNull())
+  {
+    for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+    {
+      aGroupIter.Value()->Set (theOwnerId);
+    }
+  }
+}
+
+// =======================================================================
+// function : BVH
+// purpose  :
+// =======================================================================
+void Select3D_SensitivePrimitiveArray::BVH()
+{
+  if (!myContent.IsDirty())
+  {
+    return;
+  }
+
+  base_type::BVH();
+  if (myGroups.IsNull())
+  {
+    return;
+  }
+
+  Standard_Integer aNbToUpdate = 0;
+  for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+  {
+    if (aGroupIter.Value()->myContent.IsDirty())
+    {
+      ++aNbToUpdate;
+    }
+  }
+
+  if (aNbToUpdate > 0)
+  {
+    Select3D_SensitivePrimitiveArray_BVHFunctor aFunctor (*myGroups);
+    OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, aFunctor, aNbToUpdate <= 1);
+  }
+}
+
 // =======================================================================
 // function : Size
 // purpose  :
@@ -457,6 +684,11 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer
 {
   const Standard_Integer anElemIdx  = myBvhIndices.Index (theIdx);
   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theIdx);
+  if (!myGroups.IsNull())
+  {
+    return myGroups->Value (anElemIdx)->BoundingBox();
+  }
+
   Select3D_BndBox3d aBox;
   switch (myPrimType)
   {
@@ -531,6 +763,13 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer
 Standard_Real Select3D_SensitivePrimitiveArray::Center (const Standard_Integer theIdx,
                                                         const Standard_Integer theAxis) const
 {
+  if (!myGroups.IsNull())
+  {
+    const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
+    const gp_Pnt aCenter = myGroups->Value (anElemIdx)->CenterOfGeometry();
+    return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
+  }
+
   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());
@@ -579,6 +818,15 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::BoundingBox()
 void Select3D_SensitivePrimitiveArray::computeBoundingBox()
 {
   myBndBox.Clear();
+  if (!myGroups.IsNull())
+  {
+    for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+    {
+      myBndBox.Combine (aGroupIter.Value()->BoundingBox());
+    }
+    return;
+  }
+
   if (myVerts.IsNull())
   {
     return;
@@ -639,6 +887,14 @@ Select3D_BndBox3d Select3D_SensitivePrimitiveArray::applyTransformation()
 Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                             SelectBasics_PickResult& thePickResult)
 {
+  if (!myDetectedElemMap.IsNull())
+  {
+    myDetectedElemMap->ChangeMap().Clear();
+  }
+  if (!myDetectedNodeMap.IsNull())
+  {
+    myDetectedNodeMap->ChangeMap().Clear();
+  }
   myMinDepthElem      = RealLast();
   myMinDepthNode      = RealLast();
   myMinDepthEdge      = RealLast();
@@ -646,7 +902,77 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_Selecti
   myDetectedNode      = -1;
   myDetectedEdgeNode1 = -1;
   myDetectedEdgeNode2 = -1;
-  return Select3D_SensitiveSet::Matches (theMgr, thePickResult);
+  const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull();
+  if (myGroups.IsNull()
+   || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point
+   || !toDetectRange)
+  {
+    if (!Select3D_SensitiveSet::Matches (theMgr, thePickResult))
+    {
+      return Standard_False;
+    }
+
+    if (!myGroups.IsNull() && myDetectedIdx != -1)
+    {
+      const Standard_Integer anIndex = myBvhIndices.Index (myDetectedIdx);
+      const Handle(Select3D_SensitivePrimitiveArray)& aLastGroup = myGroups->Value (anIndex);
+      myMinDepthElem      = aLastGroup->myMinDepthElem;
+      myMinDepthNode      = aLastGroup->myMinDepthNode;
+      myMinDepthEdge      = aLastGroup->myMinDepthEdge;
+      myDetectedElem      = aLastGroup->myDetectedElem;
+      myDetectedNode      = aLastGroup->myDetectedNode;
+      myDetectedEdgeNode1 = aLastGroup->myDetectedEdgeNode1;
+      myDetectedEdgeNode2 = aLastGroup->myDetectedEdgeNode2;
+    }
+    return Standard_True;
+  }
+
+  Standard_Real aDepth = RealLast();
+  bool isFailed = false;
+  const bool toMatchAll = !theMgr.IsOverlapAllowed();
+  for (Standard_Integer aGroupIter = 0; aGroupIter < myBvhIndices.NbElements; ++aGroupIter)
+  {
+    const Standard_Integer anElemIdx = myBvhIndices.Index (aGroupIter);
+    SelectBasics_PickResult aMatchResult;
+    Handle(Select3D_SensitivePrimitiveArray)& aChild = myGroups->ChangeValue (anElemIdx);
+    const bool isMatched = aChild->Matches (theMgr, aMatchResult);
+    if (!myDetectedElemMap.IsNull())
+    {
+      myDetectedElemMap->ChangeMap().Unite (aChild->myDetectedElemMap->Map());
+    }
+    if (!myDetectedNodeMap.IsNull())
+    {
+      myDetectedNodeMap->ChangeMap().Unite (aChild->myDetectedNodeMap->Map());
+    }
+
+    if (!isMatched)
+    {
+      if (toMatchAll)
+      {
+        isFailed = true;
+        if (!toDetectRange)
+        {
+          break;
+        }
+      }
+    }
+    else
+    {
+      if (aDepth > aMatchResult.Depth())
+      {
+        myDetectedIdx = aGroupIter;
+        aDepth = aMatchResult.Depth();
+      }
+    }
+  }
+  if (isFailed)
+  {
+    thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
+    return Standard_False;
+  }
+
+  thePickResult = SelectBasics_PickResult (aDepth, theMgr.DistToGeometryCenter (CenterOfGeometry()));
+  return Standard_True;
 }
 
 // =======================================================================
@@ -657,7 +983,19 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
                                                                     Standard_Integer theElemIdx,
                                                                     Standard_Real& theMatchDepth)
 {
-  const Standard_Integer anElemIdx  = myBvhIndices.Index (theElemIdx);
+  const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+  if (!myGroups.IsNull())
+  {
+    SelectBasics_PickResult aResult;
+    if (myGroups->Value (anElemIdx)->Matches (theMgr, aResult))
+    {
+      theMatchDepth = aResult.Depth();
+      return Standard_True;
+    }
+    theMatchDepth = RealLast();
+    return Standard_False;
+  }
+
   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
   Select3D_BndBox3d aBox;
   Standard_Boolean aResult = Standard_False;
@@ -693,6 +1031,17 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
               myDetectedElem = myDetectedNode = aPointIndex;
               myMinDepthElem = myMinDepthNode = aCurrentDepth;
             }
+            if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+            {
+              if (!myDetectedElemMap.IsNull())
+              {
+                myDetectedElemMap->ChangeMap().Add (aPointIndex);
+              }
+              if (!myDetectedNodeMap.IsNull())
+              {
+                myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+              }
+            }
             aResult = Standard_True;
           }
         }
@@ -705,7 +1054,8 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
       Graphic3d_Vec3i aTriNodes;
       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
       {
-        const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
+        const Standard_Integer aTriIndex     = anElemIdx + anElemIter;
+        const Standard_Integer anIndexOffset = aTriIndex * 3;
         getTriIndices (myIndices, anIndexOffset, aTriNodes);
         gp_Pnt aPnts[3];
         if (myIs3d)
@@ -728,11 +1078,16 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
           {
             if (aCurrentDepth <= myMinDepthElem)
             {
-              myDetectedElem = anElemIdx + anElemIter;
+              myDetectedElem = aTriIndex;
               myMinDepthElem = aCurrentDepth;
             }
             aResult = Standard_True;
           }
+          if (!myDetectedElemMap.IsNull()
+            && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+          {
+            myDetectedElemMap->ChangeMap().Add (aTriIndex);
+          }
         }
         if (myToDetectNode)
         {
@@ -745,6 +1100,11 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics
                 myDetectedNode = aTriNodes[aNodeIter];
                 myMinDepthNode = aCurrentDepth;
               }
+              if (!myDetectedNodeMap.IsNull()
+                && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+              {
+                myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
+              }
               aResult = Standard_True;
             }
           }
@@ -797,7 +1157,13 @@ Standard_Real Select3D_SensitivePrimitiveArray::distanceToCOG (SelectBasics_Sele
 Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
                                                                     const Standard_Integer               theElemIdx)
 {
-  const Standard_Integer anElemIdx  = myBvhIndices.Index (theElemIdx);
+  const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
+  if (!myGroups.IsNull())
+  {
+    Standard_Real aDummy;
+    return overlapsElement (theMgr, theElemIdx, aDummy);
+  }
+
   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
   switch (myPrimType)
   {
@@ -822,6 +1188,18 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
         {
           return Standard_False;
         }
+
+        if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+        {
+          if (!myDetectedElemMap.IsNull())
+          {
+            myDetectedElemMap->ChangeMap().Add (aPointIndex);
+          }
+          if (!myDetectedNodeMap.IsNull())
+          {
+            myDetectedNodeMap->ChangeMap().Add (aPointIndex);
+          }
+        }
       }
       return Standard_True;
     }
@@ -830,7 +1208,8 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
       Graphic3d_Vec3i aTriNodes;
       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
       {
-        const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
+        const Standard_Integer aTriIndex     = anElemIdx + anElemIter;
+        const Standard_Integer anIndexOffset = aTriIndex * 3;
         getTriIndices (myIndices, anIndexOffset, aTriNodes);
         gp_Pnt aPnts[3];
         if (myIs3d)
@@ -852,6 +1231,20 @@ Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics
         {
           return Standard_False;
         }
+
+        if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
+        {
+          if (!myDetectedElemMap.IsNull())
+          {
+            myDetectedElemMap->ChangeMap().Add (aTriIndex);
+          }
+          if (!myDetectedNodeMap.IsNull())
+          {
+            myDetectedNodeMap->ChangeMap().Add (aTriNodes[0]);
+            myDetectedNodeMap->ChangeMap().Add (aTriNodes[1]);
+            myDetectedNodeMap->ChangeMap().Add (aTriNodes[2]);
+          }
+        }
       }
       return Standard_True;
     }
index 0c3402e..653a3f9 100644 (file)
@@ -21,6 +21,7 @@
 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
 #include <Select3D_SensitiveSet.hxx>
 #include <Select3D_BVHIndexBuffer.hxx>
+#include <TColStd_HPackedMapOfInteger.hxx>
 
 //! Sensitive for triangulation or point set defined by Primitive Array.
 //! The primitives can be optionally combined into patches within BVH tree
@@ -57,26 +58,30 @@ public:
   //! @param theIndexLower   the theIndices range - first value (inclusive), starting from 0 and multiple by 3
   //! @param theIndexUpper   the theIndices range - last  value (inclusive), upto theIndices->NbElements-1 and multiple by 3
   //! @param theToEvalMinMax compute bounding box within initialization
+  //! @param theNbGroups     number of groups to split the vertex array into several parts
   Standard_EXPORT bool InitTriangulation (const Handle(Graphic3d_Buffer)&      theVerts,
                                           const Handle(Graphic3d_IndexBuffer)& theIndices,
                                           const TopLoc_Location&               theInitLoc,
                                           const Standard_Integer               theIndexLower,
                                           const Standard_Integer               theIndexUpper,
-                                          const bool                           theToEvalMinMax = true);
+                                          const bool                           theToEvalMinMax = true,
+                                          const Standard_Integer               theNbGroups = 1);
 
   //! Initialize the sensitive object from triangualtion.
   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
   //! @param theIndices      index array defining triangulation
   //! @param theInitLoc      location
   //! @param theToEvalMinMax compute bounding box within initialization
+  //! @param theNbGroups     number of groups to split the vertex array into several parts
   bool InitTriangulation (const Handle(Graphic3d_Buffer)&      theVerts,
                           const Handle(Graphic3d_IndexBuffer)& theIndices,
                           const TopLoc_Location&               theInitLoc,
-                          const bool                           theToEvalMinMax = true)
+                          const bool                           theToEvalMinMax = true,
+                          const Standard_Integer               theNbGroups = 1)
   {
     const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
                                                           : (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
-    return InitTriangulation (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax);
+    return InitTriangulation (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
   }
 
   //! Initialize the sensitive object from point set.
@@ -88,38 +93,44 @@ public:
   //! @param theIndexLower   the theIndices range - first value (inclusive), starting from 0
   //! @param theIndexUpper   the theIndices range - last  value (inclusive), upto theIndices->NbElements-1
   //! @param theToEvalMinMax compute bounding box within initialization
+  //! @param theNbGroups     number of groups to split the vertex array into several parts
   Standard_EXPORT bool InitPoints (const Handle(Graphic3d_Buffer)&      theVerts,
                                    const Handle(Graphic3d_IndexBuffer)& theIndices,
                                    const TopLoc_Location&               theInitLoc,
                                    const Standard_Integer               theIndexLower,
                                    const Standard_Integer               theIndexUpper,
-                                   const bool                           theToEvalMinMax = true);
+                                   const bool                           theToEvalMinMax = true,
+                                   const Standard_Integer               theNbGroups = 1);
 
   //! Initialize the sensitive object from point set.
   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
   //! @param theIndices      index array to define subset of points
   //! @param theInitLoc      location
   //! @param theToEvalMinMax compute bounding box within initialization
+  //! @param theNbGroups     number of groups to split the vertex array into several parts
   bool InitPoints (const Handle(Graphic3d_Buffer)&      theVerts,
                    const Handle(Graphic3d_IndexBuffer)& theIndices,
                    const TopLoc_Location&               theInitLoc,
-                   const bool                           theToEvalMinMax = true)
+                   const bool                           theToEvalMinMax = true,
+                   const Standard_Integer               theNbGroups = 1)
   {
     const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
                                                           : (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
-    return InitPoints (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax);
+    return InitPoints (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
   }
 
   //! Initialize the sensitive object from point set.
   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
   //! @param theInitLoc      location
   //! @param theToEvalMinMax compute bounding box within initialization
+  //! @param theNbGroups     number of groups to split the vertex array into several parts
   bool InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
                    const TopLoc_Location&          theInitLoc,
-                   const bool                      theToEvalMinMax = true)
+                   const bool                      theToEvalMinMax = true,
+                   const Standard_Integer          theNbGroups = 1)
   {
     const Standard_Integer anUpper = !theVerts.IsNull() ? (theVerts->NbElements - 1) : 0;
-    return InitPoints (theVerts, Handle(Graphic3d_IndexBuffer)(), theInitLoc, 0, anUpper, theToEvalMinMax);
+    return InitPoints (theVerts, Handle(Graphic3d_IndexBuffer)(), theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
   }
 
   //! Assign new not transformed bounding box.
@@ -128,36 +139,61 @@ public:
   {
     myBndBox = Select3D_BndBox3d (SelectMgr_Vec3 (theMinX, theMinY, theMinZ),
                                   SelectMgr_Vec3 (theMaxX, theMaxY, theMaxZ));
+    if (!myGroups.IsNull())
+    {
+      for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
+      {
+        aGroupIter.Value()->myBndBox = myBndBox;
+      }
+    }
   }
 
-  //! Return flag indicating detection of elements (true by default).
+  //! Return flag to keep index of last topmost detected element, TRUE by default.
   bool ToDetectElements() const { return myToDetectElem; }
 
-  //! Setup detection of elements.
+  //! Setup keeping of the index of last topmost detected element (axis picking).
   void SetDetectElements (bool theToDetect) { myToDetectElem = theToDetect; }
 
-  //! Return flag indicating detection of nodes (false by default).
+  //! Return flag to keep index map of last detected elements, FALSE by default (rectangle selection).
+  bool ToDetectElementMap() const { return !myDetectedElemMap.IsNull(); }
+
+  //! Setup keeping of the index map of last detected elements (rectangle selection).
+  Standard_EXPORT void SetDetectElementMap (bool theToDetect);
+
+  //! Return flag to keep index of last topmost detected node, FALSE by default.
   bool ToDetectNodes() const { return myToDetectNode; }
 
-  //! Setup detection of nodes.
+  //! Setup keeping of the index of last topmost detected node (for axis picking).
   void SetDetectNodes (bool theToDetect) { myToDetectNode = theToDetect; }
 
-  //! Return flag indicating detection of edges (false by default).
+  //! Return flag to keep index map of last detected nodes, FALSE by default (rectangle selection).
+  bool ToDetectNodeMap() const { return !myDetectedNodeMap.IsNull(); }
+
+  //! Setup keeping of the index map of last detected nodes (rectangle selection).
+  Standard_EXPORT void SetDetectNodeMap (bool theToDetect);
+
+  //! Return flag to keep index of last topmost detected edge, FALSE by default.
   bool ToDetectEdges() const { return myToDetectEdge; }
 
-  //! Setup detection of edges.
+  //! Setup keeping of the index of last topmost detected edge (axis picking).
   void SetDetectEdges (bool theToDetect) { myToDetectEdge = theToDetect; }
 
-  //! Return last detected element or -1 if undefined.
+  //! Return last topmost detected element or -1 if undefined (axis picking).
   Standard_Integer LastDetectedElement() const { return myDetectedElem; }
 
-  //! Return last detected node or -1 if undefined.
+  //! Return the index map of last detected elements (rectangle selection).
+  const Handle(TColStd_HPackedMapOfInteger)& LastDetectedElementMap() const { return myDetectedElemMap; }
+
+  //! Return last topmost detected node or -1 if undefined (axis picking).
   Standard_Integer LastDetectedNode() const { return myDetectedNode; }
 
-  //! Return the first node of last detected edge or -1 if undefined.
+  //! Return the index map of last detected nodes (rectangle selection).
+  const Handle(TColStd_HPackedMapOfInteger)& LastDetectedNodeMap() const { return myDetectedNodeMap; }
+
+  //! Return the first node of last topmost detected edge or -1 if undefined (axis picking).
   Standard_Integer LastDetectedEdgeNode1() const { return myDetectedEdgeNode1; }
 
-  //! Return the second node of last detected edge or -1 if undefined.
+  //! Return the second node of last topmost detected edge or -1 if undefined (axis picking).
   Standard_Integer LastDetectedEdgeNode2() const { return myDetectedEdgeNode2; }
 
 public:
@@ -174,7 +210,7 @@ public:
   //! Returns the amount of nodes in triangulation
   virtual Standard_Integer NbSubElements() Standard_OVERRIDE
   {
-    return myBvhIndices.NbElements;
+    return !myGroups.IsNull() ? myGroups->Size() : myBvhIndices.NbElements;
   }
 
   //! Returns bounding box of triangle/edge with index theIdx
@@ -213,6 +249,12 @@ public:
     return myInvInitLocation;
   }
 
+  //! Sets the owner for all entities in group
+  Standard_EXPORT virtual void Set (const Handle(SelectBasics_EntityOwner)& theOwnerId) Standard_OVERRIDE;
+
+  //! Builds BVH tree for sensitive set.
+  Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
+
 protected:
 
   //! Compute bounding box.
@@ -248,30 +290,40 @@ protected:
 
 private:
 
-  Handle(Graphic3d_Buffer)         myVerts;              //!< source data - nodes position
-  Handle(Graphic3d_IndexBuffer)    myIndices;            //!< source data - primitive indexes
-  Graphic3d_TypeOfPrimitiveArray   myPrimType;           //!< primitives type
-  Standard_Integer                 myIndexLower;         //!< index range - first index in myIndices (inclusive)
-  Standard_Integer                 myIndexUpper;         //!< index range - last  index in myIndices (inclusive)
-  Standard_Size                    myPosOffset;          //!< offset to the position vertex attribute
-  Standard_Integer                 myPatchSizeMax;       //!< patch size limit (1 by default)
-  float                            myPatchDistance;      //!< distance between elements in patch
-  bool                             myIs3d;               //!< flag indicating that position attribute has 3 components
-  TopLoc_Location                  myInitLocation;
-  gp_Pnt                           myCDG3D;              //!< Center of the whole triangulation
-  Select3D_BVHIndexBuffer          myBvhIndices;         //!< Indexes of edges or triangles for BVH tree
-  mutable Select3D_BndBox3d        myBndBox;             //!< Bounding box of the whole triangulation
-  gp_GTrsf                         myInvInitLocation;
-  Standard_Real                    myMinDepthElem;       //!< the depth of nearest detected element
-  Standard_Real                    myMinDepthNode;       //!< the depth of nearest detected node
-  Standard_Real                    myMinDepthEdge;       //!< the depth of nearest detected edge
-  Standard_Integer                 myDetectedElem;       //!< index of detected element
-  Standard_Integer                 myDetectedNode;       //!< index of detected node
-  Standard_Integer                 myDetectedEdgeNode1;  //!< index of detected edge node 1
-  Standard_Integer                 myDetectedEdgeNode2;  //!< index of detected edge node 2
-  bool                             myToDetectElem;       //!< flag to detect element
-  bool                             myToDetectNode;       //!< flag to detect node
-  bool                             myToDetectEdge;       //!< flag to detect edge
+  typedef NCollection_Shared<NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)> > Select3D_PrimArraySubGroupArray;
+  struct Select3D_SensitivePrimitiveArray_InitFunctor;
+  struct Select3D_SensitivePrimitiveArray_BVHFunctor;
+
+private:
+
+  Handle(Select3D_PrimArraySubGroupArray) myGroups;         //!< sub-groups of sensitive entities
+
+  Handle(Graphic3d_Buffer)            myVerts;              //!< source data - nodes position
+  Handle(Graphic3d_IndexBuffer)       myIndices;            //!< source data - primitive indexes
+  Graphic3d_TypeOfPrimitiveArray      myPrimType;           //!< primitives type
+  Standard_Integer                    myIndexLower;         //!< index range - first index in myIndices (inclusive)
+  Standard_Integer                    myIndexUpper;         //!< index range - last  index in myIndices (inclusive)
+  Standard_Size                       myPosOffset;          //!< offset to the position vertex attribute
+  Standard_Integer                    myPatchSizeMax;       //!< patch size limit (1 by default)
+  float                               myPatchDistance;      //!< distance between elements in patch
+  bool                                myIs3d;               //!< flag indicating that position attribute has 3 components
+  TopLoc_Location                     myInitLocation;
+  gp_Pnt                              myCDG3D;              //!< Center of the whole triangulation
+  Select3D_BVHIndexBuffer             myBvhIndices;         //!< Indexes of edges or triangles for BVH tree
+  mutable Select3D_BndBox3d           myBndBox;             //!< Bounding box of the whole triangulation
+  gp_GTrsf                            myInvInitLocation;
+  Handle(TColStd_HPackedMapOfInteger) myDetectedElemMap;    //!< index map of last detected elements
+  Handle(TColStd_HPackedMapOfInteger) myDetectedNodeMap;    //!< index map of last detected nodes
+  Standard_Real                       myMinDepthElem;       //!< the depth of nearest detected element
+  Standard_Real                       myMinDepthNode;       //!< the depth of nearest detected node
+  Standard_Real                       myMinDepthEdge;       //!< the depth of nearest detected edge
+  Standard_Integer                    myDetectedElem;       //!< index of last detected element
+  Standard_Integer                    myDetectedNode;       //!< index of last detected node
+  Standard_Integer                    myDetectedEdgeNode1;  //!< index of last detected edge node 1
+  Standard_Integer                    myDetectedEdgeNode2;  //!< index of last detected edge node 2
+  bool                                myToDetectElem;       //!< flag to keep info about last detected element
+  bool                                myToDetectNode;       //!< flag to keep info about last detected node
+  bool                                myToDetectEdge;       //!< flag to keep info about last detected edge
 
 public:
 
index be810f0..88d3ded 100644 (file)
@@ -74,10 +74,9 @@ void Select3D_SensitiveSet::BVH()
 Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeManager& theMgr,
                                                  SelectBasics_PickResult& thePickResult)
 {
+  myDetectedIdx = -1;
   const BVH_Tree<Standard_Real, 3, BVH_BinaryTree>* aBVH = myContent.GetBVH().get();
-
   thePickResult = SelectBasics_PickResult (RealLast(), RealLast());
-
   if (myContent.Size() < 1 || !theMgr.Overlaps (aBVH->MinPoint (0),
                                                 aBVH->MaxPoint (0)))
   {
@@ -90,7 +89,6 @@ Standard_Boolean Select3D_SensitiveSet::Matches (SelectBasics_SelectingVolumeMan
 
   Standard_Integer aMatchesNb = -1;
   Standard_Real    aMinDepth  = RealLast();
-
   for (;;)
   {
     const BVH_Vec4i& aData = aBVH->NodeInfoBuffer()[aNode];