0025180: Visualization - Homogeneous transformation API in TKV3d
[occt.git] / src / AIS / AIS_ColoredShape.cxx
1 // Created on: 2014-04-24
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <AIS_ColoredShape.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRepTools.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Graphic3d_AspectFillArea3d.hxx>
23 #include <Graphic3d_AspectLine3d.hxx>
24 #include <Graphic3d_Group.hxx>
25 #include <Graphic3d_StructureManager.hxx>
26 #include <Graphic3d_Texture2Dmanual.hxx>
27 #include <Precision.hxx>
28 #include <Prs3d.hxx>
29 #include <Prs3d_LineAspect.hxx>
30 #include <Prs3d_IsoAspect.hxx>
31 #include <Prs3d_Presentation.hxx>
32 #include <Prs3d_ShadingAspect.hxx>
33 #include <Prs3d_Root.hxx>
34 #include <PrsMgr_PresentationManager3d.hxx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <StdPrs_ShadedShape.hxx>
37 #include <StdPrs_ToolTriangulatedShape.hxx>
38 #include <StdPrs_WFShape.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <TopoDS_Iterator.hxx>
43
44
45
46
47 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape,AIS_Shape)
48 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer,Prs3d_Drawer)
49
50 //=======================================================================
51 //function : AIS_ColoredShape
52 //purpose  :
53 //=======================================================================
54 AIS_ColoredShape::AIS_ColoredShape (const TopoDS_Shape& theShape)
55 : AIS_Shape (theShape)
56 {
57   // disable dedicated line aspects
58   myDrawer->SetFreeBoundaryAspect  (myDrawer->LineAspect());
59   myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
60   myDrawer->SetSeenLineAspect      (myDrawer->LineAspect());
61 }
62
63 //=======================================================================
64 //function : AIS_ColoredShape
65 //purpose  :
66 //=======================================================================
67 AIS_ColoredShape::AIS_ColoredShape (const Handle(AIS_Shape)& theShape)
68 : AIS_Shape (theShape->Shape())
69 {
70   // disable dedicated line aspects
71   myDrawer->SetFreeBoundaryAspect  (myDrawer->LineAspect());
72   myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
73   myDrawer->SetSeenLineAspect      (myDrawer->LineAspect());
74   if (theShape->HasMaterial())
75   {
76     SetMaterial (theShape->Material());
77   }
78   if (theShape->HasColor())
79   {
80     SetColor (theShape->Color());
81   }
82   if (theShape->HasWidth())
83   {
84     SetWidth (theShape->Width());
85   }
86   if (theShape->IsTransparent())
87   {
88     SetTransparency (theShape->Transparency());
89   }
90 }
91
92 //=======================================================================
93 //function : CustomAspects
94 //purpose  :
95 //=======================================================================
96 Handle(AIS_ColoredDrawer) AIS_ColoredShape::CustomAspects (const TopoDS_Shape& theShape)
97 {
98   Handle(AIS_ColoredDrawer) aDrawer;
99   myShapeColors.Find (theShape, aDrawer);
100   if (aDrawer.IsNull())
101   {
102     aDrawer = new AIS_ColoredDrawer (myDrawer);
103     myShapeColors.Bind (theShape, aDrawer);
104     LoadRecomputable (AIS_WireFrame);
105     LoadRecomputable (AIS_Shaded);
106   }
107   return aDrawer;
108 }
109
110 //=======================================================================
111 //function : ClearCustomAspects
112 //purpose  :
113 //=======================================================================
114 void AIS_ColoredShape::ClearCustomAspects()
115 {
116   if (myShapeColors.IsEmpty())
117   {
118     return;
119   }
120   myShapeColors.Clear();
121   LoadRecomputable (AIS_WireFrame);
122   LoadRecomputable (AIS_Shaded);
123 }
124
125 //=======================================================================
126 //function : UnsetCustomAspects
127 //purpose  :
128 //=======================================================================
129 void AIS_ColoredShape::UnsetCustomAspects (const TopoDS_Shape&    theShape,
130                                            const Standard_Boolean theToUnregister)
131 {
132   if (!myShapeColors.IsBound (theShape))
133   {
134     return;
135   }
136
137   LoadRecomputable (AIS_WireFrame);
138   LoadRecomputable (AIS_Shaded);
139   if (theToUnregister)
140   {
141     myShapeColors.UnBind (theShape);
142     return;
143   }
144
145   myShapeColors.ChangeFind (theShape) = new AIS_ColoredDrawer (myDrawer);
146 }
147
148 //=======================================================================
149 //function : SetCustomColor
150 //purpose  :
151 //=======================================================================
152 void AIS_ColoredShape::SetCustomColor (const TopoDS_Shape&   theShape,
153                                        const Quantity_Color& theColor)
154 {
155   if (theShape.IsNull())
156   {
157     return;
158   }
159
160   const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
161   setColor (aDrawer, theColor);
162   aDrawer->SetOwnColor (theColor);
163   LoadRecomputable (AIS_WireFrame);
164   LoadRecomputable (AIS_Shaded);
165 }
166
167 //=======================================================================
168 //function : SetCustomWidth
169 //purpose  :
170 //=======================================================================
171 void AIS_ColoredShape::SetCustomWidth (const TopoDS_Shape& theShape,
172                                        const Standard_Real theLineWidth)
173 {
174   if (theShape.IsNull())
175   {
176     return;
177   }
178
179   const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
180   setWidth (CustomAspects (theShape), theLineWidth);
181   aDrawer->SetOwnWidth (theLineWidth);
182   LoadRecomputable (AIS_WireFrame);
183   LoadRecomputable (AIS_Shaded);
184 }
185
186 //=======================================================================
187 //function : SetColor
188 //purpose  :
189 //=======================================================================
190
191 void AIS_ColoredShape::SetColor (const Quantity_Color&  theColor)
192 {
193   setColor (myDrawer, theColor);
194   myOwnColor  = theColor;
195   hasOwnColor = Standard_True;
196   LoadRecomputable (AIS_WireFrame);
197   LoadRecomputable (AIS_Shaded);
198   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
199   {
200     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
201     if (aDrawer->HasOwnColor())
202     {
203       continue;
204     }
205
206     if (aDrawer->HasOwnShadingAspect())
207     {
208       aDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
209     }
210     if (aDrawer->HasOwnLineAspect())
211     {
212       aDrawer->LineAspect()->SetColor (theColor);
213     }
214     if (aDrawer->HasOwnWireAspect())
215     {
216       aDrawer->WireAspect()->SetColor (theColor);
217     }
218   }
219 }
220
221 //=======================================================================
222 //function : SetWidth
223 //purpose  :
224 //=======================================================================
225
226 void AIS_ColoredShape::SetWidth (const Standard_Real    theLineWidth)
227 {
228   setWidth (myDrawer, theLineWidth);
229   myOwnWidth = theLineWidth;
230   LoadRecomputable (AIS_WireFrame);
231   LoadRecomputable (AIS_Shaded);
232   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
233   {
234     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
235     if (aDrawer->HasOwnWidth())
236     {
237       continue;
238     }
239
240     if (aDrawer->HasOwnLineAspect())
241     {
242       aDrawer->LineAspect()->SetWidth (theLineWidth);
243     }
244     if (aDrawer->HasOwnWireAspect())
245     {
246       aDrawer->WireAspect()->SetWidth (theLineWidth);
247     }
248   }
249 }
250
251 //=======================================================================
252 //function : SetTransparency
253 //purpose  :
254 //=======================================================================
255
256 void AIS_ColoredShape::SetTransparency (const Standard_Real theValue)
257 {
258   setTransparency (myDrawer, theValue);
259   myTransparency = theValue;
260   LoadRecomputable (AIS_WireFrame);
261   LoadRecomputable (AIS_Shaded);
262   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
263   {
264     const Handle(Prs3d_Drawer)& aDrawer = anIter.Value();
265     if (aDrawer->HasOwnShadingAspect())
266     {
267       aDrawer->ShadingAspect()->SetTransparency (theValue, myCurrentFacingModel);
268     }
269   }
270 }
271
272 //=======================================================================
273 //function : SetMaterial
274 //purpose  :
275 //=======================================================================
276
277 void AIS_ColoredShape::SetMaterial (const Graphic3d_MaterialAspect& theMaterial)
278 {
279   setMaterial (myDrawer, theMaterial, HasColor(), IsTransparent());
280   //myOwnMaterial = theMaterial;
281   hasOwnMaterial = Standard_True;
282   LoadRecomputable (AIS_Shaded);
283   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
284   {
285     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
286     //if (aDrawer->HasOwnMaterial()) continue;
287     if (aDrawer->HasOwnShadingAspect())
288     {
289       setMaterial (aDrawer, theMaterial, aDrawer->HasOwnColor(), Standard_False); // aDrawer->IsTransparent()
290     }
291   }
292 }
293
294 //=======================================================================
295 //function : Compute
296 //purpose  :
297 //=======================================================================
298 void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
299                                 const Handle(Prs3d_Presentation)&           thePrs,
300                                 const Standard_Integer                      theMode)
301 {
302   thePrs->Clear();
303   if (IsInfinite())
304   {
305     thePrs->SetInfiniteState (Standard_True);
306   }
307
308   if (theMode == AIS_Shaded)
309   {
310     if (myDrawer->IsAutoTriangulation())
311     {
312       // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
313       StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
314
315       // After this call if type of deflection is relative
316       // computed deflection coefficient is stored as absolute.
317       Standard_Boolean wasRecomputed = StdPrs_ToolTriangulatedShape::Tessellate (myshape, myDrawer);
318
319       // Set to update wireframe presentation on triangulation.
320       if (myDrawer->IsoOnTriangulation() && wasRecomputed)
321       {
322         SetToUpdate (AIS_WireFrame);
323       }
324     }
325   }
326   else // WireFrame mode
327   {
328     StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
329
330     // After this call if type of deflection is relative
331     // computed deflection coefficient is stored as absolute.
332     Prs3d::GetDeflection (myshape, myDrawer);
333   }
334
335   TopoDS_Compound anOpened, aClosed;
336   BRep_Builder aBuilder;
337   aBuilder.MakeCompound (aClosed);
338   aBuilder.MakeCompound (anOpened);
339   if (theMode == AIS_Shaded && myshape.ShapeType() <= TopAbs_SOLID)
340   {
341     StdPrs_ShadedShape::ExploreSolids (myshape, aBuilder, aClosed, anOpened, Standard_False);
342   }
343   else
344   {
345     aBuilder.Add (anOpened, myshape);
346   }
347
348   // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
349   DataMapOfShapeCompd aDispatchedOpened [(size_t)TopAbs_SHAPE];
350   dispatchColors (anOpened, myShapeColors, aDispatchedOpened);
351   addShapesWithCustomProps (thePrs, aDispatchedOpened, theMode, StdPrs_Volume_Opened);
352
353   if (theMode == AIS_Shaded)
354   {
355     if (isShapeEntirelyVisible())
356     {
357       // myShapeColors + aClosed --> array[TopAbs_ShapeEnum] of map of color-to-compound
358       DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
359       dispatchColors (aClosed, myShapeColors, aDispatchedClosed);
360       addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode, StdPrs_Volume_Closed);
361     }
362     else
363     {
364       for (TopoDS_Iterator aSolidIter (aClosed); aSolidIter.More(); aSolidIter.Next())
365       {
366         DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
367         dispatchColors (aSolidIter.Value(), myShapeColors, aDispatchedClosed);
368         addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode,
369                                   isShapeEntirelyVisible (aDispatchedClosed) ? StdPrs_Volume_Closed : StdPrs_Volume_Opened);
370       }
371     }
372   }
373 }
374
375 //=======================================================================
376 //function : addShapesWithCustomProps
377 //purpose  :
378 //=======================================================================
379 void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
380                                                  DataMapOfShapeCompd*              theDispatched,
381                                                  const Standard_Integer            theMode,
382                                                  const StdPrs_Volume               theVolume)
383 {
384   Handle(AIS_ColoredDrawer) aCustomDrawer;
385   for (size_t aShType = 0; aShType < (size_t )TopAbs_SHAPE; ++aShType)
386   {
387     DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
388     for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap);
389          aMapIter.More(); aMapIter.Next())
390     {
391       const TopoDS_Shape&    aShapeKey  = aMapIter.Key();   // key shape with detailed color or a base shape
392       const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
393       Handle(Prs3d_Drawer) aDrawer;
394       if (myShapeColors.Find (aShapeKey, aCustomDrawer))
395       {
396         aDrawer = aCustomDrawer;
397         if (aCustomDrawer->IsHidden())
398         {
399           continue;
400         }
401       }
402       else
403       {
404         aDrawer = myDrawer;
405       }
406
407       // It is supposed that absolute deflection contains previously computed relative deflection
408       // (if deflection type is relative).
409       // In case of CustomDrawer it is taken from Link().
410       Aspect_TypeOfDeflection aPrevType = aDrawer->TypeOfDeflection();
411       aDrawer->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
412
413       // Draw each kind of subshapes and personal-colored shapes in a separate group
414       // since it's necessary to set transparency/material for all subshapes
415       // without affecting their unique colors
416       if (theMode == AIS_Shaded
417        && aShapeDraw.ShapeType() <= TopAbs_FACE
418        && !IsInfinite())
419       {
420         StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer, theVolume);
421       }
422       else
423       {
424         StdPrs_WFShape::Add (thePrs, aShapeDraw, aDrawer);
425       }
426       aDrawer->SetTypeOfDeflection (aPrevType);
427     }
428   }
429 }
430
431 //=======================================================================
432 //function : dispatchColors
433 //purpose  :
434 //=======================================================================
435 Standard_Boolean AIS_ColoredShape::dispatchColors (const TopoDS_Shape&        theBaseKey,
436                                                    const TopoDS_Shape&        theSubshapeToParse,
437                                                    const DataMapOfShapeShape& theSubshapeKeyshapeMap,
438                                                    const TopAbs_ShapeEnum     theParentType,
439                                                    DataMapOfShapeCompd*       theTypeKeyshapeDrawshapeArray)
440 {
441   TopAbs_ShapeEnum aShType = theSubshapeToParse.ShapeType();
442   if (aShType == TopAbs_SHAPE)
443   {
444     return Standard_False;
445   }
446
447   // check own setting of current shape
448   TopoDS_Shape     aKeyShape   = theBaseKey;
449   Standard_Boolean isOverriden = theSubshapeKeyshapeMap.Find (theSubshapeToParse, aKeyShape);
450
451   // iterate on sub-shapes
452   BRep_Builder aBBuilder;
453   TopoDS_Shape aShapeCopy = theSubshapeToParse.EmptyCopied();
454   aShapeCopy.Closed (theSubshapeToParse.Closed());
455   Standard_Boolean isSubOverride = Standard_False;
456   Standard_Integer nbDef = 0;
457   for (TopoDS_Iterator it (theSubshapeToParse); it.More(); it.Next())
458   {
459     if (dispatchColors (theBaseKey, it.Value(),
460                         theSubshapeKeyshapeMap, aShType,
461                         theTypeKeyshapeDrawshapeArray))
462     {
463       isSubOverride = Standard_True;
464     }
465     else
466     {
467       aBBuilder.Add (aShapeCopy, it.Value());
468       ++nbDef;
469     }
470   }
471   if (aShType == TopAbs_FACE || !isSubOverride)
472   {
473     aShapeCopy = theSubshapeToParse;
474   }
475   else if (nbDef == 0)
476   {
477     return isOverriden || isSubOverride; // empty compound
478   }
479
480   // if any of styles is overridden regarding to default one, add rest to map
481   if (isOverriden
482   || (isSubOverride && theParentType != TopAbs_WIRE  // avoid drawing edges when vertex color is overridden
483                     && theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
484   || (theParentType == TopAbs_SHAPE && !(isOverriden || isSubOverride))) // bind original shape to default color
485   {
486     TopoDS_Compound aCompound;
487     DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theTypeKeyshapeDrawshapeArray[(size_t )aShType];
488     if (!aKeyshapeDrawshapeMap.FindFromKey (aKeyShape, aCompound))
489     {
490       aBBuilder.MakeCompound (aCompound);
491       aKeyshapeDrawshapeMap.Add (aKeyShape, aCompound);
492     }
493     aBBuilder.Add (aCompound, aShapeCopy);
494   }
495   return isOverriden || isSubOverride;
496 }
497
498 //! Function to check if specified compound is sub-shape of another one
499 inline Standard_Boolean isFirstCmpContainSecondOne (const TopoDS_Shape& theFirstCmp,
500                                                     const TopoDS_Shape& theSecondCmp)
501 {
502   if (theFirstCmp.ShapeType()  != TopAbs_COMPOUND
503    || theSecondCmp.ShapeType() != TopAbs_COMPOUND)
504   {
505     return Standard_False;
506   }
507
508   for (TopoDS_Iterator aFirstCmpIter (theFirstCmp); aFirstCmpIter.More(); aFirstCmpIter.Next())
509   {
510     if (aFirstCmpIter.Value().ShapeType() != TopAbs_COMPOUND)
511     {
512       continue;
513     }
514     else if (aFirstCmpIter.Value() == theSecondCmp
515           || isFirstCmpContainSecondOne (aFirstCmpIter.Value(), theSecondCmp))
516     {
517       return Standard_True;
518     }
519   }
520   return Standard_False;
521 }
522
523 //=======================================================================
524 //function : dispatchColors
525 //purpose  :
526 //=======================================================================
527 void AIS_ColoredShape::dispatchColors (const TopoDS_Shape&  theBaseShape,
528                                        const AIS_DataMapOfShapeDrawer& theKeyshapeColorMap,
529                                        DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
530 {
531   // Extract <theShapeColors> map (KeyshapeColored -> Color)
532   // to subshapes map (Subshape -> KeyshapeColored).
533   // This needed when colored shape is not part of <theBaseShape>
534   // (but subshapes are) and actually container for subshapes.
535   DataMapOfShapeShape aSubshapeKeyshapeMap;
536   for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (theKeyshapeColorMap);
537        aKeyShapeIter.More(); aKeyShapeIter.Next())
538   {
539     const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
540     bindSubShapes (aSubshapeKeyshapeMap, theBaseShape, aKeyShape, aKeyShape);
541   }
542
543   // Fill the array of maps per shape type
544   dispatchColors (theBaseShape, theBaseShape,
545                   aSubshapeKeyshapeMap, TopAbs_SHAPE,
546                   theTypeKeyshapeDrawshapeArray);
547 }
548
549 //=======================================================================
550 //function : isShapeEntirelyVisible
551 //purpose  :
552 //=======================================================================
553 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const
554 {
555   Handle(AIS_ColoredDrawer) aCustomDrawer;
556   for (size_t aShType = (size_t )TopAbs_COMPOUND; aShType <= (size_t )TopAbs_FACE; ++aShType)
557   {
558     const DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
559     for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap); aMapIter.More(); aMapIter.Next())
560     {
561       if (myShapeColors.Find (aMapIter.Key(), aCustomDrawer)
562       && !aCustomDrawer.IsNull()
563       &&  aCustomDrawer->IsHidden())
564       {
565         return Standard_False;
566       }
567     }
568   }
569   return Standard_True;
570 }
571
572 //=======================================================================
573 //function : isShapeEntirelyVisible
574 //purpose  :
575 //=======================================================================
576 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible() const
577 {
578   for (AIS_DataMapOfShapeDrawer::Iterator aMapIter (myShapeColors); aMapIter.More(); aMapIter.Next())
579   {
580     if (aMapIter.Value()->IsHidden())
581     {
582       return Standard_False;
583     }
584   }
585   return Standard_True;
586 }
587
588 //=======================================================================
589 //function : bindSubShapes
590 //purpose  :
591 //=======================================================================
592 void AIS_ColoredShape::bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
593                                       const TopoDS_Shape&  theBaseShape,
594                                       const TopoDS_Shape&  theShapeWithColor,
595                                       const TopoDS_Shape&  theColorKeyShape)
596 {
597   TopAbs_ShapeEnum aShapeWithColorType = theShapeWithColor.ShapeType();
598   if (aShapeWithColorType == TopAbs_COMPOUND)
599   {
600     if (isFirstCmpContainSecondOne (theBaseShape, theShapeWithColor))
601     {
602       if (!theSubshapeKeyshapeMap.IsBound (theShapeWithColor))
603       {
604         theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
605       }
606     }
607     else
608     {
609       for (TopoDS_Iterator aSubShapeIter (theShapeWithColor); aSubShapeIter.More(); aSubShapeIter.Next())
610       {
611         bindSubShapes (theSubshapeKeyshapeMap, theBaseShape, aSubShapeIter.Value(), theColorKeyShape);
612       }
613     }
614   }
615   else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
616   {
617     for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_FACE); anExp.More(); anExp.Next())
618     {
619       if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
620       {
621         theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
622       }
623     }
624   }
625   else if (aShapeWithColorType == TopAbs_WIRE)
626   {
627     for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_EDGE); anExp.More(); anExp.Next())
628     {
629       if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
630       {
631         theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
632       }
633     }
634   }
635   else
636   {
637     // bind single face, edge and vertex
638     // force rebind if required due to the color of single shape has
639     // higher priority than the color of "compound" shape (wire is a
640     // compound of edges, shell is a compound of faces) that contains
641     // this single shape.
642     theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
643   }
644 }
645