0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / Select3D / Select3D_SensitivePrimitiveArray.hxx
1 // Created on: 2016-02-20
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2016 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _Select3D_SensitivePrimitiveArray_Header
17 #define _Select3D_SensitivePrimitiveArray_Header
18
19 #include <Graphic3d_Buffer.hxx>
20 #include <Graphic3d_IndexBuffer.hxx>
21 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
22 #include <Select3D_SensitiveSet.hxx>
23 #include <Select3D_BVHIndexBuffer.hxx>
24 #include <TColStd_HPackedMapOfInteger.hxx>
25
26 //! Sensitive for triangulation or point set defined by Primitive Array.
27 //! The primitives can be optionally combined into patches within BVH tree
28 //! to reduce its building time in expense of extra traverse time.
29 class Select3D_SensitivePrimitiveArray : public Select3D_SensitiveSet
30 {
31
32 public:
33
34   //! Constructs an empty sensitive object.
35   Standard_EXPORT Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId);
36
37   //! Return patch size limit (1 by default).
38   Standard_Integer PatchSizeMax() const { return myPatchSizeMax; }
39
40   //! Assign patch size limit.
41   //! Should be set before initialization.
42   void SetPatchSizeMax (const Standard_Integer thePatchSizeMax) { myPatchSizeMax = thePatchSizeMax; }
43
44   //! Maximum allowed distance between consequential elements in patch (ShortRealLast() by default).
45   //! Has no effect on indexed triangulation.
46   float PatchDistance() const { return myPatchDistance; }
47
48   //! Assign patch distance limit.
49   //! Should be set before initialization.
50   void SetPatchDistance (const float thePatchDistMax) { myPatchDistance = thePatchDistMax; }
51
52   //! Initialize the sensitive object from triangualtion.
53   //! The sub-triangulation can be specified by arguments theIndexLower and theIndexUpper
54   //! (these are for iterating theIndices, not to restrict the actual index values!).
55   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
56   //! @param theIndices      index array defining triangulation
57   //! @param theInitLoc      location
58   //! @param theIndexLower   the theIndices range - first value (inclusive), starting from 0 and multiple by 3
59   //! @param theIndexUpper   the theIndices range - last  value (inclusive), upto theIndices->NbElements-1 and multiple by 3
60   //! @param theToEvalMinMax compute bounding box within initialization
61   //! @param theNbGroups     number of groups to split the vertex array into several parts
62   Standard_EXPORT bool InitTriangulation (const Handle(Graphic3d_Buffer)&      theVerts,
63                                           const Handle(Graphic3d_IndexBuffer)& theIndices,
64                                           const TopLoc_Location&               theInitLoc,
65                                           const Standard_Integer               theIndexLower,
66                                           const Standard_Integer               theIndexUpper,
67                                           const bool                           theToEvalMinMax = true,
68                                           const Standard_Integer               theNbGroups = 1);
69
70   //! Initialize the sensitive object from triangualtion.
71   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
72   //! @param theIndices      index array defining triangulation
73   //! @param theInitLoc      location
74   //! @param theToEvalMinMax compute bounding box within initialization
75   //! @param theNbGroups     number of groups to split the vertex array into several parts
76   bool InitTriangulation (const Handle(Graphic3d_Buffer)&      theVerts,
77                           const Handle(Graphic3d_IndexBuffer)& theIndices,
78                           const TopLoc_Location&               theInitLoc,
79                           const bool                           theToEvalMinMax = true,
80                           const Standard_Integer               theNbGroups = 1)
81   {
82     const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
83                                                           : (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
84     return InitTriangulation (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
85   }
86
87   //! Initialize the sensitive object from point set.
88   //! The sub-set of points can be specified by arguments theIndexLower and theIndexUpper
89   //! (these are for iterating theIndices, not to restrict the actual index values!).
90   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
91   //! @param theIndices      index array defining points
92   //! @param theInitLoc      location
93   //! @param theIndexLower   the theIndices range - first value (inclusive), starting from 0
94   //! @param theIndexUpper   the theIndices range - last  value (inclusive), upto theIndices->NbElements-1
95   //! @param theToEvalMinMax compute bounding box within initialization
96   //! @param theNbGroups     number of groups to split the vertex array into several parts
97   Standard_EXPORT bool InitPoints (const Handle(Graphic3d_Buffer)&      theVerts,
98                                    const Handle(Graphic3d_IndexBuffer)& theIndices,
99                                    const TopLoc_Location&               theInitLoc,
100                                    const Standard_Integer               theIndexLower,
101                                    const Standard_Integer               theIndexUpper,
102                                    const bool                           theToEvalMinMax = true,
103                                    const Standard_Integer               theNbGroups = 1);
104
105   //! Initialize the sensitive object from point set.
106   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
107   //! @param theIndices      index array to define subset of points
108   //! @param theInitLoc      location
109   //! @param theToEvalMinMax compute bounding box within initialization
110   //! @param theNbGroups     number of groups to split the vertex array into several parts
111   bool InitPoints (const Handle(Graphic3d_Buffer)&      theVerts,
112                    const Handle(Graphic3d_IndexBuffer)& theIndices,
113                    const TopLoc_Location&               theInitLoc,
114                    const bool                           theToEvalMinMax = true,
115                    const Standard_Integer               theNbGroups = 1)
116   {
117     const Standard_Integer anUpper = !theIndices.IsNull() ? (theIndices->NbElements - 1)
118                                                           : (!theVerts.IsNull() ? (theVerts->NbElements - 1) : 0);
119     return InitPoints (theVerts, theIndices, theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
120   }
121
122   //! Initialize the sensitive object from point set.
123   //! @param theVerts        attributes array containing Graphic3d_TOA_POS with type Graphic3d_TOD_VEC3 or Graphic3d_TOD_VEC2
124   //! @param theInitLoc      location
125   //! @param theToEvalMinMax compute bounding box within initialization
126   //! @param theNbGroups     number of groups to split the vertex array into several parts
127   bool InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
128                    const TopLoc_Location&          theInitLoc,
129                    const bool                      theToEvalMinMax = true,
130                    const Standard_Integer          theNbGroups = 1)
131   {
132     const Standard_Integer anUpper = !theVerts.IsNull() ? (theVerts->NbElements - 1) : 0;
133     return InitPoints (theVerts, Handle(Graphic3d_IndexBuffer)(), theInitLoc, 0, anUpper, theToEvalMinMax, theNbGroups);
134   }
135
136   //! Assign new not transformed bounding box.
137   void SetMinMax (double theMinX, double theMinY, double theMinZ,
138                   double theMaxX, double theMaxY, double theMaxZ)
139   {
140     myBndBox = Select3D_BndBox3d (SelectMgr_Vec3 (theMinX, theMinY, theMinZ),
141                                   SelectMgr_Vec3 (theMaxX, theMaxY, theMaxZ));
142     if (!myGroups.IsNull())
143     {
144       for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
145       {
146         aGroupIter.Value()->myBndBox = myBndBox;
147       }
148     }
149   }
150
151   //! Return flag to keep index of last topmost detected element, TRUE by default.
152   bool ToDetectElements() const { return myToDetectElem; }
153
154   //! Setup keeping of the index of last topmost detected element (axis picking).
155   void SetDetectElements (bool theToDetect) { myToDetectElem = theToDetect; }
156
157   //! Return flag to keep index map of last detected elements, FALSE by default (rectangle selection).
158   bool ToDetectElementMap() const { return !myDetectedElemMap.IsNull(); }
159
160   //! Setup keeping of the index map of last detected elements (rectangle selection).
161   Standard_EXPORT void SetDetectElementMap (bool theToDetect);
162
163   //! Return flag to keep index of last topmost detected node, FALSE by default.
164   bool ToDetectNodes() const { return myToDetectNode; }
165
166   //! Setup keeping of the index of last topmost detected node (for axis picking).
167   void SetDetectNodes (bool theToDetect) { myToDetectNode = theToDetect; }
168
169   //! Return flag to keep index map of last detected nodes, FALSE by default (rectangle selection).
170   bool ToDetectNodeMap() const { return !myDetectedNodeMap.IsNull(); }
171
172   //! Setup keeping of the index map of last detected nodes (rectangle selection).
173   Standard_EXPORT void SetDetectNodeMap (bool theToDetect);
174
175   //! Return flag to keep index of last topmost detected edge, FALSE by default.
176   bool ToDetectEdges() const { return myToDetectEdge; }
177
178   //! Setup keeping of the index of last topmost detected edge (axis picking).
179   void SetDetectEdges (bool theToDetect) { myToDetectEdge = theToDetect; }
180
181   //! Return last topmost detected element or -1 if undefined (axis picking).
182   Standard_Integer LastDetectedElement() const { return myDetectedElem; }
183
184   //! Return the index map of last detected elements (rectangle selection).
185   const Handle(TColStd_HPackedMapOfInteger)& LastDetectedElementMap() const { return myDetectedElemMap; }
186
187   //! Return last topmost detected node or -1 if undefined (axis picking).
188   Standard_Integer LastDetectedNode() const { return myDetectedNode; }
189
190   //! Return the index map of last detected nodes (rectangle selection).
191   const Handle(TColStd_HPackedMapOfInteger)& LastDetectedNodeMap() const { return myDetectedNodeMap; }
192
193   //! Return the first node of last topmost detected edge or -1 if undefined (axis picking).
194   Standard_Integer LastDetectedEdgeNode1() const { return myDetectedEdgeNode1; }
195
196   //! Return the second node of last topmost detected edge or -1 if undefined (axis picking).
197   Standard_Integer LastDetectedEdgeNode2() const { return myDetectedEdgeNode2; }
198
199 public:
200
201   //! Checks whether the sensitive entity is overlapped by current selecting volume.
202   Standard_EXPORT virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr,
203                                                     SelectBasics_PickResult&             thePickResult) Standard_OVERRIDE;
204
205   Standard_EXPORT virtual Handle(Select3D_SensitiveEntity) GetConnected() Standard_OVERRIDE;
206
207   //! Returns the length of array of triangles or edges
208   Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE;
209
210   //! Returns the amount of nodes in triangulation
211   virtual Standard_Integer NbSubElements() Standard_OVERRIDE
212   {
213     return !myGroups.IsNull() ? myGroups->Size() : myBvhIndices.NbElements;
214   }
215
216   //! Returns bounding box of triangle/edge with index theIdx
217   Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIdx) const Standard_OVERRIDE;
218
219   //! Returns geometry center of triangle/edge with index theIdx
220   //! in array along the given axis theAxis
221   Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIdx,
222                                                 const Standard_Integer theAxis) const Standard_OVERRIDE;
223
224   //! Swaps items with indexes theIdx1 and theIdx2 in array
225   Standard_EXPORT virtual void Swap (const Standard_Integer theIdx1,
226                                      const Standard_Integer theIdx2) Standard_OVERRIDE;
227
228   //! Returns bounding box of the triangulation. If location
229   //! transformation is set, it will be applied
230   Standard_EXPORT virtual Select3D_BndBox3d BoundingBox() Standard_OVERRIDE;
231
232   //! Returns center of triangulation. If location transformation
233   //! is set, it will be applied
234   virtual gp_Pnt CenterOfGeometry() const Standard_OVERRIDE
235   {
236     return myCDG3D;
237   }
238
239   //! Returns true if the shape corresponding to the entity has init location
240   virtual Standard_Boolean HasInitLocation() const Standard_OVERRIDE
241   {
242     return !myInitLocation.IsIdentity();
243   }
244
245   //! Returns inversed location transformation matrix if the shape corresponding
246   //! to this entity has init location set. Otherwise, returns identity matrix.
247   virtual gp_GTrsf InvInitLocation() const Standard_OVERRIDE
248   {
249     return myInvInitLocation;
250   }
251
252   //! Sets the owner for all entities in group
253   Standard_EXPORT virtual void Set (const Handle(SelectBasics_EntityOwner)& theOwnerId) Standard_OVERRIDE;
254
255   //! Builds BVH tree for sensitive set.
256   Standard_EXPORT virtual void BVH() Standard_OVERRIDE;
257
258 protected:
259
260   //! Compute bounding box.
261   Standard_EXPORT void computeBoundingBox();
262
263   //! Inner function for transformation application to bounding
264   //! box of the triangulation
265   Standard_EXPORT Select3D_BndBox3d applyTransformation();
266
267   //! Auxiliary getter.
268   const Graphic3d_Vec3& getPosVec3 (const Standard_Integer theIndex) const
269   {
270     return *reinterpret_cast<const Graphic3d_Vec3* >(myVerts->value (theIndex) + myPosOffset);
271   }
272
273   //! Auxiliary getter.
274   const Graphic3d_Vec2& getPosVec2 (const Standard_Integer theIndex) const
275   {
276     return *reinterpret_cast<const Graphic3d_Vec2* >(myVerts->value (theIndex) + myPosOffset);
277   }
278
279   //! Checks whether the element with index theIdx overlaps the current selecting volume
280   Standard_EXPORT virtual Standard_Boolean overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
281                                                             Standard_Integer theElemIdx,
282                                                             Standard_Real& theMatchDepth) Standard_OVERRIDE;
283
284   //! Calculates distance from the 3d projection of used-picked screen point to center of the geometry
285   Standard_EXPORT virtual Standard_Real distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) Standard_OVERRIDE;
286
287   //! Checks whether the entity with index theIdx is inside the current selecting volume
288   Standard_EXPORT virtual Standard_Boolean elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
289                                                             const Standard_Integer               theElemIdx) Standard_OVERRIDE;
290
291 private:
292
293   typedef NCollection_Shared<NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)> > Select3D_PrimArraySubGroupArray;
294   struct Select3D_SensitivePrimitiveArray_InitFunctor;
295   struct Select3D_SensitivePrimitiveArray_BVHFunctor;
296
297 private:
298
299   Handle(Select3D_PrimArraySubGroupArray) myGroups;         //!< sub-groups of sensitive entities
300
301   Handle(Graphic3d_Buffer)            myVerts;              //!< source data - nodes position
302   Handle(Graphic3d_IndexBuffer)       myIndices;            //!< source data - primitive indexes
303   Graphic3d_TypeOfPrimitiveArray      myPrimType;           //!< primitives type
304   Standard_Integer                    myIndexLower;         //!< index range - first index in myIndices (inclusive)
305   Standard_Integer                    myIndexUpper;         //!< index range - last  index in myIndices (inclusive)
306   Standard_Size                       myPosOffset;          //!< offset to the position vertex attribute
307   Standard_Integer                    myPatchSizeMax;       //!< patch size limit (1 by default)
308   float                               myPatchDistance;      //!< distance between elements in patch
309   bool                                myIs3d;               //!< flag indicating that position attribute has 3 components
310   TopLoc_Location                     myInitLocation;
311   gp_Pnt                              myCDG3D;              //!< Center of the whole triangulation
312   Select3D_BVHIndexBuffer             myBvhIndices;         //!< Indexes of edges or triangles for BVH tree
313   mutable Select3D_BndBox3d           myBndBox;             //!< Bounding box of the whole triangulation
314   gp_GTrsf                            myInvInitLocation;
315   Handle(TColStd_HPackedMapOfInteger) myDetectedElemMap;    //!< index map of last detected elements
316   Handle(TColStd_HPackedMapOfInteger) myDetectedNodeMap;    //!< index map of last detected nodes
317   Standard_Real                       myMinDepthElem;       //!< the depth of nearest detected element
318   Standard_Real                       myMinDepthNode;       //!< the depth of nearest detected node
319   Standard_Real                       myMinDepthEdge;       //!< the depth of nearest detected edge
320   Standard_Integer                    myDetectedElem;       //!< index of last detected element
321   Standard_Integer                    myDetectedNode;       //!< index of last detected node
322   Standard_Integer                    myDetectedEdgeNode1;  //!< index of last detected edge node 1
323   Standard_Integer                    myDetectedEdgeNode2;  //!< index of last detected edge node 2
324   bool                                myToDetectElem;       //!< flag to keep info about last detected element
325   bool                                myToDetectNode;       //!< flag to keep info about last detected node
326   bool                                myToDetectEdge;       //!< flag to keep info about last detected edge
327
328 public:
329
330   DEFINE_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
331
332 };
333
334 DEFINE_STANDARD_HANDLE(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
335
336 #endif // _Select3D_SensitivePrimitiveArray_Header