Managing Attribute Inheritance

The PRC assembly tree is hierarchical. As such, certain attributes may be inherited from parent node to child node. Inheritable attributes include visibility, color, transparency, layer, line pattern, and line width. Each type of attribute may be inherited independently. Collectively, all the attributes make up the entity’s behavior . HOOPS Exchange uses the concepts of father inheritance and son inheritance to determine how attributes are propagated down the tree.

Inheritance always propagates in one direction - from parent to child. Each type of inheritance has a certain strength that determines whether or not the attribute is passed to child nodes.

  • Son inheritance is strongest. A node with son inheritance will always pass its own attributes to child nodes - unless the child nodes also have the son inheritance behavior. If a child node has son inheritance, the child will express its own attributes. Son inheritance will propagate down the assembly tree until the terminal leaf node.

  • Father inheritance also allows a node to pass its attributes to child nodes. However, this only works if the child nodes have either 1) no behavior setting of their own or 2) a setting of father inheritance, in which case the attributes for the topmost node with father inheritance will be applied to a child node with father inheritance, overriding its local attribute settings.

  • No inheritance - Nodes are not required to have a behavior setting. In this case, the node’s attributes will not override the attributes of its children. However, any other type of inheritance propagated from above may override the “no inheritance” setting. “No inheritance” is the implied setting if the node has neither father nor son inheritance.

Let’s look at a few examples that show how inheritance works in an assembly tree. For this example, we’ll use color because it is easy to visualize. In the diagrams below, the colored boxes represent nodes. The color in the top half of each box is the color that was set locally on that node. The color in the bottom half is the color that is actually expressed in the geometry due to the rules of inheritance.

../../_images/inheritance1.png

In this diagram, son inheritance in the first box overrides the father inheritance in box 2. The orange color continues to propagate down the tree; however, the blue box also has son inheritance. Thus, orange stops and blue is propagated.

../../_images/inheritance2.png

Here, father inheritance overrides the color for the boxes in which inheritance is not set at all. Even though the box at the bottom of the tree has father inheritance and sets the color to red, the box is orange because attributes in the topmost node with father inheritance will override attributes in any child nodes with father inheritance.

../../_images/inheritance3.png

If no inheritance is set, color will only inherit to child nodes with no color of their own. However, the red box has father inheritance, so red is used for that box.

How does this look in code? Well, behaviors are always associated with an entity’s graphical data. Thus, if you need to find the inheritance type for a product occurrence node, you could do something like the following:

// get root-base-with-graphics data from 'myProductOccurrence' node
A3DRootBaseWithGraphicsData rootBaseWithGraphics;
A3D_INITIALIZE_DATA(A3DRootBaseWithGraphicsData, rootBaseWithGraphics);
A3DRootBaseWithGraphicsGet(myProductOccurrence, &rootBaseWithGraphics);

// get graphics data associated with the root-base-with-graphics
A3DGraphicsData graphicsData;
A3D_INITIALIZE_DATA(A3DGraphicsData, graphicsData);
A3DGraphicsGet(rootBaseWithGraphics.m_pGraphics, &graphicsData);

// graphicsData.m_usBehaviour has the behavior information

You may have noticed that the field graphicsData.m_usBehaviour is a simple type - A3DUns16, and is used as a bit field. Thus, to get the value for color, you need to perform bitwise operations:

A3DUns16 colorInheritance = graphicsData.m_usBehaviour & kA3DGraphicsSonHeritColor;

if (colorInheritance)
        // it is of type kA3DGraphicsSonHeritColor

colorInheritance = graphicsData.m_usBehaviour & kA3DGraphicsFatherHeritColor;

if (colorInheritance)
        // it is of type kA3DGraphicsFatherHeritColor

// test for other behavior types

You can see all possible values for the behavior bit field in A3DSDKGraphics.h.

As mentioned previously, attributes such as color and transform are usually computed for an entire entity after considering the effects of the inheritance. In some cases, however, it would be useful to be able to completely override the computed attribute and replace it with another. Additionally, it is not possible to apply an attribute to a single subentity - such as a face - at the product occurrence level. Entity references solve these problems.

The product occurrence node has an entity reference field of type A3DMiscEntityReference. If this field is not NULL, this indicates the node’s attributes should be supplanted by the attributes in the entity reference. You can use this mechanism to redefine color, transparency, visibility, and transformation. Attributes defined in this way are inheritable to child entities.

Subentity Attributes

The same pattern is used to apply attributes at the subentity level. For example, when a face has a different color than the rest of the model, it will use an entity reference. Doing so requires the model to have a B-rep definition, because tessellation alone does not have a concept of individual faces. This type of reference is of type A3DMiscReferenceOnTopology.

Other Behaviors

This section mainly dealt with color, but the same concepts apply to all behaviors. One behavior that may require special consideration is the kA3DGraphicsShow flag, which controls entity visibility. Unlike other behaviors, the value is ignored if a kA3DGraphicsSonHeritShow or kA3DGraphicsFatherHeritShow flag is set. Therefore, an invisible entity must have its graphics data set up like this:

A3DGraphicsData sGraphicData;
A3D_INITIALIZE_DATA(A3DGraphicsData, sGraphicData);
sGraphicData.m_usBehaviour &= ~kA3DGraphicsShow;