#include <gp_Pnt2d.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <Graphic3d_AspectLine3d.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_Group.hxx>
#include <Graphic3d_StructureManager.hxx>
#include <Graphic3d_Texture2Dmanual.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Iterator.hxx>
-
-
-
IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredShape,AIS_Shape)
IMPLEMENT_STANDARD_RTTIEXT(AIS_ColoredDrawer,Prs3d_Drawer)
+namespace
+{
+ //! Collect all sub-compounds into map.
+ static void collectSubCompounds (TopTools_MapOfShape& theMap,
+ const TopoDS_Shape& theShape)
+ {
+ for (TopoDS_Iterator aChildIter (theShape); aChildIter.More(); aChildIter.Next())
+ {
+ const TopoDS_Shape& aShape = aChildIter.Value();
+ if (aShape.ShapeType() == TopAbs_COMPOUND
+ && theMap.Add (aShape))
+ {
+ collectSubCompounds (theMap, theShape);
+ }
+ }
+ }
+}
+
//=======================================================================
//function : AIS_ColoredShape
//purpose :
Prs3d::GetDeflection (myshape, myDrawer);
}
- TopoDS_Compound anOpened, aClosed;
- BRep_Builder aBuilder;
- aBuilder.MakeCompound (aClosed);
- aBuilder.MakeCompound (anOpened);
- if (theMode == AIS_Shaded && myshape.ShapeType() <= TopAbs_SOLID)
- {
- StdPrs_ShadedShape::ExploreSolids (myshape, aBuilder, aClosed, anOpened, Standard_False);
- }
- else
- {
- aBuilder.Add (anOpened, myshape);
- }
-
- // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
- DataMapOfShapeCompd aDispatchedOpened [(size_t)TopAbs_SHAPE];
- dispatchColors (anOpened, myShapeColors, aDispatchedOpened);
- addShapesWithCustomProps (thePrs, aDispatchedOpened, theMode, StdPrs_Volume_Opened);
-
- if (theMode == AIS_Shaded)
+ // Extract myShapeColors map (KeyshapeColored -> Color)
+ // to subshapes map (Subshape -> Color).
+ // This needed when colored shape is not part of BaseShape
+ // (but subshapes are) and actually container for subshapes.
+ AIS_DataMapOfShapeDrawer aSubshapeDrawerMap;
{
- if (isShapeEntirelyVisible())
+ // unroll compounds specified for grouping sub-shapes with the same style
+ // (e.g. the compounds that are not a part of the main shape)
+ TopTools_MapOfShape aMapOfOwnCompounds;
+ if (myshape.ShapeType() == TopAbs_COMPOUND)
{
- // myShapeColors + aClosed --> array[TopAbs_ShapeEnum] of map of color-to-compound
- DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
- dispatchColors (aClosed, myShapeColors, aDispatchedClosed);
- addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode, StdPrs_Volume_Closed);
+ aMapOfOwnCompounds.Add (myshape);
+ collectSubCompounds (aMapOfOwnCompounds, myshape);
}
- else
+ for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
+ aKeyShapeIter.More(); aKeyShapeIter.Next())
{
- for (TopoDS_Iterator aSolidIter (aClosed); aSolidIter.More(); aSolidIter.Next())
+ const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
+ if (aKeyShape.ShapeType() != TopAbs_COMPOUND
+ || aMapOfOwnCompounds.Contains (aKeyShape))
{
- DataMapOfShapeCompd aDispatchedClosed [(size_t)TopAbs_SHAPE];
- dispatchColors (aSolidIter.Value(), myShapeColors, aDispatchedClosed);
- addShapesWithCustomProps (thePrs, aDispatchedClosed, theMode,
- isShapeEntirelyVisible (aDispatchedClosed) ? StdPrs_Volume_Closed : StdPrs_Volume_Opened);
+ continue;
+ }
+
+ for (TopoDS_Iterator aChildIter (aKeyShape); aChildIter.More(); aChildIter.Next())
+ {
+ const TopoDS_Shape& aShape = aChildIter.Value();
+ if (!myShapeColors.IsBound (aShape))
+ {
+ bindSubShapes (aSubshapeDrawerMap, aShape, aKeyShapeIter.Value());
+ }
}
}
+
+ // assign other sub-shapes with styles
+ for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (myShapeColors);
+ aKeyShapeIter.More(); aKeyShapeIter.Next())
+ {
+ const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
+ if (myshape == aKeyShape
+ || (aKeyShape.ShapeType() == TopAbs_COMPOUND
+ && !aMapOfOwnCompounds.Contains (aKeyShape)))
+ {
+ continue;
+ }
+
+ bindSubShapes (aSubshapeDrawerMap, aKeyShape, aKeyShapeIter.Value());
+ }
}
+
+ Handle(AIS_ColoredDrawer) aBaseDrawer;
+ myShapeColors.Find (myshape, aBaseDrawer);
+
+ // myShapeColors + anOpened --> array[TopAbs_ShapeEnum] of map of color-to-compound
+ DataMapOfDrawerCompd aDispatchedOpened[(size_t)TopAbs_SHAPE];
+ DataMapOfDrawerCompd aDispatchedClosed;
+ dispatchColors (aBaseDrawer, myshape,
+ aSubshapeDrawerMap, TopAbs_COMPOUND, Standard_False,
+ aDispatchedOpened, theMode == AIS_Shaded ? aDispatchedClosed : aDispatchedOpened[TopAbs_FACE]);
+ addShapesWithCustomProps (thePrs, aDispatchedOpened, aDispatchedClosed, theMode);
}
//=======================================================================
//purpose :
//=======================================================================
void AIS_ColoredShape::addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
- DataMapOfShapeCompd* theDispatched,
- const Standard_Integer theMode,
- const StdPrs_Volume theVolume)
+ const DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
+ const DataMapOfDrawerCompd& theDrawerClosedFaces,
+ const Standard_Integer theMode)
{
- Handle(AIS_ColoredDrawer) aCustomDrawer;
- for (size_t aShType = 0; aShType < (size_t )TopAbs_SHAPE; ++aShType)
- {
- DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
- for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap);
+ Handle(Graphic3d_Group) anOpenGroup, aClosedGroup;
+ for (size_t aShType = 0; aShType <= (size_t )TopAbs_SHAPE; ++aShType)
+ {
+ const Standard_Boolean isClosed = aShType == TopAbs_SHAPE;
+ Handle(Graphic3d_Group)& aShadedGroup = isClosed ? aClosedGroup : anOpenGroup;
+ const DataMapOfDrawerCompd& aDrawerShapeMap = isClosed
+ ? theDrawerClosedFaces
+ : theDrawerOpenedShapePerType[aShType];
+ for (DataMapOfDrawerCompd::Iterator aMapIter (aDrawerShapeMap);
aMapIter.More(); aMapIter.Next())
{
- const TopoDS_Shape& aShapeKey = aMapIter.Key(); // key shape with detailed color or a base shape
+ const Handle(AIS_ColoredDrawer)& aCustomDrawer = aMapIter.Key();
const TopoDS_Compound& aShapeDraw = aMapIter.Value(); // compound of subshapes with <aShType> type
Handle(Prs3d_Drawer) aDrawer;
- if (myShapeColors.Find (aShapeKey, aCustomDrawer))
+ if (!aCustomDrawer.IsNull())
{
aDrawer = aCustomDrawer;
if (aCustomDrawer->IsHidden())
&& aShapeDraw.ShapeType() <= TopAbs_FACE
&& !IsInfinite())
{
- StdPrs_ShadedShape::Add (thePrs, aShapeDraw, aDrawer, theVolume);
+ // add wireframe presentation for isolated edges and vertices
+ StdPrs_ShadedShape::AddWireframeForFreeElements (thePrs, aShapeDraw, aDrawer);
+
+ // add special wireframe presentation for faces without triangulation
+ StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (thePrs, aShapeDraw, aDrawer);
+
+ Handle(Graphic3d_ArrayOfTriangles) aTriangles = StdPrs_ShadedShape::FillTriangles (aShapeDraw);
+ if (!aTriangles.IsNull())
+ {
+ if (aShadedGroup.IsNull())
+ {
+ aShadedGroup = Prs3d_Root::NewGroup (thePrs);
+ aShadedGroup->SetClosed (isClosed);
+ }
+ aShadedGroup->SetPrimitivesAspect (aDrawer->ShadingAspect()->Aspect());
+ aShadedGroup->AddPrimitiveArray (aTriangles);
+ }
+
+ if (aDrawer->FaceBoundaryDraw())
+ {
+ Handle(Graphic3d_ArrayOfSegments) aBndSegments = StdPrs_ShadedShape::FillFaceBoundaries (aShapeDraw);
+ if (!aBndSegments.IsNull())
+ {
+ if (aShadedGroup.IsNull())
+ {
+ aShadedGroup = Prs3d_Root::NewGroup (thePrs);
+ aShadedGroup->SetClosed (isClosed);
+ }
+
+ Handle(Graphic3d_AspectLine3d) aBoundaryAspect = aDrawer->FaceBoundaryAspect()->Aspect();
+ aShadedGroup->SetPrimitivesAspect (aBoundaryAspect);
+ aShadedGroup->AddPrimitiveArray (aBndSegments);
+ }
+ }
}
else
{
//function : dispatchColors
//purpose :
//=======================================================================
-Standard_Boolean AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseKey,
- const TopoDS_Shape& theSubshapeToParse,
- const DataMapOfShapeShape& theSubshapeKeyshapeMap,
- const TopAbs_ShapeEnum theParentType,
- DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
+Standard_Boolean AIS_ColoredShape::dispatchColors (const Handle(AIS_ColoredDrawer)& theParentDrawer,
+ const TopoDS_Shape& theShapeToParse,
+ const AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
+ const TopAbs_ShapeEnum theParentType,
+ const Standard_Boolean theIsParentClosed,
+ DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
+ DataMapOfDrawerCompd& theDrawerClosedFaces)
{
- TopAbs_ShapeEnum aShType = theSubshapeToParse.ShapeType();
- if (aShType == TopAbs_SHAPE)
+ const TopAbs_ShapeEnum aShapeType = theShapeToParse.ShapeType();
+ if (aShapeType == TopAbs_SHAPE)
{
return Standard_False;
}
// check own setting of current shape
- TopoDS_Shape aKeyShape = theBaseKey;
- Standard_Boolean isOverriden = theSubshapeKeyshapeMap.Find (theSubshapeToParse, aKeyShape);
+ Handle(AIS_ColoredDrawer) aDrawer = theParentDrawer;
+ const Standard_Boolean isOverriden = theShapeDrawerMap.Find (theShapeToParse, aDrawer);
+ if (isOverriden
+ && aDrawer->IsHidden())
+ {
+ return Standard_True;
+ }
+
+ // handle compounds, solids and shells
+ Standard_Boolean isSubOverride = Standard_False;
+ if (aShapeType <= TopAbs_SHELL)
+ {
+ // detect parts of closed solids
+ Standard_Boolean isClosedShell = theParentType == TopAbs_SOLID
+ && aShapeType == TopAbs_SHELL
+ && BRep_Tool::IsClosed (theShapeToParse)
+ && StdPrs_ToolTriangulatedShape::IsTriangulated (theShapeToParse);
+ if (isClosedShell)
+ {
+ for (TopoDS_Iterator aFaceIter (theShapeToParse); aFaceIter.More(); aFaceIter.Next())
+ {
+ const TopoDS_Shape& aFace = aFaceIter.Value();
+ Handle(AIS_ColoredDrawer) aFaceDrawer;
+ if (aFace.ShapeType() == TopAbs_FACE
+ && theShapeDrawerMap.Find (aFace, aFaceDrawer)
+ && aFaceDrawer->IsHidden())
+ {
+ isClosedShell = Standard_False;
+ break;
+ }
+ }
+ }
+
+ for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
+ {
+ const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
+ if (dispatchColors (aDrawer, aSubShape,
+ theShapeDrawerMap, aShapeType,
+ isClosedShell,
+ theDrawerOpenedShapePerType,
+ theDrawerClosedFaces))
+ {
+ isSubOverride = Standard_True;
+ }
+ }
+ return isOverriden || isSubOverride;
+ }
// iterate on sub-shapes
BRep_Builder aBBuilder;
- TopoDS_Shape aShapeCopy = theSubshapeToParse.EmptyCopied();
- aShapeCopy.Closed (theSubshapeToParse.Closed());
- Standard_Boolean isSubOverride = Standard_False;
+ TopoDS_Shape aShapeCopy = theShapeToParse.EmptyCopied();
+ aShapeCopy.Closed (theShapeToParse.Closed());
Standard_Integer nbDef = 0;
- for (TopoDS_Iterator it (theSubshapeToParse); it.More(); it.Next())
- {
- if (dispatchColors (theBaseKey, it.Value(),
- theSubshapeKeyshapeMap, aShType,
- theTypeKeyshapeDrawshapeArray))
+ for (TopoDS_Iterator aSubShapeIter (theShapeToParse); aSubShapeIter.More(); aSubShapeIter.Next())
+ {
+ const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
+ if (dispatchColors (aDrawer, aSubShape,
+ theShapeDrawerMap, aShapeType,
+ theIsParentClosed,
+ theDrawerOpenedShapePerType,
+ theDrawerClosedFaces))
{
isSubOverride = Standard_True;
}
else
{
- aBBuilder.Add (aShapeCopy, it.Value());
+ aBBuilder.Add (aShapeCopy, aSubShape);
++nbDef;
}
}
- if (aShType == TopAbs_FACE || !isSubOverride)
+ if (aShapeType == TopAbs_FACE || !isSubOverride)
{
- aShapeCopy = theSubshapeToParse;
+ aShapeCopy = theShapeToParse;
}
else if (nbDef == 0)
{
if (isOverriden
|| (isSubOverride && theParentType != TopAbs_WIRE // avoid drawing edges when vertex color is overridden
&& theParentType != TopAbs_FACE) // avoid drawing edges of the same color as face
- || (theParentType == TopAbs_SHAPE && !(isOverriden || isSubOverride))) // bind original shape to default color
+ || (theParentType <= TopAbs_SHELL && !(isOverriden || isSubOverride))) // bind original shape to default color
{
TopoDS_Compound aCompound;
- DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theTypeKeyshapeDrawshapeArray[(size_t )aShType];
- if (!aKeyshapeDrawshapeMap.FindFromKey (aKeyShape, aCompound))
+ DataMapOfDrawerCompd& aDrawerShapeMap = theIsParentClosed
+ && aShapeType == TopAbs_FACE
+ ? theDrawerClosedFaces
+ : theDrawerOpenedShapePerType[(size_t)aShapeType];
+ if (!aDrawerShapeMap.FindFromKey (aDrawer, aCompound))
{
aBBuilder.MakeCompound (aCompound);
- aKeyshapeDrawshapeMap.Add (aKeyShape, aCompound);
+ aDrawerShapeMap.Add (aDrawer, aCompound);
}
aBBuilder.Add (aCompound, aShapeCopy);
}
return isOverriden || isSubOverride;
}
-//! Function to check if specified compound is sub-shape of another one
-inline Standard_Boolean isFirstCmpContainSecondOne (const TopoDS_Shape& theFirstCmp,
- const TopoDS_Shape& theSecondCmp)
-{
- if (theFirstCmp.ShapeType() != TopAbs_COMPOUND
- || theSecondCmp.ShapeType() != TopAbs_COMPOUND)
- {
- return Standard_False;
- }
-
- for (TopoDS_Iterator aFirstCmpIter (theFirstCmp); aFirstCmpIter.More(); aFirstCmpIter.Next())
- {
- if (aFirstCmpIter.Value().ShapeType() != TopAbs_COMPOUND)
- {
- continue;
- }
- else if (aFirstCmpIter.Value() == theSecondCmp
- || isFirstCmpContainSecondOne (aFirstCmpIter.Value(), theSecondCmp))
- {
- return Standard_True;
- }
- }
- return Standard_False;
-}
-
-//=======================================================================
-//function : dispatchColors
-//purpose :
-//=======================================================================
-void AIS_ColoredShape::dispatchColors (const TopoDS_Shape& theBaseShape,
- const AIS_DataMapOfShapeDrawer& theKeyshapeColorMap,
- DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray)
-{
- // Extract <theShapeColors> map (KeyshapeColored -> Color)
- // to subshapes map (Subshape -> KeyshapeColored).
- // This needed when colored shape is not part of <theBaseShape>
- // (but subshapes are) and actually container for subshapes.
- DataMapOfShapeShape aSubshapeKeyshapeMap;
- for (AIS_DataMapOfShapeDrawer::Iterator aKeyShapeIter (theKeyshapeColorMap);
- aKeyShapeIter.More(); aKeyShapeIter.Next())
- {
- const TopoDS_Shape& aKeyShape = aKeyShapeIter.Key();
- bindSubShapes (aSubshapeKeyshapeMap, theBaseShape, aKeyShape, aKeyShape);
- }
-
- // Fill the array of maps per shape type
- dispatchColors (theBaseShape, theBaseShape,
- aSubshapeKeyshapeMap, TopAbs_SHAPE,
- theTypeKeyshapeDrawshapeArray);
-}
-
-//=======================================================================
-//function : isShapeEntirelyVisible
-//purpose :
-//=======================================================================
-Standard_Boolean AIS_ColoredShape::isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const
-{
- Handle(AIS_ColoredDrawer) aCustomDrawer;
- for (size_t aShType = (size_t )TopAbs_COMPOUND; aShType <= (size_t )TopAbs_FACE; ++aShType)
- {
- const DataMapOfShapeCompd& aKeyshapeDrawshapeMap = theDispatched[aShType];
- for (DataMapOfShapeCompd::Iterator aMapIter (aKeyshapeDrawshapeMap); aMapIter.More(); aMapIter.Next())
- {
- if (myShapeColors.Find (aMapIter.Key(), aCustomDrawer)
- && !aCustomDrawer.IsNull()
- && aCustomDrawer->IsHidden())
- {
- return Standard_False;
- }
- }
- }
- return Standard_True;
-}
-
//=======================================================================
//function : isShapeEntirelyVisible
//purpose :
//function : bindSubShapes
//purpose :
//=======================================================================
-void AIS_ColoredShape::bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
- const TopoDS_Shape& theBaseShape,
- const TopoDS_Shape& theShapeWithColor,
- const TopoDS_Shape& theColorKeyShape)
+void AIS_ColoredShape::bindSubShapes (AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
+ const TopoDS_Shape& theKeyShape,
+ const Handle(AIS_ColoredDrawer)& theDrawer)
{
- TopAbs_ShapeEnum aShapeWithColorType = theShapeWithColor.ShapeType();
+ TopAbs_ShapeEnum aShapeWithColorType = theKeyShape.ShapeType();
if (aShapeWithColorType == TopAbs_COMPOUND)
{
- if (isFirstCmpContainSecondOne (theBaseShape, theShapeWithColor))
- {
- if (!theSubshapeKeyshapeMap.IsBound (theShapeWithColor))
- {
- theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
- }
- }
- else
- {
- for (TopoDS_Iterator aSubShapeIter (theShapeWithColor); aSubShapeIter.More(); aSubShapeIter.Next())
- {
- bindSubShapes (theSubshapeKeyshapeMap, theBaseShape, aSubShapeIter.Value(), theColorKeyShape);
- }
- }
+ theShapeDrawerMap.Bind (theKeyShape, theDrawer);
}
else if (aShapeWithColorType == TopAbs_SOLID || aShapeWithColorType == TopAbs_SHELL)
{
- for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_FACE); anExp.More(); anExp.Next())
+ for (TopExp_Explorer anExp (theKeyShape, TopAbs_FACE); anExp.More(); anExp.Next())
{
- if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
+ if (!theShapeDrawerMap.IsBound (anExp.Current()))
{
- theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
+ theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
}
}
}
else if (aShapeWithColorType == TopAbs_WIRE)
{
- for (TopExp_Explorer anExp (theShapeWithColor, TopAbs_EDGE); anExp.More(); anExp.Next())
+ for (TopExp_Explorer anExp (theKeyShape, TopAbs_EDGE); anExp.More(); anExp.Next())
{
- if (!theSubshapeKeyshapeMap.IsBound (anExp.Current()))
+ if (!theShapeDrawerMap.IsBound (anExp.Current()))
{
- theSubshapeKeyshapeMap.Bind (anExp.Current(), theColorKeyShape);
+ theShapeDrawerMap.Bind (anExp.Current(), theDrawer);
}
}
}
// higher priority than the color of "compound" shape (wire is a
// compound of edges, shell is a compound of faces) that contains
// this single shape.
- theSubshapeKeyshapeMap.Bind (theShapeWithColor, theColorKeyShape);
+ theShapeDrawerMap.Bind (theKeyShape, theDrawer);
}
}
-
#include <NCollection_IndexedDataMap.hxx>
#include <StdPrs_Volume.hxx>
#include <TopoDS_Compound.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TColStd_MapTransientHasher.hxx>
//! Presentation of the shape with customizable sub-shapes properties.
class AIS_ColoredShape : public AIS_Shape
protected:
- typedef NCollection_DataMap<TopoDS_Shape, TopoDS_Shape, TopTools_ShapeMapHasher> DataMapOfShapeShape;
- typedef NCollection_IndexedDataMap<TopoDS_Shape, TopoDS_Compound, TopTools_ShapeMapHasher> DataMapOfShapeCompd;
+ typedef NCollection_IndexedDataMap<Handle(AIS_ColoredDrawer), TopoDS_Compound, TColStd_MapTransientHasher> DataMapOfDrawerCompd;
protected:
//! Recursive function to map shapes.
- //! @param theBaseKey the key to be used for undetailed shapes (default colors)
- //! @param theSubshapeToParse the subshape to be parsed
- //! @param theSubshapeKeyshapeMap shapes map Subshape (in the base shape) -> Keyshape (detailed shape)
- //! @param theParentType the parent subshape type
- //! @param theTypeKeyshapeDrawshapeArray the array of shape types to fill
- Standard_EXPORT static Standard_Boolean dispatchColors (const TopoDS_Shape& theBaseKey,
- const TopoDS_Shape& theSubshapeToParse,
- const DataMapOfShapeShape& theSubshapeKeyshapeMap,
- const TopAbs_ShapeEnum theParentType,
- DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray);
-
- Standard_EXPORT static void dispatchColors (const TopoDS_Shape& theBaseShape,
- const AIS_DataMapOfShapeDrawer& theKeyshapeColorMap,
- DataMapOfShapeCompd* theTypeKeyshapeDrawshapeArray);
-
+ //! @param theParentDrawer the drawer to be used for undetailed shapes (default colors)
+ //! @param theShapeToParse the subshape to be recursively parsed
+ //! @param theShapeDrawerMap shapes map Subshape (in the base shape) -> Drawer
+ //! @param theParentType the parent subshape type
+ //! @param theIsParentClosed flag indicating that specified shape is part of closed Solid
+ //! @param theDrawerOpenedShapePerType the array of shape types to fill
+ //! @param theDrawerClosedFaces the map for closed faces
+ Standard_EXPORT static Standard_Boolean dispatchColors (const Handle(AIS_ColoredDrawer)& theParentDrawer,
+ const TopoDS_Shape& theShapeToParse,
+ const AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
+ const TopAbs_ShapeEnum theParentType,
+ const Standard_Boolean theIsParentClosed,
+ DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
+ DataMapOfDrawerCompd& theDrawerClosedFaces);
protected:
//! Add shape to presentation
- //! @param thePrs the presentation
- //! @param theDispatched the shapes map with unique attributes
- //! @param theMode display mode
- //! @param theVolume how to interpret theDispatched shapes - as Closed volumes, as Open volumes
- //! or to perform Autodetection
+ //! @param thePrs the presentation
+ //! @param theDrawerOpenedShapePerType the shapes map with unique attributes
+ //! @param theDrawerClosedFaces the map of attributes for closed faces
+ //! @param theMode display mode
Standard_EXPORT void addShapesWithCustomProps (const Handle(Prs3d_Presentation)& thePrs,
- DataMapOfShapeCompd* theDispatched,
- const Standard_Integer theMode,
- const StdPrs_Volume theVolume);
+ const DataMapOfDrawerCompd* theDrawerOpenedShapePerType,
+ const DataMapOfDrawerCompd& theDrawerClosedFaces,
+ const Standard_Integer theMode);
//! Check all shapes from myShapeColorsfor visibility
Standard_EXPORT Standard_Boolean isShapeEntirelyVisible() const;
- //! Check a shape with unique attributes for visibility of all 2d subshape
- Standard_EXPORT Standard_Boolean isShapeEntirelyVisible (DataMapOfShapeCompd* theDispatched) const;
-
//! Resolve (parse) theKeyShape into subshapes, search in they for theBaseShape,
- //! bind all resolved subshapes with theOriginKeyShape and store all binds in theSubshapeKeyshapeMap
- //! @param theSubshapeKeyshapeMap shapes map: resolved and found theBaseShape subshape -> theOriginKeyShape
- //! @param theBaseShape a shape to be sought
- //! @param theBaseKey a shape to be resolved (parse) into smaller (in topological sense)
- //! subshapes for new bind cycle
- //! @param theOriginKeyShape the key to be used for undetailed shapes (default colors)
- Standard_EXPORT static void bindSubShapes (DataMapOfShapeShape& theSubshapeKeyshapeMap,
- const TopoDS_Shape& theBaseShape,
- const TopoDS_Shape& theKeyShape,
- const TopoDS_Shape& theOriginKeyShape);
+ //! bind all resolved subshapes with theOriginKeyShape and store all binds in theShapeDrawerMap
+ //! @param theShapeDrawerMap shapes map: resolved and found theBaseShape subshape -> theOriginKeyShape
+ //! @param theKeyShape a shape to be resolved (parse) into smaller (in topological sense)
+ //! subshapes for new bind cycle
+ //! @param theDrawer assigned drawer
+ Standard_EXPORT void bindSubShapes (AIS_DataMapOfShapeDrawer& theShapeDrawerMap,
+ const TopoDS_Shape& theKeyShape,
+ const Handle(AIS_ColoredDrawer)& theDrawer);
protected:
}
//! Compute boundary presentation for faces of the shape.
- static void computeFaceBoundaries (const TopoDS_Shape& theShape,
- const Handle(Prs3d_Presentation)& thePrs,
- const Handle(Prs3d_Drawer)& theDrawer)
+ static Handle(Graphic3d_ArrayOfSegments) fillFaceBoundaries (const TopoDS_Shape& theShape)
{
// collection of all triangulation nodes on edges
// for computing boundaries presentation
- NCollection_List<Handle(TColgp_HArray1OfPnt)> aNodeCollection;
Standard_Integer aNodeNumber = 0;
Standard_Integer aNbPolylines = 0;
}
if (aNodeNumber == 0)
{
- return;
+ return Handle(Graphic3d_ArrayOfSegments)();
}
// create indexed segments array to pack polylines from different edges into single array
}
}
}
-
- // set up aspect and add polyline data
- Handle(Graphic3d_AspectLine3d) aBoundaryAspect = theDrawer->FaceBoundaryAspect()->Aspect();
-
- Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePrs);
- aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect);
- aPrsGrp->AddPrimitiveArray (aSegments);
+ return aSegments;
}
} // anonymous namespace
if (theDrawer->FaceBoundaryDraw())
{
- computeFaceBoundaries (theShape, thePrs, theDrawer);
+ Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape);
+ if (!aBndSegments.IsNull())
+ {
+ Handle(Graphic3d_AspectLine3d) aBoundaryAspect = theDrawer->FaceBoundaryAspect()->Aspect();
+ Handle(Graphic3d_Group) aPrsGrp = Prs3d_Root::CurrentGroup (thePrs);
+ aPrsGrp->SetGroupPrimitivesAspect (aBoundaryAspect);
+ aPrsGrp->AddPrimitiveArray (aBndSegments);
+ }
}
}
+
+// =======================================================================
+// function : FillTriangles
+// purpose :
+// =======================================================================
+Handle(Graphic3d_ArrayOfTriangles) StdPrs_ShadedShape::FillTriangles (const TopoDS_Shape& theShape,
+ const Standard_Boolean theHasTexels,
+ const gp_Pnt2d& theUVOrigin,
+ const gp_Pnt2d& theUVRepeat,
+ const gp_Pnt2d& theUVScale)
+{
+ return fillTriangles (theShape, theHasTexels, theUVOrigin, theUVRepeat, theUVScale);
+}
+
+// =======================================================================
+// function : FillFaceBoundaries
+// purpose :
+// =======================================================================
+Handle(Graphic3d_ArrayOfSegments) StdPrs_ShadedShape::FillFaceBoundaries (const TopoDS_Shape& theShape)
+{
+ return fillFaceBoundaries (theShape);
+}
+
+// =======================================================================
+// function : AddWireframeForFreeElements
+// purpose :
+// =======================================================================
+void StdPrs_ShadedShape::AddWireframeForFreeElements (const Handle (Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle (Prs3d_Drawer)& theDrawer)
+{
+ wireframeFromShape (thePrs, theShape, theDrawer);
+}
+
+// =======================================================================
+// function : AddWireframeForFacesWithoutTriangles
+// purpose :
+// =======================================================================
+void StdPrs_ShadedShape::AddWireframeForFacesWithoutTriangles (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer)
+{
+ wireframeNoTriangFacesFromShape (thePrs, theShape, theDrawer);
+}
#include <Prs3d_Drawer.hxx>
#include <StdPrs_Volume.hxx>
#include <Standard_Boolean.hxx>
+
+class Graphic3d_ArrayOfSegments;
+class Graphic3d_ArrayOfTriangles;
class Prs3d_Presentation;
class TopoDS_Shape;
class gp_Pnt2d;
class BRep_Builder;
class TopoDS_Compound;
-
//! Auxiliary procedures to prepare Shaded presentation of specified shape.
-class StdPrs_ShadedShape : public Prs3d_Root
+class StdPrs_ShadedShape : public Prs3d_Root
{
public:
-
- DEFINE_STANDARD_ALLOC
-
//! Shades <theShape>.
//! @param theVolumeType defines the way how to interpret input shapes - as Closed volumes (to activate back-face
//! into two compounds for separate processing of closed and unclosed sub-shapes
Standard_EXPORT static void ExploreSolids (const TopoDS_Shape& theShape, const BRep_Builder& theBuilder, TopoDS_Compound& theClosed, TopoDS_Compound& theOpened, const Standard_Boolean theIgnore1DSubShape);
+ //! Computes wireframe presentation for free wires and vertices
+ Standard_EXPORT static void AddWireframeForFreeElements (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer);
+ //! Computes special wireframe presentation for faces without triangulation.
+ Standard_EXPORT static void AddWireframeForFacesWithoutTriangles (const Handle(Prs3d_Presentation)& thePrs,
+ const TopoDS_Shape& theShape,
+ const Handle(Prs3d_Drawer)& theDrawer);
+public:
-protected:
-
-
-
-
-
-private:
-
-
-
-
+ //! Create primitive array with triangles for specified shape.
+ //! @param theShape [in] the shape with precomputed triangulation
+ static Handle(Graphic3d_ArrayOfTriangles) FillTriangles (const TopoDS_Shape& theShape)
+ {
+ gp_Pnt2d aDummy;
+ return FillTriangles (theShape, Standard_False, aDummy, aDummy, aDummy);
+ }
+
+ //! Create primitive array of triangles for specified shape.
+ //! @param theShape the shape with precomputed triangulation
+ //! @param theHasTexels define UV coordinates in primitive array
+ //! @param theUVOrigin origin for UV coordinates
+ //! @param theUVRepeat repeat parameters for UV coordinates
+ //! @param theUVScale scale coefficients for UV coordinates
+ //! @return triangles array or NULL if specified face does not have computed triangulation
+ Standard_EXPORT static Handle(Graphic3d_ArrayOfTriangles) FillTriangles (const TopoDS_Shape& theShape,
+ const Standard_Boolean theHasTexels,
+ const gp_Pnt2d& theUVOrigin,
+ const gp_Pnt2d& theUVRepeat,
+ const gp_Pnt2d& theUVScale);
+
+ //! Define primitive array of boundary segments for specified shape.
+ //! @param theShape segments array or NULL if specified face does not have computed triangulation
+ Standard_EXPORT static Handle(Graphic3d_ArrayOfSegments) FillFaceBoundaries (const TopoDS_Shape& theShape);
};
-
-
-
-
-
-
#endif // _StdPrs_ShadedShape_HeaderFile
//purpose :
//=======================================================================
-void XCAFPrs::CollectStyleSettings (const TDF_Label &L,
- const TopLoc_Location &loc,
- XCAFPrs_DataMapOfShapeStyle &settings)
+void XCAFPrs::CollectStyleSettings (const TDF_Label& theLabel,
+ const TopLoc_Location& theLoc,
+ XCAFPrs_DataMapOfShapeStyle& theSettings)
{
- Handle(XCAFDoc_ColorTool) CTool = XCAFDoc_DocumentTool::ColorTool( L );
-
// for references, first collect colors of referred shape
- TDF_Label Lref;
- if ( XCAFDoc_ShapeTool::GetReferredShape ( L, Lref ) ) {
- TopLoc_Location locSub = loc.Multiplied ( XCAFDoc_ShapeTool::GetLocation ( L ) );
- CollectStyleSettings ( Lref, locSub, settings );
+ {
+ TDF_Label aLabelRef;
+ if (XCAFDoc_ShapeTool::GetReferredShape (theLabel, aLabelRef))
+ {
+ TopLoc_Location aLocSub = theLoc.Multiplied (XCAFDoc_ShapeTool::GetLocation (theLabel));
+ CollectStyleSettings (aLabelRef, aLocSub, theSettings);
+ }
}
-
+
// for assemblies, first collect colors defined in components
- TDF_LabelSequence seq;
- if ( XCAFDoc_ShapeTool::GetComponents ( L, seq ) && seq.Length() >0 ) {
- for ( Standard_Integer i = 1; i <= seq.Length(); i++ ) {
- CollectStyleSettings ( seq.Value(i), loc, settings );
+ {
+ TDF_LabelSequence aComponentLabSeq;
+ if (XCAFDoc_ShapeTool::GetComponents (theLabel, aComponentLabSeq)
+ && !aComponentLabSeq.IsEmpty())
+ {
+ for (TDF_LabelSequence::Iterator aComponentIter (aComponentLabSeq); aComponentIter.More(); aComponentIter.Next())
+ {
+ const TDF_Label& aComponentLab = aComponentIter.Value();
+ CollectStyleSettings (aComponentLab, theLoc, theSettings);
+ }
}
}
- // collect settings on subshapes and the shape itself
- seq.Clear();
- XCAFDoc_ShapeTool::GetSubShapes ( L, seq );
- seq.Append ( L );
- for ( Standard_Integer i = 1; i <= seq.Length(); i++ ) {
- TDF_Label lab = seq.Value(i);
- XCAFPrs_Style style;
- Handle(XCAFDoc_LayerTool) LTool = XCAFDoc_DocumentTool::LayerTool( lab );
- Handle(TColStd_HSequenceOfExtendedString) LayNames = new TColStd_HSequenceOfExtendedString;
-
- LTool->GetLayers(lab, LayNames);
- Standard_Integer InVisCount = 0;
- for ( Standard_Integer iL = 1; iL <= LayNames->Length(); iL++) {
- if ( !LTool->IsVisible( LTool->FindLayer(LayNames->Value(iL)) ) ) InVisCount++;
+ // collect settings on subshapes
+ Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theLabel);
+ TDF_LabelSequence aLabSeq;
+ XCAFDoc_ShapeTool::GetSubShapes (theLabel, aLabSeq);
+ // and add the shape itself
+ aLabSeq.Append (theLabel);
+ for (TDF_LabelSequence::Iterator aLabIter (aLabSeq); aLabIter.More(); aLabIter.Next())
+ {
+ const TDF_Label& aLabel = aLabIter.Value();
+ XCAFPrs_Style aStyle;
+
+ Standard_Boolean isVisible = aColorTool->IsVisible (aLabel);
+ if (isVisible)
+ {
+ Handle(XCAFDoc_LayerTool) aLayerTool = XCAFDoc_DocumentTool::LayerTool (aLabel);
+ Handle(TColStd_HSequenceOfExtendedString) aLayerNames = new TColStd_HSequenceOfExtendedString();
+ aLayerTool->GetLayers (aLabel, aLayerNames);
+ Standard_Integer aNbHidden = 0;
+ for (TColStd_HSequenceOfExtendedString::Iterator aLayerIter (*aLayerNames); aLayerIter.More(); aLayerIter.Next())
+ {
+ const TCollection_ExtendedString& aLayerName = aLayerIter.Value();
+ if (!aLayerTool->IsVisible (aLayerTool->FindLayer (aLayerName)))
+ {
+ ++aNbHidden;
+ }
+ }
+ isVisible = aNbHidden == 0
+ || aNbHidden != aLayerNames->Length();
}
- if ( (InVisCount >0 && InVisCount == LayNames->Length()) ||
- !CTool->IsVisible(lab) ) {
- style.SetVisibility(Standard_False);
+
+ if (!isVisible)
+ {
+ aStyle.SetVisibility (Standard_False);
}
- else {
- Quantity_Color C;
- if ( CTool->GetColor ( lab, XCAFDoc_ColorGen, C ) ) {
- style.SetColorCurv ( C );
- style.SetColorSurf ( C );
+ else
+ {
+ Quantity_Color aColor;
+ if (aColorTool->GetColor (aLabel, XCAFDoc_ColorGen, aColor))
+ {
+ aStyle.SetColorCurv (aColor);
+ aStyle.SetColorSurf (aColor);
+ }
+ if (aColorTool->GetColor (aLabel, XCAFDoc_ColorSurf, aColor))
+ {
+ aStyle.SetColorSurf (aColor);
+ }
+ if (aColorTool->GetColor (aLabel, XCAFDoc_ColorCurv, aColor))
+ {
+ aStyle.SetColorCurv (aColor);
}
- if ( CTool->GetColor ( lab, XCAFDoc_ColorSurf, C ) )
- style.SetColorSurf ( C );
- if ( CTool->GetColor ( lab, XCAFDoc_ColorCurv, C ) )
- style.SetColorCurv ( C );
}
+
// PTV try to set color from SHUO structure
- Handle(XCAFDoc_ShapeTool) STool = CTool->ShapeTool();
- Handle(XCAFDoc_GraphNode) SHUO;
- TDF_AttributeSequence theSHUOAttrs;
- if (STool->IsComponent( lab ) ) {
- STool->GetAllComponentSHUO( lab, theSHUOAttrs );
- for (Standard_Integer shuoIndx = 1; shuoIndx <= theSHUOAttrs.Length(); shuoIndx++) {
- SHUO = Handle(XCAFDoc_GraphNode)::DownCast(theSHUOAttrs.Value(shuoIndx));
- if ( SHUO.IsNull() )
+ Handle(XCAFDoc_ShapeTool) aShapeTool = aColorTool->ShapeTool();
+ if (aShapeTool->IsComponent (aLabel))
+ {
+ TDF_AttributeSequence aShuoAttribSeq;
+ aShapeTool->GetAllComponentSHUO (aLabel, aShuoAttribSeq);
+ for (TDF_AttributeSequence::Iterator aShuoAttribIter (aShuoAttribSeq); aShuoAttribIter.More(); aShuoAttribIter.Next())
+ {
+ Handle(XCAFDoc_GraphNode) aShuoNode = Handle(XCAFDoc_GraphNode)::DownCast (aShuoAttribIter.Value());
+ if (aShuoNode.IsNull())
+ {
continue;
- TDF_Label aSHUOlab = SHUO->Label();
+ }
- TDF_LabelSequence aLabSeq;
- STool->GetSHUONextUsage( aSHUOlab, aLabSeq );
- if (aLabSeq.Length() < 1 )
- continue;
-
- Quantity_Color C;
- XCAFPrs_Style SHUOstyle;
- if (!CTool->IsVisible( aSHUOlab ) )
- SHUOstyle.SetVisibility(Standard_False);
- else {
- if ( CTool->GetColor ( aSHUOlab, XCAFDoc_ColorGen, C ) ) {
- SHUOstyle.SetColorCurv ( C );
- SHUOstyle.SetColorSurf ( C );
+ const TDF_Label aShuolab = aShuoNode->Label();
+ {
+ TDF_LabelSequence aShuoLabSeq;
+ aShapeTool->GetSHUONextUsage (aShuolab, aShuoLabSeq);
+ if (aShuoLabSeq.IsEmpty())
+ {
+ continue;
}
- if ( CTool->GetColor ( aSHUOlab, XCAFDoc_ColorSurf, C ) )
- SHUOstyle.SetColorSurf ( C );
- if ( CTool->GetColor ( aSHUOlab, XCAFDoc_ColorCurv, C ) )
- SHUOstyle.SetColorCurv ( C );
}
- if ( !SHUOstyle.IsSetColorCurv() &&
- !SHUOstyle.IsSetColorSurf() &&
- SHUOstyle.IsVisible() )
+
+ Quantity_Color aColor;
+ XCAFPrs_Style aShuoStyle;
+ if (!aColorTool->IsVisible (aShuolab))
+ {
+ aShuoStyle.SetVisibility (Standard_False);
+ }
+ else
+ {
+ if (aColorTool->GetColor (aShuolab, XCAFDoc_ColorGen, aColor))
+ {
+ aShuoStyle.SetColorCurv (aColor);
+ aShuoStyle.SetColorSurf (aColor);
+ }
+ if (aColorTool->GetColor (aShuolab, XCAFDoc_ColorSurf, aColor))
+ {
+ aShuoStyle.SetColorSurf (aColor);
+ }
+ if (aColorTool->GetColor (aShuolab, XCAFDoc_ColorCurv, aColor))
+ {
+ aShuoStyle.SetColorCurv (aColor);
+ }
+ }
+ if (!aShuoStyle.IsSetColorCurv()
+ && !aShuoStyle.IsSetColorSurf()
+ && aShuoStyle.IsVisible())
+ {
continue;
-
- // set style for all component from Next Usage Occurrence.
-#ifdef OCCT_DEBUG
+ }
+
+ // set style for all component from Next Usage Occurrence.
+ #ifdef OCCT_DEBUG
cout << "Set the style for SHUO next_usage-occurrance" << endl;
-#endif
+ #endif
/*
// may be work, but static it returns excess shapes. It is more faster to use OLD version.
// PTV 14.02.2003 NEW version using API of ShapeTool
- TopTools_SequenceOfShape aSHUOShapeSeq;
- STool->GetAllStyledComponents( SHUO, aSHUOShapeSeq );
- for (Standard_Integer si= 1; si <= aSHUOShapeSeq.Length(); si++) {
- TopoDS_Shape aSHUOSh = aSHUOShapeSeq.Value(si);
- if (!aSHUOSh.IsNull())
- settings.Bind ( aSHUOSh, SHUOstyle );
- }
- */
- // OLD version that was written before ShapeTool API, and ti FASTER for presentation
+ TopTools_SequenceOfShape aShuoShapeSeq;
+ aShapeTool->GetAllStyledComponents (aShuoNode, aShuoShapeSeq);
+ for (TopTools_SequenceOfShape::Iterator aShuoShapeIter (aShuoShapeSeq); aShuoShapeIter.More(); aShuoShapeIter.Next())
+ {
+ const TopoDS_Shape& aShuoShape = aShuoShapeIter.Value();
+ if (!aShuoShape.IsNull())
+ theSettings.Bind (aShuoShape, aShuoStyle);
+ }*/
+ // OLD version that was written before ShapeTool API, and it FASTER for presentation
// get TOP location of SHUO component
- TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation ( lab );
+ TopLoc_Location compLoc = XCAFDoc_ShapeTool::GetLocation (aLabel);
TopLoc_IndexedMapOfLocation aPrevLocMap;
- // get previous setted location
- if ( !loc.IsIdentity() )
- aPrevLocMap.Add( loc );
-
- aPrevLocMap.Add( compLoc );
- TopTools_SequenceOfShape aSHUOShapeSeq;
+ // get previous set location
+ if (!theLoc.IsIdentity())
+ {
+ aPrevLocMap.Add (theLoc);
+ }
+ aPrevLocMap.Add (compLoc);
+
// get shapes of SHUO Next_Usage components
- getShapesOfSHUO( aPrevLocMap, STool, aSHUOlab, aSHUOShapeSeq );
- for (Standard_Integer n = 1; n <= aSHUOShapeSeq.Length(); n++ ) {
- TopoDS_Shape aSHUOSh = aSHUOShapeSeq.Value( n );
- settings.Bind ( aSHUOSh, SHUOstyle );
+ TopTools_SequenceOfShape aShuoShapeSeq;
+ getShapesOfSHUO (aPrevLocMap, aShapeTool, aShuolab, aShuoShapeSeq);
+ for (TopTools_SequenceOfShape::Iterator aShuoShapeIter (aShuoShapeSeq); aShuoShapeIter.More(); aShuoShapeIter.Next())
+ {
+ const TopoDS_Shape& aShuoShape = aShuoShapeIter.Value();
+ theSettings.Bind (aShuoShape, aShuoStyle);
}
continue;
}
}
- if ( !style.IsSetColorCurv() &&
- !style.IsSetColorSurf() &&
- style.IsVisible() )
+
+ if (!aStyle.IsSetColorCurv()
+ && !aStyle.IsSetColorSurf()
+ && aStyle.IsVisible())
+ {
continue;
- TopoDS_Shape sub = XCAFDoc_ShapeTool::GetShape ( lab );
- sub.Move ( loc );
- settings.Bind ( sub, style );
+ }
+
+ TopoDS_Shape aSubshape = XCAFDoc_ShapeTool::GetShape (aLabel);
+ if (aSubshape.ShapeType() == TopAbs_COMPOUND)
+ {
+ const TopoDS_Iterator aShapeIter (aSubshape);
+ if (!aShapeIter.More())
+ {
+ continue;
+ }
+ }
+ aSubshape.Move (theLoc);
+ theSettings.Bind (aSubshape, aStyle);
}
}
--- /dev/null
+puts "==========="
+puts "OCC28036"
+puts "Visualization, AIS_ColoredShape - handle correctly nested compounds within Shaded display mode"
+puts "==========="
+puts ""
+
+pload MODELING VISUALIZATION
+box b1 0 0 0 1 2 3
+box b2 0 3 0 2 1 3
+box b3 3 0 0 3 2 1
+compound b1 b2 c12
+compound c12 b3 c
+
+vclear
+vinit View1
+vaxo
+vdisplay -dispMode 1 c
+vfit
+
+vaspects c -setColor BLUE1
+vaspects c -subshapes b1 -setColor RED
+vaspects c -subshapes c12 -setColor GREEN
+
+if { [vreadpixel 100 100 rgb name] != "RED3" } { puts "Error: wrong subshape color" }
+if { [vreadpixel 200 100 rgb name] != "GREEN3" } { puts "Error: wrong subshape color" }
+if { [vreadpixel 200 300 rgb name] != "BLUE3" } { puts "Error: wrong subshape color" }
+
+vdump $imagedir/${casename}.png
--- /dev/null
+puts "==========="
+puts "OCC28036"
+puts "Visualization, AIS_ColoredShape - handle correctly nested compounds within Shaded display mode"
+puts "==========="
+puts ""
+
+pload MODELING VISUALIZATION
+
+clear
+box b1 0 0 0 100 200 1
+box b2 150 0 0 100 50 1
+box b3 150 50 0 100 150 1
+
+for {set i 1} {$i <= 3} {incr i} { tcopy b${i} b1_${i}; ttranslate b1_${i} 0 -300 0 }
+for {set i 1} {$i <= 3} {incr i} { tcopy b${i} b2_${i}; ttranslate b2_${i} 0 0 0 }
+for {set i 1} {$i <= 3} {incr i} { tcopy b${i} b3_${i}; ttranslate b3_${i} 0 300 0 }
+
+# make a reference scene with per-object colors
+vclear
+vinit View1
+vsetdispmode 1
+vaxo
+
+vdisplay b1_1 b1_2 b1_3
+vsetcolor b1_1 RED
+vsetcolor b1_2 GREEN
+vsetcolor b1_3 BLUE1
+
+vdisplay b2_1 b2_2 b2_3
+vsetcolor b2_1 RED
+vsetcolor b2_2 GREEN
+vsetcolor b2_3 BLUE1
+
+vdisplay b3_1 b3_2 b3_3
+vsetcolor b3_1 RED
+vsetcolor b3_2 GREEN
+vsetcolor b3_3 BLUE1
+vfit
+vdump $imagedir/${casename}_ref.png
+
+# make a scene with sub-colors and nested compounds
+for {set j 1} {$j <= 3} {incr j} { compound b${j}_2 b${j}_3 b${j}_23 }
+for {set j 1} {$j <= 3} {incr j} { compound b${j}_1 b${j}_23 b${j}_123 }
+compound b1_123 b2_123 b3_123 b123_123
+
+vclear
+vdisplay b123_123
+
+compound b1_23 b2_23 b3_23 b123_23
+vaspects b123_123 -subshapes b123_23 -setColor GREEN
+
+vaspects b123_123 -subshapes b1_123 -setColor RED
+vaspects b123_123 -subshapes b2_123 -setColor RED
+vaspects b123_123 -subshapes b3_123 -setColor RED
+
+compound b2_3 b3_3 b23_3
+vaspects b123_123 -subshapes b1_3 -setColor BLUE1
+vaspects b123_123 -subshapes b23_3 -setColor BLUE1
+
+if { [vreadpixel 50 250 rgb name] != "RED3" } { puts "Error: wrong color" }
+if { [vreadpixel 175 175 rgb name] != "RED3" } { puts "Error: wrong color" }
+if { [vreadpixel 300 100 rgb name] != "RED3" } { puts "Error: wrong color" }
+
+if { [vreadpixel 100 310 rgb name] != "GREEN3"} { puts "Error: wrong color" }
+if { [vreadpixel 200 230 rgb name] != "GREEN3"} { puts "Error: wrong color" }
+if { [vreadpixel 320 170 rgb name] != "GREEN3"} { puts "Error: wrong color" }
+
+if { [vreadpixel 130 280 rgb name] != "BLUE3" } { puts "Error: wrong color" }
+if { [vreadpixel 250 200 rgb name] != "BLUE3" } { puts "Error: wrong color" }
+if { [vreadpixel 350 150 rgb name] != "BLUE3" } { puts "Error: wrong color" }
+
+vdump $imagedir/${casename}.png