Introduction to Element Descriptors

An element descriptor is a multiple linked list of elements that an application can easily traverse. All memory associated to the element descriptor is allocated by MicroStation.

Element descriptors are an in memory representation of elements in the design file; they do not reside in the design file. When a complex element (for example, a cell or text node) is read into an element descriptor, the element descriptor read function sets up all of the nesting for that complex element.

MicroStation updates the header information in complex elements when the elements in the element descriptor are written back to disk. This removes the responsibility of setting words to follow (WTF), maintaining elementSize, etc., from your application.

Element descriptors can represent cells and shared cells, complex chains and shapes, or a group of elements such as the selection set or fence contents.

Element descriptor header information includes:

struct msElementDescr // defined in mselems.h
{
struct
{
struct MSElementDescr *next; // ptr to first entry in list
struct MSElementDescr *previous; // ptr to last entry in list
struct MSElementDescr *myHeader; // ptr to my hdr
struct MSElementDescr *firstElem; // ptr to first elem if header
DgnModelRefP *dgnModelRef; // valid only if from cache
ElementRef *elementRef; // valid only if from cache
Int32 isHeader; // is this a complex header
Int32 isValid; // INTERNAL USE ONLY
Int32 userData1; // available for user
Int32 userData2; // available for user
} h;
MSElement el; // elem data
};

Sample element descriptors

MDL_Programmer's_Guide-09-2-1.jpg

This is an in-memory representation of a cell with three primitive elements. myHeader points back to the cell header from each component element.

MDL_Programmer's_Guide-09-2-2.jpg

This is an in-memory representation of a cell with two primitive elements and on nested cell.

MDL_Programmer's_Guide-09-2-3.jpg

This is an in-memory representation of a selection set.

Recursive programming

A recursive function is a function that calls itself. Element descriptors, because of their multiple links, lend themselves quite well to recursive programming.

Recursive programming and element descriptors are perfectly suited for nested complex elements because at each level of nesting the application simply calls the recursive function to do any processing.

Recursive programs can be difficult to debug because it is often difficult to determine how deeply nested the program is at any given time.

Stack usage must be carefully monitored when recursively processing element descriptors. Each invocation of the recursive function uses stack space for all of its automatic variables.

This is an example of a recursive function that modifies an element descriptor:

Private void modElementDescriptor
(
MSElementDescr *elmdP
)
{
do
{
// if this is a header element, call with first child element
if (elmdP->h.isHeader)
modElementDescriptor(elmdP->h.firstElem);
else
changeElement(elmdP->el);
}while (elmdP->h.next != NULL);
}

Functions that use element descriptors

Functions that use element descriptors include all mdlElmdscr_..., mdlModify_..., mdlCell_..., mdlSharedCell_..., mdlBspline_... and mdlDynamic_setElmDescr, with more to come.

Element descriptor validation

Element descriptors validate the data in complex headers, including range, class and level bit map, words in description, number of elements, number of poles and maximum length of a text element in a text node.

Validation is automatic when an element descriptor is added to the design file.

To force an element descriptor to be validated, set elmdP->isValid to FALSE.

We never set elmdP->isValid to TRUE. An application can check if the flag is TRUE, but should never set it to TRUE. 

Cautions about memory use and element descriptor size

Element descriptors can use a lot of memory. Although MicroStation allocates the memory for an element descriptor, an application must tell MicroStation to free the memory allocated to an element descriptor when the application is finished with it. For debugging, periodically use the command SHOW HEAP ELMD to determine if all memory allocated to element descriptors has been freed.

Do not copy to/from element descriptors using sizeof(MSElement). The el portion of the element descriptor is dynamically allocated to only hold the size of the actual element. To get the size of the el portion of the element descriptor, call mdlElement_size.


Copyright © 2017 Bentley Systems, Incorporated. All rights reserved.