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