1 // Created on: 2016-02-20
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2016 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Select3D_SensitivePrimitiveArray.hxx>
18 #include <OSD_Parallel.hxx>
19 #include <Standard_Atomic.hxx>
21 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
26 //! Auxiliary converter.
27 static inline gp_Pnt vecToPnt (const Graphic3d_Vec3& theVec)
29 return gp_Pnt (theVec.x(), theVec.y(), theVec.z());
32 //! Auxiliary converter.
33 static inline gp_Pnt vecToPnt (const Graphic3d_Vec2& theVec)
35 return gp_Pnt (theVec.x(), theVec.y(), 0.0);
39 //! Auxiliary function to find shared node between two triangles.
40 static inline bool hasSharedNode (const Standard_Integer* theTri1,
41 const Standard_Integer* theTri2)
43 return theTri1[0] == theTri2[0]
44 || theTri1[1] == theTri2[0]
45 || theTri1[2] == theTri2[0]
46 || theTri1[0] == theTri2[1]
47 || theTri1[1] == theTri2[1]
48 || theTri1[2] == theTri2[1]
49 || theTri1[0] == theTri2[2]
50 || theTri1[1] == theTri2[2]
51 || theTri1[2] == theTri2[2];
54 //! Fill in the triangle nodes indices.
55 static inline void getTriIndices (const Handle(Graphic3d_IndexBuffer)& theIndices,
56 const Standard_Integer theIndexOffset,
57 Standard_Integer* theNodes)
59 if (!theIndices.IsNull())
61 theNodes[0] = theIndices->Index (theIndexOffset + 0);
62 theNodes[1] = theIndices->Index (theIndexOffset + 1);
63 theNodes[2] = theIndices->Index (theIndexOffset + 2);
67 theNodes[0] = theIndexOffset + 0;
68 theNodes[1] = theIndexOffset + 1;
69 theNodes[2] = theIndexOffset + 2;
75 //! Functor for initializing groups in parallel threads.
76 struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_InitFunctor
78 Select3D_SensitivePrimitiveArray_InitFunctor (Select3D_SensitivePrimitiveArray& thePrimArray,
79 Standard_Integer theDivStep,
80 Standard_Boolean theToEvalMinMax)
81 : myPrimArray (thePrimArray),
82 myDivStep (theDivStep),
83 myToEvalMinMax (theToEvalMinMax),
84 myToComputeBvh (Standard_True),
86 void operator()(const Standard_Integer& theIndex) const
88 Handle(Select3D_SensitivePrimitiveArray)& anEntity = myPrimArray.myGroups->ChangeValue (theIndex);
89 const Standard_Integer aLower = myPrimArray.myIndexLower + theIndex * myDivStep;
90 const Standard_Integer anUpper = Min (aLower + myDivStep - 1, myPrimArray.myIndexUpper);
91 anEntity = new Select3D_SensitivePrimitiveArray (myPrimArray.myOwnerId);
92 anEntity->SetPatchSizeMax (myPrimArray.myPatchSizeMax);
93 anEntity->SetPatchDistance (myPrimArray.myPatchDistance);
94 anEntity->SetDetectElements (myPrimArray.myToDetectElem);
95 anEntity->SetDetectElementMap (myPrimArray.ToDetectElementMap());
96 anEntity->SetDetectNodes (myPrimArray.myToDetectNode);
97 anEntity->SetDetectNodeMap (myPrimArray.ToDetectNodeMap());
98 anEntity->SetSensitivityFactor(myPrimArray.SensitivityFactor());
99 switch (myPrimArray.myPrimType)
101 case Graphic3d_TOPA_POINTS:
103 if (!anEntity->InitPoints (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
105 Standard_Atomic_Increment (&myNbFailures);
110 case Graphic3d_TOPA_TRIANGLES:
112 if (!anEntity->InitTriangulation (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
114 Standard_Atomic_Increment (&myNbFailures);
121 Standard_Atomic_Increment (&myNbFailures);
131 Standard_Boolean IsDone() const { return myNbFailures == 0; }
133 Select3D_SensitivePrimitiveArray_InitFunctor operator= (Select3D_SensitivePrimitiveArray_InitFunctor& );
135 Select3D_SensitivePrimitiveArray& myPrimArray;
136 Standard_Integer myDivStep;
137 Standard_Boolean myToEvalMinMax;
138 Standard_Boolean myToComputeBvh;
139 mutable volatile Standard_Integer myNbFailures;
142 //! Functor for computing BVH in parallel threads.
143 struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_BVHFunctor
145 Select3D_SensitivePrimitiveArray_BVHFunctor (NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& theGroups) : myGroups (theGroups) {}
146 void operator()(const Standard_Integer& theIndex) const { myGroups.ChangeValue (theIndex)->BVH(); }
148 Select3D_SensitivePrimitiveArray_BVHFunctor operator= (Select3D_SensitivePrimitiveArray_BVHFunctor& );
150 NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& myGroups;
153 // =======================================================================
154 // function : Select3D_SensitivePrimitiveArray
156 // =======================================================================
157 Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle(SelectMgr_EntityOwner)& theOwnerId)
158 : Select3D_SensitiveSet (theOwnerId),
160 myPosStride (Standard_Size(-1)),
161 myPrimType (Graphic3d_TOPA_UNDEFINED),
165 myPatchDistance (ShortRealLast()),
167 myBvhIndices (Graphic3d_Buffer::DefaultAllocator()),
168 myMinDepthElem (RealLast()),
169 myMinDepthNode (RealLast()),
170 myMinDepthEdge (RealLast()),
173 myDetectedEdgeNode1 (-1),
174 myDetectedEdgeNode2 (-1),
175 myToDetectElem (true),
176 myToDetectNode (false),
177 myToDetectEdge (false)
182 // =======================================================================
183 // function : SetDetectElementMap
185 // =======================================================================
186 void Select3D_SensitivePrimitiveArray::SetDetectElementMap (bool theToDetect)
190 myDetectedElemMap.Nullify();
194 if (myDetectedElemMap.IsNull())
196 myDetectedElemMap = new TColStd_HPackedMapOfInteger();
200 myDetectedElemMap->ChangeMap().Clear();
204 // =======================================================================
205 // function : SetDetectNodeMap
207 // =======================================================================
208 void Select3D_SensitivePrimitiveArray::SetDetectNodeMap (bool theToDetect)
212 myDetectedNodeMap.Nullify();
216 if (myDetectedNodeMap.IsNull())
218 myDetectedNodeMap = new TColStd_HPackedMapOfInteger();
222 myDetectedNodeMap->ChangeMap().Clear();
226 // =======================================================================
227 // function : InitTriangulation
229 // =======================================================================
230 bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d_Buffer)& theVerts,
231 const Handle(Graphic3d_IndexBuffer)& theIndices,
232 const TopLoc_Location& theInitLoc,
233 const Standard_Integer theIndexLower,
234 const Standard_Integer theIndexUpper,
235 const bool theToEvalMinMax,
236 const Standard_Integer theNbGroups)
240 myPrimType = Graphic3d_TOPA_TRIANGLES;
247 myPosStride = Standard_Size(-1);
248 myBvhIndices.release();
250 myInitLocation = theInitLoc;
251 myCDG3D.SetCoord (0.0, 0.0, 0.0);
252 if (theVerts.IsNull()
253 || theVerts->NbElements == 0)
258 Standard_Integer aPosAttribIndex = 0;
259 myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
260 if (myPosData == NULL)
265 const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
266 myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
267 || anAttrib.DataType == Graphic3d_TOD_VEC4;
268 if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
274 if (!theIndices.IsNull())
276 if (theIndexLower < 0
277 || theIndexUpper >= theIndices->NbElements
278 || theIndices->NbElements == 0)
285 if (theIndexLower < 0
286 || theIndexUpper >= theVerts->NbElements)
292 Standard_Integer aTriFrom = theIndexLower / 3;
293 Standard_Integer aNbTris = (theIndexUpper - theIndexLower + 1) / 3;
294 const bool hasGroups = (theNbGroups > 1) && (aNbTris / theNbGroups > 10);
299 if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbTris, !hasGroups && myPatchSizeMax > 1))
305 myIndices = theIndices;
306 myIndexLower = theIndexLower;
307 myIndexUpper = theIndexUpper;
308 myInvInitLocation = myInitLocation.Transformation().Inverted();
311 myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
312 const Standard_Integer aDivStep = (aNbTris / theNbGroups) * 3;
313 Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
314 OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
315 if (!anInitFunctor.IsDone())
319 for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
321 Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
322 myBndBox.Combine (anEntity->BoundingBox());
323 myBvhIndices.SetIndex (aGroupIter, aGroupIter);
324 myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
326 myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
329 computeBoundingBox();
334 Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
335 Standard_Integer aTriNodes1[3] = { -1, -1, -1 };
336 Standard_Integer aTriNodes2[3] = { -1, -1, -1 };
337 Standard_Integer* aTriNodesPrev = aTriNodes1;
338 Standard_Integer* aTriNodes = aTriNodes2;
339 Standard_Integer aPatchFrom = 0;
340 Standard_Integer aPatchSize = 0;
341 if (myBvhIndices.HasPatches())
343 myBvhIndices.NbElements = 0;
345 for (Standard_Integer aTriIter = 0; aTriIter < aNbTris; ++aTriIter)
347 const Standard_Integer anIndexOffset = (aTriFrom + aTriIter) * 3;
348 getTriIndices (myIndices, anIndexOffset, aTriNodes);
351 const Graphic3d_Vec3& aNode1 = getPosVec3 (aTriNodes[0]);
352 const Graphic3d_Vec3& aNode2 = getPosVec3 (aTriNodes[1]);
353 const Graphic3d_Vec3& aNode3 = getPosVec3 (aTriNodes[2]);
354 aCenter += (aNode1 + aNode2 + aNode3) / 3.0;
358 const Graphic3d_Vec2& aNode1 = getPosVec2 (aTriNodes[0]);
359 const Graphic3d_Vec2& aNode2 = getPosVec2 (aTriNodes[1]);
360 const Graphic3d_Vec2& aNode3 = getPosVec2 (aTriNodes[2]);
361 aCenter += Graphic3d_Vec3((aNode1 + aNode2 + aNode3) / 3.0);
363 if (myBvhIndices.HasPatches())
365 std::swap (aTriNodes, aTriNodesPrev);
366 if (aPatchSize < myPatchSizeMax
367 && hasSharedNode (aTriNodes, aTriNodesPrev))
374 myBvhIndices.SetIndex (myBvhIndices.NbElements++, aTriFrom + aPatchFrom, aPatchSize);
375 aPatchFrom = aTriIter;
381 myBvhIndices.SetIndex (aTriIter, aTriFrom + aTriIter);
386 myBvhIndices.SetIndex (myBvhIndices.NbElements++, aTriFrom + aPatchFrom, aPatchSize);
388 aCenter /= float(aNbTris);
390 myCDG3D = vecToPnt (aCenter);
393 computeBoundingBox();
398 // =======================================================================
399 // function : InitPoints
401 // =======================================================================
402 bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer)& theVerts,
403 const Handle(Graphic3d_IndexBuffer)& theIndices,
404 const TopLoc_Location& theInitLoc,
405 const Standard_Integer theIndexLower,
406 const Standard_Integer theIndexUpper,
407 const bool theToEvalMinMax,
408 const Standard_Integer theNbGroups)
412 myPrimType = Graphic3d_TOPA_POINTS;
419 myPosStride = Standard_Size(-1);
420 myBvhIndices.release();
422 myInitLocation = theInitLoc;
423 if (theVerts.IsNull()
424 || theVerts->NbElements == 0)
429 Standard_Integer aPosAttribIndex = 0;
430 myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
431 if (myPosData == NULL)
436 const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
437 myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
438 || anAttrib.DataType == Graphic3d_TOD_VEC4;
439 if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
445 if (!theIndices.IsNull())
447 if (theIndexLower < 0
448 || theIndexUpper >= theIndices->NbElements
449 || theIndices->NbElements == 0)
456 if (theIndexLower < 0
457 || theIndexUpper >= theVerts->NbElements)
463 const Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
464 const bool hasGroups = (theNbGroups > 1) && (aNbPoints / theNbGroups > 10);
469 if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbPoints, !hasGroups && myPatchSizeMax > 1))
475 myIndices = theIndices;
476 myIndexLower = theIndexLower;
477 myIndexUpper = theIndexUpper;
478 myInvInitLocation = myInitLocation.Transformation().Inverted();
481 myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
482 const Standard_Integer aDivStep = aNbPoints / theNbGroups;
483 Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
484 OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
485 if (!anInitFunctor.IsDone())
489 for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
491 Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
492 myBndBox.Combine (anEntity->BoundingBox());
493 myBvhIndices.SetIndex (aGroupIter, aGroupIter);
494 myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
496 myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
499 computeBoundingBox();
504 Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
505 Standard_Integer aPatchFrom = 0;
506 Standard_Integer aPatchSize = 0;
507 if (myBvhIndices.HasPatches())
509 myBvhIndices.NbElements = 0;
511 const float aPatchSize2 = myPatchDistance < ShortRealLast()
512 ? myPatchDistance * myPatchDistance
514 const Graphic3d_Vec3* aPnt3dPrev = NULL;
515 const Graphic3d_Vec3* aPnt3d = NULL;
516 const Graphic3d_Vec2* aPnt2dPrev = NULL;
517 const Graphic3d_Vec2* aPnt2d = NULL;
518 for (Standard_Integer aPointIter = 0; aPointIter < aNbPoints; ++aPointIter)
520 const Standard_Integer anIndexOffset = (theIndexLower + aPointIter);
521 const Standard_Integer aPointIndex = !myIndices.IsNull()
522 ? myIndices->Index (anIndexOffset)
526 aPnt3d = &getPosVec3 (aPointIndex);
531 aPnt2d = &getPosVec2 (aPointIndex);
532 aCenter += Graphic3d_Vec3(*aPnt2d);
535 if (myBvhIndices.HasPatches())
539 std::swap (aPnt3d, aPnt3dPrev);
540 if (aPatchSize < myPatchSizeMax
542 && (*aPnt3dPrev - *aPnt3d).SquareModulus() < aPatchSize2)
550 std::swap (aPnt2d, aPnt2dPrev);
551 if (aPatchSize < myPatchSizeMax
553 && (*aPnt2dPrev - *aPnt2d).SquareModulus() < aPatchSize2)
560 myBvhIndices.SetIndex (myBvhIndices.NbElements++, theIndexLower + aPatchFrom,
561 aPatchSize != 0 ? aPatchSize : 1);
562 aPatchFrom = aPointIter;
567 myBvhIndices.SetIndex (aPointIter, theIndexLower + aPointIter);
572 myBvhIndices.SetIndex (myBvhIndices.NbElements++, theIndexLower + aPatchFrom, aPatchSize);
574 aCenter /= float(aNbPoints);
576 myCDG3D = vecToPnt (aCenter);
579 computeBoundingBox();
584 // =======================================================================
585 // function : GetConnected
587 // =======================================================================
588 Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected()
590 Handle(Select3D_SensitivePrimitiveArray) aNewEntity = new Select3D_SensitivePrimitiveArray (myOwnerId);
593 case Graphic3d_TOPA_POINTS:
595 aNewEntity->InitPoints (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
598 case Graphic3d_TOPA_TRIANGLES:
600 aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
608 //=======================================================================
611 //=======================================================================
612 void Select3D_SensitivePrimitiveArray::Set (const Handle(SelectMgr_EntityOwner)& theOwnerId)
614 base_type::Set (theOwnerId);
615 if (!myGroups.IsNull())
617 for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
619 aGroupIter.Value()->Set (theOwnerId);
624 // =======================================================================
627 // =======================================================================
628 void Select3D_SensitivePrimitiveArray::BVH()
630 if (!myContent.IsDirty())
636 if (myGroups.IsNull())
641 Standard_Integer aNbToUpdate = 0;
642 for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
644 if (aGroupIter.Value()->myContent.IsDirty())
652 Select3D_SensitivePrimitiveArray_BVHFunctor aFunctor (*myGroups);
653 OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, aFunctor, aNbToUpdate <= 1);
657 // =======================================================================
660 // =======================================================================
661 Standard_Integer Select3D_SensitivePrimitiveArray::Size() const
663 return myBvhIndices.NbElements;
666 // =======================================================================
669 // =======================================================================
670 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer theIdx) const
672 const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
673 const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theIdx);
674 if (!myGroups.IsNull())
676 return myGroups->Value (anElemIdx)->BoundingBox();
679 Select3D_BndBox3d aBox;
682 case Graphic3d_TOPA_POINTS:
684 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
686 const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
687 const Standard_Integer aPointIndex = !myIndices.IsNull()
688 ? myIndices->Index (anIndexOffset)
692 const Graphic3d_Vec3& aPoint = getPosVec3 (aPointIndex);
693 aBox.Add (SelectMgr_Vec3 (aPoint.x(), aPoint.y(), aPoint.z()));
697 const Graphic3d_Vec2& aPoint = getPosVec2 (aPointIndex);
698 aBox.Add (SelectMgr_Vec3 (aPoint.x(), aPoint.y(), 0.0));
703 case Graphic3d_TOPA_TRIANGLES:
705 Standard_Integer aTriNodes[3];
708 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
710 const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
711 getTriIndices (myIndices, anIndexOffset, aTriNodes);
712 const Graphic3d_Vec3& aNode1 = getPosVec3 (aTriNodes[0]);
713 const Graphic3d_Vec3& aNode2 = getPosVec3 (aTriNodes[1]);
714 const Graphic3d_Vec3& aNode3 = getPosVec3 (aTriNodes[2]);
715 Graphic3d_Vec3 aMinPnt = (aNode1.cwiseMin (aNode2)).cwiseMin (aNode3);
716 Graphic3d_Vec3 aMaxPnt = (aNode1.cwiseMax (aNode2)).cwiseMax (aNode3);
717 aBox.Add (SelectMgr_Vec3 (aMinPnt.x(), aMinPnt.y(), aMinPnt.z()));
718 aBox.Add (SelectMgr_Vec3 (aMaxPnt.x(), aMaxPnt.y(), aMaxPnt.z()));
723 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
725 const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
726 getTriIndices (myIndices, anIndexOffset, aTriNodes);
727 const Graphic3d_Vec2& aNode1 = getPosVec2 (aTriNodes[0]);
728 const Graphic3d_Vec2& aNode2 = getPosVec2 (aTriNodes[1]);
729 const Graphic3d_Vec2& aNode3 = getPosVec2 (aTriNodes[2]);
730 Graphic3d_Vec2 aMinPnt = (aNode1.cwiseMin (aNode2)).cwiseMin (aNode3);
731 Graphic3d_Vec2 aMaxPnt = (aNode1.cwiseMax (aNode2)).cwiseMax (aNode3);
732 aBox.Add (SelectMgr_Vec3 (aMinPnt.x(), aMinPnt.y(), 0.0));
733 aBox.Add (SelectMgr_Vec3 (aMaxPnt.x(), aMaxPnt.y(), 0.0));
746 // =======================================================================
749 // =======================================================================
750 Standard_Real Select3D_SensitivePrimitiveArray::Center (const Standard_Integer theIdx,
751 const Standard_Integer theAxis) const
753 if (!myGroups.IsNull())
755 const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
756 const gp_Pnt aCenter = myGroups->Value (anElemIdx)->CenterOfGeometry();
757 return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
760 const Select3D_BndBox3d& aBox = Box (theIdx);
761 SelectMgr_Vec3 aCenter = (aBox.CornerMin() + aBox.CornerMax()) * 0.5;
762 return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
765 // =======================================================================
768 // =======================================================================
769 void Select3D_SensitivePrimitiveArray::Swap (const Standard_Integer theIdx1,
770 const Standard_Integer theIdx2)
772 Standard_Integer anElemIdx1 = myBvhIndices.Index (theIdx1);
773 Standard_Integer anElemIdx2 = myBvhIndices.Index (theIdx2);
774 if (myBvhIndices.HasPatches())
776 Standard_Integer aPatchSize1 = myBvhIndices.PatchSize (theIdx1);
777 Standard_Integer aPatchSize2 = myBvhIndices.PatchSize (theIdx2);
778 myBvhIndices.SetIndex (theIdx1, anElemIdx2, aPatchSize2);
779 myBvhIndices.SetIndex (theIdx2, anElemIdx1, aPatchSize1);
783 myBvhIndices.SetIndex (theIdx1, anElemIdx2);
784 myBvhIndices.SetIndex (theIdx2, anElemIdx1);
788 // =======================================================================
789 // function : BoundingBox
791 // =======================================================================
792 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::BoundingBox()
794 if (!myBndBox.IsValid())
796 computeBoundingBox();
798 return applyTransformation();
801 // =======================================================================
802 // function : computeBoundingBox
804 // =======================================================================
805 void Select3D_SensitivePrimitiveArray::computeBoundingBox()
808 if (!myGroups.IsNull())
810 for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
812 myBndBox.Combine (aGroupIter.Value()->BoundingBox());
817 if (myVerts.IsNull())
822 const Standard_Integer aNbVerts = myVerts->NbElements;
825 for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
827 const Graphic3d_Vec3& aVert = getPosVec3 (aVertIter);
828 myBndBox.Add (SelectMgr_Vec3 (aVert.x(), aVert.y(), aVert.z()));
833 for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
835 const Graphic3d_Vec2& aVert = getPosVec2 (aVertIter);
836 myBndBox.Add (SelectMgr_Vec3 (aVert.x(), aVert.y(), 0.0));
841 // =======================================================================
842 // function : applyTransformation
844 // =======================================================================
845 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::applyTransformation()
847 if (!HasInitLocation())
852 Select3D_BndBox3d aBndBox;
853 for (Standard_Integer aX = 0; aX <=1; ++aX)
855 for (Standard_Integer aY = 0; aY <=1; ++aY)
857 for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
859 gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
860 aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
861 aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
862 aVertex.Transform (myInitLocation.Transformation());
863 aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
870 // =======================================================================
871 // function : Matches
873 // =======================================================================
874 Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_SelectingVolumeManager& theMgr,
875 SelectBasics_PickResult& thePickResult)
877 if (!myDetectedElemMap.IsNull())
879 myDetectedElemMap->ChangeMap().Clear();
881 if (!myDetectedNodeMap.IsNull())
883 myDetectedNodeMap->ChangeMap().Clear();
885 myMinDepthElem = RealLast();
886 myMinDepthNode = RealLast();
887 myMinDepthEdge = RealLast();
890 myDetectedEdgeNode1 = -1;
891 myDetectedEdgeNode2 = -1;
892 const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull();
893 if (myGroups.IsNull()
894 || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point
897 if (!matches (theMgr, thePickResult, toDetectRange))
899 return Standard_False;
902 if (!myGroups.IsNull() && myDetectedIdx != -1)
904 const Standard_Integer anIndex = myBvhIndices.Index (myDetectedIdx);
905 const Handle(Select3D_SensitivePrimitiveArray)& aLastGroup = myGroups->Value (anIndex);
906 myMinDepthElem = aLastGroup->myMinDepthElem;
907 myMinDepthNode = aLastGroup->myMinDepthNode;
908 myMinDepthEdge = aLastGroup->myMinDepthEdge;
909 myDetectedElem = aLastGroup->myDetectedElem;
910 myDetectedNode = aLastGroup->myDetectedNode;
911 myDetectedEdgeNode1 = aLastGroup->myDetectedEdgeNode1;
912 myDetectedEdgeNode2 = aLastGroup->myDetectedEdgeNode2;
914 return Standard_True;
917 SelectBasics_PickResult aPickResult;
918 bool hasResults = false;
919 for (Standard_Integer aGroupIter = 0; aGroupIter < myBvhIndices.NbElements; ++aGroupIter)
921 const Standard_Integer anElemIdx = myBvhIndices.Index (aGroupIter);
922 Handle(Select3D_SensitivePrimitiveArray)& aChild = myGroups->ChangeValue (anElemIdx);
923 if (aChild->Matches (theMgr, aPickResult))
926 if (!myDetectedElemMap.IsNull())
928 myDetectedElemMap->ChangeMap().Unite (aChild->myDetectedElemMap->Map());
930 if (!myDetectedNodeMap.IsNull())
932 myDetectedNodeMap->ChangeMap().Unite (aChild->myDetectedNodeMap->Map());
934 if (thePickResult.Depth() > aPickResult.Depth())
936 myDetectedIdx = aGroupIter;
937 thePickResult = aPickResult;
943 return Standard_False;
945 thePickResult.SetDistToGeomCenter(theMgr.DistToGeometryCenter(CenterOfGeometry()));
946 return Standard_True;
949 // =======================================================================
950 // function : overlapsElement
952 // =======================================================================
953 Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics_PickResult& thePickResult,
954 SelectBasics_SelectingVolumeManager& theMgr,
955 Standard_Integer theElemIdx,
956 Standard_Boolean theIsFullInside)
958 const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
959 if (!myGroups.IsNull())
961 return myGroups->Value (anElemIdx)->Matches (theMgr, thePickResult);
964 const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
965 Select3D_BndBox3d aBox;
966 Standard_Boolean aResult = Standard_False;
967 SelectBasics_PickResult aPickResult;
970 case Graphic3d_TOPA_POINTS:
972 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
974 const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
975 const Standard_Integer aPointIndex = !myIndices.IsNull()
976 ? myIndices->Index (anIndexOffset)
981 aPoint = vecToPnt (getPosVec3 (aPointIndex));
985 aPoint = vecToPnt (getPosVec2 (aPointIndex));
991 if (theIsFullInside || theMgr.Overlaps (aPoint, aPickResult))
993 if (aPickResult.Depth() <= myMinDepthNode)
995 myDetectedElem = myDetectedNode = aPointIndex;
996 myMinDepthElem = myMinDepthNode = aPickResult.Depth();
998 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1000 if (!myDetectedElemMap.IsNull())
1002 myDetectedElemMap->ChangeMap().Add (aPointIndex);
1004 if (!myDetectedNodeMap.IsNull())
1006 myDetectedNodeMap->ChangeMap().Add (aPointIndex);
1009 aResult = Standard_True;
1012 thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
1016 case Graphic3d_TOPA_TRIANGLES:
1018 Graphic3d_Vec3i aTriNodes;
1019 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1021 const Standard_Integer aTriIndex = anElemIdx + anElemIter;
1022 const Standard_Integer anIndexOffset = aTriIndex * 3;
1023 getTriIndices (myIndices, anIndexOffset, aTriNodes);
1027 aPnts[0] = vecToPnt (getPosVec3 (aTriNodes[0]));
1028 aPnts[1] = vecToPnt (getPosVec3 (aTriNodes[1]));
1029 aPnts[2] = vecToPnt (getPosVec3 (aTriNodes[2]));
1033 aPnts[0] = vecToPnt (getPosVec2 (aTriNodes[0]));
1034 aPnts[1] = vecToPnt (getPosVec2 (aTriNodes[1]));
1035 aPnts[2] = vecToPnt (getPosVec2 (aTriNodes[2]));
1040 if (theIsFullInside || theMgr.Overlaps (aPnts[0], aPnts[1], aPnts[2], Select3D_TOS_INTERIOR, aPickResult))
1042 if (aPickResult.Depth() <= myMinDepthElem)
1044 myDetectedElem = aTriIndex;
1045 myMinDepthElem = aPickResult.Depth();
1047 aResult = Standard_True;
1048 if (!myDetectedElemMap.IsNull()
1049 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1051 myDetectedElemMap->ChangeMap().Add(aTriIndex);
1057 for (int aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
1059 if (theIsFullInside || theMgr.Overlaps (aPnts[aNodeIter], aPickResult))
1061 if (aPickResult.Depth() <= myMinDepthNode)
1063 myDetectedNode = aTriNodes[aNodeIter];
1064 myMinDepthNode = aPickResult.Depth();
1066 if (!myDetectedNodeMap.IsNull()
1067 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1069 myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
1071 aResult = Standard_True;
1077 for (int aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
1079 int aNode1 = aNodeIter == 0 ? 2 : (aNodeIter - 1);
1080 int aNode2 = aNodeIter;
1081 if (theIsFullInside || theMgr.Overlaps (aPnts[aNode1], aPnts[aNode2], aPickResult))
1083 if (aPickResult.Depth() <= myMinDepthEdge)
1085 myDetectedEdgeNode1 = aTriNodes[aNode1];
1086 myDetectedEdgeNode2 = aTriNodes[aNode2];
1087 myMinDepthEdge = aPickResult.Depth();
1089 aResult = Standard_True;
1093 thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
1099 return Standard_False;
1106 // =======================================================================
1107 // function : distanceToCOG
1109 // =======================================================================
1110 Standard_Real Select3D_SensitivePrimitiveArray::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
1112 return theMgr.DistToGeometryCenter (myCDG3D);
1115 // =======================================================================
1116 // function : elementIsInside
1118 // =======================================================================
1119 Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
1120 Standard_Integer theElemIdx,
1121 Standard_Boolean theIsFullInside)
1123 const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
1124 if (!myGroups.IsNull())
1126 SelectBasics_PickResult aDummy;
1127 return myGroups->Value (anElemIdx)->Matches (theMgr, aDummy);
1130 const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
1133 case Graphic3d_TOPA_POINTS:
1135 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1137 const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
1138 const Standard_Integer aPointIndex = !myIndices.IsNull()
1139 ? myIndices->Index (anIndexOffset)
1144 aPoint = vecToPnt (getPosVec3 (aPointIndex));
1148 aPoint = vecToPnt (getPosVec2 (aPointIndex));
1150 if (!theIsFullInside && !theMgr.Overlaps (aPoint))
1152 return Standard_False;
1155 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1157 if (!myDetectedElemMap.IsNull())
1159 myDetectedElemMap->ChangeMap().Add (aPointIndex);
1161 if (!myDetectedNodeMap.IsNull())
1163 myDetectedNodeMap->ChangeMap().Add (aPointIndex);
1167 return Standard_True;
1169 case Graphic3d_TOPA_TRIANGLES:
1171 Graphic3d_Vec3i aTriNodes;
1172 for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1174 const Standard_Integer aTriIndex = anElemIdx + anElemIter;
1175 const Standard_Integer anIndexOffset = aTriIndex * 3;
1176 getTriIndices (myIndices, anIndexOffset, aTriNodes);
1180 aPnts[0] = vecToPnt (getPosVec3 (aTriNodes[0]));
1181 aPnts[1] = vecToPnt (getPosVec3 (aTriNodes[1]));
1182 aPnts[2] = vecToPnt (getPosVec3 (aTriNodes[2]));
1186 aPnts[0] = vecToPnt (getPosVec2 (aTriNodes[0]));
1187 aPnts[1] = vecToPnt (getPosVec2 (aTriNodes[1]));
1188 aPnts[2] = vecToPnt (getPosVec2 (aTriNodes[2]));
1191 if (!theIsFullInside && ( !theMgr.Overlaps (aPnts[0])
1192 || !theMgr.Overlaps (aPnts[1])
1193 || !theMgr.Overlaps (aPnts[2])))
1195 return Standard_False;
1198 if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1200 if (!myDetectedElemMap.IsNull())
1202 myDetectedElemMap->ChangeMap().Add (aTriIndex);
1204 if (!myDetectedNodeMap.IsNull())
1206 myDetectedNodeMap->ChangeMap().Add (aTriNodes[0]);
1207 myDetectedNodeMap->ChangeMap().Add (aTriNodes[1]);
1208 myDetectedNodeMap->ChangeMap().Add (aTriNodes[2]);
1212 return Standard_True;
1216 return Standard_False;
1221 // =======================================================================
1222 // function : DumpJson
1224 // =======================================================================
1225 void Select3D_SensitivePrimitiveArray::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1227 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1228 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveSet)
1230 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPosStride)
1231 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPrimType)
1232 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexLower)
1233 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexUpper)
1234 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPatchSizeMax)
1235 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPatchDistance)
1236 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIs3d)
1237 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myInitLocation)
1238 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)
1240 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthElem)
1241 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthNode)
1242 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthEdge)
1244 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedElem)
1245 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedNode)
1246 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedEdgeNode1)
1247 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedEdgeNode2)
1248 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectElem)
1249 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectNode)
1250 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectEdge)