ImportExport Example
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 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 Building Code Examples 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 Extending the Import Export 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.
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 Initializing HOOPS Exchange.
48static void initialize_exchange(void) {
49 const A3DBool loaded = A3DSDKLoadLibraryA(HOOPS_BINARY_DIRECTORY);
50 REQUIRE(loaded);
51
52 A3DStatus status = A3DLicPutUnifiedLicense(HOOPS_LICENSE);
53 REQUIRE(status == A3D_SUCCESS);
54
55 status = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);
56 REQUIRE(status == A3D_SUCCESS);
57
58 status = A3DDllSetCallbacksReport(Sample::PrintMessage, Sample::PrintWarning, Sample::PrintError);
59 REQUIRE(status == A3D_SUCCESS);
60}
259static void terminate_exchange(void) {
260 A3DStatus status = A3DDllTerminate();
261 REQUIRE(status == A3D_SUCCESS);
262
263 A3DSDKUnloadLibrary();
264}
Importing a CAD File
Importing a CAD file is done using the 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 A3DRWParamsLoadData structure:
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 A3DAsmModelFileLoadFromFile():
74static A3DAsmModelFile* import_cad_file(const std::string& file_path) {
75 A3DAsmModelFile* model_file = A3D_NULL_HANDLE;
76
77 // Configure import parameters
78 A3DRWParamsLoadData read_params = A3D_MAKE_DATA(A3DRWParamsLoadData);
79 read_params.m_sGeneral.m_bReadSolids = A3D_TRUE;
80 read_params.m_sGeneral.m_bReadSurfaces = A3D_TRUE;
81 read_params.m_sGeneral.m_bReadWireframes = A3D_TRUE;
82 read_params.m_sGeneral.m_bReadPmis = A3D_TRUE;
83 read_params.m_sGeneral.m_bReadAttributes = A3D_TRUE;
84 read_params.m_sGeneral.m_bReadHiddenObjects = A3D_TRUE;
85 read_params.m_sGeneral.m_bReadConstructionAndReferences = A3D_FALSE;
86 read_params.m_sGeneral.m_bReadActiveFilter = A3D_TRUE;
87 read_params.m_sGeneral.m_eReadingMode2D3D = kA3DRead_3D;
88 read_params.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
89 read_params.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown;
90 read_params.m_sGeneral.m_dLongWireframeThreshold = 24690.0;
91 read_params.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
92 read_params.m_sAssembly.m_bUseRootDirectory = A3D_TRUE;
93 read_params.m_sMultiEntries.m_bLoadDefault = A3D_TRUE;
94 read_params.m_sPmi.m_bAlwaysSubstituteFont = A3D_FALSE;
95 read_params.m_sPmi.m_pcSubstitutionFont = const_cast<char*>("Myriad CAD");
96
97 // Load the file
98 const A3DStatus status = A3DAsmModelFileLoadFromFile(
99 file_path.c_str(),
100 &read_params,
101 &model_file
102 );
103
104 REQUIRE_ANY_OF(status, A3D_SUCCESS, A3D_LOAD_MISSING_COMPONENTS);
105
106 return model_file;
107}
The model file entity returned by A3DAsmModelFileLoadFromFile() must be freed once you don’t need it, using A3DAsmModelFileDelete().
This is done later in the main() function:
Exporting a CAD File
HOOPS Exchange doesn’t provide a centralized export function, like A3DAsmModelFileLoadFromFile().
Instead, each format has its own specific function and parameter structure type.
For example, to export a file to STL, use A3DAsmModelFileExportToStlFile() along with the A3DRWParamsExportStlData structure:
A3DStatus export_status = A3D_SUCCESS;
A3DRWParamsExportStlData export_data = A3D_MAKE_DATA(A3DRWParamsExportStlData);
export_data.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
export_status = A3DAsmModelFileExportToStlFile(model_file, &export_data, c_file_path);
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:
////////////////////////////////////////////////////////////////////////////////
/// 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 A3DEModellerType value corresponding to the file format.
The export_cad_file() function uses this value to select which function to call:
123static void export_cad_file(A3DAsmModelFile* model_file, const std::string& file_path) {
124 A3DStatus export_status = A3D_SUCCESS;
125 const char* const c_file_path = file_path.c_str();
126 const A3DEModellerType type = get_file_format(file_path);
127
128 // Each format has its own export params and function
129 switch (type) {
130
131 case kA3DModellerIges: {
132 A3DRWParamsExportIgesData export_data = A3D_MAKE_DATA(A3DRWParamsExportIgesData);
133 export_status = A3DAsmModelFileExportToIgesFile(model_file, &export_data, c_file_path);
134 break;
135 }
136
137 case kA3DModellerStep: {
138 A3DRWParamsExportStepData export_data = A3D_MAKE_DATA(A3DRWParamsExportStepData);
139 export_status = A3DAsmModelFileExportToStepFile(model_file, &export_data, c_file_path);
140 break;
141 }
142
143 case kA3DModellerJt: {
144 A3DRWParamsExportJTData export_data = A3D_MAKE_DATA(A3DRWParamsExportJTData);
145 export_data.m_eWriteGeomTessMode = kA3DWriteGeomAndTess;
146 export_data.m_bWritePMI = A3D_TRUE;
147 export_status = A3DAsmModelFileExportToJTFile(model_file, &export_data, c_file_path);
148 break;
149 }
150
151 case kA3DModellerWrl: {
152 export_status = A3DAsmModelFileExportToVrmlFile(model_file, c_file_path);
153 break;
154 }
155
156 case kA3DModellerXML: {
157 A3DRWParamsExportXMLData export_data = A3D_MAKE_DATA(A3DRWParamsExportXMLData);
158 export_data.m_bExportMetadata = A3D_TRUE;
159 export_data.m_bExportTransformations = A3D_TRUE;
160 export_data.m_bExportColorMaterial = A3D_TRUE;
161 export_data.m_bExportProductInformationByFormat = A3D_FALSE;
162 export_status = A3DAsmModelFileExportToXMLFile(model_file, &export_data, c_file_path,NULL,NULL,NULL);
163 break;
164 }
165
166 case kA3DModeller3mf: {
167 A3DRWParamsExport3mfData export_data = A3D_MAKE_DATA(A3DRWParamsExport3mfData);
168 export_status = A3DAsmModelFileExportTo3mfFile(model_file, &export_data, c_file_path);
169 break;
170 }
171
172 case kA3DModellerU3D: {
173 A3DRWParamsExportU3DData export_data = A3D_MAKE_DATA(A3DRWParamsExportU3DData);
174 export_data.m_eU3DVersion = kA3DECMA3;
175 export_status = A3DAsmModelFileExportToU3DFile(model_file, &export_data, c_file_path);
176 break;
177 }
178
179 case kA3DModellerPrc: {
180 A3DRWParamsExportPrcData export_data = A3D_MAKE_DATA(A3DRWParamsExportPrcData);
181 export_data.m_eCompressBrepType = kA3DCompressionMedium;
182 export_status = A3DAsmModelFileExportToPrcFile(model_file, &export_data, c_file_path,NULL);
183 break;
184 }
185
186 case kA3DModellerOBJ: {
187 A3DRWParamsExportObjData export_data = A3D_MAKE_DATA(A3DRWParamsExportObjData);
188 export_status = A3DAsmModelFileExportToObjFile(model_file, &export_data, c_file_path);
189 break;
190 }
191
192 case kA3DModellerFBX: {
193 A3DRWParamsExportFbxData export_data = A3D_MAKE_DATA(A3DRWParamsExportFbxData);
194 export_status = A3DAsmModelFileExportToFbxFile(model_file, &export_data, c_file_path);
195 break;
196 }
197
198 case kA3DModellerGltf: {
199 A3DRWParamsExportGltfData export_data = A3D_MAKE_DATA(A3DRWParamsExportGltfData);
200 export_status = A3DAsmModelFileExportToGltfFile(model_file, &export_data, c_file_path);
201 break;
202 }
203#if defined HOOPS_EXCHANGE
204 case kA3DModellerParasolid: {
205 A3DRWParamsExportParasolidData export_data = A3D_MAKE_DATA(A3DRWParamsExportParasolidData);
206 export_status = A3DAsmModelFileExportToParasolidFile(model_file, &export_data, c_file_path);
207 break;
208 }
209
210 case kA3DModellerAcis: {
211 A3DRWParamsExportAcisData export_data = A3D_MAKE_DATA(A3DRWParamsExportAcisData);
212 export_status = A3DAsmModelFileExportToAcisFile(model_file, &export_data, c_file_path);
213 break;
214 }
215#endif
216
217#if defined _MSC_VER || defined __linux__
218#ifndef TS_PUBLISH_DISABLED
219 case kA3DModeller3dHtml: {
220 A3DRWParamsExportHtmlData export_data = A3D_MAKE_DATA(A3DRWParamsExportHtmlData);
221 export_data.m_bIncludeMeasurementInformation = A3D_TRUE;
222 export_status = A3DAsmModelFileExportToHTMLFile(model_file, &export_data, c_file_path);
223 break;
224 }
225#endif
226#endif
227
228 case kA3DModellerStl: {
229 A3DRWParamsExportStlData export_data = A3D_MAKE_DATA(A3DRWParamsExportStlData);
230 export_data.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
231 export_status = A3DAsmModelFileExportToStlFile(model_file, &export_data, c_file_path);
232 break;
233 }
234
235#if defined (A3DAPI_EXPERIMENTAL) || defined (A3DAPI_EXPERIMENTAL_WITHOUT_WARNING)
236 case experimental_kA3DModellerUSD: {
237 A3DRWParamsExportUSDData export_data = A3D_MAKE_DATA(A3DRWParamsExportUSDData);
238 export_status = A3DAsmModelFileExportToUSDFile(model_file, &export_data, c_file_path);
239 break;
240 }
241#endif
242
243 default : {
244 export_status = A3D_WRITE_WRITER_NOT_IMPLEMENTED;
245 break;
246 }
247 }
248
249 REQUIRE(export_status == A3D_SUCCESS);
250}
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
{
Sample::Arguments args;
if(!Sample::ParseArguments(argc, argv, args)) {
return EXIT_FAILURE;
}
Sample::StartLogger(args.verbose, args.log_path);
initialize_exchange();
A3DAsmModelFile* model_file = import_cad_file(args.input_path);
export_cad_file(model_file, args.output_path);
const A3DStatus model_file_deleted = A3DAsmModelFileDelete(model_file);
REQUIRE(model_file_deleted == A3D_SUCCESS);
terminate_exchange();
return EXIT_SUCCESS;
}