Logo

Getting Started

  • Technical Overview
  • Evaluating HOOPS Exchange
  • File Formats
  • Supported Platforms

Tutorials

  • 1. Set Up Your Environment
  • 2. File-to-File Translation
  • 3. Print Structure
  • 4. Write a CAD Viewer

Programming Guide

  • Fundamentals
    • Initializing HOOPS Exchange
  • Basic Operations
    • Simple Load and Export
    • PRC
    • Building PRC
    • Using Progress Functions
  • Entities
  • Geometry
    • Reading Model Geometry
    • Reading Tessellation
    • Getting B-Rep Data
    • Tessellation Example
    • Approximating Curves and Surfaces as Analytics
    • Converting B-Rep to NURBS
  • Entity Attributes and Metadata
    • Colors and Materials
    • Managing Attribute Inheritance
    • Transformations
    • Getting the Bounding Box
    • Generic Attributes
    • A Complete Example
    • Unit Attributes
  • Markup and Views
  • Advanced Functions
  • HOOPS Exchange for Parasolid Developers
    • HOOPS Exchange for Parasolid Developers
    • HOOPS Exchange for Parasolid Developers: Getting Started
  • Feature Trees
  • Publications
  • BIM
  • Distributing Your Application
  • Tree Traversal API

API References

  • HOOPS Exchange API Primer
    • API Conventions
    • Working with C#
  • Exchange Modules
    • Bit Field for Behavior on Graphics
    • Display Style
    • Bit field flag Defining how Linked files are managed, for Revit files.
    • Graphics
    • Textures
    • Fundamental Type Definitions
    • Base Module
    • Load & Export Module
    • Tools Module
    • Entity Access and Creation
  • All C Structures
  • All C Functions
  • All Files
    • A3DCommonReadWrite.h
    • A3DSDK.h
    • A3DSDKAdvancedTools.h
    • A3DSDKBase.h
    • A3DSDKBim.h
    • A3DSDKConstraint.h
    • A3DSDKConstraintEnums.h
    • A3DSDKDraw.h
    • A3DSDKDrawing.h
    • A3DSDKEnums.h
    • A3DSDKErrorCodes.h
    • A3DSDKFeature.h
    • A3DSDKFeatureEnums.h
    • A3DSDKFeatureHoleEnums.h
    • A3DSDKFeaturePatternEnums.h
    • A3DSDKFeatureThreadEnums.h
    • A3DSDKGeometry.h
    • A3DSDKGeometryCrv.h
    • A3DSDKGeometrySrf.h
    • A3DSDKGlobalData.h
    • A3DSDKGraphics.h
    • A3DSDKInitializeFunctions.h
    • A3DSDKLicense.h
    • A3DSDKMarkup.h
    • A3DSDKMarkupDefinition.h
    • A3DSDKMarkupDimension.h
    • A3DSDKMarkupLeaderDefinition.h
    • A3DSDKMarkupSymbol.h
    • A3DSDKMarkupText.h
    • A3DSDKMarkupTolerance.h
    • A3DSDKMarkupWelding.h
    • A3DSDKMath.h
    • A3DSDKMisc.h
    • A3DSDKPublication.h
    • A3DSDKReadWrite.h
    • A3DSDKRepItems.h
    • A3DSDKRootEntities.h
    • A3DSDKSemanticMarkupCreation.h
    • A3DSDKStructure.h
    • A3DSDKTessellation.h
    • A3DSDKTexture.h
    • A3DSDKTools.h
    • A3DSDKTopology.h
    • A3DSDKTypes.h

