HOOPS Exchange是什么?
是一組軟件庫,可以幫助開發(fā)人員在開發(fā)應(yīng)用程序時讀取和寫入主流的 2D 和 3D 格式。HOOPS Exchange 支持在主流的3D 文件格式中讀取 CAD 數(shù)據(jù),并支持將 3D 數(shù)據(jù)轉(zhuǎn)換為 PRC 數(shù)據(jù)格式,這是一種高度可壓縮和開放的文件格式,并已通過國際標(biāo)準(zhǔn)化組織 (ISO 14739-1:2014) 的認(rèn)證。PRC 也是 Adobe PDF 中用于 3D 的格式之一。HOOPS Exchange 持續(xù)優(yōu)化讀取各種 3D 數(shù)據(jù)的功能,尤其是對于來自計算機輔助設(shè)計 (CAD) 系統(tǒng)的數(shù)據(jù)。
打印裝配結(jié)構(gòu)
學(xué)習(xí)創(chuàng)建一個使用 HOOPS Exchange 打印輸入文件的匯編結(jié)構(gòu)的基本應(yīng)用程序。
介紹
本教程將引導(dǎo)您使用 HOOPS Exchange 編寫控制臺應(yīng)用程序的基礎(chǔ)知識。完成本教程后,您應(yīng)該對該技術(shù)有足夠的了解,可以開始將 HOOPS Exchange 集成到您的應(yīng)用程序中。
本教程的先決條件是對 C/C++ 應(yīng)用程序開發(fā)有基本的了解。您應(yīng)該從配置為構(gòu)建和運行基本“hello world”示例應(yīng)用程序的 IDE 開始本教程。無需高級 CAD 專業(yè)知識或 GUI 開發(fā)技能。
完成的項目將加載指定的輸入文件并將程序集結(jié)構(gòu)打印到stdout.
使用 HOOPS Exchange 構(gòu)建
在本節(jié)中,您將學(xué)習(xí)如何將 HOOPS Exchange 添加到構(gòu)建系統(tǒng)中。
要使用 HOOPS Exchange 構(gòu)建,我們必須將包含文件夾添加到搜索路徑。在 macOS 和 Linux 上,我們還必須添加動態(tài)鏈接器庫“dl”。
添加包含文件夾
Windows 用戶應(yīng)在 Visual Studio 中編輯項目屬性,并在 C/C++ 窗格中添加包含文件夾。
如果您正在使用cmake,請編輯CMakeLists.txt以下行并將其添加到文件中:
包含目錄(/opt/ts3d/HOOPS_Exchange_Publish_2021_SP2_U2/include)
注意:參數(shù)應(yīng)指定您安裝 HOOPS Exchange 的位置。
添加動態(tài)鏈接器(僅限 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")
萬一()
構(gòu)建并運行
作為健全性檢查,請記住構(gòu)建并運行!
包括 HOOPS Exchange
在本節(jié)中,您將學(xué)習(xí)如何在源代碼中正確包含 HOOPS Exchange。
要使用 HOOPS Exchange API,您必須包含其標(biāo)頭。這個包羅萬象的標(biāo)題使您可以訪問整個工具包。在 IDE 的編輯器中打開main.cpp 。將以下行添加到文件頂部的第 1 行。
#include <A3DSDKIncludes.h>
添加此行后,如果您在上一節(jié)中正確指定了包含路徑,您應(yīng)該能夠構(gòu)建和運行。
要正確初始化 HOOPS Exchange,應(yīng)用程序中的一個編譯單元必須在包含上述標(biāo)頭之前聲明一個預(yù)處理器宏。通過添加此預(yù)處理器定義,您將啟用創(chuàng)建 API 本身的全局實例的代碼。在包含 Exchange 標(biāo)頭之前添加以下行。
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
請記住,這個預(yù)處理器定義應(yīng)該只存在于您的一個編譯單元中。如果多個編譯單元包含該定義,您將在鏈接時遇到重復(fù)的符號。由于我們的項目只包含一個編譯單元(main.cpp),這不會有問題,但是在將 HOOPS Exchange 集成到您自己的應(yīng)用程序中時,您應(yīng)該注意這一點。
現(xiàn)在可能是像以前一樣構(gòu)建和運行項目的好時機。
初始化 HOOPS Exchange
在本節(jié)中,您將學(xué)習(xí)如何初始化 HOOPS Exchange 庫。我們還將介紹用于在使用后將其拆除的功能。
加載庫
第一步是將動態(tài)庫加載到內(nèi)存中,并將所有 API 函數(shù)指針初始化為對應(yīng)的實現(xiàn)。聽起來很復(fù)雜,對吧?幸運的是,這是通過簡單地調(diào)用一個函數(shù)來完成的。在 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;
}
確保您指定為參數(shù)的路徑與您的安裝和平臺的細(xì)節(jié)相匹配。我們將信守承諾,在完成后卸載庫。輕松完成 - 只需在返回0之前添加此行。
A3DSDKUnloadLibrary();
返回0;
構(gòu)建并運行。
提供許可證
要解鎖 HOOPS Exchange 工具包,您必須使用許可證字符串。您的許可證字符串應(yīng)保密。您將使用的許可證字符串位于 HOOPS Exchange 包含文件夾中名為hoops_license.h的文件中。驗證它是否存在。
通過在文件頂部添加以下行來包含許可證文件頭。
#include <hoops_license.h>
使用 API 解鎖 HOOPS Exchange,方法是在您剛剛添加的庫加載功能之后添加以下代碼行。
A3DStatus常量license_status = A3DLicPutUnifiedLicense( HOOPS_LICENSE );
如果(A3D_SUCCESS!= license_status){
std::cerr << "無法授權(quán) HOOPS Exchange" << std::endl;
std::cerr << "狀態(tài):" << A3DMiscGetErrorMsg( license_status ) <<
標(biāo)準(zhǔn)::endl;
返回-1;
}其他{
std::cout << "已授權(quán)。" << std::endl;
}
如果您在卸載庫后意外添加了此代碼,您將遇到問題。HOOPS_LICENSE是包含在hoops_license.h中的預(yù)處理器定義。它是一個包含您的許可證密鑰的長字符串。
您現(xiàn)在可以通過按原樣運行代碼來驗證您的許可證是否存在并且處于良好的工作狀態(tài)。如果一切正常,您應(yīng)該會看到“許可”消息。在標(biāo)準(zhǔn)輸出上。
初始化 HOOPS Exchange
最后一步允許 HOOPS Exchange 執(zhí)行其內(nèi)部狀態(tài)的初始化。此外,此函數(shù)會檢查以確保您包含的 Exchange 標(biāo)頭中聲明的版本號與嵌入到動態(tài)庫中的版本號匹配。這是要添加的代碼行。
A3DStatus const init_status = A3DDllInitialize(A3D_DLL_MAJORVERSION, A3D_DLL_MINORVERSION);
如果(A3D_SUCCESS!= init_status){
std::cerr << "無法初始化 HOOPS Exchange。" << std::endl;
std::cerr << "狀態(tài):" << A3DMiscGetErrorMsg( init_status ) <<
標(biāo)準(zhǔn)::endl;
返回-1;
}其他{
std::cout << "準(zhǔn)備使用。" << std::endl;
}
// 這里使用交換
A3DDllTerminate();
A3DSDKUnloadLibrary();
返回0;
這就是它的全部。如果您覺得這太費力并且適合您的使用,您可以改用 class A3DSDKHOOPSExchangeLoader。它在內(nèi)部實現(xiàn)了所有這些功能。唯一需要注意的是,您聲明的對象的生命周期必須匹配或超過您對任何 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 << "狀態(tài):" << A3DMiscGetErrorMsg(loader.m_eSDKStatus) <<
標(biāo)準(zhǔn)::endl;
返回-1;
}
std::cout << "準(zhǔn)備使用。" << std::endl;
返回0;
}
這更容易。請記住要小心管理加載器對象的生命周期。對于本教程,我們可以堅持使用更簡單的實現(xiàn)。在 macOS 和 Linux 上,去掉參數(shù)前面的“L”。
現(xiàn)在您了解了 HOOPS Exchange 是如何初始化的。如果出現(xiàn)問題,您可以很好地找出原因。
加載文件
在本節(jié)中,您將學(xué)習(xí)使用 HOOPS Exchange 加載文件的最基本方法。為了實現(xiàn)這個目標(biāo),您將首先聲明和初始化加載選項。加載選項由加載 API 使用,該 API 返回加載文件的句柄。
配置加載選項
我們將用于加載輸入文件的 API 接受一個控制其行為的選項結(jié)構(gòu)。由于目標(biāo)是簡單地加載文件并打印程序集結(jié)構(gòu),因此默認(rèn)選項就可以了。
聲明選項結(jié)構(gòu)并使用以下代碼對其進(jìn)行初始化。稍后我們將更詳細(xì)地描述此代碼。
A3DRWParamsLoadData load_params;
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, load_params);
接下來,我們需要一個變量來保存生成的模型文件句柄。
A3DAsmModelFile *model_file = nullptr ;
這聲明了一個不透明的句柄,用于引用與您剛剛加載的文件關(guān)聯(lián)的數(shù)據(jù)。您將很快了解如何訪問數(shù)據(jù)。
最后,我們可以調(diào)用加載文件的 Exchange 函數(shù)。請注意此處輸入文件的硬編碼文件路徑。您至少應(yīng)該將其更改為您的安裝路徑,但您可以將其指向您想要的任何文件,前提是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 <<
標(biāo)準(zhǔn)::endl;
std::cerr << "狀態(tài):" << A3DMiscGetErrorMsg( load_status ) <<
標(biāo)準(zhǔn)::endl;
返回-1;
}其他{
std::cout << "加載的文件:" << input_file << std::endl;
}
讓我們成為好公民,并為自己打掃衛(wèi)生。假設(shè)模型文件有一些用途,當(dāng)我們完成后,應(yīng)該在程序退出之前清理它。
A3DAsmModelFileDelete(model_file);
model_file = nullptr ;
返回0;
當(dāng)您構(gòu)建并運行此時擁有的代碼時,您將擁有代碼并了解如何使用 HOOPS Exchange 工具包加載任何受支持的文件格式。您應(yīng)該會看到一條寫入標(biāo)準(zhǔn)輸出的消息,聲明已加載失敗。
獲取 HOOPS Exchange 實體的名稱
在本節(jié)中,您將學(xué)習(xí)如何從 HOOPS Exchange API 中提取數(shù)據(jù),以便在您的應(yīng)用程序中使用它。您還將了解從 Exchange 檢索所有數(shù)據(jù)的基本使用模式。
讓我們將模型文件對象的名稱打印到stdout. 在 main 之上創(chuàng)建一個函數(shù),如下所示:
#include <字符串>
std::string getName(A3DEntity *ntt) {
返回std::string();
}
A3DEntity是一種通用句柄類型,可用于引用 Exchange 中的任何對象。我們將使用這樣一個事實,即 Exchange 中的每個對象都有一組可通過 A3DRootBase 接口獲得的通用基礎(chǔ)數(shù)據(jù)。
聲明并初始化存儲
HOOPS Exchange 使用 C 風(fēng)格的結(jié)構(gòu)來讀取(和寫入)其內(nèi)部數(shù)據(jù)表示。在我們讀取數(shù)據(jù)之前,我們必須聲明一個適當(dāng)類型的結(jié)構(gòu)來保存結(jié)果。該結(jié)構(gòu)必須在使用之前使用宏進(jìn)行初始化。在其他可能的事情中,初始化宏設(shè)置m_usStructSize字段,作為內(nèi)部檢查。在剛剛存根的函數(shù)中,添加以下代碼行。
標(biāo)準(zhǔn)::字符串名稱;
A3DRootBaseData rbd;
A3D_INITIALIZE_DATA(A3DRootBaseData, rbd);
讀取數(shù)據(jù)
使用 HOOPS Exchange API 時,遵循的模式很普遍。每當(dāng)您讀取數(shù)據(jù)時,您必須確保進(jìn)行相應(yīng)的調(diào)用以釋放它。這種模式看起來像這樣。
if ( A3D_SUCCESS == A3DRootBaseGet( ntt, &rbd ) ) {
名稱 = rbd.m_pcName ?rbd.m_pcName : "" ;
A3DRootBaseGet( nullptr , &rbd);
您可以通過此處找到的包裝器對象避免初始化和使用模式。出于本教程的目的,我們將堅持使用更純粹的方法。
完成后,您的函數(shù)應(yīng)如下所示:
#include <字符串>
std::string getName(A3DEntity *ntt) {
標(biāo)準(zhǔn)::字符串名稱;
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;
當(dāng)我們迭代裝配結(jié)構(gòu)時,我們在這里編寫的功能肯定會派上用場。
構(gòu)建并運行
花點時間構(gòu)建和運行您剛剛添加的代碼。除了指示文件已加載的消息外,您現(xiàn)在應(yīng)該看到模型文件對象的名稱打印到標(biāo)準(zhǔn)輸出。
遍歷程序集
在本節(jié)中,您將了解負(fù)責(zé)在模型文件中表示裝配結(jié)構(gòu)的 Exchange 對象。您還將學(xué)習(xí)遍歷結(jié)構(gòu)的常用方法。
遞歸結(jié)構(gòu)
在 HOOPS Exchange 中,用于表示裝配結(jié)構(gòu)中節(jié)點的對象類型是A3DAsmProductOccurrence. 模型文件包含一個或多個(但通常只有一個)“根節(jié)點”的集合,它們是產(chǎn)品的出現(xiàn)。
每個產(chǎn)品出現(xiàn)對象本身可以包含一個或多個節(jié)點的集合,這些節(jié)點也是產(chǎn)品出現(xiàn)對象。因此,我們有一個遞歸結(jié)構(gòu),用于表示模型文件中的裝配層次結(jié)構(gòu)。
除了可能擁有一個裝配節(jié)點集合之外,產(chǎn)品引用還可以包含一個零件。
讓我們利用所有先前奠定的基礎(chǔ)來編寫一個遍歷裝配結(jié)構(gòu)并打印節(jié)點名稱的遞歸函數(shù)。在 main 上方、下方創(chuàng)建以下函數(shù)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],縮進(jìn) + 1);
}
}
A3DAsmProductOccurrenceGet( nullptr , &pd);
}
最后一步
現(xiàn)在有了這個函數(shù),我們可以修改主函數(shù)體來使用它。回想一下,我們有一個模型文件對象,因此我們必須檢索其內(nèi)容并遍歷根裝配節(jié)點的集合。對于每個根節(jié)點,我們將調(diào)用 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);
構(gòu)建并運行應(yīng)用程序,看看我們已經(jīng)完成了我們設(shè)定的目標(biāo)。您的輸出應(yīng)如下所示:
準(zhǔn)備啟用。加載文件: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<螺栓>曲軸曲軸飛輪
結(jié)論
通過完成本教程,您已經(jīng)學(xué)到了很多東西。您已經(jīng)奠定了基礎(chǔ)技能,這些技能在您使用 HOOPS Exchange 的過程中會很有用。
您擁有的完整代碼應(yīng)如下所示:
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <iostream>
#include <字符串>
std::string getName(A3DEntity *ntt) {
標(biāo)準(zhǔn)::字符串名稱;
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],縮進(jìn) + 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 << "狀態(tài):" << A3DMiscGetErrorMsg(loader.m_eSDKStatus) << std::endl;
返回-1;
}
std::cout << "準(zhǔn)備使用。" << 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 << "狀態(tài):" << 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技術(shù)詳情歡迎進(jìn)入
慧都科技是中國地區(qū)的指定經(jīng)銷商,提供售賣、HOOPS 60天的免費試用、中文技術(shù)支持,同時提供工業(yè)3D解決方案,如果您對此感興趣,歡迎電話咨詢:023-68661681
↓ ↓ 關(guān)注“HOOPS技術(shù)”微信公眾號,了解HOOPS技術(shù)的真實應(yīng)用 ↓ ↓
標(biāo)簽:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@ke049m.cn