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