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_Group.hxx>
25 #include <Graphic3d_StructureManager.hxx>
26 #include <Graphic3d_Texture2Dmanual.hxx>
27 #include <Precision.hxx>
29 #include <Prs3d_LineAspect.hxx>
30 #include <Prs3d_IsoAspect.hxx>
31 #include <Prs3d_Presentation.hxx>
32 #include <Prs3d_ShadingAspect.hxx>
33 #include <Prs3d_Root.hxx>
34 #include <PrsMgr_PresentationManager3d.hxx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <StdPrs_ShadedShape.hxx>
37 #include <StdPrs_ToolTriangulatedShape.hxx>
38 #include <StdPrs_WFShape.hxx>
39 #include <TopExp_Explorer.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <TopoDS_Iterator.hxx>
47 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape,AIS_Shape)
48 IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer,Prs3d_Drawer)
50 //=======================================================================
51 //function : AIS_ColoredShape
53 //=======================================================================
54 AIS_ColoredShape::AIS_ColoredShape (const TopoDS_Shape& theShape)
55 : AIS_Shape (theShape)
57 // disable dedicated line aspects
58 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
59 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
60 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
63 //=======================================================================
64 //function : AIS_ColoredShape
66 //=======================================================================
67 AIS_ColoredShape::AIS_ColoredShape (const Handle(AIS_Shape)& theShape)
68 : AIS_Shape (theShape->Shape())
70 // disable dedicated line aspects
71 myDrawer->SetFreeBoundaryAspect (myDrawer->LineAspect());
72 myDrawer->SetUnFreeBoundaryAspect(myDrawer->LineAspect());
73 myDrawer->SetSeenLineAspect (myDrawer->LineAspect());
74 if (theShape->HasMaterial())
76 SetMaterial (theShape->Material());
78 if (theShape->HasColor())
80 SetColor (theShape->Color());
82 if (theShape->HasWidth())
84 SetWidth (theShape->Width());
86 if (theShape->IsTransparent())
88 SetTransparency (theShape->Transparency());
92 //=======================================================================
93 //function : CustomAspects
95 //=======================================================================
96 Handle(AIS_ColoredDrawer) AIS_ColoredShape::CustomAspects (const TopoDS_Shape& theShape)
98 Handle(AIS_ColoredDrawer) aDrawer;
99 myShapeColors.Find (theShape, aDrawer);
100 if (aDrawer.IsNull())
102 aDrawer = new AIS_ColoredDrawer (myDrawer);
103 myShapeColors.Bind (theShape, aDrawer);
104 LoadRecomputable (AIS_WireFrame);
105 LoadRecomputable (AIS_Shaded);
110 //=======================================================================
111 //function : ClearCustomAspects
113 //=======================================================================
114 void AIS_ColoredShape::ClearCustomAspects()
116 if (myShapeColors.IsEmpty())
120 myShapeColors.Clear();
121 LoadRecomputable (AIS_WireFrame);
122 LoadRecomputable (AIS_Shaded);
125 //=======================================================================
126 //function : UnsetCustomAspects
128 //=======================================================================
129 void AIS_ColoredShape::UnsetCustomAspects (const TopoDS_Shape& theShape,
130 const Standard_Boolean theToUnregister)
132 if (!myShapeColors.IsBound (theShape))
137 LoadRecomputable (AIS_WireFrame);
138 LoadRecomputable (AIS_Shaded);
141 myShapeColors.UnBind (theShape);
145 myShapeColors.ChangeFind (theShape) = new AIS_ColoredDrawer (myDrawer);
148 //=======================================================================
149 //function : SetCustomColor
151 //=======================================================================
152 void AIS_ColoredShape::SetCustomColor (const TopoDS_Shape& theShape,
153 const Quantity_Color& theColor)
155 if (theShape.IsNull())
160 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
161 setColor (aDrawer, theColor);
162 aDrawer->SetOwnColor (theColor);
163 LoadRecomputable (AIS_WireFrame);
164 LoadRecomputable (AIS_Shaded);
167 //=======================================================================
168 //function : SetCustomWidth
170 //=======================================================================
171 void AIS_ColoredShape::SetCustomWidth (const TopoDS_Shape& theShape,
172 const Standard_Real theLineWidth)
174 if (theShape.IsNull())
179 const Handle(AIS_ColoredDrawer)& aDrawer = CustomAspects (theShape);
180 setWidth (CustomAspects (theShape), theLineWidth);
181 aDrawer->SetOwnWidth (theLineWidth);
182 LoadRecomputable (AIS_WireFrame);
183 LoadRecomputable (AIS_Shaded);
186 //=======================================================================
187 //function : SetColor
189 //=======================================================================
191 void AIS_ColoredShape::SetColor (const Quantity_Color& theColor)
193 setColor (myDrawer, theColor);
194 myOwnColor = theColor;
195 hasOwnColor = Standard_True;
196 LoadRecomputable (AIS_WireFrame);
197 LoadRecomputable (AIS_Shaded);
198 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
200 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
201 if (aDrawer->HasOwnColor())
206 if (aDrawer->HasOwnShadingAspect())
208 aDrawer->ShadingAspect()->SetColor (theColor, myCurrentFacingModel);
210 if (aDrawer->HasOwnLineAspect())
212 aDrawer->LineAspect()->SetColor (theColor);
214 if (aDrawer->HasOwnWireAspect())
216 aDrawer->WireAspect()->SetColor (theColor);
221 //=======================================================================
222 //function : SetWidth
224 //=======================================================================
226 void AIS_ColoredShape::SetWidth (const Standard_Real theLineWidth)
228 setWidth (myDrawer, theLineWidth);
229 myOwnWidth = theLineWidth;
230 LoadRecomputable (AIS_WireFrame);
231 LoadRecomputable (AIS_Shaded);
232 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
234 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
235 if (aDrawer->HasOwnWidth())
240 if (aDrawer->HasOwnLineAspect())
242 aDrawer->LineAspect()->SetWidth (theLineWidth);
244 if (aDrawer->HasOwnWireAspect())
246 aDrawer->WireAspect()->SetWidth (theLineWidth);
251 //=======================================================================
252 //function : SetTransparency
254 //=======================================================================
256 void AIS_ColoredShape::SetTransparency (const Standard_Real theValue)
258 setTransparency (myDrawer, theValue);
259 myTransparency = theValue;
260 LoadRecomputable (AIS_WireFrame);
261 LoadRecomputable (AIS_Shaded);
262 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
264 const Handle(Prs3d_Drawer)& aDrawer = anIter.Value();
265 if (aDrawer->HasOwnShadingAspect())
267 aDrawer->ShadingAspect()->SetTransparency (theValue, myCurrentFacingModel);
272 //=======================================================================
273 //function : SetMaterial
275 //=======================================================================
277 void AIS_ColoredShape::SetMaterial (const Graphic3d_MaterialAspect& theMaterial)
279 setMaterial (myDrawer, theMaterial, HasColor(), IsTransparent());
280 //myOwnMaterial = theMaterial;
281 hasOwnMaterial = Standard_True;
282 LoadRecomputable (AIS_Shaded);
283 for (AIS_DataMapOfShapeDrawer::Iterator anIter (myShapeColors); anIter.More(); anIter.Next())
285 const Handle(AIS_ColoredDrawer)& aDrawer = anIter.Value();
286 //if (aDrawer->HasOwnMaterial()) continue;
287 if (aDrawer->HasOwnShadingAspect())
289 setMaterial (aDrawer, theMaterial, aDrawer->HasOwnColor(), Standard_False); // aDrawer->IsTransparent()
294 //=======================================================================
297 //=======================================================================
298 void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
299 const Handle(Prs3d_Presentation)& thePrs,
300 const Standard_Integer theMode)
302 if (myshape.IsNull())
309 thePrs->SetInfiniteState (Standard_True);
312 if (theMode == AIS_Shaded)
314 if (myDrawer->IsAutoTriangulation())
316 // compute mesh for entire shape beforehand to ensure consistency and optimizations (parallelization)
317 StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
319 // After this call if type of deflection is relative
320 // computed deflection coefficient is stored as absolute.
321 Standard_Boolean wasRecomputed = StdPrs_ToolTriangulatedShape::Tessellate (myshape, myDrawer);
323 // Set to update wireframe presentation on triangulation.
324 if (myDrawer->IsoOnTriangulation() && wasRecomputed)
326 SetToUpdate (AIS_WireFrame);
330 else // WireFrame mode
332 StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
334 // After this call if type of deflection is relative
335 // computed deflection coefficient is stored as absolute.
336 Prs3d::GetDeflection (myshape, myDrawer);
339 TopoDS_Compound anOpened, aClosed;
340 BRep_Builder aBuilder;
341 aBuilder.MakeCompound (aClosed);
342 aBuilder.MakeCompound (anOpened);
343 if (theMode == AIS_Shaded && myshape.ShapeType() <= TopAbs_SOLID)
345 StdPrs_ShadedShape::ExploreSolids (myshape, aBuilder, aClosed, anOpened, Standard_False);
349 aBuilder.Add (anOpened, myshape);
352 // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
353 DataMapOfShapeCompd aDispatchedOpened [(size_t)TopAbs_SHAPE];
354 dispatchColors (anOpened, myShapeColors, aDispatchedOpened);
355 addShapesWithCustomProps (thePrs, aDispatchedOpened, theMode, StdPrs_Volume_Opened);
357 if (theMode == AIS_Shaded)
359 if (isShapeEntirelyVisible())
361 // myShapeColors + aClosed --> array[TopAbs_ShapeEnum] of map of color-to-compound
362 DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
363 dispatchColors (aClosed, myShapeColors, aDispatchedClosed);
364 addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode, StdPrs_Volume_Closed);
368 for (TopoDS_Iterator aSolidIter (aClosed); aSolidIter.More(); aSolidIter.Next())
370 DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
371 dispatchColors (aSolidIter.Value(), myShapeColors, aDispatchedClosed);
372 addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode,
373 isShapeEntirelyVisible (aDispatchedClosed) ? StdPrs_Volume_Closed : StdPrs_Volume_Opened);
379 //=======================================================================
380 //function : addShapesWithCustomProps
382 //=======================================================================
383 void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
384 DataMapOfShapeCompd* theDispatched,
385 const Standard_Integer theMode,
386 const StdPrs_Volume theVolume)
388 Handle(AIS_ColoredDrawer) aCustomDrawer;
389 for (size_t aShType = 0; aShType < (size_t )TopAbs_SHAPE; ++aShType)
391 DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
392 for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap);
393 aMapIter.More(); aMapIter.Next())
395 const TopoDS_Shape& aShapeKey = aMapIter.Key(); // key shape with detailed color or a base shape
396 const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
397 Handle(Prs3d_Drawer) aDrawer;
398 if (myShapeColors.Find (aShapeKey, aCustomDrawer))
400 aDrawer = aCustomDrawer;
401 if (aCustomDrawer->IsHidden())
411 // It is supposed that absolute deflection contains previously computed relative deflection
412 // (if deflection type is relative).
413 // In case of CustomDrawer it is taken from Link().
414 Aspect_TypeOfDeflection aPrevType = aDrawer->TypeOfDeflection();
415 aDrawer->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
417 // Draw each kind of subshapes and personal-colored shapes in a separate group
418 // since it's necessary to set transparency/material for all subshapes
419 // without affecting their unique colors
420 if (theMode == AIS_Shaded
421 && aShapeDraw.ShapeType() <= TopAbs_FACE
424 StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer, theVolume);
428 StdPrs_WFShape::Add (thePrs, aShapeDraw, aDrawer);
430 aDrawer->SetTypeOfDeflection (aPrevType);
435 //=======================================================================
436 //function : dispatchColors
438 //=======================================================================
439 Standard_Boolean AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseKey,
440 const TopoDS_Shape& theSubshapeToParse,
441 const DataMapOfShapeShape& theSubshapeKeyshapeMap,
442 const TopAbs_ShapeEnum theParentType,
443 DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
445 TopAbs_ShapeEnum aShType = theSubshapeToParse.ShapeType();
446 if (aShType == TopAbs_SHAPE)
448 return Standard_False;
451 // check own setting of current shape
452 TopoDS_Shape aKeyShape = theBaseKey;
453 Standard_Boolean isOverriden = theSubshapeKeyshapeMap.Find (theSubshapeToParse, aKeyShape);
455 // iterate on sub-shapes
456 BRep_Builder aBBuilder;
457 TopoDS_Shape aShapeCopy = theSubshapeToParse.EmptyCopied();
458 aShapeCopy.Closed (theSubshapeToParse.Closed());
459 Standard_Boolean isSubOverride = Standard_False;
460 Standard_Integer nbDef = 0;
461 for (TopoDS_Iterator it (theSubshapeToParse); it.More(); it.Next())
463 if (dispatchColors (theBaseKey, it.Value(),
464 theSubshapeKeyshapeMap, aShType,
465 theTypeKeyshapeDrawshapeArray))
467 isSubOverride = Standard_True;
471 aBBuilder.Add (aShapeCopy, it.Value());
475 if (aShType == TopAbs_FACE || !isSubOverride)
477 aShapeCopy = theSubshapeToParse;
481 return isOverriden || isSubOverride; // empty compound
484 // if any of styles is overridden regarding to default one, add rest to map
486 || (isSubOverride && theParentType != TopAbs_WIRE // avoid drawing edges when vertex color is overridden
487 && theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
488 || (theParentType == TopAbs_SHAPE && !(isOverriden || isSubOverride))) // bind original shape to default color
490 TopoDS_Compound aCompound;
491 DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theTypeKeyshapeDrawshapeArray[(size_t )aShType];
492 if (!aKeyshapeDrawshapeMap.FindFromKey (aKeyShape, aCompound))
494 aBBuilder.MakeCompound (aCompound);
495 aKeyshapeDrawshapeMap.Add (aKeyShape, aCompound);
497 aBBuilder.Add (aCompound, aShapeCopy);
499 return isOverriden || isSubOverride;
502 //! Function to check if specified compound is sub-shape of another one
503 inline Standard_Boolean isFirstCmpContainSecondOne (const TopoDS_Shape& theFirstCmp,
504 const TopoDS_Shape& theSecondCmp)
506 if (theFirstCmp.ShapeType() != TopAbs_COMPOUND
507 || theSecondCmp.ShapeType() != TopAbs_COMPOUND)
509 return Standard_False;
512 for (TopoDS_Iterator aFirstCmpIter (theFirstCmp); aFirstCmpIter.More(); aFirstCmpIter.Next())
514 if (aFirstCmpIter.Value().ShapeType() != TopAbs_COMPOUND)
518 else if (aFirstCmpIter.Value() == theSecondCmp
519 || isFirstCmpContainSecondOne (aFirstCmpIter.Value(), theSecondCmp))
521 return Standard_True;
524 return Standard_False;
527 //=======================================================================
528 //function : dispatchColors
530 //=======================================================================
531 void AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseShape,
532 const AIS_DataMapOfShapeDrawer& theKeyshapeColorMap,
533 DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
535 // Extract <theShapeColors> map (KeyshapeColored -> Color)
536 // to subshapes map (Subshape -> KeyshapeColored).
537 // This needed when colored shape is not part of <theBaseShape>
538 // (but subshapes are) and actually container for subshapes.
539 DataMapOfShapeShape aSubshapeKeyshapeMap;
540 for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (theKeyshapeColorMap);
541 aKeyShapeIter.More(); aKeyShapeIter.Next())
543 const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
544 bindSubShapes (aSubshapeKeyshapeMap, theBaseShape, aKeyShape, aKeyShape);
547 // Fill the array of maps per shape type
548 dispatchColors (theBaseShape, theBaseShape,
549 aSubshapeKeyshapeMap, TopAbs_SHAPE,
550 theTypeKeyshapeDrawshapeArray);
553 //=======================================================================
554 //function : isShapeEntirelyVisible
556 //=======================================================================
557 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const
559 Handle(AIS_ColoredDrawer) aCustomDrawer;
560 for (size_t aShType = (size_t )TopAbs_COMPOUND; aShType <= (size_t )TopAbs_FACE; ++aShType)
562 const DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
563 for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap); aMapIter.More(); aMapIter.Next())
565 if (myShapeColors.Find (aMapIter.Key(), aCustomDrawer)
566 && !aCustomDrawer.IsNull()
567 && aCustomDrawer->IsHidden())
569 return Standard_False;
573 return Standard_True;
576 //=======================================================================
577 //function : isShapeEntirelyVisible
579 //=======================================================================
580 Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible() const
582 for (AIS_DataMapOfShapeDrawer::Iterator aMapIter (myShapeColors); aMapIter.More(); aMapIter.Next())
584 if (aMapIter.Value()->IsHidden())
586 return Standard_False;
589 return Standard_True;
592 //=======================================================================
593 //function : bindSubShapes
595 //=======================================================================
596 void AIS_ColoredShape::bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
597 const TopoDS_Shape& theBaseShape,
598 const TopoDS_Shape& theShapeWithColor,
599 const TopoDS_Shape& theColorKeyShape)
601 TopAbs_ShapeEnum aShapeWithColorType = theShapeWithColor.ShapeType();
602 if (aShapeWithColorType == TopAbs_COMPOUND)
604 if (isFirstCmpContainSecondOne (theBaseShape, theShapeWithColor))
606 if (!theSubshapeKeyshapeMap.IsBound (theShapeWithColor))
608 theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
613 for (TopoDS_Iterator aSubShapeIter (theShapeWithColor); aSubShapeIter.More(); aSubShapeIter.Next())
615 bindSubShapes (theSubshapeKeyshapeMap, theBaseShape, aSubShapeIter.Value(), theColorKeyShape);
619 else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
621 for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_FACE); anExp.More(); anExp.Next())
623 if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
625 theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
629 else if (aShapeWithColorType == TopAbs_WIRE)
631 for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_EDGE); anExp.More(); anExp.Next())
633 if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
635 theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
641 // bind single face, edge and vertex
642 // force rebind if required due to the color of single shape has
643 // higher priority than the color of "compound" shape (wire is a
644 // compound of edges, shell is a compound of faces) that contains
645 // this single shape.
646 theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);