Markup and Views

In HOOPS Exchange, markup refers to PMI and all the supporting infrastructure related to displaying it with the model. HOOPS Exchange groups this data into the markup module. Most markup is represented as tessellation, although certain instances can be represented as either tessellation or semantic data.


Despite being an important part of the PRC standard, markup is not represented by an entity type. Instead, one of three annotation entities are used. Annotation entities are represented by A3DMkpAnnotationEntity structures, and the structure can be one of three types:

  • Annotation item encapsulates a single markup object. The type is kA3DTypeMkpAnnotationItem.

  • Annotation set is a group of annotation entities. The type is kA3DTypeMkpAnnotationSet.

  • Annotation reference is a reference to another annotation. The type is kA3DTypeMkpAnnotationReference.

Annotation entities may be present on product occurrences or part definitions.

Parsing Annotation Entities

The A3DMkpAnnotationItemData structure references an A3DMkpMarkup. This markup contains tessellation, leaders, and linked item information that is available by using the function A3DMkpMarkupGet. In addition, this markup can also contain definition data (type information) and specific data (type, leader, linked items, etc.). This data is stored in a common structure, A3DMarkupDefinitionData, and in a specific structure corresponding to the type returned by the function A3DEntityGetType. For the structures corresponding to markup with a definition, only access functions are defined. In other words, it’s only possible to create a A3DMkpMarkup object and access the data.

Parsing Tessellation of Markup

Not all files contain semantic PMI, but PMI in tessellated form is always available, so you are guaranteed to at least get a A3DMkpMarkup structure.

This is an example of getting the PMI tessellation:

A3DMkpMarkupData markupNodeData;
A3D_INITIALIZE_DATA(A3DMkpMarkupData, markupNodeData);
A3DMkpMarkupGet(markupNode, &markupNodeData);

// since tessellation is always available, you can get it from the markupNodeData
A3DTessMarkupData tessMarkupData;
A3D_INITIALIZE_DATA(A3DTessMarkupData, tessMarkupData);
A3DTessMarkupGet(markupNodeData.m_pTessellation, &tessMarkupData);

Parsing Markup Types

Different types of markup are possible, such as dimensions, GDT, datum, or text. All markup will have different information depending on its type, and each type must be parsed accordingly. Get the type of the markup, and then get the corresponding information (if the markup is a dimension, use A3DMarkupDimensionGet to retrieve the information about the dimension):

A3DStatus iRet = A3DEntityGetType(pMarkup, &eType);

iRet = A3DMarkupDefinitionGet((A3DMarkupDefinition*)pMarkup, &sMarkupData);
if(iRet != A3D_SUCCESS)
        A3DMarkupDefinitionGet(NULL, &sMarkupData);
        return A3D_ERROR;

if(eType == kA3DTypeMarkupText)
        iRet = A3DMarkupTextGet(pMarkup, &sMarkupData);
else if(eType == kA3DTypeMarkupRichText)
        iRet = A3DMarkupRichTextGet(pMarkup, &sMarkupData);
else if(eType == kA3DTypeMarkupDatum)
        iRet = A3DMarkupDatumGet(pMarkup, &sMarkupData);
else if(eType == kA3DTypeMarkupGDT)
        iRet = A3DMarkupGDTGet(pMarkup, &sMarkupData);
else if(eType == kA3DTypeMarkupDimension)
        iRet = A3DMarkupDimensionGet(pMarkup, &sMarkupData);
        return A3D_NOT_IMPLEMENTED;

Semantic PMI

If the markup is a GDT and has been created in a semantic way in the native CAD software, you can retrieve the semantic information for the Feature Control Frame, using the function A3DMDSemanticFeatureControlFrameGet. If there is no semantic information associated to the GDT, you can still retrieve non-semantic information as text (in A3DMDFCFDraftingRowData) using the function A3DMDFeatureControlFrameGet. Note that A3DMarkupDimension represents semantic markup.

Parsing Leader Lines

If the markup has leader lines, you can retrieve the tessellation of the leaders and, in some cases, linked items associated with the leaders. Parse it just like you would parse linked items (see below: Linked items associated with markup) or tessellation (see Parsing tessellation of markup).

Linked Items Associated With Markup

A linked item is a reference from a markup to an entity. It is stored in an annotation, markup, or view structure. When a markup contains a link, the link is directed from the annotation entity to a PRC entity. Linked items can represent a link to any type of entity: a solid, a topological entity, a construction entity,a coordinate system, tessellation, or even another markup.

Each linked item represents a single link. A markup owns as many linked items as the number of entities it references. For instance, if you have a dimension line that indicates the distance between two planes, the dimension is a markup object. It will have two A3DMiscMarkupLinkedItem references, and each reference will define a link to a single plane. See scheme below:


Within the linked item object, the member A3DMiscMarkupLinkedItemData.m_pReference must be filled with a reference to the object. A3DMiscMarkupLinkedItemData is inherited from A3DMiscEntityReferenceData, so A3DMiscMarkupLinkedItemData.m_pReference is equivalent to A3DMiscEntityReferenceData.m_pEntity. A3DMiscEntityReferenceData is an object containing certain information(e.g., A3DMiscEntityReferenceData.m_pCoordinateSystem) and a reference (A3DMiscEntityReferenceData.m_pEntity).

A3DMiscMarkupLinkedItemData.m_pReference can be a pointer to a Representation Item, a Product Occurrence or a reference to an A3DMiscReferenceOnTessData or A3DMiscReferenceOnTopologyData object.

An example of how to parse linked items can be found in the PRC2XML sample. In the file PRC2XMLMarkup.cpp, see the traverseLinkedItem function. In this example, pMkpLinkedItem is cast as a A3DMiscEntityReference:

traverseEntityReference((A3DMiscEntityReference*)pMkpLinkedItem, mkplinkeditem);

Linked Items and Assembly

To help the linked item retrieve the correct entity to reference, the field A3DMiscMarkupLinkedItemData.m_pTargetProductOccurrence must be filled with the product occurrence containing the reference. In case the reference is a part, the Target PO is the one that is holding the part. If the reference is a subassembly (a sub PO contained in a top-level PO), then the target PO must be the upper level of this subassembly.

  • Linked Item 1.1 references the Part or a subcomponent of the PO A.a.

  • m_pReference is a miscellaneous reference to Part or sub-PO, and m_targetPO is a pointer to PO A.a.

  • Linked Item 1.2 references the component PO A.a.

  • m_pReference is a miscellaneous reference to the PO A.a, and m_targetPO is a pointer to PO A.

A3DMiscMarkupLinkedItemData.m_pTargetProductOccurrence can be left null if the markup is located at the same level in the assembly tree as the reference – i.e., if the markup is held by the same product occurrence as the reference. HOOPS Exchange will automatically search the entity referenced in the Part, prototype, or sub POs of the PO that owns the markups.

  • Linked Item A.1.1 references Part A. Part A and Markup A.1 are contained in the same Product Occurrence A, so the m_targetPO can be null.

  • Linked Item 1.1 references Product Occurrence A. PO A and Markup 1 are held together on the same level by the root Product Occurrence, so m_targetPO can be null.

A linked item is used to symbolize a link in a very generic manner. But it is designed to adapt to the constraints of assembly trees. Hence it will not be possible to link to a reference to a A3D_PRODUCT_FLAG_CONTAINER “product occurrence container” located at an equal or higher level in the assembly tree. This is inconsistent and a bad design because it doesn’t correspond to the way CAD files are created.

  • Linked Item B.1.1 is inconsistent because it references the assembly file itself, located at a higher level in the assembly tree.

  • Linked Item B.1.2 is inconsistent because it references another sub-component of the root assembly. In a CAD file this would be like a part file referencing another part file directly without knowing its place in the assembly file.

Getting Markup Tolerances

A Markup Tolerance can be one of two types:

  • A3DMDToleranceSizeData

  • A3DMDFeatureControlFrameData

A3DMDToleranceSizeData is a concatenation on a line of dimensions for defining an element. For example, for a hole we can have an A3DMDToleranceSizeValueData for the depth and a A3DMDToleranceSizeValueData for the diameter. A3DMDToleranceSizeValueData contains a dimension value and EA3DMDDimensionType “an enumerator” specifying type of dimension. And information like the symbol before the value. An instance of A3DMDToleranceSizeValueData can be filled in using A3DMDToleranceSizeValueGet().

These tolerance can be read from the A3DMarkupGDTData.m_ppsMarkupTolerances array.

Show and Delete Behaviors

In A3DMiscMarkupLinkedItemData, note the boolean fields such as A3DMiscMarkupLinkedItemData.m_bMarkupDeleteControl and A3DMiscMarkupLinkedItemData.m_bLeaderShowControl, which enable you to control what happens when a referenced entity is deleted, hidden, or shown.

For example, if the A3DMiscMarkupLinkedItemData.m_bMarkupDeleteControl flag is enabled, then the markup will be deleted when the entity is deleted. Similarly, if the A3DMiscMarkupLinkedItemData.m_bLeaderShowControl is enabled, then the markup is shown when the associated entity is shown.

Parsing Views

PMI items are often organized under PMI views. A PMI view includes a camera and defines a particular model state - often including visibility for particular parts, certain PMI items, highlighted parts, or even parts arranged in an exploded view. These elements are all managed by linked items.

The purpose of a PMI view is to arrange the model to convey a certain idea. The HOOPS Exchange type for a PMI view is A3DMkpViewData. This object can be part of a product occurrence or a part definition.

Parsing Annotations

Inside the view, A3DMkpViewData.m_ppAnnotations allows you to select which annotations to display when the view is selected. This member can only be filled with annotations defined in the same Product Occurrence as the View.

To select PMI located in child nodes of the Product Occurrence containing the View, use a linked item.

Parsing the Display Scene Parameters

In the structure A3DGraphSceneDisplayParametersData, you will find information about the graph scene. Here is a code snippet to retrieve graph scene data:

A3DMkpViewData sData;

A3DGraphSceneDisplayParameters * pGraphSceneParam = sData.m_pSceneDisplayParameters

A3DGraphSceneDisplayParametersData sData;
A3D_INITIALIZE_DATA(A3DGraphSceneDisplayParametersData, sData);

A3DInt32 iRet = A3DGraphSceneDisplayParametersGet(pGraphSceneParam, &sData);

Camera, Lights, Styles

With the A3DGraphCameraData, you will be able to retrieve information about the position of your camera in the view. The graph scene parameters also contain information about style, background color, etc.

Cutting Planes

In the A3DGraphSceneDisplayParametersData, you can find the information related to the clipping planes in the field m_ppClippingPlanes. Here is a code snippet for retrieving the cutting planes of a view:

A3DGraphSceneDisplayParametersData sData;
A3D_INITIALIZE_DATA(A3DGraphSceneDisplayParametersData, sData);

A3DInt32 iRet = A3DGraphSceneDisplayParametersGet(pGraphSceneParam, &sData);
for (int ui=0; ui < sData.m_uiPlaneSize; ui++)

Parsing Linked Items Associated to the View

As previously mentioned, linked items define the view as a particular model state - visibility of particular parts, display of certain PMI items, highlighted parts, or parts arranged in an exploded view.

Visibility of Items and PMI Using Linked Items

For files in an assembly context, it is possible to change the visibility of parts or markups in a view using linked items.

To do this A3DMkpViewData has a linked item array and an annotation array.

To change the visibility of an entity within a particular view, the view must contain a linked item to the desired entity with a new A3DRootBaseWithGraphicsData attached to the linked item: A3DRootBaseWithGraphicsSet(pLinkedItem, sGraphicsData); By default, every markup in the scene will be hidden once a view is selected. To select which annotations will remain visible, populate the member A3DMkpViewData.m_ppAnnotations with pointers to the appropriate annotations.

Position of Items and PMI Using Linked Items

Using a linked item, it’s also possible to control the position of an item in a view.

To do this, define a new coordinate system to alter the position of the item. Fill the A3DMiscEntityReferenceData with the new coordinate and the entity you want to reference. And set the linked item entity reference in A3DMiscMarkupLinkedItemData.m_pReference.

Don’t forget to specify the product occurrence to which the item belongs (or set to NULL if the item is at the same level).

Exploded View Sample

Here we are creating an exploded view in which one of the model’s two Product Occurrences will be “exploded”:

// creating the linked item
A3DMiscMarkupLinkedItem* pMarkupLinkedItem = NULL;
A3DMiscMarkupLinkedItemData sLinkedItemData;
A3D_INITIALIZE_DATA(A3DMiscMarkupLinkedItemData, sLinkedItemData);

// setting the target ProductOccurrence to NULL if the reference is at the same level as the PO,
//    or to the level above if the PO tree has several levels
sLinkedItemData.m_pTargetProductOccurrence = NULL;
// setting a non-null reference to create the LI
sLinkedItemData.m_pReference = sData.m_ppPOccurrences[0];

CHECK_RET(A3DMiscMarkupLinkedItemCreate(&sLinkedItemData, &pMarkupLinkedItem));

// creating the entity reference containing the new coordinate system
A3DMiscEntityReferenceData sEntityReferenceData;
A3D_INITIALIZE_DATA(A3DMiscEntityReferenceData, sEntityReferenceData);

// applying the new coordinate system on the first ProductOccurrence
sEntityReferenceData.m_pEntity = sData.m_ppPOccurrences[0];
sEntityReferenceData.m_pCoordinateSystem = psRiCoordinateSystem;

// setting the linked item with the new entity reference
CHECK_RET(A3DMiscEntityReferenceSet(pMarkupLinkedItem, &sEntityReferenceData));

// adding the linked item to the view and creating of the view
mkpViewData.m_uiLinkedItemsSize = 1;
mkpViewData.m_ppLinkedItems = (A3DMiscMarkupLinkedItem**)
        malloc(size_t(mkpViewData.m_uiLinkedItemsSize) * sizeof(A3DMiscMarkupLinkedItem*));
mkpViewData.m_ppLinkedItems[0] = pMarkupLinkedItem;

To summarize, when determining how a view should be arranged, you must consider three things:

  • the markup associated with the view

  • the linked items associated with the view (some markup not associated to the view will have its visibility changed in this view)

Not all CAD model files have markup, linked items, or filters in their views. Some file formats do not support these entities, so your application must decide how to handle each situation based on the type of file you are parsing.

Parsing Filters

A filter (A3DAsmLayerFilterItemData) can be associated with a view. One or more layer indexes will be associated to this filter. The filter contains a flag that defines whether the layers are inclusive or exclusive:

  • If inclusive (A3DAsmLayerFilterItemData::m_bIsInclusive = A3D_TRUE), all the items are unfiltered, except the ones associated to the layer

  • If exclusive (A3DAsmLayerFilterItemData::m_bIsInclusive = A3D_FALSE), all the items are filtered except the ones associated to the layer

Each object is associated to a layer in the GraphicsData. In the view, we retrieve the layer indices and determine if they are inclusive or exclusive. All the objects associated to these layer indices will be filtered (if the layer is inclusive) or unfiltered (and all the objects not associated to the view will be filtered) if the layer is exclusive.

Note that filters are not found in all CAD files, and some file formats don’t support them at all.