0031458: Visualization - refine classes across Prs3d and StdPrs packages
[occt.git] / src / SelectMgr / SelectMgr_SelectionImageFiller.cxx
1 // Copyright (c) 2020 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <SelectMgr_SelectionImageFiller.hxx>
15
16 #include <SelectMgr_ViewerSelector.hxx>
17
18 namespace
19 {
20   //! Help class for filling pixel with random color.
21   class GeneratedEntityColorFiller : public SelectMgr_SelectionImageFiller
22   {
23   public:
24     GeneratedEntityColorFiller (Image_PixMap& thePixMap,
25                                 SelectMgr_ViewerSelector* theSelector)
26     : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
27     {
28       // generate per-entity colors in the order as they have been activated
29       for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelector->SelectableObjects()); anObjIter.More(); anObjIter.Next())
30       {
31         const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
32         for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
33         {
34           const Handle(SelectMgr_Selection)& aSel = aSelIter.Value();
35           for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
36           {
37             const Handle(SelectMgr_SensitiveEntity)& aSens = aSelEntIter.Value();
38             if (!myMapEntityColors.IsBound (aSens->BaseSensitive()))
39             {
40               Quantity_Color aColor;
41               randomPastelColor (aColor);
42               myMapEntityColors.Bind (aSens->BaseSensitive(), aColor);
43             }
44           }
45         }
46       }
47     }
48
49     virtual void Fill (const Standard_Integer theCol,
50                        const Standard_Integer theRow,
51                        const Standard_Integer thePicked) Standard_OVERRIDE
52     {
53       if (thePicked < 1
54        || thePicked > myMainSel->NbPicked())
55       {
56         myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
57         return;
58       }
59
60       const Handle(Select3D_SensitiveEntity)& aPickedEntity = myMainSel->PickedEntity (thePicked);
61       Quantity_Color aColor (Quantity_NOC_BLACK);
62       myMapEntityColors.Find (aPickedEntity, aColor);
63       myImage->SetPixelColor (theCol, theRow, aColor);
64     }
65
66   protected:
67     NCollection_DataMap<Handle(Select3D_SensitiveEntity), Quantity_Color> myMapEntityColors;
68   };
69
70   //! Help class for filling pixel with normalized depth of ray.
71   class NormalizedDepthFiller : public SelectMgr_SelectionImageFiller
72   {
73   public:
74     NormalizedDepthFiller (Image_PixMap& thePixMap,
75                            SelectMgr_ViewerSelector* theSelector,
76                            const Standard_Boolean theToInverse)
77     : SelectMgr_SelectionImageFiller (thePixMap, theSelector),
78       myDepthMin ( RealLast()),
79       myDepthMax (-RealLast()),
80       myToInverse(theToInverse)
81     {
82       myUnnormImage.InitZero (Image_Format_GrayF, thePixMap.SizeX(), thePixMap.SizeY());
83     }
84
85     //! Accumulate the data.
86     virtual void Fill (const Standard_Integer theCol,
87                        const Standard_Integer theRow,
88                        const Standard_Integer thePicked) Standard_OVERRIDE
89     {
90       if (myUnnormImage.IsEmpty())
91       {
92         return;
93       }
94
95       if (thePicked < 1
96        || thePicked > myMainSel->NbPicked())
97       {
98         myUnnormImage.ChangeValue<float> (theRow, theCol) = ShortRealLast();
99         return;
100       }
101
102       const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
103       myUnnormImage.ChangeValue<float> (theRow, theCol) = float(aSortCriterion.Depth);
104       myDepthMin = Min (myDepthMin, aSortCriterion.Depth);
105       myDepthMax = Max (myDepthMax, aSortCriterion.Depth);
106     }
107
108     //! Normalize the depth values.
109     virtual void Flush() Standard_OVERRIDE
110     {
111       float aFrom  = 0.0f;
112       float aDelta = 1.0f;
113       if (myDepthMin <= myDepthMax)
114       {
115         aFrom  = float(myDepthMin);
116         aDelta = float(myDepthMax) - float(myDepthMin);
117         if (aDelta <= ShortRealEpsilon())
118         {
119           aDelta = 1.0f;
120         }
121       }
122       for (Standard_Size aRowIter = 0; aRowIter < myUnnormImage.SizeY(); ++aRowIter)
123       {
124         for (Standard_Size aColIter = 0; aColIter < myUnnormImage.SizeX(); ++aColIter)
125         {
126           float aDepth = myUnnormImage.Value<float> (aRowIter, aColIter);
127           if (aDepth <= -ShortRealLast()
128            || aDepth >=  ShortRealLast())
129           {
130             myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
131                                     Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
132             continue;
133           }
134
135           float aNormDepth = (aDepth - aFrom) / aDelta;
136           if (myToInverse)
137           {
138             aNormDepth = 1.0f - aNormDepth;
139           }
140           myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
141                                   Quantity_ColorRGBA (aNormDepth, aNormDepth, aNormDepth, 1.0f));
142         }
143       }
144     }
145
146   private:
147     Image_PixMap     myUnnormImage;
148     Standard_Real    myDepthMin;
149     Standard_Real    myDepthMax;
150     Standard_Boolean myToInverse;
151   };
152
153   //! Help class for filling pixel with unnormalized depth of ray.
154   class UnnormalizedDepthFiller : public SelectMgr_SelectionImageFiller
155   {
156   public:
157     UnnormalizedDepthFiller (Image_PixMap& thePixMap,
158                              SelectMgr_ViewerSelector* theSelector)
159     : SelectMgr_SelectionImageFiller (thePixMap, theSelector) {}
160
161     virtual void Fill (const Standard_Integer theCol,
162                        const Standard_Integer theRow,
163                        const Standard_Integer thePicked) Standard_OVERRIDE
164     {
165       if (thePicked < 1
166        || thePicked > myMainSel->NbPicked())
167       {
168         myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
169         return;
170       }
171
172       const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
173       const float aDepth = float(aSortCriterion.Depth);
174       myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (Graphic3d_Vec4 (aDepth, aDepth, aDepth, 1.0f)));
175     }
176   };
177
178   //! Help class for filling pixel with color of detected object.
179   class GeneratedOwnerColorFiller : public SelectMgr_SelectionImageFiller
180   {
181   public:
182     GeneratedOwnerColorFiller (Image_PixMap& thePixMap,
183                                SelectMgr_ViewerSelector* theSelector)
184     : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
185     {
186       // generate per-owner colors in the order as they have been activated
187       for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelector->SelectableObjects()); anObjIter.More(); anObjIter.Next())
188       {
189         const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
190         for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
191         {
192           const Handle(SelectMgr_Selection)& aSel = aSelIter.Value();
193           for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
194           {
195             const Handle(SelectMgr_SensitiveEntity)& aSens   = aSelEntIter.Value();
196             const Handle(SelectBasics_EntityOwner)&  anOwner = aSens->BaseSensitive()->OwnerId();
197             if (!myMapOwnerColors.IsBound (anOwner))
198             {
199               Quantity_Color aColor;
200               randomPastelColor (aColor);
201               myMapOwnerColors.Bind (anOwner, aColor);
202             }
203           }
204         }
205       }
206     }
207
208     virtual void Fill (const Standard_Integer theCol,
209                        const Standard_Integer theRow,
210                        const Standard_Integer thePicked) Standard_OVERRIDE
211     {
212       if (thePicked < 1
213        || thePicked > myMainSel->NbPicked())
214       {
215         myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
216         return;
217       }
218
219       const Handle(SelectMgr_EntityOwner)& aPickedOwner = myMainSel->Picked (thePicked);
220       Quantity_Color aColor (Quantity_NOC_BLACK);
221       myMapOwnerColors.Find (aPickedOwner, aColor);
222       myImage->SetPixelColor (theCol, theRow, aColor);
223     }
224
225   protected:
226     NCollection_DataMap<Handle(SelectBasics_EntityOwner), Quantity_Color> myMapOwnerColors;
227   };
228
229   //! Help class for filling pixel with random color for each selection mode.
230   class GeneratedSelModeColorFiller : public SelectMgr_SelectionImageFiller
231   {
232   public:
233     GeneratedSelModeColorFiller (Image_PixMap& thePixMap,
234                                  SelectMgr_ViewerSelector* theSelector)
235     : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
236     {
237       // generate standard modes in proper order, consider custom objects would use similar scheme
238       myMapSelectionModeColors.Bind (     0, Quantity_NOC_WHITE);          // default (entire object selection)
239       myMapSelectionModeColors.Bind (     1, Quantity_NOC_YELLOW);         // TopAbs_VERTEX
240       myMapSelectionModeColors.Bind (     2, Quantity_NOC_GREEN);          // TopAbs_EDGE
241       myMapSelectionModeColors.Bind (     3, Quantity_NOC_RED);            // TopAbs_WIRE
242       myMapSelectionModeColors.Bind (     4, Quantity_NOC_BLUE1);          // TopAbs_FACE
243       myMapSelectionModeColors.Bind (     5, Quantity_NOC_CYAN1);          // TopAbs_SHELL
244       myMapSelectionModeColors.Bind (     6, Quantity_NOC_PURPLE);         // TopAbs_SOLID
245       myMapSelectionModeColors.Bind (     7, Quantity_NOC_MAGENTA1);       // TopAbs_COMPSOLID
246       myMapSelectionModeColors.Bind (     8, Quantity_NOC_BROWN);          // TopAbs_COMPOUND
247       myMapSelectionModeColors.Bind (0x0010, Quantity_NOC_PINK);           // MeshVS_SMF_Volume
248       myMapSelectionModeColors.Bind (0x001E, Quantity_NOC_LIMEGREEN);      // MeshVS_SMF_Element
249       myMapSelectionModeColors.Bind (0x001F, Quantity_NOC_DARKOLIVEGREEN); // MeshVS_SMF_All
250       myMapSelectionModeColors.Bind (0x0100, Quantity_NOC_GOLD);           // MeshVS_SMF_Group
251     }
252
253     virtual void Fill (const Standard_Integer theCol,
254                        const Standard_Integer theRow,
255                        const Standard_Integer thePicked) Standard_OVERRIDE
256     {
257       if (thePicked < 1
258        || thePicked > myMainSel->NbPicked())
259       {
260         myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
261         return;
262       }
263
264       Standard_Integer aSelectionMode = -1;
265       const Handle(SelectMgr_SelectableObject)& aSelectable = myMainSel->Picked       (thePicked)->Selectable();
266       const Handle(Select3D_SensitiveEntity)&   anEntity    = myMainSel->PickedEntity (thePicked);
267       for (SelectMgr_SequenceOfSelection::Iterator aSelIter (aSelectable->Selections()); aSelIter.More(); aSelIter.Next())
268       {
269         const Handle(SelectMgr_Selection)& aSelection = aSelIter.Value();
270         for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
271         {
272           if (aSelEntIter.Value()->BaseSensitive() == anEntity)
273           {
274             aSelectionMode = aSelection->Mode();
275             break;
276           }
277         }
278       }
279       if (aSelectionMode == -1)
280       {
281         myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
282         return;
283       }
284
285       if (!myMapSelectionModeColors.IsBound (aSelectionMode))
286       {
287         Quantity_Color aColor;
288         randomPastelColor (aColor);
289         myMapSelectionModeColors.Bind (aSelectionMode, aColor);
290       }
291
292       const Quantity_Color& aColor = myMapSelectionModeColors.Find (aSelectionMode);
293       myImage->SetPixelColor (theCol, theRow, aColor);
294     }
295
296   protected:
297     NCollection_DataMap<Standard_Integer, Quantity_Color> myMapSelectionModeColors;
298   };
299
300   //! Help class for filling pixel with color of detected shape.
301   class DetectedObjectColorFiller : public SelectMgr_SelectionImageFiller
302   {
303   public:
304     DetectedObjectColorFiller (Image_PixMap& thePixMap,
305                                SelectMgr_ViewerSelector* theSelector)
306     : SelectMgr_SelectionImageFiller (thePixMap, theSelector) {}
307
308     virtual void Fill (const Standard_Integer theCol,
309                        const Standard_Integer theRow,
310                        const Standard_Integer thePicked) Standard_OVERRIDE
311     {
312       Quantity_Color aColor (Quantity_NOC_BLACK);
313       if (thePicked > 0
314        && thePicked <= myMainSel->NbPicked())
315       {
316         const Handle(SelectMgr_SelectableObject)& aSelectable = myMainSel->Picked (thePicked)->Selectable();
317         aColor = aSelectable->Attributes()->Color();
318       }
319       myImage->SetPixelColor (theCol, theRow, aColor);
320     }
321   };
322 }
323
324 // =======================================================================
325 // function : CreateFiller
326 // purpose  :
327 // =======================================================================
328 Handle(SelectMgr_SelectionImageFiller) SelectMgr_SelectionImageFiller::CreateFiller (Image_PixMap& thePixMap,
329                                                                                      SelectMgr_ViewerSelector* theSelector,
330                                                                                      StdSelect_TypeOfSelectionImage theType)
331 {
332   switch (theType)
333   {
334     case StdSelect_TypeOfSelectionImage_NormalizedDepth:
335     case StdSelect_TypeOfSelectionImage_NormalizedDepthInverted:
336     {
337       return new NormalizedDepthFiller (thePixMap, theSelector, theType == StdSelect_TypeOfSelectionImage_NormalizedDepthInverted);
338     }
339     case StdSelect_TypeOfSelectionImage_UnnormalizedDepth:
340     {
341       return new UnnormalizedDepthFiller (thePixMap, theSelector);
342     }
343     case StdSelect_TypeOfSelectionImage_ColoredDetectedObject:
344     {
345       return new DetectedObjectColorFiller (thePixMap, theSelector);
346     }
347     case StdSelect_TypeOfSelectionImage_ColoredEntity:
348     {
349       return new GeneratedEntityColorFiller (thePixMap, theSelector);
350     }
351     case StdSelect_TypeOfSelectionImage_ColoredOwner:
352     {
353       return new GeneratedOwnerColorFiller (thePixMap, theSelector);
354     }
355     case StdSelect_TypeOfSelectionImage_ColoredSelectionMode:
356     {
357       return new GeneratedSelModeColorFiller (thePixMap, theSelector);
358     }
359   }
360   return Handle(SelectMgr_SelectionImageFiller)();
361 }