########################
File-to-File Translation
########################

This tutorial walks you through the ``ImportExport`` sample code one of the :doc:`samples </sample_codes>` included with HOOPS Exchange.
The sample demonstrates the basic workflow of reading an input file and exporting it to a new format.

As a prerequisite, ensure you have followed the previous tutorial about :doc:`Set Up Your Environment </tutorials/c/environment-setup>`.
Ensure you can build and run the ``ImportExport`` sample. The sample code can be found in the ``samples/`` folder of your package.

The Code
========

Open ``ImportExport.cpp`` in your editor.
Since the sample is a complete implementation, you're not required to add anything new to the program.
To facilitate learning, we'll examine each of the functional areas with a deep dive into what the code is doing.

**At the top of the file, you'll notice two lines of code related to including and initializing HOOPS Exchange:**

.. code:: cpp

   #define INITIALIZE_A3D_API
   #include <A3DSDKIncludes.h>

The definition of ``INITIALIZE_A3D_API`` before including the Exchange header triggers the inclusion of initialization code.
This should only be present in a single compilation unit of an application, and in this sample, it's in *ImportExport.cpp*.


**In the `main` function's body, you'll find logic for handling command-line arguments.**

If you run the program without specifying input and/or output files, defaults are used:

         * The default input file is *samples/data/catiaV5/CV5\Aquo\Bottle/\Aquo Bottle.CATProduct*.
         * The default output file is the input file name with *.prc* appended.


**Following the command line processing, you'll see the following line of code:**

.. code:: cpp

   A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY));

This line constructs an object that is declared and implemented inline.
Its role includes loading and initializing HOOPS Exchange and unlocking the product using your license key found in *hoops_license.h*.
Additionally, its destructor is implemented to de-initialize and unload HOOPS Exchange.
You can examine this class's inline implementation.


**Next, the sample connects callbacks for custom memory allocation and freeing.**

.. code:: cpp

   CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
   CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError));

While not required for using HOOPS Exchange, it can be helpful when debugging memory-related issues.
After connecting the memory callbacks, the code establishes a callback for handling information, warning, and error messages from the library.
Again, this isn't mandatory for using HOOPS Exchange, but it can provide valuable information.
The samples all print the messages received by the callback to ``stdout``.


**The heart of the sample is the next three lines of code:**

.. code:: cpp

   A3DImport sImport(acSrcFileName)
   A3DExport sExport(acDstFileName)
   CHECK_RET(sHoopsExchangeLoader.Convert(sImport, sExport))

It declares an import object and an export object, then uses the Convert method on ``A3DSDKHOOPSExchangeLoader`` to perform the conversion.
Each of these classes and methods are implemented in ``A3DSDKInternalConvert.hxx``, allowing you to examine them more closely.

The ``A3DImport`` class serves as a container for the input filename and an options struct controlling the reader's behavior.
Internally, it initializes the options with common values.

Similarly, the ``A3DExport`` class serves as a container for the output filename and an options struct controlling the writer's behavior.
This class examines the file extension and sets an enumeration indicating the desired format.


**The final step of this tutorial is the call to "Convert()":**

.. code:: cpp

   CHECK_RET(sHoopsExchangeLoader.Convert(sImport, sExport));

The method's implementation first reads the input file and uses the file type determined by the ``A3DExport`` class to invoke the appropriate function for writing the desired output file format.


Playing With The Sample
=======================

In this section we will tweak the code and see the changes.

