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