0026413: Visualization, SelectMgr_ViewerSelector - Pixel tolerance is overridden...
[occt.git] / src / StdSelect / StdSelect_ViewerSelector3d.cxx
1 // Created on: 1995-03-15
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <StdSelect_ViewerSelector3d.hxx>
18 #include <StdSelect.hxx>
19 #include <SelectBasics_SensitiveEntity.hxx>
20 #include <Graphic3d_AspectLine3d.hxx>
21 #include <gp_Pnt.hxx>
22 #include <gp_Lin.hxx>
23 #include <gp_Pnt2d.hxx>
24 #include <gp_Dir.hxx>
25 #include <gp_Ax3.hxx>
26 #include <gp_GTrsf.hxx>
27 #include <gp_Pln.hxx>
28 #include <Select3D_SensitiveEntity.hxx>
29 #include <Graphic3d_ArrayOfPolylines.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <Graphic3d_SequenceOfHClipPlane.hxx>
32 #include <Graphic3d_Structure.hxx>
33 #include <SelectMgr_SelectableObject.hxx>
34 #include <TColgp_HArray1OfPnt.hxx>
35 #include <TColgp_Array1OfPnt.hxx>
36 #include <TColgp_Array1OfPnt2d.hxx>
37 #include <TColgp_HArray1OfPnt2d.hxx>
38 #include <Select3D_SensitiveCurve.hxx>
39 #include <Select3D_SensitiveSegment.hxx>
40 #include <Select3D_SensitiveFace.hxx>
41 #include <Select3D_SensitiveCircle.hxx>
42 #include <Select3D_SensitivePoint.hxx>
43 #include <Select3D_SensitiveTriangulation.hxx>
44 #include <Select3D_SensitiveTriangle.hxx>
45 #include <Select3D_SensitiveWire.hxx>
46 #include <Select3D_SensitiveBox.hxx>
47 #include <SelectMgr_Selection.hxx>
48 #include <SelectMgr_EntityOwner.hxx>
49
50 #include <Aspect_Grid.hxx>
51 #include <Aspect_TypeOfMarker.hxx>
52 #include <Aspect_Window.hxx>
53 #include <Graphic3d_AspectMarker3d.hxx>
54 #include <Graphic3d_ArrayOfPoints.hxx>
55 #include <Poly_Connect.hxx>
56 #include <TColStd_HArray1OfInteger.hxx>
57
58 #include <Poly_Array1OfTriangle.hxx>
59 #include <Poly_Triangulation.hxx>
60 #include <OSD_Environment.hxx>
61 #include <V3d.hxx>
62 #include <V3d_View.hxx>
63 #include <V3d_Viewer.hxx>
64 #include <TColgp_SequenceOfPnt.hxx>
65
66 #include <OSD_Timer.hxx>
67
68
69 static Standard_Integer StdSel_NumberOfFreeEdges (const Handle(Poly_Triangulation)& Trg)
70 {
71   Standard_Integer nFree = 0;
72   Poly_Connect pc(Trg);
73   Standard_Integer t[3];
74   Standard_Integer i, j;
75   for (i = 1; i <= Trg->NbTriangles(); i++)
76   {
77     pc.Triangles (i, t[0], t[1], t[2]);
78     for (j = 0; j < 3; j++)
79       if (t[j] == 0) nFree++;
80   }
81   return nFree;
82 }
83
84 //=======================================================================
85 // Function : Constructor
86 // Purpose  :
87 //=======================================================================
88 StdSelect_ViewerSelector3d::StdSelect_ViewerSelector3d() {}
89
90 //=======================================================================
91 // Function: SetPixelTolerance
92 // Purpose :
93 //=======================================================================
94 void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Real theTolerance)
95 {
96   if (myTolerances.Tolerance() != theTolerance)
97   {
98     if (theTolerance < 0.0)
99       myTolerances.ResetDefaults();
100     else
101       myTolerances.SetCustomTolerance (theTolerance);
102     myToUpdateTolerance = Standard_True;
103   }
104 }
105
106 //=======================================================================
107 // Function: Pick
108 // Purpose :
109 //=======================================================================
110 void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
111                                        const Standard_Integer theYPix,
112                                        const Handle(V3d_View)& theView)
113 {
114   SetClipping (theView->GetClipPlanes());
115
116   if(myToUpdateTolerance)
117   {
118     mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
119     myToUpdateTolerance = Standard_False;
120   }
121
122   mySelectingVolumeMgr.SetCamera (theView->Camera());
123   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point);
124   Standard_Integer aWidth = 0, aHeight = 0;
125   theView->Window()->Size (aWidth, aHeight);
126   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
127   gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
128                       static_cast<Standard_Real> (theYPix));
129   mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
130
131   TraverseSensitives();
132 }
133
134 //=======================================================================
135 // Function: Pick
136 // Purpose :
137 //=======================================================================
138 void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPMin,
139                                        const Standard_Integer theYPMin,
140                                        const Standard_Integer theXPMax,
141                                        const Standard_Integer theYPMax,
142                                        const Handle(V3d_View)& theView)
143 {
144   mySelectingVolumeMgr.SetCamera (theView->Camera());
145   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box);
146   Standard_Integer aWidth = 0, aHeight = 0;
147   theView->Window()->Size (aWidth, aHeight);
148   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
149   gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin),
150                          static_cast<Standard_Real> (theYPMin));
151   gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax),
152                          static_cast<Standard_Real> (theYPMax));
153   mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos,
154                                              aMaxMousePos);
155
156   TraverseSensitives();
157 }
158
159 //=======================================================================
160 // Function: Pick
161 // Purpose : Selection using a polyline
162 //=======================================================================
163 void StdSelect_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline,
164                                        const Handle(V3d_View)& theView)
165 {
166   mySelectingVolumeMgr.SetCamera (theView->Camera());
167   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline);
168   Standard_Integer aWidth = 0, aHeight = 0;
169   theView->Window()->Size (aWidth, aHeight);
170   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
171   mySelectingVolumeMgr.BuildSelectingVolume (thePolyline);
172
173   TraverseSensitives();
174 }
175
176 //=======================================================================
177 // Function: DisplaySensitive.
178 // Purpose : Display active primitives.
179 //=======================================================================
180 void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theView)
181 {
182   // Preparation des structures
183   if (mystruct.IsNull())
184   {
185     mystruct = new Graphic3d_Structure (theView->Viewer()->Viewer());
186   }
187
188   if (mysensgroup.IsNull())
189   {
190     mysensgroup = mystruct->NewGroup();
191   }
192
193   Quantity_Color aColor (Quantity_NOC_INDIANRED3);
194   Handle(Graphic3d_AspectMarker3d) aMarkerAspect =
195     new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0);
196
197   mysensgroup->SetPrimitivesAspect (aMarkerAspect);
198   mysensgroup->SetPrimitivesAspect (
199     new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
200
201   for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjects->Size(); ++anObjectIdx)
202   {
203     const Handle (SelectMgr_SelectableObject)& anObject = mySelectableObjects->GetObjectById (anObjectIdx);
204     for (anObject->Init(); anObject->More(); anObject->Next())
205     {
206       if (anObject->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
207       {
208         ComputeSensitivePrs (anObject->CurrentSelection(), anObject->Transformation());
209       }
210     }
211   }
212
213   mysensgroup->Structure()->SetDisplayPriority (10);
214   mystruct->Display();
215
216   theView->Update();
217 }
218
219 //=======================================================================
220 // Function: ClearSensitive
221 // Purpose :
222 //=======================================================================
223 void StdSelect_ViewerSelector3d::ClearSensitive (const Handle(V3d_View)& theView)
224 {
225   if (mysensgroup.IsNull())
226   {
227     return;
228   }
229
230   mysensgroup->Clear();
231
232   if (theView.IsNull())
233   {
234     return;
235   }
236
237   theView->Update();
238 }
239
240 //=======================================================================
241 //function : DisplaySenstive
242 //purpose  :
243 //=======================================================================
244 void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
245                                                    const gp_Trsf& theTrsf,
246                                                    const Handle(V3d_View)& theView,
247                                                    const Standard_Boolean theToClearOthers)
248 {
249   if (mystruct.IsNull())
250   {
251     mystruct = new Graphic3d_Structure (theView->Viewer()->Viewer());
252   }
253
254   if (mysensgroup.IsNull())
255   {
256     mysensgroup = mystruct->NewGroup();
257     Quantity_Color aColor (Quantity_NOC_INDIANRED3);
258     Handle(Graphic3d_AspectMarker3d) aMarkerAspect =
259       new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0);
260
261     mysensgroup-> SetPrimitivesAspect (aMarkerAspect);
262     mysensgroup->SetPrimitivesAspect (
263       new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
264   }
265
266   if (theToClearOthers)
267   {
268     mysensgroup->Clear();
269   }
270
271   ComputeSensitivePrs (theSel, theTrsf);
272
273   mystruct->SetDisplayPriority (10);
274   mystruct->Display();
275
276   theView->Update();
277 }
278
279 //=======================================================================
280 //function : ComputeSensitivePrs
281 //purpose  :
282 //=======================================================================
283 void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(SelectMgr_Selection)& theSel,
284                                                       const gp_Trsf& theLoc)
285 {
286   TColgp_SequenceOfPnt aSeqLines, aSeqFree;
287   TColStd_SequenceOfInteger aSeqBnds;
288
289   for (theSel->Init(); theSel->More(); theSel->Next())
290   {
291     Handle(Select3D_SensitiveEntity) Ent =
292       Handle(Select3D_SensitiveEntity)::DownCast(theSel->Sensitive()->BaseSensitive());
293     const Standard_Boolean hasloc = theLoc.Form() != gp_Identity;
294
295     //==============
296     // Box
297     //=============
298
299     if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveBox))
300     {
301       const Bnd_Box& B = Handle(Select3D_SensitiveBox)::DownCast (Ent)->Box();
302       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
303       B.Get (xmin, ymin, zmin, xmax, ymax, zmax);
304       Standard_Integer i;
305       gp_Pnt theboxpoint[8] =
306       {
307         gp_Pnt(xmin,ymin,zmin),
308         gp_Pnt(xmax,ymin,zmin),
309         gp_Pnt(xmax,ymax,zmin),
310         gp_Pnt(xmin,ymax,zmin),
311         gp_Pnt(xmin,ymin,zmax),
312         gp_Pnt(xmax,ymin,zmax),
313         gp_Pnt(xmax,ymax,zmax),
314         gp_Pnt(xmin,ymax,zmax)
315       };
316       if(hasloc)
317       {
318         for (i = 0; i <= 7; i++)
319           theboxpoint[i].Transform (theLoc);
320       }
321
322       aSeqBnds.Append(5);
323       for (i = 0; i < 4; i++)
324         aSeqLines.Append(theboxpoint[i]);
325       aSeqLines.Append(theboxpoint[0]);
326
327       aSeqBnds.Append(5);
328       for (i = 4; i < 8; i++)
329         aSeqLines.Append(theboxpoint[i]);
330       aSeqLines.Append(theboxpoint[4]);
331
332       for (i = 0; i < 4; i++)
333       {
334         aSeqBnds.Append(2);
335         aSeqLines.Append(theboxpoint[i]);
336         aSeqLines.Append(theboxpoint[i+4]);
337       }
338     }
339     //==============
340     // Face
341     //=============
342     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveFace))
343     {
344       Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(Ent);
345       Handle(TColgp_HArray1OfPnt) TheHPts;
346       aFace->GetPoints(TheHPts);
347       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
348
349       aSeqBnds.Append(ThePts.Length());
350       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
351       {
352         if (hasloc)
353           aSeqLines.Append(ThePts(I).Transformed (theLoc));
354         else
355           aSeqLines.Append(ThePts(I));
356       }
357     }
358     //==============
359     // Curve
360     //=============
361     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
362     {
363       Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(Ent);
364       Handle(TColgp_HArray1OfPnt) TheHPts;
365       aCurve->Points3D(TheHPts);
366       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
367
368       aSeqBnds.Append(ThePts.Length());
369       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
370       {
371         if (hasloc)
372           aSeqLines.Append(ThePts(I).Transformed (theLoc));
373         else
374           aSeqLines.Append(ThePts(I));
375       }
376     }
377     //==============
378     // Wire
379     //=============
380     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveWire))
381     {
382       Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(Ent);
383       const NCollection_Vector<Handle(Select3D_SensitiveEntity)>& anEntities = aWire->GetEdges();
384
385       for (int i = 0; i < anEntities.Length(); i++)
386       {
387         Handle(Select3D_SensitiveEntity) SubEnt = Handle(Select3D_SensitiveEntity)::DownCast(anEntities.Value(i));
388
389         //Segment
390         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
391         {
392           gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->StartPoint().XYZ());
393           gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->EndPoint().XYZ());
394           if (hasloc)
395           {
396             P1.Transform(theLoc);
397             P2.Transform(theLoc);
398           }
399           aSeqBnds.Append(2);
400           aSeqLines.Append(P1);
401           aSeqLines.Append(P2);
402         }
403
404         //circle
405         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
406         {
407           Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(SubEnt);
408           Standard_Integer aFrom, aTo;
409           aCircle->ArrayBounds (aFrom, aTo);
410           aTo -= 2;
411           for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
412           {
413             gp_Pnt aPnts[3] =
414             {
415               gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
416               gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
417               gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
418             };
419
420             if (hasloc)
421             {
422               aPnts[0].Transform (theLoc);
423               aPnts[1].Transform (theLoc);
424               aPnts[2].Transform (theLoc);
425             }
426
427             aSeqBnds.Append (4);
428             aSeqLines.Append (aPnts[0]);
429             aSeqLines.Append (aPnts[1]);
430             aSeqLines.Append (aPnts[2]);
431             aSeqLines.Append (aPnts[0]);
432           }
433         }
434
435         //curve
436         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
437         {
438           Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(SubEnt);
439           Handle(TColgp_HArray1OfPnt) TheHPts;
440           aCurve->Points3D (TheHPts);
441           const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
442
443           aSeqBnds.Append(ThePts.Length());
444           for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
445           {
446             if (hasloc)
447               aSeqLines.Append(ThePts(I).Transformed (theLoc));
448             else
449               aSeqLines.Append(ThePts(I));
450           }
451         }
452       }
453     }
454     //==============
455     // Segment
456     //=============
457     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
458     {
459       gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->StartPoint().XYZ());
460       gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->EndPoint().XYZ());
461       if (hasloc)
462       {
463         P1.Transform (theLoc);
464         P2.Transform (theLoc);
465       }
466       aSeqBnds.Append(2);
467       aSeqLines.Append(P1);
468       aSeqLines.Append(P2);
469     }
470     //==============
471     // Circle
472     //=============
473     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
474     {
475       Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(Ent);
476       Standard_Integer aFrom, aTo;
477       aCircle->ArrayBounds (aFrom, aTo);
478       aTo -= 2;
479       for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
480       {
481         gp_Pnt aPnts[3] =
482         {
483           gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
484           gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
485           gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
486         };
487
488         if (hasloc)
489         {
490           aPnts[0].Transform (theLoc);
491           aPnts[1].Transform (theLoc);
492           aPnts[2].Transform (theLoc);
493         }
494
495         aSeqBnds.Append (4);
496         aSeqLines.Append (aPnts[0]);
497         aSeqLines.Append (aPnts[1]);
498         aSeqLines.Append (aPnts[2]);
499         aSeqLines.Append (aPnts[0]);
500       }
501     }
502     //==============
503     // Point
504     //=============
505     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitivePoint))
506     {
507       gp_Pnt P = hasloc ?
508         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point() :
509         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theLoc);
510       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
511       anArrayOfPoints->AddVertex (P.X(), P.Y(), P.Z());
512       mysensgroup->AddPrimitiveArray (anArrayOfPoints);
513     }
514     //============================================================
515     // Triangulation : On met un petit offset ves l'interieur...
516     //==========================================================
517     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangulation))
518     {
519       Handle(Poly_Triangulation) PT (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->Triangulation());
520
521       const Poly_Array1OfTriangle& triangles = PT->Triangles();
522       const TColgp_Array1OfPnt& Nodes = PT->Nodes();
523       Standard_Integer n[3];
524
525       TopLoc_Location iloc, bidloc;
526       if (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->HasInitLocation())
527         bidloc = Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->GetInitLocation();
528
529       if (bidloc.IsIdentity())
530         iloc = theLoc;
531       else
532         iloc = theLoc * bidloc;
533
534       Standard_Integer i;
535       for (i = 1; i <= PT->NbTriangles(); i++)
536       {
537         triangles (i).Get (n[0], n[1], n[2]);
538         gp_Pnt P1 (Nodes (n[0]).Transformed (iloc));
539         gp_Pnt P2 (Nodes (n[1]).Transformed (iloc));
540         gp_Pnt P3 (Nodes (n[2]).Transformed (iloc));
541         gp_XYZ V1 (P1.XYZ());
542         gp_XYZ V2 (P2.XYZ());
543         gp_XYZ V3 (P3.XYZ());
544         gp_XYZ CDG (P1.XYZ()); CDG += (P2.XYZ()); CDG += (P3.XYZ()); CDG /= 3.0;
545         V1 -= CDG; V2 -= CDG; V3 -= CDG;
546         V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
547         V1 += CDG; V2 += CDG; V3 += CDG;
548
549         aSeqBnds.Append(4);
550         aSeqLines.Append(gp_Pnt(V1));
551         aSeqLines.Append(gp_Pnt(V2));
552         aSeqLines.Append(gp_Pnt(V3));
553         aSeqLines.Append(gp_Pnt(V1));
554       }
555
556       // recherche des bords libres...
557
558       Handle(TColStd_HArray1OfInteger) FreeEdges = new TColStd_HArray1OfInteger (1, 2 * StdSel_NumberOfFreeEdges (PT));
559       TColStd_Array1OfInteger& FreeE = FreeEdges->ChangeArray1();
560       Poly_Connect pc (PT);
561       Standard_Integer t[3];
562       Standard_Integer j;
563       Standard_Integer fr (1);
564       for (i = 1; i <= PT->NbTriangles(); i++)
565       {
566         pc.Triangles (i, t[0], t[1], t[2]);
567         triangles (i).Get (n[0], n[1], n[2]);
568         for (j = 0; j < 3; j++)
569         {
570           Standard_Integer k = (j + 1) % 3;
571           if (t[j] == 0)
572           {
573             FreeE (fr)    = n[j];
574             FreeE (fr + 1)= n[k];
575             fr += 2;
576           }
577         }
578       }
579       for (Standard_Integer ifri = 1; ifri <= FreeE.Length(); ifri += 2)
580       {
581         gp_Pnt pe1 (Nodes (FreeE (ifri)).Transformed (iloc)), pe2 (Nodes (FreeE (ifri + 1)).Transformed (iloc));
582         aSeqFree.Append(pe1);
583         aSeqFree.Append(pe2);
584       }
585     }
586     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangle))
587     {
588       Handle(Select3D_SensitiveTriangle) Str = Handle(Select3D_SensitiveTriangle)::DownCast(Ent);
589       gp_Pnt P1, P2, P3;
590       Str->Points3D (P1, P2, P3);
591       gp_Pnt CDG = Str->Center3D();
592
593       gp_XYZ V1 (P1.XYZ()); V1 -= (CDG.XYZ());
594       gp_XYZ V2 (P2.XYZ()); V2 -= (CDG.XYZ());
595       gp_XYZ V3 (P3.XYZ()); V3 -= (CDG.XYZ());
596       V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
597       V1 += CDG.XYZ(); V2 += CDG.XYZ(); V3 += CDG.XYZ();
598
599       aSeqBnds.Append(4);
600       aSeqLines.Append(gp_Pnt(V1));
601       aSeqLines.Append(gp_Pnt(V2));
602       aSeqLines.Append(gp_Pnt(V3));
603       aSeqLines.Append(gp_Pnt(V1));
604     }
605   }
606
607   Standard_Integer i;
608
609   if (aSeqLines.Length())
610   {
611     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),aSeqBnds.Length());
612     for (i = 1; i <= aSeqLines.Length(); i++)
613       aPrims->AddVertex(aSeqLines(i));
614     for (i = 1; i <= aSeqBnds.Length(); i++)
615       aPrims->AddBound(aSeqBnds(i));
616     myareagroup->AddPrimitiveArray(aPrims);
617   }
618
619   if (aSeqFree.Length())
620   {
621     mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0));
622     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqFree.Length(),aSeqFree.Length()/2);
623     for (i = 1; i <= aSeqFree.Length(); i++)
624     {
625       aPrims->AddBound(2);
626       aPrims->AddVertex(aSeqLines(i++));
627       aPrims->AddVertex(aSeqLines(i));
628     }
629     mysensgroup->AddPrimitiveArray(aPrims);
630     mysensgroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
631   }
632 }
633
634 //=======================================================================
635 //function : SetClipping
636 //purpose  :
637 //=======================================================================
638 void StdSelect_ViewerSelector3d::SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes)
639 {
640   myClipPlanes = thePlanes;
641 }
642
643 //=======================================================================
644 //function : HasDepthClipping
645 //purpose  :
646 //=======================================================================
647 Standard_Boolean StdSelect_ViewerSelector3d::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const
648 {
649   if (!theOwner->HasSelectable())
650   {
651     return Standard_False;
652   }
653
654   const Handle(SelectMgr_SelectableObject)& aSelectable = theOwner->Selectable();
655   return (aSelectable->GetClipPlanes().Size() > 0);
656 }