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