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