######################
Traverse CAD Structure
######################

This tutorial guides you through the basics of creating a console application with HOOPS Exchange.
By the end of this tutorial, you will have a solid understanding of the technology, allowing you to seamlessly integrate HOOPS Exchange into your own applications.

The completed project will load a specified input file and print the assembly structure to standard output.

.. sidebar:: Table of Contents

   .. contents:: :depth: 3

   |

.. _Prerequisites:

Prerequisites
=============

Before you begin, ensure that your environment is correctly configured, please refer to the :doc:`Environment Setup Guide </tutorials/cs/environment-setup>` for detailed instructions.

1. Locate and open the :ref:`sample_print_assy_struct` sample code, available in the C# samples solution.

   The input model filename is provided as a program agrument. Replace the input model with ``samples\data\catiaV5\CV5_Micro_engine\_micro engine.CATProduct``

2. Build the project and run the generated application.
   
.. admonition:: Tip

    Redirect the output of the console to a text file using this command: ``./PrintAssemblyStructure > /Users/temp/output.txt``


Tree structure of a CAD file
============================

Designing a CAD assembly consists of creating detailed 3D models of each individual part using CAD software, precisely defining dimensions, shapes, features, and more. 
Once the individual components are modeled, they are imported into an assembly workspace. In this workspace, they are positioned and connected accurately using constraints and mates. 
Individual components can be instantiated and used multiple times.

The CAD file embeds the 3D models and their data, as well as the **Model Tree**, which contains the structure of the assembly file. 
The Model Tree, referred to as ``A3DTree``, is composed of sub-assemblies and sub-parts, called ``A3DTreeNode``. 
In this tutorial, we will learn how to traverse and parse this model tree to retrieve information stored at each node of the assembly.


Load, traverse, and get node info
=================================

The *PrintAssemblyStructure* sample comes with the code to import a CAD model and traverse its structure. It recursively visits the child nodes by going deeper into the model tree. This is done by acquiring the model's root node, printing its name, then getting references to its child nodes.

The sample is divided into two parts:

1. Load a CAD file and traverse its model file structure.
2. Print information of an entity within the structure.

The first part - loading a CAD file - is covered in the previous tutorial. The tutorial on this page focuses on the latter section, where we traverse the tree structure of a model file to retrieve the entity's type and name using a traversal function.


.. _print_assembly_traverse:

Get node name
~~~~~~~~~~~~~

HOOPS Exchange organizes CAD file structure as a tree hierarchy. Since complex models can have very deep hierarchies, it follows that the simplest way to navigate through a CAD file is using recursion. We will demostrate this by printing the name of the root node. From there, we loop through the list of child nodes and call ``RecursivelyPrintName`` on each of them. The output will show each node's depth and relationship to other nodes in the hierarchy. 

The code below shows the implementation. The parameter ``po`` is the product occurrence - the instance of whatever node is currently being visited. If there is a part associated with the product occurrence, its name and type are printed, otherwise, the child nodes are visited.

.. code:: cs

    static void RecursivelyPrintName(IntPtr po, int indent)
    {
        Write(GetNameAndType(po), indent);
        indent++;
        using var d = new A3DAsmProductOccurrenceWrapper(po);
        foreach (var childPo in d.m_ppPOccurrences)
        {
            RecursivelyPrintName(childPo, indent);
        }
        var part = GetPartDefinition(po);
        if (part != IntPtr.Zero)
        {
            Write(GetNameAndType(part), indent + 1);
        }
    }

The ``indent`` parameter is only used to keep in memory the current level of tree traversal. It will be used to provide the indentation while displaying each node name.

The following function writes the name of each entity as it is being traversed:

.. code:: cs

    static string GetNameAndType(IntPtr entity)
    {
        using var rootBase = new A3DRootBaseWrapper(entity);
        var type = A3DEEntityType.kA3DTypeUnknown;
        API.A3DEntityGetType(entity, ref type);
        return rootBase.m_pcName + " [" + type.ToString() + "]";
    }

It is here where you could also do any other node processing necessary during the traversal, such as inspecting or modifying data.

Run the application with its arguments as described in the :ref:`Prerequisites` section of this tutorial.
The standard output should display something similar to the following:

.. code:: text

   Name: Product1; Type: kA3DTypeAsmProductOccurrence
     Name: HOUSING(HOUSING.1); Type: kA3DTypeAsmProductOccurrence
       Name: MechanicalTool.1; Type: kA3DTypeRiBrepModel
       Name: Open_body.1; Type: kA3DTypeRiSet
     Name: CYLINDER LINER(CYLINDER LINER.1); Type: kA3DTypeAsmProductOccurrence
       Name: MechanicalTool.1; Type: kA3DTypeRiSet
         Name: MechanicalTool.1; Type: kA3DTypeRiBrepModel
     Name: HOUSING TOP(HOUSING TOP.1); Type: kA3DTypeAsmProductOccurrence
       Name: MechanicalTool.1; Type: kA3DTypeRiSet
         Name: MechanicalTool.1; Type: kA3DTypeRiBrepModel
     Name: MOBILE PART(MOBILE PART.1); Type: kA3DTypeAsmProductOccurrence
       Name: PUSH ROD(PUSH ROD.1); Type: kA3DTypeAsmProductOccurrence
         Name: MechanicalTool.1; Type: kA3DTypeRiSet
           Name: MechanicalTool.1; Type: kA3DTypeRiBrepModel
   ...

The output gives you the structure of the assembly file, name, and entity type for each node of the assembly traversed by the function.