Additional Resources

  • Release Notes
    • Fixed Bugs List
    • HOOPS Exchange 2024
    • HOOPS Exchange 2023 SP2 U2
    • HOOPS Exchange 2023 SP2 U1
    • HOOPS Exchange 2023 SP2
    • HOOPS Exchange 2023 SP1 U1
    • HOOPS Exchange 2023 SP1
    • HOOPS Exchange 2023 U1
    • HOOPS Exchange 2023
    • HOOPS Exchange 2022 SP2 U2
    • HOOPS Exchange 2022 SP2 U1
    • HOOPS Exchange 2022 SP2
    • HOOPS Exchange 2022 SP1 U1
    • HOOPS Exchange 2022 SP1
    • HOOPS Exchange 2022 U2
    • HOOPS Exchange 2022 U1
    • HOOPS Exchange 2022
    • HOOPS Exchange 2021 SP2 U2
    • HOOPS Exchange 2021 SP2 U1
    • HOOPS Exchange 2021 SP2
    • HOOPS Exchange 2021 SP1 U1
    • HOOPS Exchange 2021 SP1
    • HOOPS Exchange 2021 U2
    • HOOPS Exchange 2021 U1
    • HOOPS Exchange 2021
    • HOOPS Exchange 2020 SP2 U2
    • HOOPS Exchange 2020 SP2 U1
    • HOOPS Exchange 2020 SP2
    • HOOPS Exchange 2020 SP1 U1
    • HOOPS Exchange 2020 SP1
    • HOOPS Exchange 2020 U1
    • HOOPS Exchange 2020
    • HOOPS Exchange 2019 SP2 U2
    • HOOPS Exchange 2019 SP2 U1
    • HOOPS Exchange 2019 SP2
    • HOOPS Exchange 2019 SP1 U1
    • HOOPS Exchange 2019 SP1
    • HOOPS Exchange 2019 U1
    • HOOPS Exchange 2019
    • HOOPS Exchange 2018 SP2 U2
    • HOOPS Exchange 2018 SP2 U1
    • HOOPS Exchange 2018 SP2
    • HOOPS Exchange 2018 SP1 U1
    • HOOPS Exchange 2018 SP1
    • HOOPS Exchange 2018 U2
    • HOOPS Exchange 2018 U1
    • HOOPS Exchange 2018
    • HOOPS Exchange 2017 SP2 U2
    • HOOPS Exchange 2017 SP2 U1
    • HOOPS Exchange 2017 SP2
    • HOOPS Exchange 2017 SP1 U2
    • HOOPS Exchange 2017 SP1 U1
    • HOOPS Exchange 2017 SP1
    • HOOPS Exchange 2017 U2
    • HOOPS Exchange 2017 U1
    • HOOPS Exchange 2017
    • HOOPS Exchange 2016 SP2 U2
    • HOOPS Exchange 2016 SP2
    • HOOPS Exchange 2016 SP1 U3
    • HOOPS Exchange 2016 SP1 U2
    • HOOPS Exchange 2016 SP1
    • HOOPS Exchange 2016
    • HOOPS Exchange 2015 SP1
    • HOOPS Exchange 2015 U1
    • HOOPS Exchange 2015
    • HOOPS Exchange - v7.2
    • HOOPS Exchange - v7.1
    • HOOPS Exchange - v7.0
    • HOOPS Exchange - v6.10
    • HOOPS Exchange - v6.00
    • HOOPS Exchange - v5.30
    • HOOPS Exchange - v5.20
    • HOOPS Exchange - v5.10
    • HOOPS Exchange - v5.0
  • Public Roadmap
  • Acknowledgments
  • Knowledge Base
  • Support
  • Community Forum
  • Sample Code
  • Downloads
  • Archives
HOOPS Exchange
  • 3. Print Structure
Previous Next

3. Print 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 stdout.

Prerequisites

For Microsoft Visual Studio Developers

This version of the tutorial uses CMake to cover most cases. Soon, we will be providing you with a turn-key Visual Studio solution in the repositoryBefore you begin, ensure that your environment is correctly configured.

Refer to the Environment Setup Guide for detailed instructions.

To start development, make sure you have the following:

  1. CMake: If not installed, download and install it from here.

    ../_images/tuto_viewer_cmake.png
  2. Source Code: Access the complete source code for this project on GitHub. Download and unzip it to your preferred location.

    Once you have CMake and the source code:

    • Run CMake.

    • Set the source directory to the path of the extracted folder.

    • Specify the binary directory path for project file generation.

    • Click the Generate button.

    Your project is now configured and ready for compilation and execution.

After successfully building and compiling the project, run the generated application. The standard output should display something similar to the following:

Product1
  HOUSING(HOUSING.1)
    MechanicalTool.1
  CYLINDER LINER(CYLINDER LINER.1)
    MechanicalTool.1
  HOUSING TOP(HOUSING TOP.1)
    MechanicalTool.1
  MOBILE PART(MOBILE PART.1)
    PUSH ROD(PUSH ROD.1)
      MechanicalTool.1
    BEARING PR DW(BEARING PR DW.1)
      MechanicalTool.1
    BEARING PR UP(BEARING PR UP.1)
      MechanicalTool.1
    AXE(AXE.1)
      MechanicalTool.1
    PISTON(PISTON.1)
...

The sample is divided into two parts:

  • Loading the CAD file into a tree structure

  • Traversing the model file while printing the name of each entity

As the main point of this tutorial, we will start with the latter. Then we will load a model file and connect to our traversal function.

Traversing the Model File

The simplest way to navigate through our model file is to use the traversal API that abstracts away the complexity of a model file by using standard tree-structure terminology.

The entire traversal is done in a recursive function that is first called on the root node of our model tree:

void traverse_tree(A3DTree* const hnd_tree, A3DTreeNode* const hnd_node, size_t depth) {

   // Display node's name...

   // Recursively call traverse_tree on child nodes...

}

The depth parameter is only used to provide the indentation while displaying each node name.

Display Nodes’ Name

To get the name of a node, use A3DTreeNodeGetName(). The function fills in a C-string that needs to be freed when the data isn’t used any longer:

The code for displaying the name looks like this:

std::cout << std::string(2 * depth, ' '); // Print indent

A3DUTF8Char* node_name = 0;
if (A3DTreeNodeGetName(hnd_node, &node_name) == A3D_SUCCESS && node_name != 0) {
    std::cout << node_name << std::endl;
    A3DTreeNodeGetName(0, &node_name);
}

Recursively Visit Child Nodes

Going deeper into the model tree is done by calling A3DTreeNodeGetChildren(). This function gets the child nodes of the currently visited one.