.. tabs::

   .. group-tab:: Windows

      **Change the command line**
    
      In Visual Studio from the Solution Tree explorer:

         * Locate the sample ``ImportExport``
         * Right click on it and select *Properties*.
         * Edit the *Command Argument* setting under the Debugging tab to change the input CAD file and output.

         Assuming that the HOOPS Exchange API package is installed on the root of your disk ``C:`` the command argument looks like this:
         
         ``"C:\<HOOPS_EXCHANGE_INSTALL_DIR>\samples\data\catiaV5\CV5_Aquo_Bottle\Bullet_Lid_Cap.CATPart" "C:\<HOOPS_EXCHANGE_INSTALL_DIR>\samples\data\catiaV5\CV5_Aquo_Bottle\Bullet_Lid_Cap.CATPart.stl"``

         .. image:: /_assets/images/vs-test-sample.png
            :width: 50%
            :align: center
            
         
         * *Run* the sample ``ImportExport`` to convert a CATIA V5 part called **Bullet_Lid_Cap.CATPart** to STL format.
         * Locate the file *Bullet_Lid_Cap.CATPart.stl* in your output folder.
         * Open the *HOOPS Demo Viewer* desktop application and and *drag & drop* your resulting **Bullet_Lid_Cap.CATPart.stl** file to quickly visualize the part:
    
         .. image:: /_assets/images/Bullet_Lid_Cap.CATPart-win.png
            :width: 50%
            :align: center

         
         You just have learned how to specify your own input CAD file and Output format.
      
      **Change the conversions settings**    
      
      In Visual Studio from the Solution Tree explorer:

         * Locate the sample ``ImportExport``
         * Under the Debugging tab edit the *Command Argument* setting to specify the input CAD file and output.

      Assuming that the HOOPS Exchange API package is installed on the root of your disk ``C:`` the command argument looks like this:

      ``"C:\<HOOPS_EXCHANGE_INSTALL_DIR>\samples\data\pmi\PMI_Sample\CV5_Sample.CATPart" "C:\<HOOPS_EXCHANGE_INSTALL_DIR>\samples\samples\data\pmi\PMI_Sample\CV5_Sample.CATPart.prc"``

         
         * *Run* the sample to convert the file **CV5_Sample.CATPart** to PRC format.
         * Locate and *drag & drop* the resulting **CV5_Sample.CATPart.prc** in *HOOPS Demo Viewer* to visualize the part in your output folder:
         
         .. image:: /_assets/images/pmi-sample.png
            :width: 50%
            :align: center
         
         
         * Locate and open the ``A3DSDKInternalConvert.hxx`` file from your installation folder ``../include/``
         
         You are now looking at the file ``A3DSDKInternalConvert.hxx`` where all the conversion parameters :c:struct:`~A3DRWParamsGeneralData` are exposed.
         
      .. code:: cpp
      
         A3DRWParamsGeneralData m_sGeneral;				    /*!< The general reading parameters. */
         A3DRWParamsPmiData m_sPmi;						    /*!< The parameters for PMI reading. Used when `m_sGeneral.m_bReadPmis` is `A3D_TRUE`. */
         A3DRWParamsTessellationData m_sTessellation;		/*!< The tessellation reading parameters. */
         A3DRWParamsAssemblyData m_sAssembly;				/*!< The reading parameters used to load Assembly files. */
         A3DRWParamsMultiEntriesData m_sMultiEntries;		/*!< The parameters used when reading multiple models. */
         A3DRWParamsSpecificLoadData m_sSpecifics;		    /*!< The parameters specific to each CAD format. */
         A3DRWParamsIncrementalLoadData m_sIncremental;	    /*!< The reading parameters used to load specific parts of an assembly. */
         A3DRWParamsLoadData;
      
      Import and Export parameters can be added and edited as needed. Let's take an example:
      
         * Locate the setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` 
         * Change its value to setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_FALSE;``
         * *Rebuild* and *Run* the sample to convert the file **CV5_Sample.CATPart** to PRC format again.
         * Locate and *drag & drop* the resulting **CV5_Sample.CATPart.prc** in *HOOPS Demo Viewer* to visualize the part.
         * Compare the two resulting **CV5_Sample.CATPart.prc** files.
      
         .. image:: /_assets/images/pmi-sample-no-pmi.png
            :width: 50%
            :align: center
            
      As you can see that by turning off the import parameters ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` the *Product Manufacturing Information* are not converted.
         
   .. group-tab:: Linux

      **Change the command line**
            
      On Linux, open the *Terminal*:
      
         * Locate the sample ``ImportExport`` from the installation folder ``..\samples\hello_world\ImportExport``
         * Right click on the folder and select *Open in Terminal*
         * Locate the file **Bullet_Lid_Cap.CATPart** from the installation folder ``..\samples\data\catiaV5\``
         * Make sure the Sample is already built otherwise build it again. Command Line: ``make``
                  
         .. image:: /_assets/images/Import_export_make.png
            :width: 50%
            :align: center                 
                  
         * *Run* the sample ``ImportExport`` to convert a CATIA V5 part called **Bullet_Lid_Cap.CATPart** to STL format. Command Line ``./ImportExport ../samples/data/catiaV5/Bullet_Lid_Cap.CATPart ../samples/data\/atiaV5/Bullet_Lid_Cap.CATPart.stl``
                  
         .. image:: /_assets/images/Import_export_make_run.png
            :width: 50%
            :align: center
            
         * *Run* the sample ``Viewer`` to load the resulting part called **Bullet_Lid_Cap.CATPart.stl**. Command Line ``./Viewer ../samples/data/catiaV5/Bullet_Lid_Cap.CATPart.stl``
         * **Bullet_Lid_Cap.CATPart.stl** file will be displayed in an OpenGL Windows:
            
         .. image:: /_assets/images/Bullet_Lid_Cap.CATPart-linux.png
            :width: 50%
            :align: center
         
      You just have learned how to specify your own input CAD file and Output format.
      
      **Change the conversions settings**

         * Stop the execution of the sample ``Viewer`` (Ctrl+C).
         * Locate the file **CV5_Sample.CATPart** from the installation folder ``..\samples\data\pmi\``
         * *Run* the sample ``importExport`` to convert the file **CV5_Sample.CATPart** to PRC format.
         * Locate the resulting **CV5_Sample.CATPart.prc** file from the folder ``./samples/data/pmi/``
         * *Run* the sample ``Viewer`` to load the PRC file. Command Line ``./Viewer ../samples/data/pmi/CV5_Sample.CATPart.prc``
         
         .. image:: /_assets/images/pmi-sample-linux.png
            :width: 50%
            :align: center
         
         * Stop the execution of the sample ``Viewer`` (Ctrl+C).
         * Locate and open the ``A3DSDKInternalConvert.hxx`` file from your installation folder ``../include/``.
         
      You are now looking at the file ``A3DSDKInternalConvert.hxx`` where all the conversion parameters :c:struct:`~A3DRWParamsGeneralData` are exposed.
         
      .. code:: cpp
      
         A3DRWParamsGeneralData m_sGeneral;				    /*!< The general reading parameters. */
         A3DRWParamsPmiData m_sPmi;						    /*!< The parameters for PMI reading. Used when `m_sGeneral.m_bReadPmis` is `A3D_TRUE`. */
         A3DRWParamsTessellationData m_sTessellation;		/*!< The tessellation reading parameters. */
         A3DRWParamsAssemblyData m_sAssembly;				/*!< The reading parameters used to load Assembly files. */
         A3DRWParamsMultiEntriesData m_sMultiEntries;		/*!< The parameters used when reading multiple models. */
         A3DRWParamsSpecificLoadData m_sSpecifics;		    /*!< The parameters specific to each CAD format. */
         A3DRWParamsIncrementalLoadData m_sIncremental;	    /*!< The reading parameters used to load specific parts of an assembly. */
         A3DRWParamsLoadData;
      
      Import and Export parameters can be added and edited as needed. Let's take an example:
      
         * Locate the setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` 
         * Change its value to setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_FALSE;``
         * *Rebuild* ``make clean`` then ``make`` the sample ``ImportExport``
         
      The Import parameter has been changed and is now taken into account by the sample.
      
         * Locate the file **CV5_Sample.CATPart** from the installation folder ``..\samples\data\pmi\``
         * *Run* the sample ``importExport`` to convert the file **CV5_Sample.CATPart** to PRC format.
         * Locate the resulting **CV5_Sample.CATPart.prc** file from the folder ``./samples/data/pmi/``
         * *Run* the sample ``Viewer`` to load the PRC file Command Line ``./Viewer ../samples/data/pmi/CV5_Sample.CATPart.prc``
         * Compare the two resulting **CV5_Sample.CATPart.prc** files.
         
         .. image:: /_assets/images/pmi-sample-no-pmi-linux.png
            :width: 50%
            :align: center
            
      As you can see that by turning off the import parameters ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` the *Product Manufacturing Information* are not converted.

   .. group-tab:: macOS
   
      **Change the command line**
      
      On macOS, open the *Terminal*:
      
         * Locate the sample ``ImportExport`` from the installation folder ``..\samples\hello_world\ImportExport``
         * Right click on the folder and select *Open in Terminal*.
         * Locate the file **Bullet_Lid_Cap.CATPart** from the installation folder ``..\samples\data\catiaV5\``
         * Make sure the Sample is already built otherwise build it again. Command Line: ``make``
                  
         .. image:: /_assets/images/Import_export_make.png
            :width: 50%
            :align: center                 
                  
         * *Run* the sample ``ImportExport`` to convert a CATIA V5 part called **Bullet_Lid_Cap.CATPart** to STL format. Command Line ``./ImportExport ../samples/data/catiaV5/Bullet_Lid_Cap.CATPart ../samples/data\/atiaV5/Bullet_Lid_Cap.CATPart.stl``
                  
         .. image:: /_assets/images/Import_export_make_run.png
            :width: 50%
            :align: center
            
         * *Run* the sample ``Viewer`` to load the resulting part called **Bullet_Lid_Cap.CATPart.stl**. Command Line ``./Viewer ../samples/data/catiaV5/Bullet_Lid_Cap.CATPart.stl``
         * **Bullet_Lid_Cap.CATPart.stl** file will be displayed in an OpenGL Windows:
            
         .. image:: /_assets/images/Bullet_Lid_Cap.CATPart-mac.png
            :width: 50%
            :align: center
         
      You just have learned how to specify your own input CAD file and Output format.
      
      **Change the conversions settings**

         * Stop the execution of the sample ``Viewer`` (Ctrl+C).
         * Locate the file **CV5_Sample.CATPart** from the installation folder ``..\samples\data\pmi\``
         * *Run* the sample ``importExport`` to convert the file **CV5_Sample.CATPart** to PRC format.
         * Locate the resulting **CV5_Sample.CATPart.prc** file from the folder ``./samples/data/pmi/``
         * *Run* the sample ``Viewer`` to load the PRC file. Command Line ``./Viewer ../samples/data/pmi/CV5_Sample.CATPart.prc``
         
         .. image:: /_assets/images/pmi-sample-mac.png
            :width: 50%
            :align: center
         
         * Stop the execution of the sample ``Viewer`` (Ctrl+C).
         * Locate and open the ``A3DSDKInternalConvert.hxx`` file from your installation folder ``../include/``.
         
      You are now looking at the file ``A3DSDKInternalConvert.hxx`` where all the conversion parameters :c:struct:`~A3DRWParamsGeneralData` are exposed.
         
      .. code:: cpp
      
         A3DRWParamsGeneralData m_sGeneral;				    /*!< The general reading parameters. */
         A3DRWParamsPmiData m_sPmi;						    /*!< The parameters for PMI reading. Used when `m_sGeneral.m_bReadPmis` is `A3D_TRUE`. */
         A3DRWParamsTessellationData m_sTessellation;		/*!< The tessellation reading parameters. */
         A3DRWParamsAssemblyData m_sAssembly;				/*!< The reading parameters used to load Assembly files. */
         A3DRWParamsMultiEntriesData m_sMultiEntries;		/*!< The parameters used when reading multiple models. */
         A3DRWParamsSpecificLoadData m_sSpecifics;		    /*!< The parameters specific to each CAD format. */
         A3DRWParamsIncrementalLoadData m_sIncremental;	    /*!< The reading parameters used to load specific parts of an assembly. */
         A3DRWParamsLoadData;
      
      Import and Export parameters can be added and edited as needed. Let's take an example:
      
         * Locate the setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` 
         * Change its value to setting ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_FALSE;``
         * *Rebuild* ``make clean`` then ``make`` the sample ``ImportExport``
         
      The Import parameter has been changed and is now taken into account by the sample.
      
         * Locate the file **CV5_Sample.CATPart** from the installation folder ``..\samples\data\pmi\``
         * *Run*` the sample ``importExport`` to convert the file **CV5_Sample.CATPart** to PRC format.
         * Locate the resulting **CV5_Sample.CATPart.prc** file from the folder ``./samples/data/pmi/``
         * *Run* the sample ``Viewer`` to load the PRC file. Command Line ``./Viewer ../samples/data/pmi/CV5_Sample.CATPart.prc``
         * Compare the two resulting **CV5_Sample.CATPart.prc** files.
      
         .. image:: /_assets/images/pmi-sample-no-pmi-mac.png
            :width: 50%
            :align: center
      
      As you can see that by turning off the import parameters ``m_sLoadData.m_sGeneral.m_bReadPmis = A3D_TRUE;`` the *Product Manufacturing Information* are not converted.
      

   .. group-tab:: iOS
                  
      #. **Build and Run the sample IOSWriter**

         * Launch Xcode and select *Open Existing Project*.
         * In the ``../samples/ios/IOSWriter`` folder of your installed package, open ``IOSWriter.xcodeproj``
         * From the *Project navigator* bar select the file ``ts-0001.stp``
         * Right Click ``Add files to "IOSWriter"...``
         * Build the sample
         * Go to the tab ``Product`` > ``Build For`` > ``Running``
         * Run the sample ``IOSWriter``
         * Go to the tab ``Product`` > ``Run``
      
         .. image:: /_assets/images/IOSWriter.png
            :width: 50%
            :align: center
      
         * The iOS simulator will be launched
         * The file ``ts-0001.stp`` is being converted to XT (Parasolid format)
         * The ``ts-0001.prc.x_t`` file is generated and is available at:
         
         ``/Users/me/Library/Developer/CoreSimulator/Devices/XXXX/data/Containers/Data/Application/XXXX/Documents``
      
         .. image:: /_assets/images/IOSWriterRun.png
            :width: 50%
            :align: center
      
         * Locate the file ``ts-0001.stp.x_t``
         * If you have previously executed HOOPS Exchange on macOS you can re-use the sample Viewer to open your resulting ``ts-0001.prc.x_t`` file export from your iOS emulator:
      
         .. image:: /_assets/images/ios-macos-viewer.png
            :width: 50%
            :align: center
      
      **Change the conversions settings**
      
         * Open the file ``IOSWriter.cpp`` in xCode.
         
      You are now looking at the file code of the sample where all the conversion parameters :c:struct:`~A3DRWParamsGeneralData` are exposed.
         
      .. code:: cpp
      
         A3DRWParamsGeneralData m_sGeneral;				    /*!< The general reading parameters. */
         A3DRWParamsPmiData m_sPmi;						    /*!< The parameters for PMI reading. Used when `m_sGeneral.m_bReadPmis` is `A3D_TRUE`. */
         A3DRWParamsTessellationData m_sTessellation;		/*!< The tessellation reading parameters. */
         A3DRWParamsAssemblyData m_sAssembly;				/*!< The reading parameters used to load Assembly files. */
         A3DRWParamsMultiEntriesData m_sMultiEntries;		/*!< The parameters used when reading multiple models. */
         A3DRWParamsSpecificLoadData m_sSpecifics;		    /*!< The parameters specific to each CAD format. */
         A3DRWParamsIncrementalLoadData m_sIncremental;	    /*!< The reading parameters used to load specific parts of an assembly. */
         A3DRWParamsLoadData;
      
      Import and Export parameters can be added and edited as needed. 

         * Open the file ``CADFileViewController.swift`` in Xcode.
         
      You are now looking at the "commands" of the sample IOSWriter
      
         * Change the parameter ``let TYPE_EXPORT = PARASOLID`` to ``let TYPE_EXPORT = IGES``
         * Rebuild* and *Run* the sample.
         * The iOS simulator will be launched
         * The file ``ts-0001.stp`` is being converted to IGES format.
         * The ``ts-0001.stp.igs`` file is generated and is available at:
         
         ``/Users/me/Library/Developer/CoreSimulator/Devices/XXXX/data/Containers/Data/Application/XXXX/Documents``
         
         * Open the ``ts-0001.stp.igs`` file in the macOS Viewer to visualize the part:
      
         .. image:: /_assets/images/ios-macos-viewer-step.png
            :width: 50%
            :align: center
      
            
   .. group-tab:: Android

      Coming soon... 
      

   
Conclusion
==========

The file-to-file workflow is a common starting point for evaluating the capabilities of HOOPS Exchange.
Using the ``ImportExport`` sample that ships with the product, you can easily convert files from one format to another.

By completing this tutorial, you now have the knowledge of how to use HOOPS Exchange in this basic use case.
Furthermore, by examining the implementation of the helper classes involved, you'll have gained some insight into the use of the API itself.

Now that you played along with our *ImportExport* sample, you are ready to move forward and play with our :doc:`/tutorials/c/print-assembly-structure` sample.

