0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[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 <BRepMesh_IncrementalMesh.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <Graphic3d_AspectFillArea3d.hxx>
24 #include <Graphic3d_AspectLine3d.hxx>
25 #include <Graphic3d_ArrayOfTriangles.hxx>
26 #include <Graphic3d_ArrayOfSegments.hxx>
27 #include <Graphic3d_Group.hxx>
28 #include <Graphic3d_StructureManager.hxx>
29 #include <Graphic3d_Texture2Dmanual.hxx>
30 #include <Precision.hxx>
31 #include <Prs3d.hxx>
32 #include <Prs3d_LineAspect.hxx>
33 #include <Prs3d_IsoAspect.hxx>
34 #include <Prs3d_Presentation.hxx>
35 #include <Prs3d_ShadingAspect.hxx>
36 #include <Prs3d_Root.hxx>
37 #include <PrsMgr_PresentationManager3d.hxx>
38 #include <Standard_ErrorHandler.hxx>
39 #include <StdSelect_BRepSelectionTool.hxx>
40 #include <StdPrs_ShadedShape.hxx>
41 #include <StdPrs_ToolTriangulatedShape.hxx>
42 #include <StdPrs_WFShape.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopoDS.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopoDS_Iterator.hxx>
47
48 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape,AIS_Shape)
49 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer,Prs3d_Drawer)
50
51 namespace
52 {
53   //! Collect all sub-compounds into map.
54   static void collectSubCompounds (TopTools_MapOfShape& theMap,
55                                    const TopoDS_Shape&  theShape)
56   {
57     for (TopoDS_Iterator aChildIter (theShape); aChildIter.More(); aChildIter.Next())
58     {
59       const TopoDS_Shape& aShape = aChildIter.Value();
60       if (aShape.ShapeType() == TopAbs_COMPOUND
61        && theMap.Add (aShape))
62       {
63         collectSubCompounds (theMap, aShape);
64       }
65     }
66   }
67 }
68
69 //=======================================================================
70 //function : AIS_ColoredShape
71 //purpose  :
72 //=======================================================================
73 AIS_ColoredShape::AIS_ColoredShape (const TopoDS_Shape& theShape)
74 : AIS_Shape (theShape)
75 {
76   // disable dedicated line aspects
77   myDrawer->SetFreeBoundaryAspect  (myDrawer->LineAspect());
78   myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
79   myDrawer->SetSeenLineAspect      (myDrawer->LineAspect());
80 }
81
82 //=======================================================================
83 //function : AIS_ColoredShape
84 //purpose  :
85 //=======================================================================
86 AIS_ColoredShape::AIS_ColoredShape (const Handle(AIS_Shape)& theShape)
87 : AIS_Shape (theShape->Shape())
88 {
89   // disable dedicated line aspects
90   myDrawer->SetFreeBoundaryAspect  (myDrawer->LineAspect());
91   myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
92   myDrawer->SetSeenLineAspect      (myDrawer->LineAspect());
93   if (theShape->HasMaterial())
94   {
95     SetMaterial (theShape->Material());
96   }
97   if (theShape->HasColor())
98   {
99     Quantity_Color aColor;
100     theShape->Color (aColor);
101     SetColor (aColor);
102   }
103   if (theShape->HasWidth())
104   {
105     SetWidth (theShape->Width());
106   }
107   if (theShape->IsTransparent())
108   {
109     SetTransparency (theShape->Transparency());
110   }
111 }
112
113 //=======================================================================
114 //function : CustomAspects
115 //purpose  :
116 //=======================================================================
117 Handle(AIS_ColoredDrawer) AIS_ColoredShape::CustomAspects (const TopoDS_Shape& theShape)
118 {
119   Handle(AIS_ColoredDrawer) aDrawer;
120   myShapeColors.Find (theShape, aDrawer);
121   if (aDrawer.IsNull())
122   {
123     aDrawer = new AIS_ColoredDrawer (myDrawer);
124     myShapeColors.Bind (theShape, aDrawer);
125     LoadRecomputable (AIS_WireFrame);
126     LoadRecomputable (AIS_Shaded);
127   }
128   return aDrawer;
129 }
130
131 //=======================================================================
132 //function : ClearCustomAspects
133 //purpose  :
134 //=======================================================================
135 void AIS_ColoredShape::ClearCustomAspects()
136 {
137   if (myShapeColors.IsEmpty())
138   {
139     return;
140   }
141   myShapeColors.Clear();
142   LoadRecomputable (AIS_WireFrame);
143   LoadRecomputable (AIS_Shaded);
144 }
145
146 //=======================================================================
147 //function : UnsetCustomAspects
148 //purpose  :
149 //=======================================================================
150 void AIS_ColoredShape::UnsetCustomAspects (const TopoDS_Shape&    theShape,
151                                            const Standard_Boolean theToUnregister)
152 {
153   if (!myShapeColors.IsBound (theShape))
154   {
155     return;
156   }
157
158   LoadRecomputable (AIS_WireFrame);
159   LoadRecomputable (AIS_Shaded);
160   if (theToUnregister)
161   {
162     myShapeColors.UnBind (theShape);
163     return;
164   }
165
166   myShapeColors.ChangeFind (theShape) = new AIS_ColoredDrawer (myDrawer);
167 }
168
169 //=======================================================================
170 //function : SetCustomColor
171 //purpose  :
172 //=======================================================================
173 void AIS_ColoredShape::SetCustomColor (const TopoDS_Shape&   theShape,
174                                        const Quantity_Color& theColor)
175 {
176   if (theShape.IsNull())
177   {
178     return;
179   }
180
181   const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
182   setColor (aDrawer, theColor);
183   aDrawer->SetOwnColor (theColor);
184   LoadRecomputable (AIS_WireFrame);
185   LoadRecomputable (AIS_Shaded);
186 }
187
188 //=======================================================================
189 //function : SetCustomWidth
190 //purpose  :
191 //=======================================================================
192 void AIS_ColoredShape::SetCustomWidth (const TopoDS_Shape& theShape,
193                                        const Standard_Real theLineWidth)
194 {
195   if (theShape.IsNull())
196   {
197     return;
198   }
199
200   const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
201   setWidth (CustomAspects (theShape), theLineWidth);
202   aDrawer->SetOwnWidth (theLineWidth);
203   LoadRecomputable (AIS_WireFrame);
204   LoadRecomputable (AIS_Shaded);
205 }
206
207 //=======================================================================
208 //function : SetColor
209 //purpose  :
210 //=======================================================================
211
212 void AIS_ColoredShape::SetColor (const Quantity_Color&  theColor)
213 {
214   setColor (myDrawer, theColor);
215   myDrawer->SetColor (theColor);
216   hasOwnColor = Standard_True;
217   LoadRecomputable (AIS_WireFrame);
218   LoadRecomputable (AIS_Shaded);
219   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
220   {
221     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
222     if (aDrawer->HasOwnColor())
223     {
224       continue;
225     }
226
227     if (aDrawer->HasOwnShadingAspect())
228     {
229       aDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
230     }
231     if (aDrawer->HasOwnLineAspect())
232     {
233       aDrawer->LineAspect()->SetColor (theColor);
234     }
235     if (aDrawer->HasOwnWireAspect())
236     {
237       aDrawer->WireAspect()->SetColor (theColor);
238     }
239   }
240 }
241
242 //=======================================================================
243 //function : SetWidth
244 //purpose  :
245 //=======================================================================
246
247 void AIS_ColoredShape::SetWidth (const Standard_Real    theLineWidth)
248 {
249   setWidth (myDrawer, theLineWidth);
250   myOwnWidth = theLineWidth;
251   LoadRecomputable (AIS_WireFrame);
252   LoadRecomputable (AIS_Shaded);
253   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
254   {
255     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
256     if (aDrawer->HasOwnWidth())
257     {
258       continue;
259     }
260
261     if (aDrawer->HasOwnLineAspect())
262     {
263       aDrawer->LineAspect()->SetWidth (theLineWidth);
264     }
265     if (aDrawer->HasOwnWireAspect())
266     {
267       aDrawer->WireAspect()->SetWidth (theLineWidth);
268     }
269   }
270 }
271
272 //=======================================================================
273 //function : SetTransparency
274 //purpose  :
275 //=======================================================================
276
277 void AIS_ColoredShape::SetTransparency (const Standard_Real theValue)
278 {
279   setTransparency (myDrawer, theValue);
280   myDrawer->SetTransparency ((Standard_ShortReal )theValue);
281   LoadRecomputable (AIS_WireFrame);
282   LoadRecomputable (AIS_Shaded);
283   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
284   {
285     const Handle(Prs3d_Drawer)& aDrawer = anIter.Value();
286     if (aDrawer->HasOwnShadingAspect())
287     {
288       aDrawer->ShadingAspect()->SetTransparency (theValue, myCurrentFacingModel);
289     }
290   }
291 }
292
293 //=======================================================================
294 //function : UnsetTransparency
295 //purpose  :
296 //=======================================================================
297 void AIS_ColoredShape::UnsetTransparency()
298 {
299   myDrawer->SetTransparency (0.0f);
300   if (myDrawer->HasOwnShadingAspect())
301   {
302     myDrawer->ShadingAspect()->SetTransparency (0.0, myCurrentFacingModel);
303     if (!HasColor()
304      && !HasMaterial()
305      && !myDrawer->ShadingAspect()->Aspect()->ToMapTexture())
306     {
307       myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
308     }
309   }
310
311   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
312   {
313     const Handle(Prs3d_Drawer)& aDrawer = anIter.Value();
314     if (aDrawer->HasOwnShadingAspect())
315     {
316       aDrawer->ShadingAspect()->SetTransparency (0.0, myCurrentFacingModel);
317     }
318   }
319   SynchronizeAspects();
320 }
321
322 //=======================================================================
323 //function : SetMaterial
324 //purpose  :
325 //=======================================================================
326
327 void AIS_ColoredShape::SetMaterial (const Graphic3d_MaterialAspect& theMaterial)
328 {
329   setMaterial (myDrawer, theMaterial, HasColor(), IsTransparent());
330   //myOwnMaterial = theMaterial;
331   hasOwnMaterial = Standard_True;
332   LoadRecomputable (AIS_Shaded);
333   for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
334   {
335     const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
336     //if (aDrawer->HasOwnMaterial()) continue;
337     if (aDrawer->HasOwnShadingAspect())
338     {
339       setMaterial (aDrawer, theMaterial, aDrawer->HasOwnColor(), Standard_False); // aDrawer->IsTransparent()
340     }
341   }
342 }
343
344 //=======================================================================
345 //function : Compute
346 //purpose  :
347 //=======================================================================
348 void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
349                                 const Handle(Prs3d_Presentation)&           thePrs,
350                                 const Standard_Integer                      theMode)
351 {
352   if (myshape.IsNull())
353   {
354     return;
355   }
356
357   if (IsInfinite())
358   {
359     thePrs->SetInfiniteState (Standard_True);
360   }
361
362   if (theMode == AIS_Shaded)
363   {
364     if (myDrawer->IsAutoTriangulation())
365     {
366       // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
367       StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
368
369       // After this call if type of deflection is relative
370       // computed deflection coefficient is stored as absolute.
371       Standard_Boolean wasRecomputed = StdPrs_ToolTriangulatedShape::Tessellate (myshape, myDrawer);
372
373       // Set to update wireframe presentation on triangulation.
374       if (myDrawer->IsoOnTriangulation() && wasRecomputed)
375       {
376         SetToUpdate (AIS_WireFrame);
377       }
378     }
379   }
380   else // WireFrame mode
381   {
382     StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
383
384     // After this call if type of deflection is relative
385     // computed deflection coefficient is stored as absolute.
386     Prs3d::GetDeflection (myshape, myDrawer);
387   }
388
389   // Extract myShapeColors map (KeyshapeColored -> Color) to subshapes map (Subshape -> Color).
390   // This needed when colored shape is not part of BaseShape (but subshapes are) and actually container for subshapes.
391   AIS_DataMapOfShapeDrawer aSubshapeDrawerMap;
392   fillSubshapeDrawerMap (aSubshapeDrawerMap);
393
394   Handle(AIS_ColoredDrawer) aBaseDrawer;
395   myShapeColors.Find (myshape, aBaseDrawer);
396
397   // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
398   DataMapOfDrawerCompd aDispatchedOpened[(size_t)TopAbs_SHAPE];
399   DataMapOfDrawerCompd aDispatchedClosed;
400   dispatchColors (aBaseDrawer, myshape,
401                   aSubshapeDrawerMap, TopAbs_COMPOUND, Standard_False,
402                   aDispatchedOpened, theMode == AIS_Shaded ? aDispatchedClosed : aDispatchedOpened[TopAbs_FACE]);
403   addShapesWithCustomProps (thePrs, aDispatchedOpened, aDispatchedClosed, theMode);
404 }
405
406 //=======================================================================
407 //function : fillSubshapeDrawerMap
408 //purpose  :
409 //=======================================================================
410 void AIS_ColoredShape::fillSubshapeDrawerMap (AIS_DataMapOfShapeDrawer& theSubshapeDrawerMap) const
411 {
412   // unroll compounds specified for grouping sub-shapes with the same style
413   // (e.g. the compounds that are not a part of the main shape)
414   TopTools_MapOfShape aMapOfOwnCompounds;
415   if (myshape.ShapeType() == TopAbs_COMPOUND)
416   {
417     aMapOfOwnCompounds.Add (myshape);
418     collectSubCompounds (aMapOfOwnCompounds, myshape);
419   }
420   for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
421         aKeyShapeIter.More(); aKeyShapeIter.Next())
422   {
423     const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
424     if (aKeyShape.ShapeType() != TopAbs_COMPOUND
425      || aMapOfOwnCompounds.Contains (aKeyShape))
426     {
427       continue;
428     }
429
430     for (TopoDS_Iterator aChildIter (aKeyShape); aChildIter.More(); aChildIter.Next())
431     {
432       const TopoDS_Shape& aShape = aChildIter.Value();
433       if (!myShapeColors.IsBound (aShape))
434       {
435         bindSubShapes (theSubshapeDrawerMap, aShape, aKeyShapeIter.Value());
436       }
437     }
438   }
439
440   // assign other sub-shapes with styles
441   for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
442         aKeyShapeIter.More(); aKeyShapeIter.Next())
443   {
444     const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
445     if (myshape == aKeyShape
446     || (aKeyShape.ShapeType() == TopAbs_COMPOUND
447     && !aMapOfOwnCompounds.Contains (aKeyShape)))
448     {
449       continue;
450     }
451
452     bindSubShapes (theSubshapeDrawerMap, aKeyShape, aKeyShapeIter.Value());
453   }
454 }
455
456 //=======================================================================
457 //function : ComputeSelection
458 //purpose  :
459 //=======================================================================
460 void AIS_ColoredShape::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
461                                          const Standard_Integer theMode)
462 {
463   if (myshape.IsNull())
464   {
465     return;
466   }
467   else if (isShapeEntirelyVisible())
468   {
469     base_type::ComputeSelection (theSelection, theMode);
470     return;
471   }
472
473   const TopAbs_ShapeEnum aTypOfSel   = AIS_Shape::SelectionType (theMode);
474   const Standard_Real    aDeflection = Prs3d::GetDeflection (myshape, myDrawer);
475   const Standard_Real    aDeviationAngle = myDrawer->HLRAngle();
476   const Standard_Integer aPriority   = StdSelect_BRepSelectionTool::GetStandardPriority (myshape, aTypOfSel);
477   if (myDrawer->IsAutoTriangulation()
478   && !BRepTools::Triangulation (myshape, Precision::Infinite()))
479   {
480     BRepMesh_IncrementalMesh aMesher (myshape, aDeflection, Standard_False, aDeviationAngle);
481   }
482
483   AIS_DataMapOfShapeDrawer aSubshapeDrawerMap;
484   fillSubshapeDrawerMap (aSubshapeDrawerMap);
485
486   Handle(StdSelect_BRepOwner) aBrepOwner = new StdSelect_BRepOwner (myshape, aPriority);
487   if (aTypOfSel == TopAbs_SHAPE)
488   {
489     aBrepOwner = new StdSelect_BRepOwner (myshape, aPriority);
490   }
491
492   Handle(AIS_ColoredDrawer) aBaseDrawer;
493   myShapeColors.Find (myshape, aBaseDrawer);
494   computeSubshapeSelection (aBaseDrawer, aSubshapeDrawerMap, myshape, aBrepOwner, theSelection,
495                             aTypOfSel, aPriority, aDeflection, aDeviationAngle);
496
497   Handle(SelectMgr_SelectableObject) aThis (this);
498   for (theSelection->Init(); theSelection->More(); theSelection->Next())
499   {
500     Handle(SelectMgr_EntityOwner) anOwner = Handle(SelectMgr_EntityOwner)::DownCast (theSelection->Sensitive()->BaseSensitive()->OwnerId());
501     anOwner->Set (aThis);
502   }
503
504   StdSelect_BRepSelectionTool::PreBuildBVH (theSelection);
505 }
506
507 //=======================================================================
508 //function : computeSubshapeSelection
509 //purpose  :
510 //=======================================================================
511 void AIS_ColoredShape::computeSubshapeSelection (const Handle(AIS_ColoredDrawer)& theParentDrawer,
512                                                  const AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
513                                                  const TopoDS_Shape& theShape,
514                                                  const Handle(StdSelect_BRepOwner)& theOwner,
515                                                  const Handle(SelectMgr_Selection)& theSelection,
516                                                  const TopAbs_ShapeEnum theTypOfSel,
517                                                  const Standard_Integer thePriority,
518                                                  const Standard_Real theDeflection,
519                                                  const Standard_Real theDeflAngle)
520 {
521   Handle(AIS_ColoredDrawer) aDrawer = theParentDrawer;
522   theShapeDrawerMap.Find (theShape, aDrawer);
523   if (!aDrawer.IsNull()
524     && aDrawer->IsHidden())
525   {
526     return;
527   }
528
529   const Standard_Integer aNbPOnEdge = 9;
530   const Standard_Real    aMaximalParameter = 500.0;
531   if (theTypOfSel == TopAbs_SHAPE
532    && theShape.ShapeType() >= TopAbs_FACE)
533   {
534     StdSelect_BRepSelectionTool::ComputeSensitive (theShape, theOwner, theSelection,
535                                                    theDeflection, theDeflAngle, aNbPOnEdge, aMaximalParameter, myDrawer->IsAutoTriangulation());
536     return;
537   }
538   else if (theShape.ShapeType() == theTypOfSel)
539   {
540     const Standard_Boolean isComesFromDecomposition = !theShape.IsEqual (myshape);
541     Handle(StdSelect_BRepOwner) aBrepOwner = new StdSelect_BRepOwner (theShape, thePriority, isComesFromDecomposition);
542     StdSelect_BRepSelectionTool::ComputeSensitive (theShape, aBrepOwner, theSelection,
543                                                    theDeflection, theDeflAngle, aNbPOnEdge, aMaximalParameter, myDrawer->IsAutoTriangulation());
544     return;
545   }
546
547   for (TopoDS_Iterator aSubShapeIter (theShape); aSubShapeIter.More(); aSubShapeIter.Next())
548   {
549     const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
550     computeSubshapeSelection (aDrawer, theShapeDrawerMap, aSubShape,
551                               theOwner, theSelection, theTypOfSel, thePriority,
552                               theDeflection, theDeflAngle);
553   }
554 }
555
556 //=======================================================================
557 //function : addShapesWithCustomProps
558 //purpose  :
559 //=======================================================================
560 void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
561                                                  const DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
562                                                  const DataMapOfDrawerCompd& theDrawerClosedFaces,
563                                                  const Standard_Integer theMode)
564 {
565   Handle(Graphic3d_Group) anOpenGroup, aClosedGroup;
566   for (size_t aShType = 0; aShType <= (size_t )TopAbs_SHAPE; ++aShType)
567   {
568     const Standard_Boolean isClosed = aShType == TopAbs_SHAPE;
569     Handle(Graphic3d_Group)& aShadedGroup = isClosed ? aClosedGroup : anOpenGroup;
570     const DataMapOfDrawerCompd& aDrawerShapeMap = isClosed
571                                                 ? theDrawerClosedFaces
572                                                 : theDrawerOpenedShapePerType[aShType];
573     for (DataMapOfDrawerCompd::Iterator aMapIter (aDrawerShapeMap);
574          aMapIter.More(); aMapIter.Next())
575     {
576       const Handle(AIS_ColoredDrawer)& aCustomDrawer = aMapIter.Key();
577       const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
578       Handle(Prs3d_Drawer) aDrawer;
579       if (!aCustomDrawer.IsNull())
580       {
581         aDrawer = aCustomDrawer;
582         if (aCustomDrawer->IsHidden())
583         {
584           continue;
585         }
586       }
587       else
588       {
589         aDrawer = myDrawer;
590       }
591
592       // It is supposed that absolute deflection contains previously computed relative deflection
593       // (if deflection type is relative).
594       // In case of CustomDrawer it is taken from Link().
595       Aspect_TypeOfDeflection aPrevType = aDrawer->TypeOfDeflection();
596       aDrawer->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
597
598       // Draw each kind of subshapes and personal-colored shapes in a separate group
599       // since it's necessary to set transparency/material for all subshapes
600       // without affecting their unique colors
601       if (theMode == AIS_Shaded
602        && aShapeDraw.ShapeType() <= TopAbs_FACE
603        && !IsInfinite())
604       {
605         // add wireframe presentation for isolated edges and vertices
606         StdPrs_ShadedShape::AddWireframeForFreeElements (thePrs, aShapeDraw, aDrawer);
607
608         // add special wireframe presentation for faces without triangulation
609         StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (thePrs, aShapeDraw, aDrawer);
610
611         Handle(Graphic3d_ArrayOfTriangles) aTriangles = StdPrs_ShadedShape::FillTriangles (aShapeDraw,
612                                                                                            aDrawer->ShadingAspect()->Aspect()->ToMapTexture()
613                                                                                        && !aDrawer->ShadingAspect()->Aspect()->TextureMap().IsNull(),
614                                                                                            myUVOrigin, myUVRepeat, myUVScale);
615         if (!aTriangles.IsNull())
616         {
617           if (aShadedGroup.IsNull())
618           {
619             aShadedGroup = Prs3d_Root::NewGroup (thePrs);
620             aShadedGroup->SetClosed (isClosed);
621           }
622           aShadedGroup->SetPrimitivesAspect (aDrawer->ShadingAspect()->Aspect());
623           aShadedGroup->AddPrimitiveArray (aTriangles);
624         }
625
626         if (aDrawer->FaceBoundaryDraw())
627         {
628           Handle(Graphic3d_ArrayOfSegments) aBndSegments = StdPrs_ShadedShape::FillFaceBoundaries (aShapeDraw);
629           if (!aBndSegments.IsNull())
630           {
631             if (aShadedGroup.IsNull())
632             {
633               aShadedGroup = Prs3d_Root::NewGroup (thePrs);
634               aShadedGroup->SetClosed (isClosed);
635             }
636
637             Handle(Graphic3d_AspectLine3d) aBoundaryAspect = aDrawer->FaceBoundaryAspect()->Aspect();
638             aShadedGroup->SetPrimitivesAspect (aBoundaryAspect);
639             aShadedGroup->AddPrimitiveArray (aBndSegments);
640           }
641         }
642       }
643       else
644       {
645         StdPrs_WFShape::Add (thePrs, aShapeDraw, aDrawer);
646       }
647       aDrawer->SetTypeOfDeflection (aPrevType);
648     }
649   }
650 }
651
652 //=======================================================================
653 //function : dispatchColors
654 //purpose  :
655 //=======================================================================
656 Standard_Boolean AIS_ColoredShape::dispatchColors (const Handle(AIS_ColoredDrawer)& theParentDrawer,
657                                                    const TopoDS_Shape& theShapeToParse,
658                                                    const AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
659                                                    const TopAbs_ShapeEnum theParentType,
660                                                    const Standard_Boolean theIsParentClosed,
661                                                    DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
662                                                    DataMapOfDrawerCompd& theDrawerClosedFaces)
663 {
664   const TopAbs_ShapeEnum aShapeType = theShapeToParse.ShapeType();
665   if (aShapeType == TopAbs_SHAPE)
666   {
667     return Standard_False;
668   }
669
670   // check own setting of current shape
671   Handle(AIS_ColoredDrawer) aDrawer = theParentDrawer;
672   const Standard_Boolean isOverriden = theShapeDrawerMap.Find (theShapeToParse, aDrawer);
673   if (isOverriden
674    && aDrawer->IsHidden())
675   {
676     return Standard_True;
677   }
678
679   // handle compounds, solids and shells
680   Standard_Boolean isSubOverride = Standard_False;
681   if (aShapeType <= TopAbs_SHELL)
682   {
683     // detect parts of closed solids
684     Standard_Boolean isClosedShell = theParentType == TopAbs_SOLID
685                                   && aShapeType == TopAbs_SHELL
686                                   && BRep_Tool::IsClosed (theShapeToParse)
687                                   && StdPrs_ToolTriangulatedShape::IsTriangulated (theShapeToParse);
688     if (isClosedShell)
689     {
690       for (TopoDS_Iterator aFaceIter (theShapeToParse); aFaceIter.More(); aFaceIter.Next())
691       {
692         const TopoDS_Shape& aFace = aFaceIter.Value();
693         Handle(AIS_ColoredDrawer) aFaceDrawer;
694         if (aFace.ShapeType() == TopAbs_FACE
695          && theShapeDrawerMap.Find (aFace, aFaceDrawer)
696          && aFaceDrawer->IsHidden())
697         {
698           isClosedShell = Standard_False;
699           break;
700         }
701       }
702     }
703
704     for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
705     {
706       const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
707       if (dispatchColors (aDrawer, aSubShape,
708                           theShapeDrawerMap, aShapeType,
709                           isClosedShell,
710                           theDrawerOpenedShapePerType,
711                           theDrawerClosedFaces))
712       {
713         isSubOverride = Standard_True;
714       }
715     }
716     return isOverriden || isSubOverride;
717   }
718
719   // iterate on sub-shapes
720   BRep_Builder aBBuilder;
721   TopoDS_Shape aShapeCopy = theShapeToParse.EmptyCopied();
722   aShapeCopy.Closed (theShapeToParse.Closed());
723   Standard_Integer nbDef = 0;
724   for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
725   {
726     const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
727     if (dispatchColors (aDrawer, aSubShape,
728                         theShapeDrawerMap, aShapeType,
729                         theIsParentClosed,
730                         theDrawerOpenedShapePerType,
731                         theDrawerClosedFaces))
732     {
733       isSubOverride = Standard_True;
734     }
735     else
736     {
737       aBBuilder.Add (aShapeCopy, aSubShape);
738       ++nbDef;
739     }
740   }
741   if (aShapeType == TopAbs_FACE || !isSubOverride)
742   {
743     aShapeCopy = theShapeToParse;
744   }
745   else if (nbDef == 0)
746   {
747     return isOverriden || isSubOverride; // empty compound
748   }
749
750   // if any of styles is overridden regarding to default one, add rest to map
751   if (isOverriden
752   || (isSubOverride && theParentType != TopAbs_WIRE  // avoid drawing edges when vertex color is overridden
753                     && theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
754   || (theParentType <= TopAbs_SHELL && !(isOverriden || isSubOverride))) // bind original shape to default color
755   {
756     TopoDS_Compound aCompound;
757     DataMapOfDrawerCompd& aDrawerShapeMap = theIsParentClosed
758                                          && aShapeType == TopAbs_FACE
759                                           ? theDrawerClosedFaces
760                                           : theDrawerOpenedShapePerType[(size_t)aShapeType];
761     if (!aDrawerShapeMap.FindFromKey (aDrawer, aCompound))
762     {
763       aBBuilder.MakeCompound (aCompound);
764       aDrawerShapeMap.Add (aDrawer, aCompound);
765     }
766     aBBuilder.Add (aCompound, aShapeCopy);
767   }
768   return isOverriden || isSubOverride;
769 }
770
771 //=======================================================================
772 //function : isShapeEntirelyVisible
773 //purpose  :
774 //=======================================================================
775 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible() const
776 {
777   for (AIS_DataMapOfShapeDrawer::Iterator aMapIter (myShapeColors); aMapIter.More(); aMapIter.Next())
778   {
779     if (aMapIter.Value()->IsHidden())
780     {
781       return Standard_False;
782     }
783   }
784   return Standard_True;
785 }
786
787 //=======================================================================
788 //function : bindSubShapes
789 //purpose  :
790 //=======================================================================
791 void AIS_ColoredShape::bindSubShapes (AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
792                                       const TopoDS_Shape& theKeyShape,
793                                       const Handle(AIS_ColoredDrawer)& theDrawer) const
794 {
795   TopAbs_ShapeEnum aShapeWithColorType = theKeyShape.ShapeType();
796   if (aShapeWithColorType == TopAbs_COMPOUND)
797   {
798     theShapeDrawerMap.Bind (theKeyShape, theDrawer);
799   }
800   else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
801   {
802     for (TopExp_Explorer anExp (theKeyShape, TopAbs_FACE); anExp.More(); anExp.Next())
803     {
804       if (!theShapeDrawerMap.IsBound (anExp.Current()))
805       {
806         theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
807       }
808     }
809   }
810   else if (aShapeWithColorType == TopAbs_WIRE)
811   {
812     for (TopExp_Explorer anExp (theKeyShape, TopAbs_EDGE); anExp.More(); anExp.Next())
813     {
814       if (!theShapeDrawerMap.IsBound (anExp.Current()))
815       {
816         theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
817       }
818     }
819   }
820   else
821   {
822     // bind single face, edge and vertex
823     // force rebind if required due to the color of single shape has
824     // higher priority than the color of "compound" shape (wire is a
825     // compound of edges, shell is a compound of faces) that contains
826     // this single shape.
827     theShapeDrawerMap.Bind (theKeyShape, theDrawer);
828   }
829 }