d161705e7a1676e11e9e1460501f619b51794ae6
[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 <math_BullardGenerator.hxx>
56 #include <Message.hxx>
57 #include <Message_Messenger.hxx>
58 #include <Quantity_ColorHasher.hxx>
59 #include <Poly_Connect.hxx>
60 #include <TColStd_HArray1OfInteger.hxx>
61
62 #include <Poly_Array1OfTriangle.hxx>
63 #include <Poly_Triangulation.hxx>
64 #include <OSD_Environment.hxx>
65 #include <V3d.hxx>
66 #include <V3d_View.hxx>
67 #include <V3d_Viewer.hxx>
68 #include <TColgp_SequenceOfPnt.hxx>
69
70 #include <OSD_Timer.hxx>
71
72
73 IMPLEMENT_STANDARD_RTTIEXT(StdSelect_ViewerSelector3d,SelectMgr_ViewerSelector)
74
75 static Standard_Integer StdSel_NumberOfFreeEdges (const Handle(Poly_Triangulation)& Trg)
76 {
77   Standard_Integer nFree = 0;
78   Poly_Connect pc(Trg);
79   Standard_Integer t[3];
80   Standard_Integer i, j;
81   for (i = 1; i <= Trg->NbTriangles(); i++)
82   {
83     pc.Triangles (i, t[0], t[1], t[2]);
84     for (j = 0; j < 3; j++)
85       if (t[j] == 0) nFree++;
86   }
87   return nFree;
88 }
89
90 //=======================================================================
91 // Function : Constructor
92 // Purpose  :
93 //=======================================================================
94 StdSelect_ViewerSelector3d::StdSelect_ViewerSelector3d() {}
95
96 //=======================================================================
97 // Function: SetPixelTolerance
98 // Purpose :
99 //=======================================================================
100 void StdSelect_ViewerSelector3d::SetPixelTolerance (const Standard_Integer theTolerance)
101 {
102   if (myTolerances.Tolerance() != theTolerance)
103   {
104     if (theTolerance < 0)
105       myTolerances.ResetDefaults();
106     else
107       myTolerances.SetCustomTolerance (theTolerance);
108     myToUpdateTolerance = Standard_True;
109   }
110 }
111
112 //=======================================================================
113 // Function: Pick
114 // Purpose :
115 //=======================================================================
116 void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPix,
117                                        const Standard_Integer theYPix,
118                                        const Handle(V3d_View)& theView)
119 {
120   updateZLayers (theView);
121   if(myToUpdateTolerance)
122   {
123     mySelectingVolumeMgr.SetPixelTolerance (myTolerances.Tolerance());
124     myToUpdateTolerance = Standard_False;
125   }
126
127   mySelectingVolumeMgr.SetCamera (theView->Camera());
128   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Point);
129   Standard_Integer aWidth = 0, aHeight = 0;
130   theView->Window()->Size (aWidth, aHeight);
131   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
132   gp_Pnt2d aMousePos (static_cast<Standard_Real> (theXPix),
133                       static_cast<Standard_Real> (theYPix));
134   mySelectingVolumeMgr.BuildSelectingVolume (aMousePos);
135   mySelectingVolumeMgr.SetViewClipping (theView->ClipPlanes());
136
137   TraverseSensitives();
138 }
139
140 //=======================================================================
141 // Function: Pick
142 // Purpose :
143 //=======================================================================
144 void StdSelect_ViewerSelector3d::Pick (const Standard_Integer theXPMin,
145                                        const Standard_Integer theYPMin,
146                                        const Standard_Integer theXPMax,
147                                        const Standard_Integer theYPMax,
148                                        const Handle(V3d_View)& theView)
149 {
150   updateZLayers (theView);
151   mySelectingVolumeMgr.SetCamera (theView->Camera());
152   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Box);
153   Standard_Integer aWidth = 0, aHeight = 0;
154   theView->Window()->Size (aWidth, aHeight);
155   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
156   gp_Pnt2d aMinMousePos (static_cast<Standard_Real> (theXPMin),
157                          static_cast<Standard_Real> (theYPMin));
158   gp_Pnt2d aMaxMousePos (static_cast<Standard_Real> (theXPMax),
159                          static_cast<Standard_Real> (theYPMax));
160   mySelectingVolumeMgr.BuildSelectingVolume (aMinMousePos,
161                                              aMaxMousePos);
162
163   TraverseSensitives();
164 }
165
166 //=======================================================================
167 // Function: Pick
168 // Purpose : Selection using a polyline
169 //=======================================================================
170 void StdSelect_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline,
171                                        const Handle(V3d_View)& theView)
172 {
173   updateZLayers (theView);
174   mySelectingVolumeMgr.SetCamera (theView->Camera());
175   mySelectingVolumeMgr.SetActiveSelectionType (SelectMgr_SelectingVolumeManager::Polyline);
176   Standard_Integer aWidth = 0, aHeight = 0;
177   theView->Window()->Size (aWidth, aHeight);
178   mySelectingVolumeMgr.SetWindowSize (aWidth, aHeight);
179   mySelectingVolumeMgr.BuildSelectingVolume (thePolyline);
180
181   TraverseSensitives();
182 }
183
184 //=======================================================================
185 // Function: DisplaySensitive.
186 // Purpose : Display active primitives.
187 //=======================================================================
188 void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theView)
189 {
190   SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects);
191
192   for (; aSelectableIt.More(); aSelectableIt.Next())
193   {
194     const Handle (SelectMgr_SelectableObject)& anObj = aSelectableIt.Value();
195
196     Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
197
198     for (anObj->Init(); anObj->More(); anObj->Next())
199     {
200       if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated)
201       {
202         computeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), Handle(Graphic3d_TransformPers)());
203       }
204     }
205
206     myStructs.Append (aStruct);
207   }
208
209   for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx)
210   {
211     Handle(Graphic3d_Structure)& aStruct = myStructs.ChangeValue (aStructIdx);
212     aStruct->SetDisplayPriority (10);
213     aStruct->Display();
214   }
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   for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx)
226   {
227     myStructs.Value (aStructIdx)->Remove();
228   }
229
230   myStructs.Clear();
231
232   if (!theView.IsNull())
233   {
234     theView->Update();
235   }
236 }
237
238 //=======================================================================
239 //function : DisplaySenstive
240 //purpose  :
241 //=======================================================================
242 void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(SelectMgr_Selection)& theSel,
243                                                    const gp_Trsf& theTrsf,
244                                                    const Handle(V3d_View)& theView,
245                                                    const Standard_Boolean theToClearOthers)
246 {
247   if (theToClearOthers)
248   {
249     ClearSensitive (theView);
250   }
251
252   Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager());
253
254   computeSensitivePrs (aStruct, theSel, theTrsf, Handle(Graphic3d_TransformPers)());
255
256   myStructs.Append (aStruct);
257   myStructs.Last()->SetDisplayPriority (10);
258   myStructs.Last()->Display();
259
260   theView->Update();
261 }
262
263 //=======================================================================
264 //function : computeSensitivePrs
265 //purpose  :
266 //=======================================================================
267 void StdSelect_ViewerSelector3d::computeSensitivePrs (const Handle(Graphic3d_Structure)& theStructure,
268                                                       const Handle(SelectMgr_Selection)& theSel,
269                                                       const gp_Trsf& theLoc,
270                                                       const Handle(Graphic3d_TransformPers)& theTrsfPers)
271 {
272   theStructure->SetTransformPersistence (theTrsfPers);
273
274   Handle(Graphic3d_Group) aSensGroup  = theStructure->NewGroup();
275
276   Quantity_Color aColor (Quantity_NOC_INDIANRED3);
277   Handle(Graphic3d_AspectMarker3d) aMarkerAspect =
278     new Graphic3d_AspectMarker3d (Aspect_TOM_O_PLUS, aColor, 2.0);
279
280   aSensGroup->SetPrimitivesAspect (aMarkerAspect);
281   aSensGroup->SetPrimitivesAspect (
282     new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
283
284   Handle(Graphic3d_Group) anAreaGroup = theStructure->NewGroup();
285
286   anAreaGroup->SetPrimitivesAspect (
287     new Graphic3d_AspectLine3d (Quantity_NOC_AQUAMARINE1, Aspect_TOL_DASH, 1.0));
288
289   TColgp_SequenceOfPnt aSeqLines, aSeqFree;
290   TColStd_SequenceOfInteger aSeqBnds;
291
292   for (theSel->Init(); theSel->More(); theSel->Next())
293   {
294     Handle(Select3D_SensitiveEntity) Ent =
295       Handle(Select3D_SensitiveEntity)::DownCast(theSel->Sensitive()->BaseSensitive());
296     const Standard_Boolean hasloc = theLoc.Form() != gp_Identity;
297
298     //==============
299     // Box
300     //=============
301
302     if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveBox))
303     {
304       const Bnd_Box& B = Handle(Select3D_SensitiveBox)::DownCast (Ent)->Box();
305       Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
306       B.Get (xmin, ymin, zmin, xmax, ymax, zmax);
307       Standard_Integer i;
308       gp_Pnt theboxpoint[8] =
309       {
310         gp_Pnt(xmin,ymin,zmin),
311         gp_Pnt(xmax,ymin,zmin),
312         gp_Pnt(xmax,ymax,zmin),
313         gp_Pnt(xmin,ymax,zmin),
314         gp_Pnt(xmin,ymin,zmax),
315         gp_Pnt(xmax,ymin,zmax),
316         gp_Pnt(xmax,ymax,zmax),
317         gp_Pnt(xmin,ymax,zmax)
318       };
319       if(hasloc)
320       {
321         for (i = 0; i <= 7; i++)
322           theboxpoint[i].Transform (theLoc);
323       }
324
325       aSeqBnds.Append(5);
326       for (i = 0; i < 4; i++)
327         aSeqLines.Append(theboxpoint[i]);
328       aSeqLines.Append(theboxpoint[0]);
329
330       aSeqBnds.Append(5);
331       for (i = 4; i < 8; i++)
332         aSeqLines.Append(theboxpoint[i]);
333       aSeqLines.Append(theboxpoint[4]);
334
335       for (i = 0; i < 4; i++)
336       {
337         aSeqBnds.Append(2);
338         aSeqLines.Append(theboxpoint[i]);
339         aSeqLines.Append(theboxpoint[i+4]);
340       }
341     }
342     //==============
343     // Face
344     //=============
345     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveFace))
346     {
347       Handle(Select3D_SensitiveFace) aFace = Handle(Select3D_SensitiveFace)::DownCast(Ent);
348       Handle(TColgp_HArray1OfPnt) TheHPts;
349       aFace->GetPoints(TheHPts);
350       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
351
352       aSeqBnds.Append(ThePts.Length());
353       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
354       {
355         if (hasloc)
356           aSeqLines.Append(ThePts(I).Transformed (theLoc));
357         else
358           aSeqLines.Append(ThePts(I));
359       }
360     }
361     //==============
362     // Curve
363     //=============
364     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
365     {
366       Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(Ent);
367       Handle(TColgp_HArray1OfPnt) TheHPts;
368       aCurve->Points3D(TheHPts);
369       const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
370
371       aSeqBnds.Append(ThePts.Length());
372       for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
373       {
374         if (hasloc)
375           aSeqLines.Append(ThePts(I).Transformed (theLoc));
376         else
377           aSeqLines.Append(ThePts(I));
378       }
379     }
380     //==============
381     // Wire
382     //=============
383     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveWire))
384     {
385       Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast(Ent);
386       const NCollection_Vector<Handle(Select3D_SensitiveEntity)>& anEntities = aWire->GetEdges();
387
388       for (int i = 0; i < anEntities.Length(); i++)
389       {
390         Handle(Select3D_SensitiveEntity) SubEnt = anEntities.Value(i);
391
392         //Segment
393         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
394         {
395           gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->StartPoint().XYZ());
396           gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(SubEnt)->EndPoint().XYZ());
397           if (hasloc)
398           {
399             P1.Transform(theLoc);
400             P2.Transform(theLoc);
401           }
402           aSeqBnds.Append(2);
403           aSeqLines.Append(P1);
404           aSeqLines.Append(P2);
405         }
406
407         //circle
408         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
409         {
410           Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(SubEnt);
411           Standard_Integer aFrom, aTo;
412           aCircle->ArrayBounds (aFrom, aTo);
413           aTo -= 2;
414           for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
415           {
416             gp_Pnt aPnts[3] =
417             {
418               gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
419               gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
420               gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
421             };
422
423             if (hasloc)
424             {
425               aPnts[0].Transform (theLoc);
426               aPnts[1].Transform (theLoc);
427               aPnts[2].Transform (theLoc);
428             }
429
430             aSeqBnds.Append (4);
431             aSeqLines.Append (aPnts[0]);
432             aSeqLines.Append (aPnts[1]);
433             aSeqLines.Append (aPnts[2]);
434             aSeqLines.Append (aPnts[0]);
435           }
436         }
437
438         //curve
439         if (SubEnt->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCurve))
440         {
441           Handle(Select3D_SensitiveCurve) aCurve = Handle(Select3D_SensitiveCurve)::DownCast(SubEnt);
442           Handle(TColgp_HArray1OfPnt) TheHPts;
443           aCurve->Points3D (TheHPts);
444           const TColgp_Array1OfPnt& ThePts = TheHPts->Array1();
445
446           aSeqBnds.Append(ThePts.Length());
447           for (Standard_Integer I = ThePts.Lower(); I <= ThePts.Upper(); I++)
448           {
449             if (hasloc)
450               aSeqLines.Append(ThePts(I).Transformed (theLoc));
451             else
452               aSeqLines.Append(ThePts(I));
453           }
454         }
455       }
456     }
457     //==============
458     // Segment
459     //=============
460     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveSegment))
461     {
462       gp_Pnt P1 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->StartPoint().XYZ());
463       gp_Pnt P2 (Handle(Select3D_SensitiveSegment)::DownCast(Ent)->EndPoint().XYZ());
464       if (hasloc)
465       {
466         P1.Transform (theLoc);
467         P2.Transform (theLoc);
468       }
469       aSeqBnds.Append(2);
470       aSeqLines.Append(P1);
471       aSeqLines.Append(P2);
472     }
473     //==============
474     // Circle
475     //=============
476     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveCircle))
477     {
478       Handle(Select3D_SensitiveCircle) aCircle = Handle(Select3D_SensitiveCircle)::DownCast(Ent);
479       Standard_Integer aFrom, aTo;
480       aCircle->ArrayBounds (aFrom, aTo);
481       aTo -= 2;
482       for (Standard_Integer aPntIter = aFrom; aPntIter <= aTo; aPntIter += 2)
483       {
484         gp_Pnt aPnts[3] =
485         {
486           gp_Pnt (aCircle->GetPoint3d (aPntIter + 0).XYZ()),
487           gp_Pnt (aCircle->GetPoint3d (aPntIter + 1).XYZ()),
488           gp_Pnt (aCircle->GetPoint3d (aPntIter + 2).XYZ())
489         };
490
491         if (hasloc)
492         {
493           aPnts[0].Transform (theLoc);
494           aPnts[1].Transform (theLoc);
495           aPnts[2].Transform (theLoc);
496         }
497
498         aSeqBnds.Append (4);
499         aSeqLines.Append (aPnts[0]);
500         aSeqLines.Append (aPnts[1]);
501         aSeqLines.Append (aPnts[2]);
502         aSeqLines.Append (aPnts[0]);
503       }
504     }
505     //==============
506     // Point
507     //=============
508     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitivePoint))
509     {
510       gp_Pnt P = hasloc ?
511         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point() :
512         Handle(Select3D_SensitivePoint)::DownCast(Ent)->Point().Transformed (theLoc);
513       Handle(Graphic3d_ArrayOfPoints) anArrayOfPoints = new Graphic3d_ArrayOfPoints (1);
514       anArrayOfPoints->AddVertex (P.X(), P.Y(), P.Z());
515       aSensGroup->AddPrimitiveArray (anArrayOfPoints);
516     }
517     //============================================================
518     // Triangulation : On met un petit offset ves l'interieur...
519     //==========================================================
520     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangulation))
521     {
522       Handle(Poly_Triangulation) PT (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->Triangulation());
523
524       const Poly_Array1OfTriangle& triangles = PT->Triangles();
525       const TColgp_Array1OfPnt& Nodes = PT->Nodes();
526       Standard_Integer n[3];
527
528       TopLoc_Location iloc, bidloc;
529       if (Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->HasInitLocation())
530         bidloc = Handle(Select3D_SensitiveTriangulation)::DownCast (Ent)->GetInitLocation();
531
532       if (bidloc.IsIdentity())
533         iloc = theLoc;
534       else
535         iloc = theLoc * bidloc;
536
537       Standard_Integer i;
538       for (i = 1; i <= PT->NbTriangles(); i++)
539       {
540         triangles (i).Get (n[0], n[1], n[2]);
541         gp_Pnt P1 (Nodes (n[0]).Transformed (iloc));
542         gp_Pnt P2 (Nodes (n[1]).Transformed (iloc));
543         gp_Pnt P3 (Nodes (n[2]).Transformed (iloc));
544         gp_XYZ V1 (P1.XYZ());
545         gp_XYZ V2 (P2.XYZ());
546         gp_XYZ V3 (P3.XYZ());
547         gp_XYZ CDG (P1.XYZ()); CDG += (P2.XYZ()); CDG += (P3.XYZ()); CDG /= 3.0;
548         V1 -= CDG; V2 -= CDG; V3 -= CDG;
549         V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
550         V1 += CDG; V2 += CDG; V3 += CDG;
551
552         aSeqBnds.Append(4);
553         aSeqLines.Append(gp_Pnt(V1));
554         aSeqLines.Append(gp_Pnt(V2));
555         aSeqLines.Append(gp_Pnt(V3));
556         aSeqLines.Append(gp_Pnt(V1));
557       }
558
559       // recherche des bords libres...
560
561       Handle(TColStd_HArray1OfInteger) FreeEdges = new TColStd_HArray1OfInteger (1, 2 * StdSel_NumberOfFreeEdges (PT));
562       TColStd_Array1OfInteger& FreeE = FreeEdges->ChangeArray1();
563       Poly_Connect pc (PT);
564       Standard_Integer t[3];
565       Standard_Integer j;
566       Standard_Integer fr (1);
567       for (i = 1; i <= PT->NbTriangles(); i++)
568       {
569         pc.Triangles (i, t[0], t[1], t[2]);
570         triangles (i).Get (n[0], n[1], n[2]);
571         for (j = 0; j < 3; j++)
572         {
573           Standard_Integer k = (j + 1) % 3;
574           if (t[j] == 0)
575           {
576             FreeE (fr)    = n[j];
577             FreeE (fr + 1)= n[k];
578             fr += 2;
579           }
580         }
581       }
582       for (Standard_Integer ifri = 1; ifri <= FreeE.Length(); ifri += 2)
583       {
584         gp_Pnt pe1 (Nodes (FreeE (ifri)).Transformed (iloc)), pe2 (Nodes (FreeE (ifri + 1)).Transformed (iloc));
585         aSeqFree.Append(pe1);
586         aSeqFree.Append(pe2);
587       }
588     }
589     else if (Ent->DynamicType()==STANDARD_TYPE(Select3D_SensitiveTriangle))
590     {
591       Handle(Select3D_SensitiveTriangle) Str = Handle(Select3D_SensitiveTriangle)::DownCast(Ent);
592       gp_Pnt P1, P2, P3;
593       Str->Points3D (P1, P2, P3);
594       gp_Pnt CDG = Str->Center3D();
595
596       gp_XYZ V1 (P1.XYZ()); V1 -= (CDG.XYZ());
597       gp_XYZ V2 (P2.XYZ()); V2 -= (CDG.XYZ());
598       gp_XYZ V3 (P3.XYZ()); V3 -= (CDG.XYZ());
599       V1 *= 0.9; V2 *= 0.9; V3 *= 0.9;
600       V1 += CDG.XYZ(); V2 += CDG.XYZ(); V3 += CDG.XYZ();
601
602       aSeqBnds.Append(4);
603       aSeqLines.Append(gp_Pnt(V1));
604       aSeqLines.Append(gp_Pnt(V2));
605       aSeqLines.Append(gp_Pnt(V3));
606       aSeqLines.Append(gp_Pnt(V1));
607     }
608   }
609
610   Standard_Integer i;
611
612   if (aSeqLines.Length())
613   {
614     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqLines.Length(),aSeqBnds.Length());
615     for (i = 1; i <= aSeqLines.Length(); i++)
616       aPrims->AddVertex(aSeqLines(i));
617     for (i = 1; i <= aSeqBnds.Length(); i++)
618       aPrims->AddBound(aSeqBnds(i));
619     anAreaGroup->AddPrimitiveArray(aPrims);
620   }
621
622   if (aSeqFree.Length())
623   {
624     aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GREEN, Aspect_TOL_SOLID, 2.0));
625     Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(aSeqFree.Length(),aSeqFree.Length()/2);
626     for (i = 1; i <= aSeqFree.Length(); i++)
627     {
628       aPrims->AddBound(2);
629       aPrims->AddVertex(aSeqLines(i++));
630       aPrims->AddVertex(aSeqLines(i));
631     }
632     aSensGroup->AddPrimitiveArray(aPrims);
633     aSensGroup->SetPrimitivesAspect (new Graphic3d_AspectLine3d (Quantity_NOC_GRAY40, Aspect_TOL_SOLID, 2.0));
634   }
635 }
636
637 //=======================================================================
638 //function : HasDepthClipping
639 //purpose  :
640 //=======================================================================
641 Standard_Boolean StdSelect_ViewerSelector3d::HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const
642 {
643   if (!theOwner->HasSelectable())
644   {
645     return Standard_False;
646   }
647
648   const Handle(SelectMgr_SelectableObject)& aSelectable = theOwner->Selectable();
649   return !aSelectable->ClipPlanes().IsNull()
650       && !aSelectable->ClipPlanes()->IsEmpty();
651 }
652
653 //=======================================================================
654 // Function: updateZLayers
655 // Purpose :
656 //=======================================================================
657 void StdSelect_ViewerSelector3d::updateZLayers (const Handle(V3d_View)& theView)
658 {
659   myZLayerOrderMap.Clear();
660   TColStd_SequenceOfInteger aZLayers;
661   theView->Viewer()->GetAllZLayers (aZLayers);
662   Standard_Integer aPos = 0;
663   Standard_Boolean isPrevDepthWrite = true;
664   for (TColStd_SequenceOfInteger::Iterator aLayerIter (aZLayers); aLayerIter.More(); aLayerIter.Next())
665   {
666     Graphic3d_ZLayerSettings aSettings = theView->Viewer()->ZLayerSettings (aLayerIter.Value());
667     if (aSettings.ToClearDepth()
668      || isPrevDepthWrite != aSettings.ToEnableDepthWrite())
669     {
670       ++aPos;
671     }
672     isPrevDepthWrite = aSettings.ToEnableDepthWrite();
673     myZLayerOrderMap.Bind (aLayerIter.Value(), aPos);
674   }
675 }
676
677 namespace
678 {
679   //! Abstract class for filling pixel with color.
680   class BaseFiller : public Standard_Transient
681   {
682     DEFINE_STANDARD_RTTI_INLINE(BaseFiller, Standard_Transient)
683   public:
684
685     //! Main constructor.
686     BaseFiller (Image_PixMap&               thePixMap,
687                 StdSelect_ViewerSelector3d* theSelector)
688     : myImage  (&thePixMap),
689       myMainSel(theSelector) {}
690
691     //! Fill pixel at specified position.
692     virtual void Fill (const Standard_Integer theCol,
693                        const Standard_Integer theRow,
694                        const Standard_Integer thePicked) = 0;
695
696     //! Flush results into final image.
697     virtual void Flush() {}
698
699   protected:
700
701     //! Find the new unique random color.
702     void randomPastelColor (Quantity_Color& theColor)
703     {
704       for (;;)
705       {
706         nextRandomPastelColor (theColor);
707         if (myUniqueColors.Add (theColor))
708         {
709           return;
710         }
711       }
712     }
713
714     //! Fills the given color as random.
715     void nextRandomPastelColor (Quantity_Color& theColor)
716     {
717       theColor = Quantity_Color (Standard_Real(myBullardGenerator.NextInt() % 256) / 255.0,
718                                  Standard_Real(myBullardGenerator.NextInt() % 256) / 255.0,
719                                  Standard_Real(myBullardGenerator.NextInt() % 256) / 255.0,
720                                  Quantity_TOC_RGB);
721     }
722
723   protected:
724     Image_PixMap*               myImage;
725     StdSelect_ViewerSelector3d* myMainSel;
726     math_BullardGenerator       myBullardGenerator;
727     NCollection_Map<Quantity_Color, Quantity_ColorHasher> myUniqueColors;
728   };
729
730   //! Help class for filling pixel with random color.
731   class GeneratedEntityColorFiller : public BaseFiller
732   {
733     DEFINE_STANDARD_RTTI_INLINE(GeneratedEntityColorFiller, BaseFiller)
734   public:
735     GeneratedEntityColorFiller (Image_PixMap& thePixMap,
736                                 StdSelect_ViewerSelector3d* theSelector,
737                                 const SelectMgr_SelectableObjectSet& theSelObjects)
738     : BaseFiller (thePixMap, theSelector)
739     {
740       // generate per-entity colors in the order as they have been activated
741       for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelObjects); anObjIter.More(); anObjIter.Next())
742       {
743         const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
744         for (anObj->Init(); anObj->More(); anObj->Next())
745         {
746           const Handle(SelectMgr_Selection)& aSel = anObj->CurrentSelection();
747           for (aSel->Init(); aSel->More(); aSel->Next())
748           {
749             const Handle(SelectMgr_SensitiveEntity)& aSens = aSel->Sensitive();
750             if (!myMapEntityColors.IsBound (aSens->BaseSensitive()))
751             {
752               Quantity_Color aColor;
753               randomPastelColor (aColor);
754               myMapEntityColors.Bind (aSens->BaseSensitive(), aColor);
755             }
756           }
757         }
758       }
759     }
760
761     virtual void Fill (const Standard_Integer theCol,
762                        const Standard_Integer theRow,
763                        const Standard_Integer thePicked) Standard_OVERRIDE
764     {
765       if (thePicked < 1
766        || thePicked > myMainSel->NbPicked())
767       {
768         myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
769         return;
770       }
771
772       const Handle(SelectBasics_SensitiveEntity)& aPickedEntity = myMainSel->PickedEntity (thePicked);
773       Quantity_Color aColor (Quantity_NOC_BLACK);
774       myMapEntityColors.Find (aPickedEntity, aColor);
775       myImage->SetPixelColor (theCol, theRow, aColor);
776     }
777
778   protected:
779     NCollection_DataMap<Handle(SelectBasics_SensitiveEntity), Quantity_Color> myMapEntityColors;
780   };
781
782   //! Help class for filling pixel with normalized depth of ray.
783   class NormalizedDepthFiller : public BaseFiller
784   {
785     DEFINE_STANDARD_RTTI_INLINE(NormalizedDepthFiller, BaseFiller)
786   public:
787     NormalizedDepthFiller (Image_PixMap& thePixMap,
788                            StdSelect_ViewerSelector3d* theSelector,
789                            const Standard_Boolean theToInverse)
790     : BaseFiller (thePixMap, theSelector),
791       myDepthMin ( RealLast()),
792       myDepthMax (-RealLast()),
793       myToInverse(theToInverse)
794     {
795       myUnnormImage.InitZero (Image_PixMap::ImgGrayF, thePixMap.SizeX(), thePixMap.SizeY());
796     }
797
798     //! Accumulate the data.
799     virtual void Fill (const Standard_Integer theCol,
800                        const Standard_Integer theRow,
801                        const Standard_Integer thePicked) Standard_OVERRIDE
802     {
803       if (myUnnormImage.IsEmpty())
804       {
805         return;
806       }
807
808       if (thePicked < 1
809        || thePicked > myMainSel->NbPicked())
810       {
811         myUnnormImage.ChangeValue<float> (theRow, theCol) = ShortRealLast();
812         return;
813       }
814
815       const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
816       myUnnormImage.ChangeValue<float> (theRow, theCol) = float(aSortCriterion.Depth);
817       myDepthMin = Min (myDepthMin, aSortCriterion.Depth);
818       myDepthMax = Max (myDepthMax, aSortCriterion.Depth);
819     }
820
821     //! Normalize the depth values.
822     virtual void Flush() Standard_OVERRIDE
823     {
824       Standard_Real aFrom  = 0.0;
825       Standard_Real aDelta = 1.0;
826       if (myDepthMin <= myDepthMax)
827       {
828         aFrom = myDepthMin;
829         if (myDepthMin != myDepthMax)
830         {
831           aDelta = myDepthMax - myDepthMin;
832         }
833       }
834       for (Standard_Size aRowIter = 0; aRowIter < myUnnormImage.SizeY(); ++aRowIter)
835       {
836         for (Standard_Size aColIter = 0; aColIter < myUnnormImage.SizeX(); ++aColIter)
837         {
838           float aDepth = myUnnormImage.Value<float> (aRowIter, aColIter);
839           if (aDepth <= -ShortRealLast()
840            || aDepth >=  ShortRealLast())
841           {
842             myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
843                                     NCollection_Vec4<float> (0.0f, 0.0f, 0.0f, 1.0f));
844             continue;
845           }
846
847           float aNormDepth = float((Standard_Real(aDepth) - aFrom) / aDelta);
848           if (myToInverse)
849           {
850             aNormDepth = 1.0f - aNormDepth;
851           }
852           myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
853                                   NCollection_Vec4<float> (aNormDepth, aNormDepth, aNormDepth, 1.0f));
854         }
855       }
856     }
857
858   private:
859     Image_PixMap     myUnnormImage;
860     Standard_Real    myDepthMin;
861     Standard_Real    myDepthMax;
862     Standard_Boolean myToInverse;
863   };
864
865   //! Help class for filling pixel with unnormalized depth of ray.
866   class UnnormalizedDepthFiller : public BaseFiller
867   {
868     DEFINE_STANDARD_RTTI_INLINE(UnnormalizedDepthFiller, BaseFiller)
869   public:
870     UnnormalizedDepthFiller (Image_PixMap&               thePixMap,
871                              StdSelect_ViewerSelector3d* theSelector)
872     : BaseFiller (thePixMap, theSelector) {}
873
874     virtual void Fill (const Standard_Integer theCol,
875                        const Standard_Integer theRow,
876                        const Standard_Integer thePicked) Standard_OVERRIDE
877     {
878       if (thePicked < 1
879        || thePicked > myMainSel->NbPicked())
880       {
881         myImage->SetPixelColor (theCol, theRow, NCollection_Vec4<float> (0.0f, 0.0f, 0.0f, 1.0f));
882         return;
883       }
884
885       const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
886       const float aDepth = float(aSortCriterion.Depth);
887       myImage->SetPixelColor (theCol, theRow, NCollection_Vec4<float> (aDepth, aDepth, aDepth, 1.0f));
888     }
889   };
890
891   //! Help class for filling pixel with color of detected object.
892   class GeneratedOwnerColorFiller : public BaseFiller
893   {
894     DEFINE_STANDARD_RTTI_INLINE(GeneratedOwnerColorFiller, BaseFiller)
895   public:
896     GeneratedOwnerColorFiller (Image_PixMap& thePixMap,
897                                StdSelect_ViewerSelector3d* theSelector,
898                                const SelectMgr_SelectableObjectSet& theSelObjects)
899     : BaseFiller (thePixMap, theSelector)
900     {
901       // generate per-owner colors in the order as they have been activated
902       for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelObjects); anObjIter.More(); anObjIter.Next())
903       {
904         const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
905         for (anObj->Init(); anObj->More(); anObj->Next())
906         {
907           const Handle(SelectMgr_Selection)& aSel = anObj->CurrentSelection();
908           for (aSel->Init(); aSel->More(); aSel->Next())
909           {
910             const Handle(SelectMgr_SensitiveEntity)& aSens   = aSel->Sensitive();
911             const Handle(SelectBasics_EntityOwner)&  anOwner = aSens->BaseSensitive()->OwnerId();
912             if (!myMapOwnerColors.IsBound (anOwner))
913             {
914               Quantity_Color aColor;
915               randomPastelColor (aColor);
916               myMapOwnerColors.Bind (anOwner, aColor);
917             }
918           }
919         }
920       }
921     }
922
923     virtual void Fill (const Standard_Integer theCol,
924                        const Standard_Integer theRow,
925                        const Standard_Integer thePicked) Standard_OVERRIDE
926     {
927       if (thePicked < 1
928        || thePicked > myMainSel->NbPicked())
929       {
930         myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
931         return;
932       }
933
934       const Handle(SelectMgr_EntityOwner)& aPickedOwner = myMainSel->Picked (thePicked);
935       Quantity_Color aColor (Quantity_NOC_BLACK);
936       myMapOwnerColors.Find (aPickedOwner, aColor);
937       myImage->SetPixelColor (theCol, theRow, aColor);
938     }
939
940   protected:
941     NCollection_DataMap<Handle(SelectBasics_EntityOwner), Quantity_Color> myMapOwnerColors;
942   };
943
944   //! Help class for filling pixel with random color for each selection mode.
945   class GeneratedSelModeColorFiller : public BaseFiller
946   {
947     DEFINE_STANDARD_RTTI_INLINE(GeneratedSelModeColorFiller, BaseFiller)
948   public:
949     GeneratedSelModeColorFiller (Image_PixMap&               thePixMap,
950                                  StdSelect_ViewerSelector3d* theSelector)
951     : BaseFiller (thePixMap, theSelector)
952     {
953       // generate standard modes in proper order, consider custom objects would use similar scheme
954       myMapSelectionModeColors.Bind (     0, Quantity_NOC_WHITE);          // default (entire object selection)
955       myMapSelectionModeColors.Bind (     1, Quantity_NOC_YELLOW);         // TopAbs_VERTEX
956       myMapSelectionModeColors.Bind (     2, Quantity_NOC_GREEN);          // TopAbs_EDGE
957       myMapSelectionModeColors.Bind (     3, Quantity_NOC_RED);            // TopAbs_WIRE
958       myMapSelectionModeColors.Bind (     4, Quantity_NOC_BLUE1);          // TopAbs_FACE
959       myMapSelectionModeColors.Bind (     5, Quantity_NOC_CYAN1);          // TopAbs_SHELL
960       myMapSelectionModeColors.Bind (     6, Quantity_NOC_PURPLE);         // TopAbs_SOLID
961       myMapSelectionModeColors.Bind (     7, Quantity_NOC_MAGENTA1);       // TopAbs_COMPSOLID
962       myMapSelectionModeColors.Bind (     8, Quantity_NOC_BROWN);          // TopAbs_COMPOUND
963       myMapSelectionModeColors.Bind (0x0010, Quantity_NOC_PINK);           // MeshVS_SMF_Volume
964       myMapSelectionModeColors.Bind (0x001E, Quantity_NOC_LIMEGREEN);      // MeshVS_SMF_Element
965       myMapSelectionModeColors.Bind (0x001F, Quantity_NOC_DARKOLIVEGREEN); // MeshVS_SMF_All
966       myMapSelectionModeColors.Bind (0x0100, Quantity_NOC_GOLD);           // MeshVS_SMF_Group
967     }
968
969     virtual void Fill (const Standard_Integer theCol,
970                        const Standard_Integer theRow,
971                        const Standard_Integer thePicked) Standard_OVERRIDE
972     {
973       if (thePicked < 1
974        || thePicked > myMainSel->NbPicked())
975       {
976         myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
977         return;
978       }
979
980       Standard_Integer aSelectionMode = -1;
981       const Handle(SelectMgr_SelectableObject)&   aSelectable = myMainSel->Picked       (thePicked)->Selectable();
982       const Handle(SelectBasics_SensitiveEntity)& anEntity    = myMainSel->PickedEntity (thePicked);
983       for (aSelectable->Init(); aSelectable->More(); aSelectable->Next())
984       {
985         const Handle(SelectMgr_Selection)& aSelection = aSelectable->CurrentSelection();
986         for (aSelection->Init(); aSelection->More(); aSelection->Next())
987         {
988           if (aSelection->Sensitive()->BaseSensitive() == anEntity)
989           {
990             aSelectionMode = aSelection->Mode();
991             break;
992           }
993         }
994       }
995       if (aSelectionMode == -1)
996       {
997         myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
998         return;
999       }
1000
1001       if (!myMapSelectionModeColors.IsBound (aSelectionMode))
1002       {
1003         Quantity_Color aColor;
1004         randomPastelColor (aColor);
1005         myMapSelectionModeColors.Bind (aSelectionMode, aColor);
1006       }
1007
1008       const Quantity_Color& aColor = myMapSelectionModeColors.Find (aSelectionMode);
1009       myImage->SetPixelColor (theCol, theRow, aColor);
1010     }
1011
1012   protected:
1013     NCollection_DataMap<Standard_Integer, Quantity_Color> myMapSelectionModeColors;
1014   };
1015
1016   //! Help class for filling pixel with color of detected shape.
1017   class DetectedObjectColorFiller : public BaseFiller
1018   {
1019     DEFINE_STANDARD_RTTI_INLINE(DetectedObjectColorFiller, BaseFiller)
1020   public:
1021     DetectedObjectColorFiller (Image_PixMap&               thePixMap,
1022                                StdSelect_ViewerSelector3d* theSelector)
1023     : BaseFiller (thePixMap, theSelector) {}
1024
1025     virtual void Fill (const Standard_Integer theCol,
1026                        const Standard_Integer theRow,
1027                        const Standard_Integer thePicked) Standard_OVERRIDE
1028     {
1029       Quantity_Color aColor (Quantity_NOC_BLACK);
1030       if (thePicked > 0
1031        && thePicked <= myMainSel->NbPicked())
1032       {
1033         const Handle(SelectMgr_SelectableObject)& aSelectable = myMainSel->Picked (thePicked)->Selectable();
1034         aColor = aSelectable->Attributes()->Color();
1035       }
1036       myImage->SetPixelColor (theCol, theRow, aColor);
1037     }
1038   };
1039
1040 }
1041
1042 //=======================================================================
1043 //function : ToPixMap
1044 //purpose  :
1045 //=======================================================================
1046 Standard_Boolean StdSelect_ViewerSelector3d::ToPixMap (Image_PixMap&                        theImage,
1047                                                        const Handle(V3d_View)&              theView,
1048                                                        const StdSelect_TypeOfSelectionImage theType,
1049                                                        const Standard_Integer               thePickedIndex)
1050 {
1051   if (theImage.IsEmpty())
1052   {
1053     throw Standard_ProgramError("StdSelect_ViewerSelector3d::ToPixMap() has been called with empty image");
1054   }
1055
1056   Handle(BaseFiller) aFiller;
1057   switch (theType)
1058   {
1059     case StdSelect_TypeOfSelectionImage_NormalizedDepth:
1060     case StdSelect_TypeOfSelectionImage_NormalizedDepthInverted:
1061     {
1062       aFiller = new NormalizedDepthFiller (theImage, this,
1063                                            theType == StdSelect_TypeOfSelectionImage_NormalizedDepthInverted);
1064       break;
1065     }
1066     case StdSelect_TypeOfSelectionImage_UnnormalizedDepth:
1067     {
1068       aFiller = new UnnormalizedDepthFiller (theImage, this);
1069       break;
1070     }
1071     case StdSelect_TypeOfSelectionImage_ColoredDetectedObject:
1072     {
1073       aFiller = new DetectedObjectColorFiller (theImage, this);
1074       break;
1075     }
1076     case StdSelect_TypeOfSelectionImage_ColoredEntity:
1077     {
1078       aFiller = new GeneratedEntityColorFiller (theImage, this, mySelectableObjects);
1079       break;
1080     }
1081     case StdSelect_TypeOfSelectionImage_ColoredOwner:
1082     {
1083       aFiller = new GeneratedOwnerColorFiller (theImage, this, mySelectableObjects);
1084       break;
1085     }
1086     case StdSelect_TypeOfSelectionImage_ColoredSelectionMode:
1087     {
1088       aFiller = new GeneratedSelModeColorFiller (theImage, this);
1089       break;
1090     }
1091   }
1092   if (aFiller.IsNull())
1093   {
1094     return Standard_False;
1095   }
1096
1097   const Standard_Integer aSizeX = static_cast<Standard_Integer> (theImage.SizeX());
1098   const Standard_Integer aSizeY = static_cast<Standard_Integer> (theImage.SizeY());
1099   for (Standard_Integer aRowIter = 0; aRowIter < aSizeY; ++aRowIter)
1100   {
1101     for (Standard_Integer aColIter = 0; aColIter < aSizeX; ++aColIter)
1102     {
1103       Pick (aColIter, aRowIter, theView);
1104       aFiller->Fill (aColIter, aRowIter, thePickedIndex);
1105     }
1106   }
1107   aFiller->Flush();
1108   return Standard_True;
1109 }