1 // Created on: 2014-04-24
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <AIS_ColoredShape.hxx>
18 #include <AIS_InteractiveContext.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRepTools.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Graphic3d_AspectFillArea3d.hxx>
23 #include <Graphic3d_AspectLine3d.hxx>
24 #include <Graphic3d_ArrayOfTriangles.hxx>
25 #include <Graphic3d_ArrayOfSegments.hxx>
26 #include <Graphic3d_Group.hxx>
27 #include <Graphic3d_StructureManager.hxx>
28 #include <Graphic3d_Texture2Dmanual.hxx>
29 #include <Precision.hxx>
31 #include <Prs3d_LineAspect.hxx>
32 #include <Prs3d_IsoAspect.hxx>
33 #include <Prs3d_Presentation.hxx>
34 #include <Prs3d_ShadingAspect.hxx>
35 #include <Prs3d_Root.hxx>
36 #include <PrsMgr_PresentationManager3d.hxx>
37 #include <Standard_ErrorHandler.hxx>
38 #include <StdPrs_ShadedShape.hxx>
39 #include <StdPrs_ToolTriangulatedShape.hxx>
40 #include <StdPrs_WFShape.hxx>
41 #include <TopExp_Explorer.hxx>
43 #include <TopoDS_Compound.hxx>
44 #include <TopoDS_Iterator.hxx>
46 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape,AIS_Shape)
47 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer,Prs3d_Drawer)
51 //! Collect all sub-compounds into map.
52 static void collectSubCompounds (TopTools_MapOfShape& theMap,
53 const TopoDS_Shape& theShape)
55 for (TopoDS_Iterator aChildIter (theShape); aChildIter.More(); aChildIter.Next())
57 const TopoDS_Shape& aShape = aChildIter.Value();
58 if (aShape.ShapeType() == TopAbs_COMPOUND
59 && theMap.Add (aShape))
61 collectSubCompounds (theMap, theShape);
67 //=======================================================================
68 //function : AIS_ColoredShape
70 //=======================================================================
71 AIS_ColoredShape::AIS_ColoredShape (const TopoDS_Shape& theShape)
72 : AIS_Shape (theShape)
74 // disable dedicated line aspects
75 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
76 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
77 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
80 //=======================================================================
81 //function : AIS_ColoredShape
83 //=======================================================================
84 AIS_ColoredShape::AIS_ColoredShape (const Handle(AIS_Shape)& theShape)
85 : AIS_Shape (theShape->Shape())
87 // disable dedicated line aspects
88 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
89 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
90 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
91 if (theShape->HasMaterial())
93 SetMaterial (theShape->Material());
95 if (theShape->HasColor())
97 SetColor (theShape->Color());
99 if (theShape->HasWidth())
101 SetWidth (theShape->Width());
103 if (theShape->IsTransparent())
105 SetTransparency (theShape->Transparency());
109 //=======================================================================
110 //function : CustomAspects
112 //=======================================================================
113 Handle(AIS_ColoredDrawer) AIS_ColoredShape::CustomAspects (const TopoDS_Shape& theShape)
115 Handle(AIS_ColoredDrawer) aDrawer;
116 myShapeColors.Find (theShape, aDrawer);
117 if (aDrawer.IsNull())
119 aDrawer = new AIS_ColoredDrawer (myDrawer);
120 myShapeColors.Bind (theShape, aDrawer);
121 LoadRecomputable (AIS_WireFrame);
122 LoadRecomputable (AIS_Shaded);
127 //=======================================================================
128 //function : ClearCustomAspects
130 //=======================================================================
131 void AIS_ColoredShape::ClearCustomAspects()
133 if (myShapeColors.IsEmpty())
137 myShapeColors.Clear();
138 LoadRecomputable (AIS_WireFrame);
139 LoadRecomputable (AIS_Shaded);
142 //=======================================================================
143 //function : UnsetCustomAspects
145 //=======================================================================
146 void AIS_ColoredShape::UnsetCustomAspects (const TopoDS_Shape& theShape,
147 const Standard_Boolean theToUnregister)
149 if (!myShapeColors.IsBound (theShape))
154 LoadRecomputable (AIS_WireFrame);
155 LoadRecomputable (AIS_Shaded);
158 myShapeColors.UnBind (theShape);
162 myShapeColors.ChangeFind (theShape) = new AIS_ColoredDrawer (myDrawer);
165 //=======================================================================
166 //function : SetCustomColor
168 //=======================================================================
169 void AIS_ColoredShape::SetCustomColor (const TopoDS_Shape& theShape,
170 const Quantity_Color& theColor)
172 if (theShape.IsNull())
177 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
178 setColor (aDrawer, theColor);
179 aDrawer->SetOwnColor (theColor);
180 LoadRecomputable (AIS_WireFrame);
181 LoadRecomputable (AIS_Shaded);
184 //=======================================================================
185 //function : SetCustomWidth
187 //=======================================================================
188 void AIS_ColoredShape::SetCustomWidth (const TopoDS_Shape& theShape,
189 const Standard_Real theLineWidth)
191 if (theShape.IsNull())
196 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
197 setWidth (CustomAspects (theShape), theLineWidth);
198 aDrawer->SetOwnWidth (theLineWidth);
199 LoadRecomputable (AIS_WireFrame);
200 LoadRecomputable (AIS_Shaded);
203 //=======================================================================
204 //function : SetColor
206 //=======================================================================
208 void AIS_ColoredShape::SetColor (const Quantity_Color& theColor)
210 setColor (myDrawer, theColor);
211 myOwnColor = theColor;
212 hasOwnColor = Standard_True;
213 LoadRecomputable (AIS_WireFrame);
214 LoadRecomputable (AIS_Shaded);
215 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
217 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
218 if (aDrawer->HasOwnColor())
223 if (aDrawer->HasOwnShadingAspect())
225 aDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
227 if (aDrawer->HasOwnLineAspect())
229 aDrawer->LineAspect()->SetColor (theColor);
231 if (aDrawer->HasOwnWireAspect())
233 aDrawer->WireAspect()->SetColor (theColor);
238 //=======================================================================
239 //function : SetWidth
241 //=======================================================================
243 void AIS_ColoredShape::SetWidth (const Standard_Real theLineWidth)
245 setWidth (myDrawer, theLineWidth);
246 myOwnWidth = theLineWidth;
247 LoadRecomputable (AIS_WireFrame);
248 LoadRecomputable (AIS_Shaded);
249 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
251 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
252 if (aDrawer->HasOwnWidth())
257 if (aDrawer->HasOwnLineAspect())
259 aDrawer->LineAspect()->SetWidth (theLineWidth);
261 if (aDrawer->HasOwnWireAspect())
263 aDrawer->WireAspect()->SetWidth (theLineWidth);
268 //=======================================================================
269 //function : SetTransparency
271 //=======================================================================
273 void AIS_ColoredShape::SetTransparency (const Standard_Real theValue)
275 setTransparency (myDrawer, theValue);
276 myTransparency = theValue;
277 LoadRecomputable (AIS_WireFrame);
278 LoadRecomputable (AIS_Shaded);
279 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
281 const Handle(Prs3d_Drawer)& aDrawer = anIter.Value();
282 if (aDrawer->HasOwnShadingAspect())
284 aDrawer->ShadingAspect()->SetTransparency (theValue, myCurrentFacingModel);
289 //=======================================================================
290 //function : SetMaterial
292 //=======================================================================
294 void AIS_ColoredShape::SetMaterial (const Graphic3d_MaterialAspect& theMaterial)
296 setMaterial (myDrawer, theMaterial, HasColor(), IsTransparent());
297 //myOwnMaterial = theMaterial;
298 hasOwnMaterial = Standard_True;
299 LoadRecomputable (AIS_Shaded);
300 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
302 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
303 //if (aDrawer->HasOwnMaterial()) continue;
304 if (aDrawer->HasOwnShadingAspect())
306 setMaterial (aDrawer, theMaterial, aDrawer->HasOwnColor(), Standard_False); // aDrawer->IsTransparent()
311 //=======================================================================
314 //=======================================================================
315 void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
316 const Handle(Prs3d_Presentation)& thePrs,
317 const Standard_Integer theMode)
319 if (myshape.IsNull())
326 thePrs->SetInfiniteState (Standard_True);
329 if (theMode == AIS_Shaded)
331 if (myDrawer->IsAutoTriangulation())
333 // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
334 StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
336 // After this call if type of deflection is relative
337 // computed deflection coefficient is stored as absolute.
338 Standard_Boolean wasRecomputed = StdPrs_ToolTriangulatedShape::Tessellate (myshape, myDrawer);
340 // Set to update wireframe presentation on triangulation.
341 if (myDrawer->IsoOnTriangulation() && wasRecomputed)
343 SetToUpdate (AIS_WireFrame);
347 else // WireFrame mode
349 StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
351 // After this call if type of deflection is relative
352 // computed deflection coefficient is stored as absolute.
353 Prs3d::GetDeflection (myshape, myDrawer);
356 // Extract myShapeColors map (KeyshapeColored -> Color)
357 // to subshapes map (Subshape -> Color).
358 // This needed when colored shape is not part of BaseShape
359 // (but subshapes are) and actually container for subshapes.
360 AIS_DataMapOfShapeDrawer aSubshapeDrawerMap;
362 // unroll compounds specified for grouping sub-shapes with the same style
363 // (e.g. the compounds that are not a part of the main shape)
364 TopTools_MapOfShape aMapOfOwnCompounds;
365 if (myshape.ShapeType() == TopAbs_COMPOUND)
367 aMapOfOwnCompounds.Add (myshape);
368 collectSubCompounds (aMapOfOwnCompounds, myshape);
370 for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
371 aKeyShapeIter.More(); aKeyShapeIter.Next())
373 const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
374 if (aKeyShape.ShapeType() != TopAbs_COMPOUND
375 || aMapOfOwnCompounds.Contains (aKeyShape))
380 for (TopoDS_Iterator aChildIter (aKeyShape); aChildIter.More(); aChildIter.Next())
382 const TopoDS_Shape& aShape = aChildIter.Value();
383 if (!myShapeColors.IsBound (aShape))
385 bindSubShapes (aSubshapeDrawerMap, aShape, aKeyShapeIter.Value());
390 // assign other sub-shapes with styles
391 for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
392 aKeyShapeIter.More(); aKeyShapeIter.Next())
394 const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
395 if (myshape == aKeyShape
396 || (aKeyShape.ShapeType() == TopAbs_COMPOUND
397 && !aMapOfOwnCompounds.Contains (aKeyShape)))
402 bindSubShapes (aSubshapeDrawerMap, aKeyShape, aKeyShapeIter.Value());
406 Handle(AIS_ColoredDrawer) aBaseDrawer;
407 myShapeColors.Find (myshape, aBaseDrawer);
409 // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
410 DataMapOfDrawerCompd aDispatchedOpened[(size_t)TopAbs_SHAPE];
411 DataMapOfDrawerCompd aDispatchedClosed;
412 dispatchColors (aBaseDrawer, myshape,
413 aSubshapeDrawerMap, TopAbs_COMPOUND, Standard_False,
414 aDispatchedOpened, theMode == AIS_Shaded ? aDispatchedClosed : aDispatchedOpened[TopAbs_FACE]);
415 addShapesWithCustomProps (thePrs, aDispatchedOpened, aDispatchedClosed, theMode);
418 //=======================================================================
419 //function : addShapesWithCustomProps
421 //=======================================================================
422 void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
423 const DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
424 const DataMapOfDrawerCompd& theDrawerClosedFaces,
425 const Standard_Integer theMode)
427 Handle(Graphic3d_Group) anOpenGroup, aClosedGroup;
428 for (size_t aShType = 0; aShType <= (size_t )TopAbs_SHAPE; ++aShType)
430 const Standard_Boolean isClosed = aShType == TopAbs_SHAPE;
431 Handle(Graphic3d_Group)& aShadedGroup = isClosed ? aClosedGroup : anOpenGroup;
432 const DataMapOfDrawerCompd& aDrawerShapeMap = isClosed
433 ? theDrawerClosedFaces
434 : theDrawerOpenedShapePerType[aShType];
435 for (DataMapOfDrawerCompd::Iterator aMapIter (aDrawerShapeMap);
436 aMapIter.More(); aMapIter.Next())
438 const Handle(AIS_ColoredDrawer)& aCustomDrawer = aMapIter.Key();
439 const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
440 Handle(Prs3d_Drawer) aDrawer;
441 if (!aCustomDrawer.IsNull())
443 aDrawer = aCustomDrawer;
444 if (aCustomDrawer->IsHidden())
454 // It is supposed that absolute deflection contains previously computed relative deflection
455 // (if deflection type is relative).
456 // In case of CustomDrawer it is taken from Link().
457 Aspect_TypeOfDeflection aPrevType = aDrawer->TypeOfDeflection();
458 aDrawer->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
460 // Draw each kind of subshapes and personal-colored shapes in a separate group
461 // since it's necessary to set transparency/material for all subshapes
462 // without affecting their unique colors
463 if (theMode == AIS_Shaded
464 && aShapeDraw.ShapeType() <= TopAbs_FACE
467 // add wireframe presentation for isolated edges and vertices
468 StdPrs_ShadedShape::AddWireframeForFreeElements (thePrs, aShapeDraw, aDrawer);
470 // add special wireframe presentation for faces without triangulation
471 StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (thePrs, aShapeDraw, aDrawer);
473 Handle(Graphic3d_ArrayOfTriangles) aTriangles = StdPrs_ShadedShape::FillTriangles (aShapeDraw);
474 if (!aTriangles.IsNull())
476 if (aShadedGroup.IsNull())
478 aShadedGroup = Prs3d_Root::NewGroup (thePrs);
479 aShadedGroup->SetClosed (isClosed);
481 aShadedGroup->SetPrimitivesAspect (aDrawer->ShadingAspect()->Aspect());
482 aShadedGroup->AddPrimitiveArray (aTriangles);
485 if (aDrawer->FaceBoundaryDraw())
487 Handle(Graphic3d_ArrayOfSegments) aBndSegments = StdPrs_ShadedShape::FillFaceBoundaries (aShapeDraw);
488 if (!aBndSegments.IsNull())
490 if (aShadedGroup.IsNull())
492 aShadedGroup = Prs3d_Root::NewGroup (thePrs);
493 aShadedGroup->SetClosed (isClosed);
496 Handle(Graphic3d_AspectLine3d) aBoundaryAspect = aDrawer->FaceBoundaryAspect()->Aspect();
497 aShadedGroup->SetPrimitivesAspect (aBoundaryAspect);
498 aShadedGroup->AddPrimitiveArray (aBndSegments);
504 StdPrs_WFShape::Add (thePrs, aShapeDraw, aDrawer);
506 aDrawer->SetTypeOfDeflection (aPrevType);
511 //=======================================================================
512 //function : dispatchColors
514 //=======================================================================
515 Standard_Boolean AIS_ColoredShape::dispatchColors (const Handle(AIS_ColoredDrawer)& theParentDrawer,
516 const TopoDS_Shape& theShapeToParse,
517 const AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
518 const TopAbs_ShapeEnum theParentType,
519 const Standard_Boolean theIsParentClosed,
520 DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
521 DataMapOfDrawerCompd& theDrawerClosedFaces)
523 const TopAbs_ShapeEnum aShapeType = theShapeToParse.ShapeType();
524 if (aShapeType == TopAbs_SHAPE)
526 return Standard_False;
529 // check own setting of current shape
530 Handle(AIS_ColoredDrawer) aDrawer = theParentDrawer;
531 const Standard_Boolean isOverriden = theShapeDrawerMap.Find (theShapeToParse, aDrawer);
533 && aDrawer->IsHidden())
535 return Standard_True;
538 // handle compounds, solids and shells
539 Standard_Boolean isSubOverride = Standard_False;
540 if (aShapeType <= TopAbs_SHELL)
542 // detect parts of closed solids
543 Standard_Boolean isClosedShell = theParentType == TopAbs_SOLID
544 && aShapeType == TopAbs_SHELL
545 && BRep_Tool::IsClosed (theShapeToParse)
546 && StdPrs_ToolTriangulatedShape::IsTriangulated (theShapeToParse);
549 for (TopoDS_Iterator aFaceIter (theShapeToParse); aFaceIter.More(); aFaceIter.Next())
551 const TopoDS_Shape& aFace = aFaceIter.Value();
552 Handle(AIS_ColoredDrawer) aFaceDrawer;
553 if (aFace.ShapeType() == TopAbs_FACE
554 && theShapeDrawerMap.Find (aFace, aFaceDrawer)
555 && aFaceDrawer->IsHidden())
557 isClosedShell = Standard_False;
563 for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
565 const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
566 if (dispatchColors (aDrawer, aSubShape,
567 theShapeDrawerMap, aShapeType,
569 theDrawerOpenedShapePerType,
570 theDrawerClosedFaces))
572 isSubOverride = Standard_True;
575 return isOverriden || isSubOverride;
578 // iterate on sub-shapes
579 BRep_Builder aBBuilder;
580 TopoDS_Shape aShapeCopy = theShapeToParse.EmptyCopied();
581 aShapeCopy.Closed (theShapeToParse.Closed());
582 Standard_Integer nbDef = 0;
583 for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
585 const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
586 if (dispatchColors (aDrawer, aSubShape,
587 theShapeDrawerMap, aShapeType,
589 theDrawerOpenedShapePerType,
590 theDrawerClosedFaces))
592 isSubOverride = Standard_True;
596 aBBuilder.Add (aShapeCopy, aSubShape);
600 if (aShapeType == TopAbs_FACE || !isSubOverride)
602 aShapeCopy = theShapeToParse;
606 return isOverriden || isSubOverride; // empty compound
609 // if any of styles is overridden regarding to default one, add rest to map
611 || (isSubOverride && theParentType != TopAbs_WIRE // avoid drawing edges when vertex color is overridden
612 && theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
613 || (theParentType <= TopAbs_SHELL && !(isOverriden || isSubOverride))) // bind original shape to default color
615 TopoDS_Compound aCompound;
616 DataMapOfDrawerCompd& aDrawerShapeMap = theIsParentClosed
617 && aShapeType == TopAbs_FACE
618 ? theDrawerClosedFaces
619 : theDrawerOpenedShapePerType[(size_t)aShapeType];
620 if (!aDrawerShapeMap.FindFromKey (aDrawer, aCompound))
622 aBBuilder.MakeCompound (aCompound);
623 aDrawerShapeMap.Add (aDrawer, aCompound);
625 aBBuilder.Add (aCompound, aShapeCopy);
627 return isOverriden || isSubOverride;
630 //=======================================================================
631 //function : isShapeEntirelyVisible
633 //=======================================================================
634 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible() const
636 for (AIS_DataMapOfShapeDrawer::Iterator aMapIter (myShapeColors); aMapIter.More(); aMapIter.Next())
638 if (aMapIter.Value()->IsHidden())
640 return Standard_False;
643 return Standard_True;
646 //=======================================================================
647 //function : bindSubShapes
649 //=======================================================================
650 void AIS_ColoredShape::bindSubShapes (AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
651 const TopoDS_Shape& theKeyShape,
652 const Handle(AIS_ColoredDrawer)& theDrawer)
654 TopAbs_ShapeEnum aShapeWithColorType = theKeyShape.ShapeType();
655 if (aShapeWithColorType == TopAbs_COMPOUND)
657 theShapeDrawerMap.Bind (theKeyShape, theDrawer);
659 else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
661 for (TopExp_Explorer anExp (theKeyShape, TopAbs_FACE); anExp.More(); anExp.Next())
663 if (!theShapeDrawerMap.IsBound (anExp.Current()))
665 theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
669 else if (aShapeWithColorType == TopAbs_WIRE)
671 for (TopExp_Explorer anExp (theKeyShape, TopAbs_EDGE); anExp.More(); anExp.Next())
673 if (!theShapeDrawerMap.IsBound (anExp.Current()))
675 theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
681 // bind single face, edge and vertex
682 // force rebind if required due to the color of single shape has
683 // higher priority than the color of "compound" shape (wire is a
684 // compound of edges, shell is a compound of faces) that contains
685 // this single shape.
686 theShapeDrawerMap.Bind (theKeyShape, theDrawer);