0026344: Visualization - provide a support of zoom persistent selection
[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   for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjects.Size(); ++anObjectIdx)
183   {
184     const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjects.GetObjectById (anObjectIdx);
185
186     Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer());
187
188     for (anObj->Init(); anObj->More(); anObj->Next())
189     {
190       if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
191       {
192         ComputeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), Graphic3d_TransformPers());
193       }
194     }
195
196     myStructs.Append (aStruct);
197   }
198
199   for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjectsTrsfPers.Size(); ++anObjectIdx)
200   {
201     const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjectsTrsfPers.GetObjectById (anObjectIdx);
202
203     Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer());
204
205     if (!anObj->TransformPersistence().Flags || (anObj->TransformPersistence().Flags & Graphic3d_TMF_2d))
206     {
207       continue;
208     }
209
210     for (anObj->Init(); anObj->More(); anObj->Next())
211     {
212       if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
213       {
214         ComputeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), anObj->TransformPersistence());
215       }
216     }
217
218     myStructs.Append (aStruct);
219   }
220
221   for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx)
222   {
223     Handle(Graphic3d_Structure)& aStruct = myStructs.ChangeValue (aStructIdx);
224     aStruct->SetDisplayPriority (10);
225     aStruct->Display();
226   }
227
228   theView->Update();
229 }
230
231 //=======================================================================
232 // Function: ClearSensitive
233 // Purpose :
234 //=======================================================================
235 void StdSelect_ViewerSelector3d::ClearSensitive (const Handle(V3d_View)& theView)
236 {
237   for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx)
238   {
239     myStructs.Value (aStructIdx)->Remove();
240   }
241
242   myStructs.Clear();
243
244   if (!theView.IsNull())
245   {
246     theView->Update();
247   }
248 }
249
250 //=======================================================================
251 //function : DisplaySenstive
252 //purpose  :
253 //=======================================================================
254 void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
255                                                    const gp_Trsf& theTrsf,
256                                                    const Handle(V3d_View)& theView,
257                                                    const Standard_Boolean theToClearOthers)
258 {
259   if (theToClearOthers)
260   {
261     ClearSensitive (theView);
262   }
263
264   Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->Viewer());
265
266   ComputeSensitivePrs (aStruct, theSel, theTrsf, Graphic3d_TransformPers());
267
268   myStructs.Append (aStruct);
269   myStructs.Last()->SetDisplayPriority (10);
270   myStructs.Last()->Display();
271
272   theView->Update();
273 }
274
275 //=======================================================================
276 //function : ComputeSensitivePrs
277 //purpose  :
278 //=======================================================================
279 void StdSelect_ViewerSelector3d::ComputeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure,
280                                                       const Handle(SelectMgr_Selection)& theSel,
281                                                       const gp_Trsf& theLoc,
282                                                       const Graphic3d_TransformPers& theTransPers)
283 {
284   theStructure->SetTransformPersistence (theTransPers.Flags, gp_Pnt (theTransPers.Point.x(),
285                                                                      theTransPers.Point.y(),
286                                                                      theTransPers.Point.z()));
287
288   Handle(Graphic3d_Group) aSensGroup  = theStructure->NewGroup();
289
290   Quantity_Color aColor (Quantity_NOC_INDIANRED3);
291   Handle(Graphic3d_AspectMarker3d) aMarkerAspect =
292     new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0);
293
294   aSensGroup->SetPrimitivesAspect (aMarkerAspect);
295   aSensGroup->SetPrimitivesAspect (
296     new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
297
298   Handle(Graphic3d_Group) anAreaGroup = theStructure->NewGroup();
299
300   anAreaGroup->SetPrimitivesAspect (
301     new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
302
303   TColgp_SequenceOfPnt aSeqLines, aSeqFree;
304   TColStd_SequenceOfInteger aSeqBnds;
305
306   for (theSel->Init(); theSel->More(); theSel->Next())
307   {
308     Handle(Select3D_SensitiveEntity) Ent =
309       Handle(Select3D_SensitiveEntity)::DownCast(theSel->Sensitive()->BaseSensitive());
310     const Standard_Boolean hasloc = theLoc.Form() != gp_Identity;
311
312     //==============
313     // Box
314     //=============
315
316     if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveBox))
317     {
318       const Bnd_Box& B = Handle(Select3D_SensitiveBox)::DownCast (Ent)->Box();
319       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
320       B.Get (xmin, ymin, zmin, xmax, ymax, zmax);
321       Standard_Integer i;
322       gp_Pnt theboxpoint[8] =
323       {
324         gp_Pnt(xmin,ymin,zmin),
325         gp_Pnt(xmax,ymin,zmin),
326         gp_Pnt(xmax,ymax,zmin),
327         gp_Pnt(xmin,ymax,zmin),
328         gp_Pnt(xmin,ymin,zmax),
329         gp_Pnt(xmax,ymin,zmax),
330         gp_Pnt(xmax,ymax,zmax),
331         gp_Pnt(xmin,ymax,zmax)
332       };
333       if(hasloc)
334       {
335         for (i = 0; i <= 7; i++)
336           theboxpoint[i].Transform (theLoc);
337       }
338
339       aSeqBnds.Append(5);
340       for (i = 0; i < 4; i++)
341         aSeqLines.Append(theboxpoint[i]);
342       aSeqLines.Append(theboxpoint[0]);
343
344       aSeqBnds.Append(5);
345       for (i = 4; i < 8; i++)
346         aSeqLines.Append(theboxpoint[i]);
347       aSeqLines.Append(theboxpoint[4]);
348
349       for (i = 0; i < 4; i++)
350       {
351         aSeqBnds.Append(2);
352         aSeqLines.Append(theboxpoint[i]);
353         aSeqLines.Append(theboxpoint[i+4]);
354       }
355     }
356     //==============
357     // Face
358     //=============
359     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveFace))
360     {
361       Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(Ent);
362       Handle(TColgp_HArray1OfPnt) TheHPts;
363       aFace->GetPoints(TheHPts);
364       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
365
366       aSeqBnds.Append(ThePts.Length());
367       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
368       {
369         if (hasloc)
370           aSeqLines.Append(ThePts(I).Transformed (theLoc));
371         else
372           aSeqLines.Append(ThePts(I));
373       }
374     }
375     //==============
376     // Curve
377     //=============
378     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
379     {
380       Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(Ent);
381       Handle(TColgp_HArray1OfPnt) TheHPts;
382       aCurve->Points3D(TheHPts);
383       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
384
385       aSeqBnds.Append(ThePts.Length());
386       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
387       {
388         if (hasloc)
389           aSeqLines.Append(ThePts(I).Transformed (theLoc));
390         else
391           aSeqLines.Append(ThePts(I));
392       }
393     }
394     //==============
395     // Wire
396     //=============
397     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveWire))
398     {
399       Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(Ent);
400       const NCollection_Vector<Handle(Select3D_SensitiveEntity)>& anEntities = aWire->GetEdges();
401
402       for (int i = 0; i < anEntities.Length(); i++)
403       {
404         Handle(Select3D_SensitiveEntity) SubEnt = Handle(Select3D_SensitiveEntity)::DownCast(anEntities.Value(i));
405
406         //Segment
407         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
408         {
409           gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->StartPoint().XYZ());
410           gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->EndPoint().XYZ());
411           if (hasloc)
412           {
413             P1.Transform(theLoc);
414             P2.Transform(theLoc);
415           }
416           aSeqBnds.Append(2);
417           aSeqLines.Append(P1);
418           aSeqLines.Append(P2);
419         }
420
421         //circle
422         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
423         {
424           Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(SubEnt);
425           Standard_Integer aFrom, aTo;
426           aCircle->ArrayBounds (aFrom, aTo);
427           aTo -= 2;
428           for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
429           {
430             gp_Pnt aPnts[3] =
431             {
432               gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
433               gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
434               gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
435             };
436
437             if (hasloc)
438             {
439               aPnts[0].Transform (theLoc);
440               aPnts[1].Transform (theLoc);
441               aPnts[2].Transform (theLoc);
442             }
443
444             aSeqBnds.Append (4);
445             aSeqLines.Append (aPnts[0]);
446             aSeqLines.Append (aPnts[1]);
447             aSeqLines.Append (aPnts[2]);
448             aSeqLines.Append (aPnts[0]);
449           }
450         }
451
452         //curve
453         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
454         {
455           Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(SubEnt);
456           Handle(TColgp_HArray1OfPnt) TheHPts;
457           aCurve->Points3D (TheHPts);
458           const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
459
460           aSeqBnds.Append(ThePts.Length());
461           for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
462           {
463             if (hasloc)
464               aSeqLines.Append(ThePts(I).Transformed (theLoc));
465             else
466               aSeqLines.Append(ThePts(I));
467           }
468         }
469       }
470     }
471     //==============
472     // Segment
473     //=============
474     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
475     {
476       gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->StartPoint().XYZ());
477       gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->EndPoint().XYZ());
478       if (hasloc)
479       {
480         P1.Transform (theLoc);
481         P2.Transform (theLoc);
482       }
483       aSeqBnds.Append(2);
484       aSeqLines.Append(P1);
485       aSeqLines.Append(P2);
486     }
487     //==============
488     // Circle
489     //=============
490     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
491     {
492       Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(Ent);
493       Standard_Integer aFrom, aTo;
494       aCircle->ArrayBounds (aFrom, aTo);
495       aTo -= 2;
496       for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
497       {
498         gp_Pnt aPnts[3] =
499         {
500           gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
501           gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
502           gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
503         };
504
505         if (hasloc)
506         {
507           aPnts[0].Transform (theLoc);
508           aPnts[1].Transform (theLoc);
509           aPnts[2].Transform (theLoc);
510         }
511
512         aSeqBnds.Append (4);
513         aSeqLines.Append (aPnts[0]);
514         aSeqLines.Append (aPnts[1]);
515         aSeqLines.Append (aPnts[2]);
516         aSeqLines.Append (aPnts[0]);
517       }
518     }
519     //==============
520     // Point
521     //=============
522     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitivePoint))
523     {
524       gp_Pnt P = hasloc ?
525         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point() :
526         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theLoc);
527       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
528       anArrayOfPoints->AddVertex (P.X(), P.Y(), P.Z());
529       aSensGroup->AddPrimitiveArray (anArrayOfPoints);
530     }
531     //============================================================
532     // Triangulation : On met un petit offset ves l'interieur...
533     //==========================================================
534     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangulation))
535     {
536       Handle(Poly_Triangulation) PT (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->Triangulation());
537
538       const Poly_Array1OfTriangle& triangles = PT->Triangles();
539       const TColgp_Array1OfPnt& Nodes = PT->Nodes();
540       Standard_Integer n[3];
541
542       TopLoc_Location iloc, bidloc;
543       if (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->HasInitLocation())
544         bidloc = Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->GetInitLocation();
545
546       if (bidloc.IsIdentity())
547         iloc = theLoc;
548       else
549         iloc = theLoc * bidloc;
550
551       Standard_Integer i;
552       for (i = 1; i <= PT->NbTriangles(); i++)
553       {
554         triangles (i).Get (n[0], n[1], n[2]);
555         gp_Pnt P1 (Nodes (n[0]).Transformed (iloc));
556         gp_Pnt P2 (Nodes (n[1]).Transformed (iloc));
557         gp_Pnt P3 (Nodes (n[2]).Transformed (iloc));
558         gp_XYZ V1 (P1.XYZ());
559         gp_XYZ V2 (P2.XYZ());
560         gp_XYZ V3 (P3.XYZ());
561         gp_XYZ CDG (P1.XYZ()); CDG += (P2.XYZ()); CDG += (P3.XYZ()); CDG /= 3.0;
562         V1 -= CDG; V2 -= CDG; V3 -= CDG;
563         V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
564         V1 += CDG; V2 += CDG; V3 += CDG;
565
566         aSeqBnds.Append(4);
567         aSeqLines.Append(gp_Pnt(V1));
568         aSeqLines.Append(gp_Pnt(V2));
569         aSeqLines.Append(gp_Pnt(V3));
570         aSeqLines.Append(gp_Pnt(V1));
571       }
572
573       // recherche des bords libres...
574
575       Handle(TColStd_HArray1OfInteger) FreeEdges = new TColStd_HArray1OfInteger (1, 2 * StdSel_NumberOfFreeEdges (PT));
576       TColStd_Array1OfInteger& FreeE = FreeEdges->ChangeArray1();
577       Poly_Connect pc (PT);
578       Standard_Integer t[3];
579       Standard_Integer j;
580       Standard_Integer fr (1);
581       for (i = 1; i <= PT->NbTriangles(); i++)
582       {
583         pc.Triangles (i, t[0], t[1], t[2]);
584         triangles (i).Get (n[0], n[1], n[2]);
585         for (j = 0; j < 3; j++)
586         {
587           Standard_Integer k = (j + 1) % 3;
588           if (t[j] == 0)
589           {
590             FreeE (fr)    = n[j];
591             FreeE (fr + 1)= n[k];
592             fr += 2;
593           }
594         }
595       }
596       for (Standard_Integer ifri = 1; ifri <= FreeE.Length(); ifri += 2)
597       {
598         gp_Pnt pe1 (Nodes (FreeE (ifri)).Transformed (iloc)), pe2 (Nodes (FreeE (ifri + 1)).Transformed (iloc));
599         aSeqFree.Append(pe1);
600         aSeqFree.Append(pe2);
601       }
602     }
603     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangle))
604     {
605       Handle(Select3D_SensitiveTriangle) Str = Handle(Select3D_SensitiveTriangle)::DownCast(Ent);
606       gp_Pnt P1, P2, P3;
607       Str->Points3D (P1, P2, P3);
608       gp_Pnt CDG = Str->Center3D();
609
610       gp_XYZ V1 (P1.XYZ()); V1 -= (CDG.XYZ());
611       gp_XYZ V2 (P2.XYZ()); V2 -= (CDG.XYZ());
612       gp_XYZ V3 (P3.XYZ()); V3 -= (CDG.XYZ());
613       V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
614       V1 += CDG.XYZ(); V2 += CDG.XYZ(); V3 += CDG.XYZ();
615
616       aSeqBnds.Append(4);
617       aSeqLines.Append(gp_Pnt(V1));
618       aSeqLines.Append(gp_Pnt(V2));
619       aSeqLines.Append(gp_Pnt(V3));
620       aSeqLines.Append(gp_Pnt(V1));
621     }
622   }
623
624   Standard_Integer i;
625
626   if (aSeqLines.Length())
627   {
628     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),aSeqBnds.Length());
629     for (i = 1; i <= aSeqLines.Length(); i++)
630       aPrims->AddVertex(aSeqLines(i));
631     for (i = 1; i <= aSeqBnds.Length(); i++)
632       aPrims->AddBound(aSeqBnds(i));
633     anAreaGroup->AddPrimitiveArray(aPrims);
634   }
635
636   if (aSeqFree.Length())
637   {
638     aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0));
639     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqFree.Length(),aSeqFree.Length()/2);
640     for (i = 1; i <= aSeqFree.Length(); i++)
641     {
642       aPrims->AddBound(2);
643       aPrims->AddVertex(aSeqLines(i++));
644       aPrims->AddVertex(aSeqLines(i));
645     }
646     aSensGroup->AddPrimitiveArray(aPrims);
647     aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
648   }
649 }
650
651 //=======================================================================
652 //function : SetClipping
653 //purpose  :
654 //=======================================================================
655 void StdSelect_ViewerSelector3d::SetClipping (const Graphic3d_SequenceOfHClipPlane& thePlanes)
656 {
657   myClipPlanes = thePlanes;
658 }
659
660 //=======================================================================
661 //function : HasDepthClipping
662 //purpose  :
663 //=======================================================================
664 Standard_Boolean StdSelect_ViewerSelector3d::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const
665 {
666   if (!theOwner->HasSelectable())
667   {
668     return Standard_False;
669   }
670
671   const Handle(SelectMgr_SelectableObject)& aSelectable = theOwner->Selectable();
672   return (aSelectable->GetClipPlanes().Size() > 0);
673 }