HOOPS Exchange是什么?
是一组软件库,可以帮助开发人员在开发应用程序时读取和写入主流的 2D 和 3D 格式。HOOPS Exchange 支持在主流的3D 文件格式中读取 CAD 数据,并支持将 3D 数据转换为 PRC 数据格式,这是一种高度可压缩和开放的文件格式,并已通过国际标准化组织 (ISO 14739-1:2014) 的认证。PRC 也是 Adobe PDF 中用于 3D 的格式之一。HOOPS Exchange 持续优化读取各种 3D 数据的功能,尤其是对于来自计算机辅助设计 (CAD) 系统的数据。
打印装配结构
学习创建一个使用 HOOPS Exchange 打印输入文件的汇编结构的基本应用程序。
介绍
本教程将引导您使用 HOOPS Exchange 编写控制台应用程序的基础知识。完成本教程后,您应该对该技术有足够的了解,可以开始将 HOOPS Exchange 集成到您的应用程序中。
本教程的先决条件是对 C/C++ 应用程序开发有基本的了解。您应该从配置为构建和运行基本“hello world”示例应用程序的 IDE 开始本教程。无需高级 CAD 专业知识或 GUI 开发技能。
完成的项目将加载指定的输入文件并将程序集结构打印到stdout.
使用 HOOPS Exchange 构建
在本节中,您将学习如何将 HOOPS Exchange 添加到构建系统中。
要使用 HOOPS Exchange 构建,我们必须将包含文件夹添加到搜索路径。在 macOS 和 Linux 上,我们还必须添加动态链接器库“dl”。
添加包含文件夹
Windows 用户应在 Visual Studio 中编辑项目属性,并在 C/C++ 窗格中添加包含文件夹。
如果您正在使用cmake,请编辑CMakeLists.txt以下行并将其添加到文件中:
包含目录(/opt/ts3d/HOOPS_Exchange_Publish_2021_SP2_U2/include)
注意:参数应指定您安装 HOOPS Exchange 的位置。
添加动态链接器(仅限 macOS 和 Linux)
如果您正在使用 cmake 编辑 CMakeLists.txt 并将以下行添加到文件中:
target_link_libraries(he_basic_app -ldl)
这是一个完整的文件,可以作为您的简单起点 CMakeLists.txt.
cmake_minimum_required(版本 3.0.0)
项目(he_basic_app)
add_executable(he_basic_app main.cpp)
target_link_libraries(he_basic_app ${CMAKE_DL_LIBS})
如果(WIN32)
target_include_directories(he_basic_app "X:/HOOPS_Exchange_Publish_2021_SP2_U2/include")
别的()
target_include_directories(he_basic_app "/opt/local/ts3d/HOOPS_Exchange_2021_SP2_U2/include")
万一()
构建并运行
作为健全性检查,请记住构建并运行!
包括 HOOPS Exchange
在本节中,您将学习如何在源代码中正确包含 HOOPS Exchange。
要使用 HOOPS Exchange API,您必须包含其标头。这个包罗万象的标题使您可以访问整个工具包。在 IDE 的编辑器中打开main.cpp 。将以下行添加到文件顶部的第 1 行。
#include <A3DSDKIncludes.h>
添加此行后,如果您在上一节中正确指定了包含路径,您应该能够构建和运行。
要正确初始化 HOOPS Exchange,应用程序中的一个编译单元必须在包含上述标头之前声明一个预处理器宏。通过添加此预处理器定义,您将启用创建 API 本身的全局实例的代码。在包含 Exchange 标头之前添加以下行。
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
请记住,这个预处理器定义应该只存在于您的一个编译单元中。如果多个编译单元包含该定义,您将在链接时遇到重复的符号。由于我们的项目只包含一个编译单元(main.cpp),这不会有问题,但是在将 HOOPS Exchange 集成到您自己的应用程序中时,您应该注意这一点。
现在可能是像以前一样构建和运行项目的好时机。
初始化 HOOPS Exchange
在本节中,您将学习如何初始化 HOOPS Exchange 库。我们还将介绍用于在使用后将其拆除的功能。
加载库
第一步是将动态库加载到内存中,并将所有 API 函数指针初始化为对应的实现。听起来很复杂,对吧?幸运的是,这是通过简单地调用一个函数来完成的。在 main.js 中添加以下代码行。
A3DBool const is_loaded = A3DSDKLoadLibraryA( "X:/HOOPS_Exchange_Publish_2021_SP2_U2/bin/win64_v140" );
如果(!is_loaded){
std::cerr << "无法加载 HOOPS Exchange。" << std::endl;
返回-1;
}其他{
std::cout << "已加载。" << std::endl;
}
确保您指定为参数的路径与您的安装和平台的细节相匹配。我们将信守承诺,在完成后卸载库。轻松完成 - 只需在返回0之前添加此行。
A3DSDKUnloadLibrary();
返回0;
构建并运行。
提供许可证
要解锁 HOOPS Exchange 工具包,您必须使用许可证字符串。您的许可证字符串应保密。您将使用的许可证字符串位于 HOOPS Exchange 包含文件夹中名为hoops_license.h的文件中。验证它是否存在。
通过在文件顶部添加以下行来包含许可证文件头。
#include <hoops_license.h>
使用 API 解锁 HOOPS Exchange,方法是在您刚刚添加的库加载功能之后添加以下代码行。
A3DStatus常量license_status = A3DLicPutUnifiedLicense( HOOPS_LICENSE );
如果(A3D_SUCCESS!= license_status){
std::cerr << "无法授权 HOOPS Exchange" << std::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg( license_status ) <<
标准::endl;
返回-1;
}其他{
std::cout << "已授权。" << std::endl;
}
如果您在卸载库后意外添加了此代码,您将遇到问题。HOOPS_LICENSE是包含在hoops_license.h中的预处理器定义。它是一个包含您的许可证密钥的长字符串。
您现在可以通过按原样运行代码来验证您的许可证是否存在并且处于良好的工作状态。如果一切正常,您应该会看到“许可”消息。在标准输出上。
初始化 HOOPS Exchange
最后一步允许 HOOPS Exchange 执行其内部状态的初始化。此外,此函数会检查以确保您包含的 Exchange 标头中声明的版本号与嵌入到动态库中的版本号匹配。这是要添加的代码行。
A3DStatus const init_status = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);
如果(A3D_SUCCESS!= init_status){
std::cerr << "无法初始化 HOOPS Exchange。" << std::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg( init_status ) <<
标准::endl;
返回-1;
}其他{
std::cout << "准备使用。" << std::endl;
}
// 这里使用交换
A3DDllTerminate();
A3DSDKUnloadLibrary();
返回0;
这就是它的全部。如果您觉得这太费力并且适合您的使用,您可以改用 class A3DSDKHOOPSExchangeLoader。它在内部实现了所有这些功能。唯一需要注意的是,您声明的对象的生命周期必须匹配或超过您对任何 Exchange API 的使用。如果你走这条路,我们的整个程序就变成了下面这样。
int main(int,char **){
A3DSDKHOOPSExchangeLoader
装载机(L “X:/HOOPS_Exchange_Publish_2021_SP2_U2/bin/win64_v140”);
如果(!loader.m_bSDKLoaded){
std::cerr << "无法加载 HOOPS Exchange。" << std::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg(loader.m_eSDKStatus) <<
标准::endl;
返回-1;
}
std::cout << "准备使用。" << std::endl;
返回0;
}
这更容易。请记住要小心管理加载器对象的生命周期。对于本教程,我们可以坚持使用更简单的实现。在 macOS 和 Linux 上,去掉参数前面的“L”。
现在您了解了 HOOPS Exchange 是如何初始化的。如果出现问题,您可以很好地找出原因。
加载文件
在本节中,您将学习使用 HOOPS Exchange 加载文件的最基本方法。为了实现这个目标,您将首先声明和初始化加载选项。加载选项由加载 API 使用,该 API 返回加载文件的句柄。
配置加载选项
我们将用于加载输入文件的 API 接受一个控制其行为的选项结构。由于目标是简单地加载文件并打印程序集结构,因此默认选项就可以了。
声明选项结构并使用以下代码对其进行初始化。稍后我们将更详细地描述此代码。
A3DRWParamsLoadData load_params;
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, load_params);
接下来,我们需要一个变量来保存生成的模型文件句柄。
A3DAsmModelFile *model_file = nullptr ;
这声明了一个不透明的句柄,用于引用与您刚刚加载的文件关联的数据。您将很快了解如何访问数据。
最后,我们可以调用加载文件的 Exchange 函数。请注意此处输入文件的硬编码文件路径。您至少应该将其更改为您的安装路径,但您可以将其指向您想要的任何文件,前提是HOOPS Exchange支持该格式。
auto const input_file = "X:/HOOPS_Exchange_2021_SP2_U2/samples/data/prc/__drill.prc" ;
A3DStatus load_status = A3DAsmModelFileLoadFromFile( input_file, &load_params, &model_file );
如果(A3D_SUCCESS!= load_status){
std::cerr << "无法加载指定文件:" << input_file <<
标准::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg( load_status ) <<
标准::endl;
返回-1;
}其他{
std::cout << "加载的文件:" << input_file << std::endl;
}
让我们成为好公民,并为自己打扫卫生。假设模型文件有一些用途,当我们完成后,应该在程序退出之前清理它。
A3DAsmModelFileDelete(model_file);
model_file = nullptr ;
返回0;
当您构建并运行此时拥有的代码时,您将拥有代码并了解如何使用 HOOPS Exchange 工具包加载任何受支持的文件格式。您应该会看到一条写入标准输出的消息,声明已加载失败。
获取 HOOPS Exchange 实体的名称
在本节中,您将学习如何从 HOOPS Exchange API 中提取数据,以便在您的应用程序中使用它。您还将了解从 Exchange 检索所有数据的基本使用模式。
让我们将模型文件对象的名称打印到stdout. 在 main 之上创建一个函数,如下所示:
#include <字符串>
std::string getName(A3DEntity *ntt) {
返回std::string();
}
A3DEntity是一种通用句柄类型,可用于引用 Exchange 中的任何对象。我们将使用这样一个事实,即 Exchange 中的每个对象都有一组可通过 A3DRootBase 接口获得的通用基础数据。
声明并初始化存储
HOOPS Exchange 使用 C 风格的结构来读取(和写入)其内部数据表示。在我们读取数据之前,我们必须声明一个适当类型的结构来保存结果。该结构必须在使用之前使用宏进行初始化。在其他可能的事情中,初始化宏设置m_usStructSize字段,作为内部检查。在刚刚存根的函数中,添加以下代码行。
标准::字符串名称;
A3DRootBaseData rbd;
A3D_INITIALIZE_DATA(A3DRootBaseData, rbd);
读取数据
使用 HOOPS Exchange API 时,遵循的模式很普遍。每当您读取数据时,您必须确保进行相应的调用以释放它。这种模式看起来像这样。
if ( A3D_SUCCESS == A3DRootBaseGet( ntt, &rbd ) ) {
名称 = rbd.m_pcName ?rbd.m_pcName : "" ;
A3DRootBaseGet( nullptr , &rbd);
您可以通过此处找到的包装器对象避免初始化和使用模式。出于本教程的目的,我们将坚持使用更纯粹的方法。
完成后,您的函数应如下所示:
#include <字符串>
std::string getName(A3DEntity *ntt) {
标准::字符串名称;
A3DRootBaseData rbd;
A3D_INITIALIZE_DATA(A3DRootBaseData, rbd);
if ( A3D_SUCCESS == A3DRootBaseGet( ntt, &rbd ) ) {
名称 = rbd.m_pcName ?rbd.m_pcName : "" ;
}
A3DRootBaseGet( nullptr , &rbd);
返回名称;
}
打印名称
回到main,在模型文件加载成功后添加以下代码行。
std::cout << getName(model_file) << std::endl;
当我们迭代装配结构时,我们在这里编写的功能肯定会派上用场。
构建并运行
花点时间构建和运行您刚刚添加的代码。除了指示文件已加载的消息外,您现在应该看到模型文件对象的名称打印到标准输出。
遍历程序集
在本节中,您将了解负责在模型文件中表示装配结构的 Exchange 对象。您还将学习遍历结构的常用方法。
递归结构
在 HOOPS Exchange 中,用于表示装配结构中节点的对象类型是A3DAsmProductOccurrence. 模型文件包含一个或多个(但通常只有一个)“根节点”的集合,它们是产品的出现。
每个产品出现对象本身可以包含一个或多个节点的集合,这些节点也是产品出现对象。因此,我们有一个递归结构,用于表示模型文件中的装配层次结构。
除了可能拥有一个装配节点集合之外,产品引用还可以包含一个零件。
让我们利用所有先前奠定的基础来编写一个遍历装配结构并打印节点名称的递归函数。在 main 上方、下方创建以下函数getName。
无效遍历(A3DAsmProductOccurrence *po,int indent = 1){
if ( nullptr == po ) {
返回;
}
std::cout << std::string( 2*indent, ' ' ) << getName( po ) << std::endl;
A3DAsmProductOccurrenceData pd;
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, pd);
if ( A3D_SUCCESS == A3DAsmProductOccurrenceGet( po, &pd ) ) {
对于(A3DUns32 idx = 0u;idx < pd.m_uiPOccurrencesSize;++idx){
遍历(pd.m_ppPOOccurrences[idx],缩进 + 1);
}
}
A3DAsmProductOccurrenceGet( nullptr , &pd);
}
最后一步
现在有了这个函数,我们可以修改主函数体来使用它。回想一下,我们有一个模型文件对象,因此我们必须检索其内容并遍历根装配节点的集合。对于每个根节点,我们将调用 traverse。
A3DAsmModelFileData mfd;
A3D_INITIALIZE_DATA(A3DAsmModelFileData, mfd);
如果(A3D_SUCCESS == A3DAsmModelFileGet(模型文件,&mfd)){
对于(A3DUns32 idx = 0u;idx < mfd.m_uiPOccurrencesSize;++idx){
遍历(mfd.m_ppPOOccurrences[idx]);
}
}
A3DAsmModelFileGet( nullptr , &mfd);
构建并运行应用程序,看看我们已经完成了我们设定的目标。您的输出应如下所示:
准备启用。加载文件:X:/HOOPS_Exchange_2021_SP2_U2/samples/data/prc/__drill.prc __drill __drill ENGINE ENG_BLOCK_REAR ENG_BEARING ENG_BLOCK_FRONT ENG_BEARING CYLINDER BOLT_5-18<BOLT> BOLT_5-18<BOLT> BOLT_5-28<BOLT> BOLT_5-28<BOLT -28<螺栓>曲轴曲轴飞轮
结论
通过完成本教程,您已经学到了很多东西。您已经奠定了基础技能,这些技能在您使用 HOOPS Exchange 的过程中会很有用。
您拥有的完整代码应如下所示:
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <iostream>
#include <字符串>
std::string getName(A3DEntity *ntt) {
标准::字符串名称;
A3DRootBaseData rbd;
A3D_INITIALIZE_DATA(A3DRootBaseData, rbd);
if ( A3D_SUCCESS == A3DRootBaseGet( ntt, &rbd ) ) {
名称 = rbd.m_pcName ?rbd.m_pcName : "" ;
}
A3DRootBaseGet( nullptr , &rbd);
返回名称;
}
无效遍历(A3DAsmProductOccurrence *po,int indent = 1){
if ( nullptr == po ) {
返回;
}
std::cout << std::string( 2*indent, ' ' ) << getName( po ) << std::endl;
A3DAsmProductOccurrenceData pd;
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, pd);
if ( A3D_SUCCESS == A3DAsmProductOccurrenceGet( po, &pd ) ) {
对于(A3DUns32 idx = 0u;idx < pd.m_uiPOccurrencesSize;++idx){
遍历(pd.m_ppPOOccurrences[idx],缩进 + 1);
}
}
A3DAsmProductOccurrenceGet( nullptr , &pd);
}
int main(int,char **){
A3DSDKHOOPSExchangeLoader loader( "X:/HOOPS_Exchange_Publish_2021_SP2_U2/bin/win64_v140" );
如果(!loader.m_bSDKLoaded){
std::cerr << "无法加载 HOOPS Exchange。" << std::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg(loader.m_eSDKStatus) << std::endl;
返回-1;
}
std::cout << "准备使用。" << std::endl;
A3DRWParamsLoadData load_params;
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, load_params);
A3DAsmModelFile *model_file = nullptr ;
字符 常量*input_file =
"X:/HOOPS_Exchange_2021_SP2_U2/samples/data/prc/__drill.prc" ;
A3DStatus load_status = A3DAsmModelFileLoadFromFile( input_file, &load_params, &model_file );
如果(A3D_SUCCESS!= load_status){
std::cerr << "无法加载指定文件:" << input_file << std::endl;
std::cerr << "状态:" << A3DMiscGetErrorMsg( load_status ) << std::endl;
返回-1;
}其他{
std::cout << "加载的文件:" << input_file << std::endl;
}
std::cout << getName(model_file) << std::endl;
A3DAsmModelFileData mfd;
A3D_INITIALIZE_DATA(A3DAsmModelFileData, mfd);
如果(A3D_SUCCESS == A3DAsmModelFileGet(模型文件,&mfd)){
对于(A3DUns32 idx = 0u;idx < mfd.m_uiPOccurrencesSize;++idx){
遍历(mfd.m_ppPOOccurrences[idx]);
}
}
A3DAsmModelFileGet( nullptr , &mfd);
A3DAsmModelFileDelete(model_file);
model_file = nullptr ;
返回0;
}
了解HOOPS技术详情欢迎进入
慧都科技是中国地区的指定经销商,提供售卖、HOOPS 60天的免费试用、中文技术支持,同时提供工业3D解决方案,如果您对此感兴趣,欢迎电话咨询:023-68661681
↓ ↓ 关注“HOOPS技术”微信公众号,了解HOOPS技术的真实应用 ↓ ↓
标签:
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn