0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / Select3D / Select3D_SensitivePrimitiveArray.cxx
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 #include <Select3D_SensitivePrimitiveArray.hxx>
17
18 #include <NCollection_AlignedAllocator.hxx>
19 #include <OSD_Parallel.hxx>
20 #include <Standard_Atomic.hxx>
21
22 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet)
23
24 namespace
25 {
26
27   //! Auxiliary converter.
28   static inline gp_Pnt vecToPnt (const Graphic3d_Vec3& theVec)
29   {
30     return gp_Pnt (theVec.x(), theVec.y(), theVec.z());
31   }
32
33   //! Auxiliary converter.
34   static inline gp_Pnt vecToPnt (const Graphic3d_Vec2& theVec)
35   {
36     return gp_Pnt (theVec.x(), theVec.y(), 0.0);
37   }
38
39
40   //! Auxiliary function to find shared node between two triangles.
41   static inline bool hasSharedNode (const Standard_Integer* theTri1,
42                                     const Standard_Integer* theTri2)
43   {
44     return theTri1[0] == theTri2[0]
45         || theTri1[1] == theTri2[0]
46         || theTri1[2] == theTri2[0]
47         || theTri1[0] == theTri2[1]
48         || theTri1[1] == theTri2[1]
49         || theTri1[2] == theTri2[1]
50         || theTri1[0] == theTri2[2]
51         || theTri1[1] == theTri2[2]
52         || theTri1[2] == theTri2[2];
53   }
54
55   //! Fill in the triangle nodes indices.
56   static inline void getTriIndices (const Handle(Graphic3d_IndexBuffer)& theIndices,
57                                     const Standard_Integer theIndexOffset,
58                                     Standard_Integer* theNodes)
59   {
60     if (!theIndices.IsNull())
61     {
62       theNodes[0] = theIndices->Index (theIndexOffset + 0);
63       theNodes[1] = theIndices->Index (theIndexOffset + 1);
64       theNodes[2] = theIndices->Index (theIndexOffset + 2);
65     }
66     else
67     {
68       theNodes[0] = theIndexOffset + 0;
69       theNodes[1] = theIndexOffset + 1;
70       theNodes[2] = theIndexOffset + 2;
71     }
72   }
73
74 }
75
76 //! Functor for initializing groups in parallel threads.
77 struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_InitFunctor
78 {
79   Select3D_SensitivePrimitiveArray_InitFunctor (Select3D_SensitivePrimitiveArray& thePrimArray,
80                                                 Standard_Integer theDivStep,
81                                                 Standard_Boolean theToEvalMinMax)
82   : myPrimArray (thePrimArray),
83     myDivStep (theDivStep),
84     myToEvalMinMax (theToEvalMinMax),
85     myToComputeBvh (Standard_True),
86     myNbFailures (0) {}
87   void operator()(const Standard_Integer& theIndex) const
88   {
89     Handle(Select3D_SensitivePrimitiveArray)& anEntity = myPrimArray.myGroups->ChangeValue (theIndex);
90     const Standard_Integer aLower  = myPrimArray.myIndexLower + theIndex * myDivStep;
91     const Standard_Integer anUpper = Min (aLower + myDivStep - 1, myPrimArray.myIndexUpper);
92     anEntity = new Select3D_SensitivePrimitiveArray (myPrimArray.myOwnerId);
93     anEntity->SetPatchSizeMax     (myPrimArray.myPatchSizeMax);
94     anEntity->SetPatchDistance    (myPrimArray.myPatchDistance);
95     anEntity->SetDetectElements   (myPrimArray.myToDetectElem);
96     anEntity->SetDetectElementMap (myPrimArray.ToDetectElementMap());
97     anEntity->SetDetectNodes      (myPrimArray.myToDetectNode);
98     anEntity->SetDetectNodeMap    (myPrimArray.ToDetectNodeMap());
99     anEntity->SetSensitivityFactor(myPrimArray.SensitivityFactor());
100     switch (myPrimArray.myPrimType)
101     {
102       case Graphic3d_TOPA_POINTS:
103       {
104         if (!anEntity->InitPoints (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
105         {
106           Standard_Atomic_Increment (&myNbFailures);
107           return;
108         }
109         break;
110       }
111       case Graphic3d_TOPA_TRIANGLES:
112       {
113         if (!anEntity->InitTriangulation (myPrimArray.myVerts, myPrimArray.myIndices, myPrimArray.myInitLocation, aLower, anUpper, myToEvalMinMax, 1))
114         {
115           Standard_Atomic_Increment (&myNbFailures);
116           return;
117         }
118         break;
119       }
120       default:
121       {
122         Standard_Atomic_Increment (&myNbFailures);
123         return;
124       }
125     }
126
127     if (myToComputeBvh)
128     {
129       anEntity->BVH();
130     }
131   }
132   Standard_Boolean IsDone() const { return myNbFailures == 0; }
133 private:
134   Select3D_SensitivePrimitiveArray_InitFunctor operator= (Select3D_SensitivePrimitiveArray_InitFunctor& );
135 private:
136   Select3D_SensitivePrimitiveArray& myPrimArray;
137   Standard_Integer                  myDivStep;
138   Standard_Boolean                  myToEvalMinMax;
139   Standard_Boolean                  myToComputeBvh;
140   mutable volatile Standard_Integer myNbFailures;
141 };
142
143 //! Functor for computing BVH in parallel threads.
144 struct Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray_BVHFunctor
145 {
146   Select3D_SensitivePrimitiveArray_BVHFunctor (NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& theGroups) : myGroups (theGroups) {}
147   void operator()(const Standard_Integer& theIndex) const { myGroups.ChangeValue (theIndex)->BVH(); }
148 private:
149   Select3D_SensitivePrimitiveArray_BVHFunctor operator= (Select3D_SensitivePrimitiveArray_BVHFunctor& );
150 private:
151   NCollection_Array1<Handle(Select3D_SensitivePrimitiveArray)>& myGroups;
152 };
153
154 // =======================================================================
155 // function : Select3D_SensitivePrimitiveArray
156 // purpose  :
157 // =======================================================================
158 Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle(SelectMgr_EntityOwner)& theOwnerId)
159 : Select3D_SensitiveSet (theOwnerId),
160   myPosData (NULL),
161   myPosStride (Standard_Size(-1)),
162   myPrimType (Graphic3d_TOPA_UNDEFINED),
163   myIndexLower (0),
164   myIndexUpper (0),
165   myPatchSizeMax (1),
166   myPatchDistance (ShortRealLast()),
167   myIs3d (false),
168   myBvhIndices (new NCollection_AlignedAllocator(16)),
169   myMinDepthElem (RealLast()),
170   myMinDepthNode (RealLast()),
171   myMinDepthEdge (RealLast()),
172   myDetectedElem (-1),
173   myDetectedNode (-1),
174   myDetectedEdgeNode1 (-1),
175   myDetectedEdgeNode2 (-1),
176   myToDetectElem (true),
177   myToDetectNode (false),
178   myToDetectEdge (false)
179 {
180   //
181 }
182
183 // =======================================================================
184 // function : SetDetectElementMap
185 // purpose  :
186 // =======================================================================
187 void Select3D_SensitivePrimitiveArray::SetDetectElementMap (bool theToDetect)
188 {
189   if (!theToDetect)
190   {
191     myDetectedElemMap.Nullify();
192     return;
193   }
194
195   if (myDetectedElemMap.IsNull())
196   {
197     myDetectedElemMap = new TColStd_HPackedMapOfInteger();
198   }
199   else
200   {
201     myDetectedElemMap->ChangeMap().Clear();
202   }
203 }
204
205 // =======================================================================
206 // function : SetDetectNodeMap
207 // purpose  :
208 // =======================================================================
209 void Select3D_SensitivePrimitiveArray::SetDetectNodeMap (bool theToDetect)
210 {
211   if (!theToDetect)
212   {
213     myDetectedNodeMap.Nullify();
214     return;
215   }
216
217   if (myDetectedNodeMap.IsNull())
218   {
219     myDetectedNodeMap = new TColStd_HPackedMapOfInteger();
220   }
221   else
222   {
223     myDetectedNodeMap->ChangeMap().Clear();
224   }
225 }
226
227 // =======================================================================
228 // function : InitTriangulation
229 // purpose  :
230 // =======================================================================
231 bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d_Buffer)&      theVerts,
232                                                           const Handle(Graphic3d_IndexBuffer)& theIndices,
233                                                           const TopLoc_Location&               theInitLoc,
234                                                           const Standard_Integer               theIndexLower,
235                                                           const Standard_Integer               theIndexUpper,
236                                                           const bool                           theToEvalMinMax,
237                                                           const Standard_Integer               theNbGroups)
238 {
239   MarkDirty();
240   myGroups.Nullify();
241   myPrimType = Graphic3d_TOPA_TRIANGLES;
242   myBndBox.Clear();
243   myVerts.Nullify();
244   myIndices.Nullify();
245   myIndexLower = 0;
246   myIndexUpper = 0;
247   myPosData = NULL;
248   myPosStride = Standard_Size(-1);
249   myBvhIndices.release();
250   myIs3d = false;
251   myInitLocation = theInitLoc;
252   myCDG3D.SetCoord (0.0, 0.0, 0.0);
253   if (theVerts.IsNull()
254    || theVerts->NbElements == 0)
255   {
256     return false;
257   }
258
259   Standard_Integer aPosAttribIndex = 0;
260   myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
261   if (myPosData == NULL)
262   {
263     return false;
264   }
265
266   const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
267   myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
268         || anAttrib.DataType == Graphic3d_TOD_VEC4;
269   if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
270   {
271     myPosData = NULL;
272     return false;
273   }
274
275   if (!theIndices.IsNull())
276   {
277     if (theIndexLower < 0
278      || theIndexUpper >= theIndices->NbElements
279      || theIndices->NbElements == 0)
280     {
281       return false;
282     }
283   }
284   else
285   {
286     if (theIndexLower < 0
287      || theIndexUpper >= theVerts->NbElements)
288     {
289       return false;
290     }
291   }
292
293   Standard_Integer aTriFrom = theIndexLower / 3;
294   Standard_Integer aNbTris  = (theIndexUpper - theIndexLower + 1) / 3;
295   const bool hasGroups = (theNbGroups > 1) && (aNbTris / theNbGroups > 10);
296   if (aNbTris < 1)
297   {
298     return false;
299   }
300   if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbTris, !hasGroups && myPatchSizeMax > 1))
301   {
302     return false;
303   }
304
305   myVerts      = theVerts;
306   myIndices    = theIndices;
307   myIndexLower = theIndexLower;
308   myIndexUpper = theIndexUpper;
309   myInvInitLocation = myInitLocation.Transformation().Inverted();
310   if (hasGroups)
311   {
312     myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
313     const Standard_Integer aDivStep = (aNbTris / theNbGroups) * 3;
314     Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
315     OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
316     if (!anInitFunctor.IsDone())
317     {
318       return false;
319     }
320     for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
321     {
322       Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
323       myBndBox.Combine (anEntity->BoundingBox());
324       myBvhIndices.SetIndex (aGroupIter, aGroupIter);
325       myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
326     }
327     myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
328     if (theToEvalMinMax)
329     {
330       computeBoundingBox();
331     }
332     return true;
333   }
334
335   Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
336   Standard_Integer  aTriNodes1[3] = { -1, -1, -1 };
337   Standard_Integer  aTriNodes2[3] = { -1, -1, -1 };
338   Standard_Integer* aTriNodesPrev = aTriNodes1;
339   Standard_Integer* aTriNodes     = aTriNodes2;
340   Standard_Integer  aPatchFrom    = 0;
341   Standard_Integer  aPatchSize    = 0;
342   if (myBvhIndices.HasPatches())
343   {
344     myBvhIndices.NbElements = 0;
345   }
346   for (Standard_Integer aTriIter = 0; aTriIter < aNbTris; ++aTriIter)
347   {
348     const Standard_Integer anIndexOffset = (aTriFrom + aTriIter) * 3;
349     getTriIndices (myIndices, anIndexOffset, aTriNodes);
350     if (myIs3d)
351     {
352       const Graphic3d_Vec3& aNode1 = getPosVec3 (aTriNodes[0]);
353       const Graphic3d_Vec3& aNode2 = getPosVec3 (aTriNodes[1]);
354       const Graphic3d_Vec3& aNode3 = getPosVec3 (aTriNodes[2]);
355       aCenter += (aNode1 + aNode2 + aNode3) / 3.0;
356     }
357     else
358     {
359       const Graphic3d_Vec2& aNode1 = getPosVec2 (aTriNodes[0]);
360       const Graphic3d_Vec2& aNode2 = getPosVec2 (aTriNodes[1]);
361       const Graphic3d_Vec2& aNode3 = getPosVec2 (aTriNodes[2]);
362       aCenter += Graphic3d_Vec3((aNode1 + aNode2 + aNode3) / 3.0);
363     }
364     if (myBvhIndices.HasPatches())
365     {
366       std::swap (aTriNodes, aTriNodesPrev);
367       if (aPatchSize < myPatchSizeMax
368        && hasSharedNode (aTriNodes, aTriNodesPrev))
369       {
370         ++aPatchSize;
371         continue;
372       }
373       else
374       {
375         myBvhIndices.SetIndex (myBvhIndices.NbElements++, aTriFrom + aPatchFrom, aPatchSize);
376         aPatchFrom = aTriIter;
377         aPatchSize = 0;
378       }
379     }
380     else
381     {
382       myBvhIndices.SetIndex (aTriIter, aTriFrom + aTriIter);
383     }
384   }
385   if (aPatchSize != 0)
386   {
387     myBvhIndices.SetIndex (myBvhIndices.NbElements++, aTriFrom + aPatchFrom, aPatchSize);
388   }
389   aCenter /= float(aNbTris);
390
391   myCDG3D = vecToPnt (aCenter);
392   if (theToEvalMinMax)
393   {
394     computeBoundingBox();
395   }
396   return true;
397 }
398
399 // =======================================================================
400 // function : InitPoints
401 // purpose  :
402 // =======================================================================
403 bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer)&      theVerts,
404                                                    const Handle(Graphic3d_IndexBuffer)& theIndices,
405                                                    const TopLoc_Location&               theInitLoc,
406                                                    const Standard_Integer               theIndexLower,
407                                                    const Standard_Integer               theIndexUpper,
408                                                    const bool                           theToEvalMinMax,
409                                                    const Standard_Integer               theNbGroups)
410 {
411   MarkDirty();
412   myGroups.Nullify();
413   myPrimType = Graphic3d_TOPA_POINTS;
414   myBndBox.Clear();
415   myVerts.Nullify();
416   myIndices.Nullify();
417   myIndexLower = 0;
418   myIndexUpper = 0;
419   myPosData = NULL;
420   myPosStride = Standard_Size(-1);
421   myBvhIndices.release();
422   myIs3d = false;
423   myInitLocation = theInitLoc;
424   if (theVerts.IsNull()
425    || theVerts->NbElements == 0)
426   {
427     return false;
428   }
429
430   Standard_Integer aPosAttribIndex = 0;
431   myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
432   if (myPosData == NULL)
433   {
434     return false;
435   }
436
437   const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
438   myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
439         || anAttrib.DataType == Graphic3d_TOD_VEC4;
440   if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
441   {
442     myPosData = NULL;
443     return false;
444   }
445
446   if (!theIndices.IsNull())
447   {
448     if (theIndexLower < 0
449      || theIndexUpper >= theIndices->NbElements
450      || theIndices->NbElements == 0)
451     {
452       return false;
453     }
454   }
455   else
456   {
457     if (theIndexLower < 0
458      || theIndexUpper >= theVerts->NbElements)
459     {
460       return false;
461     }
462   }
463
464   const Standard_Integer aNbPoints = theIndexUpper - theIndexLower + 1;
465   const bool hasGroups = (theNbGroups > 1) && (aNbPoints / theNbGroups > 10);
466   if (aNbPoints < 1)
467   {
468     return false;
469   }
470   if (!myBvhIndices.Init (hasGroups ? theNbGroups : aNbPoints, !hasGroups && myPatchSizeMax > 1))
471   {
472     return false;
473   }
474
475   myVerts      = theVerts;
476   myIndices    = theIndices;
477   myIndexLower = theIndexLower;
478   myIndexUpper = theIndexUpper;
479   myInvInitLocation = myInitLocation.Transformation().Inverted();
480   if (hasGroups)
481   {
482     myGroups = new Select3D_PrimArraySubGroupArray (0, theNbGroups - 1);
483     const Standard_Integer aDivStep = aNbPoints / theNbGroups;
484     Select3D_SensitivePrimitiveArray_InitFunctor anInitFunctor (*this, aDivStep, theToEvalMinMax);
485     OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, anInitFunctor);
486     if (!anInitFunctor.IsDone())
487     {
488       return false;
489     }
490     for (Standard_Integer aGroupIter = 0; aGroupIter < theNbGroups; ++aGroupIter)
491     {
492       Handle(Select3D_SensitivePrimitiveArray)& anEntity = myGroups->ChangeValue (aGroupIter);
493       myBndBox.Combine (anEntity->BoundingBox());
494       myBvhIndices.SetIndex (aGroupIter, aGroupIter);
495       myCDG3D.ChangeCoord() += anEntity->CenterOfGeometry().XYZ();
496     }
497     myCDG3D.ChangeCoord().Divide (static_cast<Standard_Real> (myGroups->Size()));
498     if (theToEvalMinMax)
499     {
500       computeBoundingBox();
501     }
502     return true;
503   }
504
505   Graphic3d_Vec3 aCenter (0.0f, 0.0f, 0.0f);
506   Standard_Integer aPatchFrom = 0;
507   Standard_Integer aPatchSize = 0;
508   if (myBvhIndices.HasPatches())
509   {
510     myBvhIndices.NbElements = 0;
511   }
512   const float aPatchSize2 = myPatchDistance < ShortRealLast()
513                           ? myPatchDistance * myPatchDistance
514                           : myPatchDistance;
515   const Graphic3d_Vec3* aPnt3dPrev = NULL;
516   const Graphic3d_Vec3* aPnt3d     = NULL;
517   const Graphic3d_Vec2* aPnt2dPrev = NULL;
518   const Graphic3d_Vec2* aPnt2d     = NULL;
519   for (Standard_Integer aPointIter = 0; aPointIter < aNbPoints; ++aPointIter)
520   {
521     const Standard_Integer anIndexOffset = (theIndexLower + aPointIter);
522     const Standard_Integer aPointIndex   = !myIndices.IsNull()
523                                           ? myIndices->Index (anIndexOffset)
524                                           : anIndexOffset;
525     if (myIs3d)
526     {
527       aPnt3d = &getPosVec3 (aPointIndex);
528       aCenter += *aPnt3d;
529     }
530     else
531     {
532       aPnt2d = &getPosVec2 (aPointIndex);
533       aCenter += Graphic3d_Vec3(*aPnt2d);
534     }
535
536     if (myBvhIndices.HasPatches())
537     {
538       if (myIs3d)
539       {
540         std::swap (aPnt3d, aPnt3dPrev);
541         if (aPatchSize < myPatchSizeMax
542          && aPnt3d != NULL
543          && (*aPnt3dPrev - *aPnt3d).SquareModulus() < aPatchSize2)
544         {
545           ++aPatchSize;
546           continue;
547         }
548       }
549       else
550       {
551         std::swap (aPnt2d, aPnt2dPrev);
552         if (aPatchSize < myPatchSizeMax
553          && aPnt2d != NULL
554          && (*aPnt2dPrev - *aPnt2d).SquareModulus() < aPatchSize2)
555         {
556           ++aPatchSize;
557           continue;
558         }
559       }
560
561       myBvhIndices.SetIndex (myBvhIndices.NbElements++, theIndexLower + aPatchFrom,
562                               aPatchSize != 0 ? aPatchSize : 1);
563       aPatchFrom = aPointIter;
564       aPatchSize = 0;
565     }
566     else
567     {
568       myBvhIndices.SetIndex (aPointIter, theIndexLower + aPointIter);
569     }
570   }
571   if (aPatchSize != 0)
572   {
573     myBvhIndices.SetIndex (myBvhIndices.NbElements++, theIndexLower + aPatchFrom, aPatchSize);
574   }
575   aCenter /= float(aNbPoints);
576
577   myCDG3D = vecToPnt (aCenter);
578   if (theToEvalMinMax)
579   {
580     computeBoundingBox();
581   }
582   return true;
583 }
584
585 // =======================================================================
586 // function : GetConnected
587 // purpose  :
588 // =======================================================================
589 Handle(Select3D_SensitiveEntity) Select3D_SensitivePrimitiveArray::GetConnected()
590 {
591   Handle(Select3D_SensitivePrimitiveArray) aNewEntity = new Select3D_SensitivePrimitiveArray (myOwnerId);
592   switch (myPrimType)
593   {
594     case Graphic3d_TOPA_POINTS:
595     {
596       aNewEntity->InitPoints        (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
597       break;
598     }
599     case Graphic3d_TOPA_TRIANGLES:
600     {
601       aNewEntity->InitTriangulation (myVerts, myIndices, myInitLocation, myIndexLower, myIndexUpper, true, !myGroups.IsNull() ? myGroups->Size() : 1);
602       break;
603     }
604     default: break;
605   }
606   return aNewEntity;
607 }
608
609 //=======================================================================
610 //function : Set
611 //purpose  :
612 //=======================================================================
613 void Select3D_SensitivePrimitiveArray::Set (const Handle(SelectMgr_EntityOwner)& theOwnerId)
614 {
615   base_type::Set (theOwnerId);
616   if (!myGroups.IsNull())
617   {
618     for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
619     {
620       aGroupIter.Value()->Set (theOwnerId);
621     }
622   }
623 }
624
625 // =======================================================================
626 // function : BVH
627 // purpose  :
628 // =======================================================================
629 void Select3D_SensitivePrimitiveArray::BVH()
630 {
631   if (!myContent.IsDirty())
632   {
633     return;
634   }
635
636   base_type::BVH();
637   if (myGroups.IsNull())
638   {
639     return;
640   }
641
642   Standard_Integer aNbToUpdate = 0;
643   for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
644   {
645     if (aGroupIter.Value()->myContent.IsDirty())
646     {
647       ++aNbToUpdate;
648     }
649   }
650
651   if (aNbToUpdate > 0)
652   {
653     Select3D_SensitivePrimitiveArray_BVHFunctor aFunctor (*myGroups);
654     OSD_Parallel::For (myGroups->Lower(), myGroups->Upper() + 1, aFunctor, aNbToUpdate <= 1);
655   }
656 }
657
658 // =======================================================================
659 // function : Size
660 // purpose  :
661 // =======================================================================
662 Standard_Integer Select3D_SensitivePrimitiveArray::Size() const
663 {
664   return myBvhIndices.NbElements;
665 }
666
667 // =======================================================================
668 // function : Box
669 // purpose  :
670 // =======================================================================
671 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::Box (const Standard_Integer theIdx) const
672 {
673   const Standard_Integer anElemIdx  = myBvhIndices.Index (theIdx);
674   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theIdx);
675   if (!myGroups.IsNull())
676   {
677     return myGroups->Value (anElemIdx)->BoundingBox();
678   }
679
680   Select3D_BndBox3d aBox;
681   switch (myPrimType)
682   {
683     case Graphic3d_TOPA_POINTS:
684     {
685       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
686       {
687         const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
688         const Standard_Integer aPointIndex   = !myIndices.IsNull()
689                                              ?  myIndices->Index (anIndexOffset)
690                                              :  anIndexOffset;
691         if (myIs3d)
692         {
693           const Graphic3d_Vec3& aPoint = getPosVec3 (aPointIndex);
694           aBox.Add (SelectMgr_Vec3 (aPoint.x(), aPoint.y(), aPoint.z()));
695         }
696         else
697         {
698           const Graphic3d_Vec2& aPoint = getPosVec2 (aPointIndex);
699           aBox.Add (SelectMgr_Vec3 (aPoint.x(), aPoint.y(), 0.0));
700         }
701       }
702       break;
703     }
704     case Graphic3d_TOPA_TRIANGLES:
705     {
706       Standard_Integer aTriNodes[3];
707       if (myIs3d)
708       {
709         for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
710         {
711           const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
712           getTriIndices (myIndices, anIndexOffset, aTriNodes);
713           const Graphic3d_Vec3& aNode1 = getPosVec3 (aTriNodes[0]);
714           const Graphic3d_Vec3& aNode2 = getPosVec3 (aTriNodes[1]);
715           const Graphic3d_Vec3& aNode3 = getPosVec3 (aTriNodes[2]);
716           Graphic3d_Vec3 aMinPnt = (aNode1.cwiseMin (aNode2)).cwiseMin (aNode3);
717           Graphic3d_Vec3 aMaxPnt = (aNode1.cwiseMax (aNode2)).cwiseMax (aNode3);
718           aBox.Add (SelectMgr_Vec3 (aMinPnt.x(), aMinPnt.y(), aMinPnt.z()));
719           aBox.Add (SelectMgr_Vec3 (aMaxPnt.x(), aMaxPnt.y(), aMaxPnt.z()));
720         }
721       }
722       else
723       {
724         for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
725         {
726           const Standard_Integer anIndexOffset = (anElemIdx + anElemIter) * 3;
727           getTriIndices (myIndices, anIndexOffset, aTriNodes);
728           const Graphic3d_Vec2& aNode1 = getPosVec2 (aTriNodes[0]);
729           const Graphic3d_Vec2& aNode2 = getPosVec2 (aTriNodes[1]);
730           const Graphic3d_Vec2& aNode3 = getPosVec2 (aTriNodes[2]);
731           Graphic3d_Vec2 aMinPnt = (aNode1.cwiseMin (aNode2)).cwiseMin (aNode3);
732           Graphic3d_Vec2 aMaxPnt = (aNode1.cwiseMax (aNode2)).cwiseMax (aNode3);
733           aBox.Add (SelectMgr_Vec3 (aMinPnt.x(), aMinPnt.y(), 0.0));
734           aBox.Add (SelectMgr_Vec3 (aMaxPnt.x(), aMaxPnt.y(), 0.0));
735         }
736       }
737       break;
738     }
739     default:
740     {
741       return aBox;
742     }
743   }
744   return aBox;
745 }
746
747 // =======================================================================
748 // function : Center
749 // purpose  :
750 // =======================================================================
751 Standard_Real Select3D_SensitivePrimitiveArray::Center (const Standard_Integer theIdx,
752                                                         const Standard_Integer theAxis) const
753 {
754   if (!myGroups.IsNull())
755   {
756     const Standard_Integer anElemIdx = myBvhIndices.Index (theIdx);
757     const gp_Pnt aCenter = myGroups->Value (anElemIdx)->CenterOfGeometry();
758     return theAxis == 0 ? aCenter.X() : (theAxis == 1 ? aCenter.Y() : aCenter.Z());
759   }
760
761   const Select3D_BndBox3d& aBox = Box (theIdx);
762   SelectMgr_Vec3 aCenter = (aBox.CornerMin() + aBox.CornerMax()) * 0.5;
763   return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
764 }
765
766 // =======================================================================
767 // function : Swap
768 // purpose  :
769 // =======================================================================
770 void Select3D_SensitivePrimitiveArray::Swap (const Standard_Integer theIdx1,
771                                              const Standard_Integer theIdx2)
772 {
773   Standard_Integer anElemIdx1 = myBvhIndices.Index (theIdx1);
774   Standard_Integer anElemIdx2 = myBvhIndices.Index (theIdx2);
775   if (myBvhIndices.HasPatches())
776   {
777     Standard_Integer aPatchSize1 = myBvhIndices.PatchSize (theIdx1);
778     Standard_Integer aPatchSize2 = myBvhIndices.PatchSize (theIdx2);
779     myBvhIndices.SetIndex (theIdx1, anElemIdx2, aPatchSize2);
780     myBvhIndices.SetIndex (theIdx2, anElemIdx1, aPatchSize1);
781   }
782   else
783   {
784     myBvhIndices.SetIndex (theIdx1, anElemIdx2);
785     myBvhIndices.SetIndex (theIdx2, anElemIdx1);
786   }
787 }
788
789 // =======================================================================
790 // function : BoundingBox
791 // purpose  :
792 // =======================================================================
793 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::BoundingBox()
794 {
795   if (!myBndBox.IsValid())
796   {
797     computeBoundingBox();
798   }
799   return applyTransformation();
800 }
801
802 // =======================================================================
803 // function : computeBoundingBox
804 // purpose  :
805 // =======================================================================
806 void Select3D_SensitivePrimitiveArray::computeBoundingBox()
807 {
808   myBndBox.Clear();
809   if (!myGroups.IsNull())
810   {
811     for (Select3D_PrimArraySubGroupArray::Iterator aGroupIter (*myGroups); aGroupIter.More(); aGroupIter.Next())
812     {
813       myBndBox.Combine (aGroupIter.Value()->BoundingBox());
814     }
815     return;
816   }
817
818   if (myVerts.IsNull())
819   {
820     return;
821   }
822
823   const Standard_Integer aNbVerts = myVerts->NbElements;
824   if (myIs3d)
825   {
826     for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
827     {
828       const Graphic3d_Vec3& aVert = getPosVec3 (aVertIter);
829       myBndBox.Add (SelectMgr_Vec3 (aVert.x(), aVert.y(), aVert.z()));
830     }
831   }
832   else
833   {
834     for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
835     {
836       const Graphic3d_Vec2& aVert = getPosVec2 (aVertIter);
837       myBndBox.Add (SelectMgr_Vec3 (aVert.x(), aVert.y(), 0.0));
838     }
839   }
840 }
841
842 // =======================================================================
843 // function : applyTransformation
844 // purpose  :
845 // =======================================================================
846 Select3D_BndBox3d Select3D_SensitivePrimitiveArray::applyTransformation()
847 {
848   if (!HasInitLocation())
849   {
850     return myBndBox;
851   }
852
853   Select3D_BndBox3d aBndBox;
854   for (Standard_Integer aX = 0; aX <=1; ++aX)
855   {
856     for (Standard_Integer aY = 0; aY <=1; ++aY)
857     {
858       for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
859       {
860         gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
861                                  aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
862                                  aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
863         aVertex.Transform (myInitLocation.Transformation());
864         aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
865       }
866     }
867   }
868   return aBndBox;
869 }
870
871 // =======================================================================
872 // function : Matches
873 // purpose  :
874 // =======================================================================
875 Standard_Boolean Select3D_SensitivePrimitiveArray::Matches (SelectBasics_SelectingVolumeManager& theMgr,
876                                                             SelectBasics_PickResult& thePickResult)
877 {
878   if (!myDetectedElemMap.IsNull())
879   {
880     myDetectedElemMap->ChangeMap().Clear();
881   }
882   if (!myDetectedNodeMap.IsNull())
883   {
884     myDetectedNodeMap->ChangeMap().Clear();
885   }
886   myMinDepthElem      = RealLast();
887   myMinDepthNode      = RealLast();
888   myMinDepthEdge      = RealLast();
889   myDetectedElem      = -1;
890   myDetectedNode      = -1;
891   myDetectedEdgeNode1 = -1;
892   myDetectedEdgeNode2 = -1;
893   const bool toDetectRange = !myDetectedElemMap.IsNull() || !myDetectedNodeMap.IsNull();
894   if (myGroups.IsNull()
895    || theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point
896    || !toDetectRange)
897   {
898     if (!matches (theMgr, thePickResult, toDetectRange))
899     {
900       return Standard_False;
901     }
902
903     if (!myGroups.IsNull() && myDetectedIdx != -1)
904     {
905       const Standard_Integer anIndex = myBvhIndices.Index (myDetectedIdx);
906       const Handle(Select3D_SensitivePrimitiveArray)& aLastGroup = myGroups->Value (anIndex);
907       myMinDepthElem      = aLastGroup->myMinDepthElem;
908       myMinDepthNode      = aLastGroup->myMinDepthNode;
909       myMinDepthEdge      = aLastGroup->myMinDepthEdge;
910       myDetectedElem      = aLastGroup->myDetectedElem;
911       myDetectedNode      = aLastGroup->myDetectedNode;
912       myDetectedEdgeNode1 = aLastGroup->myDetectedEdgeNode1;
913       myDetectedEdgeNode2 = aLastGroup->myDetectedEdgeNode2;
914     }
915     return Standard_True;
916   }
917
918   SelectBasics_PickResult aPickResult;
919   bool hasResults = false;
920   for (Standard_Integer aGroupIter = 0; aGroupIter < myBvhIndices.NbElements; ++aGroupIter)
921   {
922     const Standard_Integer anElemIdx = myBvhIndices.Index (aGroupIter);
923     Handle(Select3D_SensitivePrimitiveArray)& aChild = myGroups->ChangeValue (anElemIdx);
924     if (aChild->Matches (theMgr, aPickResult))
925     {
926       hasResults = true;
927       if (!myDetectedElemMap.IsNull())
928       {
929         myDetectedElemMap->ChangeMap().Unite (aChild->myDetectedElemMap->Map());
930       }
931       if (!myDetectedNodeMap.IsNull())
932       {
933         myDetectedNodeMap->ChangeMap().Unite (aChild->myDetectedNodeMap->Map());
934       }
935       if (thePickResult.Depth() > aPickResult.Depth())
936       {
937         myDetectedIdx = aGroupIter;
938         thePickResult = aPickResult;
939       }
940     }
941   }
942   if (!hasResults)
943   {
944     return Standard_False;
945   }
946   thePickResult.SetDistToGeomCenter(theMgr.DistToGeometryCenter(CenterOfGeometry()));
947   return Standard_True;
948 }
949
950 // =======================================================================
951 // function : overlapsElement
952 // purpose  :
953 // =======================================================================
954 Standard_Boolean Select3D_SensitivePrimitiveArray::overlapsElement (SelectBasics_PickResult& thePickResult,
955                                                                     SelectBasics_SelectingVolumeManager& theMgr,
956                                                                     Standard_Integer theElemIdx,
957                                                                     Standard_Boolean theIsFullInside)
958 {
959   const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
960   if (!myGroups.IsNull())
961   {
962     return myGroups->Value (anElemIdx)->Matches (theMgr, thePickResult);
963   }
964
965   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
966   Select3D_BndBox3d aBox;
967   Standard_Boolean aResult = Standard_False;
968   SelectBasics_PickResult aPickResult;
969   switch (myPrimType)
970   {
971     case Graphic3d_TOPA_POINTS:
972     {
973       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
974       {
975         const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
976         const Standard_Integer aPointIndex   = !myIndices.IsNull()
977                                              ?  myIndices->Index (anIndexOffset)
978                                              :  anIndexOffset;
979         gp_Pnt aPoint;
980         if (myIs3d)
981         {
982           aPoint = vecToPnt (getPosVec3 (aPointIndex));
983         }
984         else
985         {
986           aPoint = vecToPnt (getPosVec2 (aPointIndex));
987         }
988
989         if (myToDetectNode
990          || myToDetectElem)
991         {
992           if (theIsFullInside || theMgr.Overlaps (aPoint, aPickResult))
993           {
994             if (aPickResult.Depth() <= myMinDepthNode)
995             {
996               myDetectedElem = myDetectedNode = aPointIndex;
997               myMinDepthElem = myMinDepthNode = aPickResult.Depth();
998             }
999             if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1000             {
1001               if (!myDetectedElemMap.IsNull())
1002               {
1003                 myDetectedElemMap->ChangeMap().Add (aPointIndex);
1004               }
1005               if (!myDetectedNodeMap.IsNull())
1006               {
1007                 myDetectedNodeMap->ChangeMap().Add (aPointIndex);
1008               }
1009             }
1010             aResult = Standard_True;
1011           }
1012         }
1013         thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
1014       }
1015       break;
1016     }
1017     case Graphic3d_TOPA_TRIANGLES:
1018     {
1019       Graphic3d_Vec3i aTriNodes;
1020       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1021       {
1022         const Standard_Integer aTriIndex     = anElemIdx + anElemIter;
1023         const Standard_Integer anIndexOffset = aTriIndex * 3;
1024         getTriIndices (myIndices, anIndexOffset, aTriNodes);
1025         gp_Pnt aPnts[3];
1026         if (myIs3d)
1027         {
1028           aPnts[0] = vecToPnt (getPosVec3 (aTriNodes[0]));
1029           aPnts[1] = vecToPnt (getPosVec3 (aTriNodes[1]));
1030           aPnts[2] = vecToPnt (getPosVec3 (aTriNodes[2]));
1031         }
1032         else
1033         {
1034           aPnts[0] = vecToPnt (getPosVec2 (aTriNodes[0]));
1035           aPnts[1] = vecToPnt (getPosVec2 (aTriNodes[1]));
1036           aPnts[2] = vecToPnt (getPosVec2 (aTriNodes[2]));
1037         }
1038
1039         if (myToDetectElem)
1040         {
1041           if (theIsFullInside || theMgr.Overlaps (aPnts[0], aPnts[1], aPnts[2], Select3D_TOS_INTERIOR, aPickResult))
1042           {
1043             if (aPickResult.Depth() <= myMinDepthElem)
1044             {
1045               myDetectedElem = aTriIndex;
1046               myMinDepthElem = aPickResult.Depth();
1047             }
1048             aResult = Standard_True;
1049             if (!myDetectedElemMap.IsNull()
1050               && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1051             {
1052               myDetectedElemMap->ChangeMap().Add(aTriIndex);
1053             }
1054           }
1055         }
1056         if (myToDetectNode)
1057         {
1058           for (int aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
1059           {
1060             if (theIsFullInside || theMgr.Overlaps (aPnts[aNodeIter], aPickResult))
1061             {
1062               if (aPickResult.Depth() <= myMinDepthNode)
1063               {
1064                 myDetectedNode = aTriNodes[aNodeIter];
1065                 myMinDepthNode = aPickResult.Depth();
1066               }
1067               if (!myDetectedNodeMap.IsNull()
1068                 && theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1069               {
1070                 myDetectedNodeMap->ChangeMap().Add (aTriNodes[aNodeIter]);
1071               }
1072               aResult = Standard_True;
1073             }
1074           }
1075         }
1076         if (myToDetectEdge)
1077         {
1078           for (int aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
1079           {
1080             int aNode1 = aNodeIter == 0 ? 2 : (aNodeIter - 1);
1081             int aNode2 = aNodeIter;
1082             if (theIsFullInside || theMgr.Overlaps (aPnts[aNode1], aPnts[aNode2], aPickResult))
1083             {
1084               if (aPickResult.Depth() <= myMinDepthEdge)
1085               {
1086                 myDetectedEdgeNode1 = aTriNodes[aNode1];
1087                 myDetectedEdgeNode2 = aTriNodes[aNode2];
1088                 myMinDepthEdge = aPickResult.Depth();
1089               }
1090               aResult = Standard_True;
1091             }
1092           }
1093         }
1094         thePickResult = SelectBasics_PickResult::Min (thePickResult, aPickResult);
1095       }
1096       break;
1097     }
1098     default:
1099     {
1100       return Standard_False;
1101     }
1102   }
1103
1104   return aResult;
1105 }
1106
1107 // =======================================================================
1108 // function : distanceToCOG
1109 // purpose  :
1110 // =======================================================================
1111 Standard_Real Select3D_SensitivePrimitiveArray::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
1112 {
1113   return theMgr.DistToGeometryCenter (myCDG3D);
1114 }
1115
1116 // =======================================================================
1117 // function : elementIsInside
1118 // purpose  :
1119 // =======================================================================
1120 Standard_Boolean Select3D_SensitivePrimitiveArray::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
1121                                                                     Standard_Integer theElemIdx,
1122                                                                     Standard_Boolean theIsFullInside)
1123 {
1124   const Standard_Integer anElemIdx = myBvhIndices.Index (theElemIdx);
1125   if (!myGroups.IsNull())
1126   {
1127     SelectBasics_PickResult aDummy;
1128     return myGroups->Value (anElemIdx)->Matches (theMgr, aDummy);
1129   }
1130
1131   const Standard_Integer aPatchSize = myBvhIndices.PatchSize (theElemIdx);
1132   switch (myPrimType)
1133   {
1134     case Graphic3d_TOPA_POINTS:
1135     {
1136       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1137       {
1138         const Standard_Integer anIndexOffset = (anElemIdx + anElemIter);
1139         const Standard_Integer aPointIndex   = !myIndices.IsNull()
1140                                              ?  myIndices->Index (anIndexOffset)
1141                                              :  anIndexOffset;
1142         gp_Pnt aPoint;
1143         if (myIs3d)
1144         {
1145           aPoint = vecToPnt (getPosVec3 (aPointIndex));
1146         }
1147         else
1148         {
1149           aPoint = vecToPnt (getPosVec2 (aPointIndex));
1150         }
1151         if (!theIsFullInside && !theMgr.Overlaps (aPoint))
1152         {
1153           return Standard_False;
1154         }
1155
1156         if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1157         {
1158           if (!myDetectedElemMap.IsNull())
1159           {
1160             myDetectedElemMap->ChangeMap().Add (aPointIndex);
1161           }
1162           if (!myDetectedNodeMap.IsNull())
1163           {
1164             myDetectedNodeMap->ChangeMap().Add (aPointIndex);
1165           }
1166         }
1167       }
1168       return Standard_True;
1169     }
1170     case Graphic3d_TOPA_TRIANGLES:
1171     {
1172       Graphic3d_Vec3i aTriNodes;
1173       for (Standard_Integer anElemIter = 0; anElemIter < aPatchSize; ++anElemIter)
1174       {
1175         const Standard_Integer aTriIndex     = anElemIdx + anElemIter;
1176         const Standard_Integer anIndexOffset = aTriIndex * 3;
1177         getTriIndices (myIndices, anIndexOffset, aTriNodes);
1178         gp_Pnt aPnts[3];
1179         if (myIs3d)
1180         {
1181           aPnts[0] = vecToPnt (getPosVec3 (aTriNodes[0]));
1182           aPnts[1] = vecToPnt (getPosVec3 (aTriNodes[1]));
1183           aPnts[2] = vecToPnt (getPosVec3 (aTriNodes[2]));
1184         }
1185         else
1186         {
1187           aPnts[0] = vecToPnt (getPosVec2 (aTriNodes[0]));
1188           aPnts[1] = vecToPnt (getPosVec2 (aTriNodes[1]));
1189           aPnts[2] = vecToPnt (getPosVec2 (aTriNodes[2]));
1190         }
1191
1192         if (!theIsFullInside && (   !theMgr.Overlaps (aPnts[0])
1193                                  || !theMgr.Overlaps (aPnts[1])
1194                                  || !theMgr.Overlaps (aPnts[2])))
1195         {
1196           return Standard_False;
1197         }
1198
1199         if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point)
1200         {
1201           if (!myDetectedElemMap.IsNull())
1202           {
1203             myDetectedElemMap->ChangeMap().Add (aTriIndex);
1204           }
1205           if (!myDetectedNodeMap.IsNull())
1206           {
1207             myDetectedNodeMap->ChangeMap().Add (aTriNodes[0]);
1208             myDetectedNodeMap->ChangeMap().Add (aTriNodes[1]);
1209             myDetectedNodeMap->ChangeMap().Add (aTriNodes[2]);
1210           }
1211         }
1212       }
1213       return Standard_True;
1214     }
1215     default:
1216     {
1217       return Standard_False;
1218     }
1219   }
1220 }
1221
1222 // =======================================================================
1223 // function : DumpJson
1224 // purpose  :
1225 // =======================================================================
1226 void Select3D_SensitivePrimitiveArray::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1227 {
1228   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1229   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveSet)
1230
1231   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPosStride)
1232   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPrimType)
1233   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexLower)
1234   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexUpper)
1235   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPatchSizeMax)
1236   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPatchDistance)
1237   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIs3d)
1238   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myInitLocation)
1239   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)
1240
1241   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthElem)
1242   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthNode)
1243   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinDepthEdge)
1244
1245   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedElem)
1246   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedNode)
1247   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedEdgeNode1)
1248   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDetectedEdgeNode2)
1249   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectElem)
1250   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectNode)
1251   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToDetectEdge)
1252 }