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