0030058: Visualization, Select3D_SensitivePrimitiveArray - the selection is not fast...
[occt.git] / src / Select3D / Select3D_SensitivePrimitiveArray.hxx
index 4e858ef..50e767b 100644 (file)
 #include <Graphic3d_Buffer.hxx>
 #include <Graphic3d_IndexBuffer.hxx>
 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
+#include <NCollection_Shared.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 +59,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 +94,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 +140,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 +211,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
@@ -208,11 +245,17 @@ public:
 
   //! Returns inversed location transformation matrix if the shape corresponding
   //! to this entity has init location set. Otherwise, returns identity matrix.
-  virtual gp_Trsf InvInitLocation() const Standard_OVERRIDE
+  virtual gp_GTrsf InvInitLocation() const Standard_OVERRIDE
   {
     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.
@@ -235,43 +278,55 @@ protected:
   }
 
   //! Checks whether the element with index theIdx overlaps the current selecting volume
-  Standard_EXPORT virtual Standard_Boolean overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
+  Standard_EXPORT virtual Standard_Boolean overlapsElement (SelectBasics_PickResult& thePickResult,
+                                                            SelectBasics_SelectingVolumeManager& theMgr,
                                                             Standard_Integer theElemIdx,
-                                                            Standard_Real& theMatchDepth) Standard_OVERRIDE;
+                                                            Standard_Boolean theIsFullInside) 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;
 
   //! 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;
+                                                            Standard_Integer theElemIdx,
+                                                            Standard_Boolean theIsFullInside) Standard_OVERRIDE;
+
+private:
+
+  typedef NCollection_Shared<NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)> > Select3D_PrimArraySubGroupArray;
+  struct Select3D_SensitivePrimitiveArray_InitFunctor;
+  struct Select3D_SensitivePrimitiveArray_BVHFunctor;
 
 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_Trsf                          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
+  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: