# Tree Traversal API

The underlying structure of HOOPS Exchange model files, namely the PRC, can be rather complex for most use cases. Most of the time, a thorough knowledge of each entity type is needed to efficiently navigate through a model file.

To facilitate their traversal, the API provides a set of abstraction functions that allow you to manipulate the model file like a simple tree-like structure.

## Terminology

An A3DTree is a hierarchical arrangement of A3DTreeNode entities. The topmost A3DTreeNode is called the root and serves as the starting point for the tree. Each node can have child nodes, and all non-root nodes have a single parent.

## Getting The Tree Entity

The entire A3DAsmModelFile entity is abstracted into a tree-like structure by using `A3DTreeCompute()`. This function returns an A3DTree entity:

    A3DTree* tree = 0;
    A3DTreeCompute(model_file, &tree, 0);

    // "tree" can be used

Once you’re done using the tree structure, release the underlying memory by calling the function again, setting the model file to 0:

    A3DTreeCompute(0, &tree, 0);

In between those calls, query the tree nodes starting from the root node, which you can get using `A3DTreeGetRootNode()`:

    A3DTreeNode* root_node = 0;
    A3DTreeGetRootNode(tree, &root_node);

Node memory is held in the A3DTree entity. Once the latter is released using `A3DTreeCompute()`, all associated nodes are dropped.

## Navigating the Tree

To traverse the PRC tree, navigate top to bottom by iteratively calling `A3DTreeNodeGetChildren()`. The function returns an array whose memory needs to be released once done.

    A3DUns32 n_child_nodes    = 0;
    A3DTreeNode** child_nodes = 0;

    A3DTreeNodeGetChildren(tree, node, &n_child_nodes, &child_nodes);

    for (A3DUns32 n = 0 ; n < n_child_nodes ; ++n) {
        A3DNode* child_node = child_nodes[n];
        // ...
    }

    // Release array memory
    A3DTreeNodeGetChildren(0, 0, &n_child_nodes, &child_nodes);

Tree Traversal Example

The following recursive function provides a depth-first traversal of an entire tree:

    void traverse_tree(A3DTree* const tree, A3DTreeNode* const node)
    {
       printf("Entering node %x\n", node);

       A3DUns32 n_child_nodes    = 0;
       A3DTreeNode** child_nodes = 0;

       A3DTreeNodeGetChildren(tree, node, &n_child_nodes, &child_nodes);

       for (A3DUns32 n = 0 ; n < n_child_nodes ; ++n) {
           traverse_tree(tree, child_nodes[n]);
       }

       A3DTreeNodeGetChildren(0, 0, &n_child_nodes, &child_nodes);

       printf("Leaving node %x\n", node);
    }

The function can be first called from a root A3DTreeNode:

    A3DTreeNode* root_node = 0;
    A3DTreeGetRootNode(tree, &root_node);

    traverse_tree(tree, root_node);

It is also possible to retrieve the parent of an A3DTreeNode:

    A3DTreeNode* parent_node = 0;
    A3DTreeNodeGetParent(tree, node, &parent_node);

## Retrieving a Node’s Entity and Attributes

At any moment, retrieve the underlying entity of a tree node using `A3DTreeNodeGetEntity()`.

    A3DEntity entity = 0;
    A3DTreeNodeGetEntity(node, &entity);

### Name

A common operation for entities is to get their name. The tree traversal API provides a shortcut function that allows you to query it directly from an A3DTreeNode:

    A3DUTF8Char* name = 0;
    if (A3D_SUCCESS == A3DTreeNodeGetName(node, &name) && name) {
        printf("Node: '%s'\n", name);
    }

    // Release memory
    A3DTreeNodeGetName(0, &name);

### Transformation

Query the underlying A3DMiscTransformation entity of an A3DTreeNode with `A3DTreeNodeGetTransformation()`:

    A3DMiscTransformation* transform = 0;
    A3DTreeNodeGetTransformation(node, &transform);

The function computes the transform of the node relative to its parent node. To retrieve the global (or net) transform, use `A3DTreeNodeGetNetTransformation()` instead.

### Visibility and Style

To get the effective visibility of an A3DTreeNode, use `A3DTreeNodeGetNetVisibility()`:

    A3DBool visible = A3D_FALSE;
    A3DTreeNodeGetNetVisibility(node, &visible);

    if (visible == A3D_TRUE) {
        printf("Entity is visible.\n");
    } else {
        printf("Entity is not visible.\n");
    }

Conversely, the net style of the node is retrieved using `A3DTreeNodeGetNetStyle()`. The function directly returns an `A3DGraphStyleData` structure.

## Getting Node Underlying Geometry

When the underlying entity of a node contains geometrical data, it is possible to compute a resulting mesh into an `A3DMeshData` structure:

    A3DMeshData mesh_data = A3D_MAKE_DATA(A3DMeshData);
    A3DTreeNodeGetGeometry(tree, node, A3D_TRUE, &mesh_data, 0);

The function is the equivalent of `A3DRiComputeMesh()` (see Getting Tessellation using A3DMeshData), except that it applies to an `A3DTreeNode` instead of an `A3DRiRepresentationItem` entity.

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your multilingual generative AI assistant for documentation. Ask me anything about HOOPS Exchange in your own language, or choose a sample question below to start a conversation:

What is HOOPS Exchange?
What are the latest release notes for HOOPS Exchange?
How do I start evaluating HOOPS Exchange?
How do I write my first sample application?
How can I get assistance?

HOOPSY may store conversations according to OpenAI's policy. Responses may not always be accurate.

HOOPSY is thinking...