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:
GeneratedEntityColorFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)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
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)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 random color.
71 class GeneratedEntityTypeColorFiller : public SelectMgr_SelectionImageFiller
72 {
73 public:
GeneratedEntityTypeColorFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)74 GeneratedEntityTypeColorFiller (Image_PixMap& thePixMap,
75 SelectMgr_ViewerSelector* theSelector)
76 : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
77 {
78 // generate per-entity colors in the order as they have been activated
79 for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelector->SelectableObjects()); anObjIter.More(); anObjIter.Next())
80 {
81 const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
82 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
83 {
84 const Handle(SelectMgr_Selection)& aSel = aSelIter.Value();
85 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
86 {
87 const Handle(SelectMgr_SensitiveEntity)& aSens = aSelEntIter.Value();
88 if (!myMapEntityColors.IsBound (aSens->BaseSensitive()->DynamicType()))
89 {
90 Quantity_Color aColor;
91 randomPastelColor (aColor);
92 myMapEntityColors.Bind (aSens->BaseSensitive()->DynamicType(), aColor);
93 }
94 }
95 }
96 }
97 }
98
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)99 virtual void Fill (const Standard_Integer theCol,
100 const Standard_Integer theRow,
101 const Standard_Integer thePicked) Standard_OVERRIDE
102 {
103 if (thePicked < 1
104 || thePicked > myMainSel->NbPicked())
105 {
106 myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
107 return;
108 }
109
110 const Handle(Select3D_SensitiveEntity)& aPickedEntity = myMainSel->PickedEntity (thePicked);
111 Quantity_Color aColor (Quantity_NOC_BLACK);
112 myMapEntityColors.Find (aPickedEntity->DynamicType(), aColor);
113 myImage->SetPixelColor (theCol, theRow, aColor);
114 }
115
116 protected:
117 NCollection_DataMap<Handle(Standard_Type), Quantity_Color> myMapEntityColors;
118 };
119
120 //! Help class for filling pixel with normalized depth of ray.
121 class NormalizedDepthFiller : public SelectMgr_SelectionImageFiller
122 {
123 public:
NormalizedDepthFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector,const Standard_Boolean theToInverse)124 NormalizedDepthFiller (Image_PixMap& thePixMap,
125 SelectMgr_ViewerSelector* theSelector,
126 const Standard_Boolean theToInverse)
127 : SelectMgr_SelectionImageFiller (thePixMap, theSelector),
128 myDepthMin ( RealLast()),
129 myDepthMax (-RealLast()),
130 myToInverse(theToInverse)
131 {
132 myUnnormImage.InitZero (Image_Format_GrayF, thePixMap.SizeX(), thePixMap.SizeY());
133 }
134
135 //! Accumulate the data.
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)136 virtual void Fill (const Standard_Integer theCol,
137 const Standard_Integer theRow,
138 const Standard_Integer thePicked) Standard_OVERRIDE
139 {
140 if (myUnnormImage.IsEmpty())
141 {
142 return;
143 }
144
145 if (thePicked < 1
146 || thePicked > myMainSel->NbPicked())
147 {
148 myUnnormImage.ChangeValue<float> (theRow, theCol) = ShortRealLast();
149 return;
150 }
151
152 const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
153 myUnnormImage.ChangeValue<float> (theRow, theCol) = float(aSortCriterion.Depth);
154 myDepthMin = Min (myDepthMin, aSortCriterion.Depth);
155 myDepthMax = Max (myDepthMax, aSortCriterion.Depth);
156 }
157
158 //! Normalize the depth values.
Flush()159 virtual void Flush() Standard_OVERRIDE
160 {
161 float aFrom = 0.0f;
162 float aDelta = 1.0f;
163 if (myDepthMin <= myDepthMax)
164 {
165 aFrom = float(myDepthMin);
166 aDelta = float(myDepthMax) - float(myDepthMin);
167 if (aDelta <= ShortRealEpsilon())
168 {
169 aDelta = 1.0f;
170 }
171 }
172 for (Standard_Size aRowIter = 0; aRowIter < myUnnormImage.SizeY(); ++aRowIter)
173 {
174 for (Standard_Size aColIter = 0; aColIter < myUnnormImage.SizeX(); ++aColIter)
175 {
176 float aDepth = myUnnormImage.Value<float> (aRowIter, aColIter);
177 if (aDepth <= -ShortRealLast()
178 || aDepth >= ShortRealLast())
179 {
180 myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
181 Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
182 continue;
183 }
184
185 float aNormDepth = (aDepth - aFrom) / aDelta;
186 if (myToInverse)
187 {
188 aNormDepth = 1.0f - aNormDepth;
189 }
190 myImage->SetPixelColor (Standard_Integer(aColIter), Standard_Integer(aRowIter),
191 Quantity_ColorRGBA (aNormDepth, aNormDepth, aNormDepth, 1.0f));
192 }
193 }
194 }
195
196 private:
197 Image_PixMap myUnnormImage;
198 Standard_Real myDepthMin;
199 Standard_Real myDepthMax;
200 Standard_Boolean myToInverse;
201 };
202
203 //! Help class for filling pixel with unnormalized depth of ray.
204 class UnnormalizedDepthFiller : public SelectMgr_SelectionImageFiller
205 {
206 public:
UnnormalizedDepthFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)207 UnnormalizedDepthFiller (Image_PixMap& thePixMap,
208 SelectMgr_ViewerSelector* theSelector)
209 : SelectMgr_SelectionImageFiller (thePixMap, theSelector) {}
210
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)211 virtual void Fill (const Standard_Integer theCol,
212 const Standard_Integer theRow,
213 const Standard_Integer thePicked) Standard_OVERRIDE
214 {
215 if (thePicked < 1
216 || thePicked > myMainSel->NbPicked())
217 {
218 myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (0.0f, 0.0f, 0.0f, 1.0f));
219 return;
220 }
221
222 const SelectMgr_SortCriterion& aSortCriterion = myMainSel->PickedData (thePicked);
223 const float aDepth = float(aSortCriterion.Depth);
224 myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (Graphic3d_Vec4 (aDepth, aDepth, aDepth, 1.0f)));
225 }
226 };
227
228 //! Help class for filling pixel with color of detected object.
229 class GeneratedOwnerColorFiller : public SelectMgr_SelectionImageFiller
230 {
231 public:
GeneratedOwnerColorFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)232 GeneratedOwnerColorFiller (Image_PixMap& thePixMap,
233 SelectMgr_ViewerSelector* theSelector)
234 : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
235 {
236 // generate per-owner colors in the order as they have been activated
237 for (SelectMgr_SelectableObjectSet::Iterator anObjIter (theSelector->SelectableObjects()); anObjIter.More(); anObjIter.Next())
238 {
239 const Handle(SelectMgr_SelectableObject)& anObj = anObjIter.Value();
240 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
241 {
242 const Handle(SelectMgr_Selection)& aSel = aSelIter.Value();
243 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
244 {
245 const Handle(SelectMgr_SensitiveEntity)& aSens = aSelEntIter.Value();
246 const Handle(SelectMgr_EntityOwner)& anOwner = aSens->BaseSensitive()->OwnerId();
247 if (!myMapOwnerColors.IsBound (anOwner))
248 {
249 Quantity_Color aColor;
250 randomPastelColor (aColor);
251 myMapOwnerColors.Bind (anOwner, aColor);
252 }
253 }
254 }
255 }
256 }
257
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)258 virtual void Fill (const Standard_Integer theCol,
259 const Standard_Integer theRow,
260 const Standard_Integer thePicked) Standard_OVERRIDE
261 {
262 if (thePicked < 1
263 || thePicked > myMainSel->NbPicked())
264 {
265 myImage->SetPixelColor (theCol, theRow, Quantity_Color(Quantity_NOC_BLACK));
266 return;
267 }
268
269 const Handle(SelectMgr_EntityOwner)& aPickedOwner = myMainSel->Picked (thePicked);
270 Quantity_Color aColor (Quantity_NOC_BLACK);
271 myMapOwnerColors.Find (aPickedOwner, aColor);
272 myImage->SetPixelColor (theCol, theRow, aColor);
273 }
274
275 protected:
276 NCollection_DataMap<Handle(SelectMgr_EntityOwner), Quantity_Color> myMapOwnerColors;
277 };
278
279 //! Help class for filling pixel with random color for each selection mode.
280 class GeneratedSelModeColorFiller : public SelectMgr_SelectionImageFiller
281 {
282 public:
GeneratedSelModeColorFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)283 GeneratedSelModeColorFiller (Image_PixMap& thePixMap,
284 SelectMgr_ViewerSelector* theSelector)
285 : SelectMgr_SelectionImageFiller (thePixMap, theSelector)
286 {
287 // generate standard modes in proper order, consider custom objects would use similar scheme
288 myMapSelectionModeColors.Bind ( 0, Quantity_NOC_WHITE); // default (entire object selection)
289 myMapSelectionModeColors.Bind ( 1, Quantity_NOC_YELLOW); // TopAbs_VERTEX
290 myMapSelectionModeColors.Bind ( 2, Quantity_NOC_GREEN); // TopAbs_EDGE
291 myMapSelectionModeColors.Bind ( 3, Quantity_NOC_RED); // TopAbs_WIRE
292 myMapSelectionModeColors.Bind ( 4, Quantity_NOC_BLUE1); // TopAbs_FACE
293 myMapSelectionModeColors.Bind ( 5, Quantity_NOC_CYAN1); // TopAbs_SHELL
294 myMapSelectionModeColors.Bind ( 6, Quantity_NOC_PURPLE); // TopAbs_SOLID
295 myMapSelectionModeColors.Bind ( 7, Quantity_NOC_MAGENTA1); // TopAbs_COMPSOLID
296 myMapSelectionModeColors.Bind ( 8, Quantity_NOC_BROWN); // TopAbs_COMPOUND
297 myMapSelectionModeColors.Bind (0x0010, Quantity_NOC_PINK); // MeshVS_SMF_Volume
298 myMapSelectionModeColors.Bind (0x001E, Quantity_NOC_LIMEGREEN); // MeshVS_SMF_Element
299 myMapSelectionModeColors.Bind (0x001F, Quantity_NOC_DARKOLIVEGREEN); // MeshVS_SMF_All
300 myMapSelectionModeColors.Bind (0x0100, Quantity_NOC_GOLD); // MeshVS_SMF_Group
301 }
302
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)303 virtual void Fill (const Standard_Integer theCol,
304 const Standard_Integer theRow,
305 const Standard_Integer thePicked) Standard_OVERRIDE
306 {
307 if (thePicked < 1
308 || thePicked > myMainSel->NbPicked())
309 {
310 myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
311 return;
312 }
313
314 Standard_Integer aSelectionMode = -1;
315 const Handle(SelectMgr_SelectableObject)& aSelectable = myMainSel->Picked (thePicked)->Selectable();
316 const Handle(Select3D_SensitiveEntity)& anEntity = myMainSel->PickedEntity (thePicked);
317 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (aSelectable->Selections()); aSelIter.More(); aSelIter.Next())
318 {
319 const Handle(SelectMgr_Selection)& aSelection = aSelIter.Value();
320 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
321 {
322 if (aSelEntIter.Value()->BaseSensitive() == anEntity)
323 {
324 aSelectionMode = aSelection->Mode();
325 break;
326 }
327 }
328 }
329 if (aSelectionMode == -1)
330 {
331 myImage->SetPixelColor (theCol, theRow, Quantity_Color (Quantity_NOC_BLACK));
332 return;
333 }
334
335 if (!myMapSelectionModeColors.IsBound (aSelectionMode))
336 {
337 Quantity_Color aColor;
338 randomPastelColor (aColor);
339 myMapSelectionModeColors.Bind (aSelectionMode, aColor);
340 }
341
342 const Quantity_Color& aColor = myMapSelectionModeColors.Find (aSelectionMode);
343 myImage->SetPixelColor (theCol, theRow, aColor);
344 }
345
346 protected:
347 NCollection_DataMap<Standard_Integer, Quantity_Color> myMapSelectionModeColors;
348 };
349
350 //! Help class for filling pixel with color of detected shape.
351 class DetectedObjectColorFiller : public SelectMgr_SelectionImageFiller
352 {
353 public:
DetectedObjectColorFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)354 DetectedObjectColorFiller (Image_PixMap& thePixMap,
355 SelectMgr_ViewerSelector* theSelector)
356 : SelectMgr_SelectionImageFiller (thePixMap, theSelector) {}
357
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)358 virtual void Fill (const Standard_Integer theCol,
359 const Standard_Integer theRow,
360 const Standard_Integer thePicked) Standard_OVERRIDE
361 {
362 Quantity_Color aColor (Quantity_NOC_BLACK);
363 if (thePicked > 0
364 && thePicked <= myMainSel->NbPicked())
365 {
366 const Handle(SelectMgr_SelectableObject)& aSelectable = myMainSel->Picked (thePicked)->Selectable();
367 aColor = aSelectable->Attributes()->Color();
368 }
369 myImage->SetPixelColor (theCol, theRow, aColor);
370 }
371 };
372
373 //! Help class for filling pixel with normal direction value.
374 class SurfaceNormalFiller : public SelectMgr_SelectionImageFiller
375 {
376 public:
SurfaceNormalFiller(Image_PixMap & thePixMap,SelectMgr_ViewerSelector * theSelector)377 SurfaceNormalFiller (Image_PixMap& thePixMap,
378 SelectMgr_ViewerSelector* theSelector)
379 : SelectMgr_SelectionImageFiller (thePixMap, theSelector) {}
380
Fill(const Standard_Integer theCol,const Standard_Integer theRow,const Standard_Integer thePicked)381 virtual void Fill (const Standard_Integer theCol,
382 const Standard_Integer theRow,
383 const Standard_Integer thePicked) Standard_OVERRIDE
384 {
385 if (thePicked <= 0
386 || thePicked > myMainSel->NbPicked())
387 {
388 myImage->SetPixelColor (theCol, theRow, Quantity_NOC_BLACK);
389 }
390 else
391 {
392 const SelectMgr_SortCriterion& aPickedData = myMainSel->PickedData (thePicked);
393 Graphic3d_Vec3 aNormal = aPickedData.Normal;
394 aNormal.Normalize();
395 if (aNormal.Modulus() > 0.0f)
396 {
397 myImage->SetPixelColor (theCol, theRow, Quantity_ColorRGBA (aNormal.x() * 0.5f + 0.5f,
398 aNormal.y() * 0.5f + 0.5f,
399 aNormal.z() * 0.5f + 0.5f, 1.0f));
400 }
401 else
402 {
403 myImage->SetPixelColor (theCol, theRow, Quantity_NOC_BLACK);
404 }
405 }
406 }
407 };
408 }
409
410 // =======================================================================
411 // function : CreateFiller
412 // purpose :
413 // =======================================================================
Handle(SelectMgr_SelectionImageFiller)414 Handle(SelectMgr_SelectionImageFiller) SelectMgr_SelectionImageFiller::CreateFiller (Image_PixMap& thePixMap,
415 SelectMgr_ViewerSelector* theSelector,
416 StdSelect_TypeOfSelectionImage theType)
417 {
418 switch (theType)
419 {
420 case StdSelect_TypeOfSelectionImage_NormalizedDepth:
421 case StdSelect_TypeOfSelectionImage_NormalizedDepthInverted:
422 {
423 return new NormalizedDepthFiller (thePixMap, theSelector, theType == StdSelect_TypeOfSelectionImage_NormalizedDepthInverted);
424 }
425 case StdSelect_TypeOfSelectionImage_UnnormalizedDepth:
426 {
427 return new UnnormalizedDepthFiller (thePixMap, theSelector);
428 }
429 case StdSelect_TypeOfSelectionImage_ColoredDetectedObject:
430 {
431 return new DetectedObjectColorFiller (thePixMap, theSelector);
432 }
433 case StdSelect_TypeOfSelectionImage_ColoredEntity:
434 {
435 return new GeneratedEntityColorFiller (thePixMap, theSelector);
436 }
437 case StdSelect_TypeOfSelectionImage_ColoredEntityType:
438 {
439 return new GeneratedEntityTypeColorFiller (thePixMap, theSelector);
440 }
441 case StdSelect_TypeOfSelectionImage_ColoredOwner:
442 {
443 return new GeneratedOwnerColorFiller (thePixMap, theSelector);
444 }
445 case StdSelect_TypeOfSelectionImage_ColoredSelectionMode:
446 {
447 return new GeneratedSelModeColorFiller (thePixMap, theSelector);
448 }
449 case StdSelect_TypeOfSelectionImage_SurfaceNormal:
450 {
451 return new SurfaceNormalFiller (thePixMap, theSelector);
452 }
453 }
454 return Handle(SelectMgr_SelectionImageFiller)();
455 }
456