####################
ImportExport Example
####################

.. sidebar::

   .. contents::
      :local:


This example code demonstrates how to programmatically import a CAD model using HOOPS Exchange and convert it to another format.
This is one of the best places to start with HOOPS Exchange.

In addition to this document, the :doc:`/tutorials/c/file-to-file-translation` tutorial provides you with ways to play along with the import and export parameters to discover HOOPS Exchange I/O capabilities.

*ImportExport* is available in HOOPS Exchange package, as part of the *samples* project.
See :doc:`build` for more information about how to build and run the example code.

What is the ImportExport Sample
===============================

This sample reads an input CAD file and converts it to any of our export formats, according to the file extension passed in parameter.
Once completed, the *ImportExport* generates a new CAD file and a log file in the same folder as the input file.

When invoked, it accepts up to 3 arguments, each having a default value:

+------------+----------------------------+
| Name       | Default                    |
+------------+----------------------------+
| **input**  | *\_Aquo Bottle.CATProduct* |
+------------+----------------------------+
| **output** | *{input}.prc*              |
+------------+----------------------------+
| **log**    | *{output}*\_Log.txt        |
+------------+----------------------------+

Use the ``--help`` option to get the full list of available parameters.

.. note:: Experimental USD export

   Since HOOPS Exchange 2025.4.0, we support exporting to USD as an experimental feature.
   The *Import Export* sample can be extended to provide this functionality.
   For more information, see :ref:`usd_wt_sample`.


The Code
========

The sample consists of a single source file, *ImportExport.cpp*.

Header Files
------------

The most important header is *A3DSDKInclude.h* that declares the entire HOOPS Exchange API.
The other headers facilitate writing example code.

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: // Exchange libraries
   :end-at: unordered_map
   :linenos:
   :lineno-match:
   :emphasize-lines: 2-4

Throughout the code, you will encounter helper functions such as ``AssertSuccess()``, ``Assert()``, and ``Sample::`` namespaced utilities.
These are part of the *SampleTools* library and are not specific to HOOPS Exchange.

Load/Unload HOOPS Exchange
--------------------------

Initializing and terminating HOOPS Exchange follows the usual pattern.
For more information, see :doc:`/guide/basic_operations/initialize-hoops-exchange`.

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: static void initialize_exchange(void) {
   :end-before: initialize_exchange()
   :linenos:
   :lineno-match:
   :emphasize-lines: 8
   

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: static void terminate_exchange(void) {
   :end-before: terminate_exchange()
   :linenos:
   :lineno-match:
   :emphasize-lines: 5

Importing a CAD File
--------------------

Importing a CAD file is done using the :c:func:`A3DAsmModelFileLoadFromFile` function.
This function reads an input file path, and internally creates an entity called a **model file**.

The first thing we need to create is a location for storing the entity identifier.
We also need to set the load parameters.
HOOPS Exchange provides you with lots of ways to customize loading, and all parameters are set in the :c:struct:`A3DRWParamsLoadData` structure:

.. code-block:: c

   A3DAsmModelFile* model_file = A3D_NULL_HANDLE;
   A3DRWParamsLoadData read_params = A3D_MAKE_DATA(A3DRWParamsLoadData);
   // Customize parameters...

The following function takes a single file path string, and returns the created entity ID.
Note the call to :c:func:`A3DAsmModelFileLoadFromFile`:

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: static A3DAsmModelFile* import_cad_file(const std::string& file_path) {
   :end-before: import_cad_file()
   :linenos:
   :lineno-match:
   :emphasize-lines: 25-29

The model file entity returned by :c:func:`A3DAsmModelFileLoadFromFile` must be freed once you don't need it, using :c:func:`A3DAsmModelFileDelete`.
This is done later in the ``main()`` function:

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: A3DAsmModelFileDelete
   :end-at: AssertSuccess
   :dedent:

Exporting a CAD File
--------------------

HOOPS Exchange doesn't provide a centralized export function, like :c:func:`A3DAsmModelFileLoadFromFile`.

Instead, each format has its own specific function and parameter structure type.
For example, to export a file to STL, use :c:func:`A3DAsmModelFileExportToStlFile` along with the :c:struct:`A3DRWParamsExportStlData` structure:

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-after: case kA3DModellerStl:
   :end-before: break
   :dedent:
   :prepend: A3DStatus export_status                  = A3D_SUCCESS;
   :append: AssertSuccess(export_status);

In order to determine which pair of function and structure to call, the example code includes a function that returns the type enumeration, according to a file path, based on the file extensions:

.. code-block:: c

   ////////////////////////////////////////////////////////////////////////////////
   /// Map file extension to A3DEModellerType
   static A3DEModellerType get_file_format(const std::string& filepath);

The implementation of the function is not in the scope of this document, but you have access to it directly from within the example code source.
``get_file_format()`` takes a file path in parameter, and returns the :c:enum:`A3DEModellerType` value corresponding to the file format.

The ``export_cad_file()`` function uses this value to select which function to call:

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-at: static void export_cad_file(A3DAsmModelFile* model_file, const std::string& file_path) {
   :end-before: export_cad_file()
   :linenos:
   :lineno-match:

The Main function
-----------------

In the ``main()`` function, we parse arguments, then call our above functions in order:

#. Initialize HOOPS Exchange
#. Load input file
#. Write output file
#. Delete loaded model file
#. Terminate HOOPS Exchange

.. literalinclude:: /../../../final-package/samples/hello_world/ImportExport/ImportExport.cpp
   :start-after: int main(int argc, char* argv[])
   :end-before: main()

Related Pages
=============

* **Getting Started:** :doc:`/start/supported-formats`.
* **Tutorial:** :doc:`/tutorials/c/file-to-file-translation`.
* **Programming Guide:** :doc:`/guide/basic_operations/load_model`.
* **API Reference:** :ref:`group__a3d__publish__modelfile__loadexport`.
* **Additional Resources:** :doc:`/sample_codes`.


The *ImportExport* example code is available in C++ and C#:

.. csv-table::
   :class: sample-location
   :stub-columns: 1

   Language,Location
   C/C++,|he_c_samples_dir|/hello_world/ImportExport
   C#,|he_cs_samples_dir|/hello_world/ImportExport