For there, we loop through the list of child nodes and call traverse_tree on each of them:

// Recursively call traverse_tree on child nodes
A3DUns32 n_child_nodes    = 0;
A3DTreeNode** child_nodes = 0;

if(A3DTreeNodeGetChildren(hnd_tree, hnd_node, &n_child_nodes, &child_nodes) == A3D_SUCCESS) {
    for (A3DUns32 n = 0 ; n < n_child_nodes ; ++n) {
        traverse_tree(hnd_tree, child_nodes[n], depth+1);
    }
    A3DTreeNodeGetChildren(0, 0, &n_child_nodes, &child_nodes);
}

Loading the Model File

Now that we know how to recursively traverse our model tree, let’s load a file and instantiate the root A3DTreeNode on which we make our first call of traverse_tree().

In the main() function, the model file is loaded through the A3DSDKHOOPSExchangeLoader helper class. At the end of the call, model_file contains a valid handle to your loaded CAD file:

A3DSDKHOOPSExchangeLoader he_loader(HE_BINARY_DIRECTORY);

A3DImport he_import(HE_DATA_DIRECTORY INPUT_FILE);
he_loader.Import(he_import);

A3DAsmModelFile* model_file = he_loader.m_psModelFile;

Then, we use A3DTreeCompute() to generate the tree structure out of model_file, and A3DTreeGetRootNode() to obtain the root node. Finally, we call traverse_tree(), that will start the traversal:

// Get the model tree
A3DTree* hnd_tree = 0;
A3DTreeCompute(model_file, &hnd_tree, 0);

// Get the root node
A3DTreeNode* hnd_root_node = 0;
A3DTreeGetRootNode(hnd_tree, &hnd_root_node);

// Run the traversal
traverse_tree(hnd_tree, hnd_root_node, 0);

// Release model tree memory
A3DTreeCompute(0, &hnd_tree, 0);

The Full Code

Here is a full working example of the Print Assembly Structure sample.

#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>

#include <iostream>
#include <string>
#include <cassert>

//////////////////////////////////////////////////////////////////////
/// INPUT_FILE
/// Default CAD input file, relative to Exchange sample data folder.
/// To see how the value is used, check the `main()` function.
#define INPUT_FILE "/prc/_micro engine.prc"

void traverse_tree(A3DTree* const hnd_tree, A3DTreeNode* const hnd_node, size_t depth) {
    // Display node's entity name
    std::cout << std::string(2 * depth, ' '); // Print indent

    A3DUTF8Char* node_name = 0;
    if (A3DTreeNodeGetName(hnd_node, &node_name) == A3D_SUCCESS && node_name != 0) {
        std::cout << node_name << std::endl;
        A3DTreeNodeGetName(0, &node_name);
    } else {
        std::cout << "N/A" << std::endl;
    }

    // Recursively call traverse_tree on child nodes
    A3DUns32 n_child_nodes    = 0;
    A3DTreeNode** child_nodes = 0;

    if(A3DTreeNodeGetChildren(hnd_tree, hnd_node, &n_child_nodes, &child_nodes) == A3D_SUCCESS) {
        for (A3DUns32 n = 0 ; n < n_child_nodes ; ++n) {
            traverse_tree(hnd_tree, child_nodes[n], depth+1);
        }
        A3DTreeNodeGetChildren(0, 0, &n_child_nodes, &child_nodes);
    }
}

int main(int argc, char* argv[]) {
    ///////////////////////////////////////////////////////////
    // INITIALIZE HOOPS EXCHANGE AND LOAD THE MODEL FILE
    A3DSDKHOOPSExchangeLoader he_loader(HE_BINARY_DIRECTORY);
    assert(he_loader.m_eSDKStatus == A3D_SUCCESS);

    A3DImport he_import(HE_DATA_DIRECTORY INPUT_FILE);
    A3DStatus status = he_loader.Import(he_import);
    assert(status == A3D_SUCCESS);
    A3DAsmModelFile* model_file = he_loader.m_psModelFile;

    ////////////////////////////////////////////////////////////
    // TRAVERSE THE MODEL TREE
    A3DTree*         hnd_tree = 0;

    status = A3DTreeCompute(model_file, &hnd_tree, 0);
    assert(status == A3D_SUCCESS);

    A3DTreeNode* hnd_root_node = 0;
    status = A3DTreeGetRootNode(hnd_tree, &hnd_root_node);
    assert(status == A3D_SUCCESS);

    traverse_tree(hnd_tree, hnd_root_node, 0);

    A3DTreeCompute(0, &hnd_tree, 0);

    /////////////////////////////////////////////////////////////
    // Everything is loaded to GPU; Exchange can be released.
    A3DAsmModelFileDelete(model_file);
    A3DDllTerminate();
    A3DSDKUnloadLibrary();

    return EXIT_SUCCESS;
}

The code is also available on GitHub.

Now that you have learned how to traverse a model file using A3DTree and A3DTreeNode, you can dive into a more complete example: Write a CAD Viewer.

Previous Next

© Copyright 2023, Tech Soft 3D

Return to top