Files
2025-12-15 23:22:33 +08:00

464 lines
16 KiB
C++

/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
/**
\file CascadedAttributes.cpp
This file demonstrates how to programmatically set the mechanism of the cascaded attributes using HOOPS Exchange.
***********************************************************************************************************************/
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <hoops_license.h>
#include "../common.hpp"
//######################################################################################################################
struct MiscCascadedAttributesGuard
{
A3DMiscCascadedAttributes* ptr_;
MiscCascadedAttributesGuard(A3DMiscCascadedAttributes* ptr): ptr_(ptr)
{}
~MiscCascadedAttributesGuard()
{
TEST_RET(A3DMiscCascadedAttributesDelete(ptr_))
ptr_ = NULL;
}
};
//######################################################################################################################
static A3DUTF8Char stpcWinTitle[_MAX_PATH];
//######################################################################################################################
/*! Given an A3DRootBaseWithGraphics*, will return the name of that entity in the out parameter m_ppcName.
*/
A3DStatus stGetName(
const A3DRootBaseWithGraphics* pPartOrProduct,
A3DUTF8Char** m_ppcName)
{
A3DRootBaseData sRootBaseData;
A3D_INITIALIZE_DATA(A3DRootBaseData, sRootBaseData);
CHECK_RET(A3DRootBaseGet(pPartOrProduct, &sRootBaseData));
const DATAGUARD(A3DRootBase) sGuard(sRootBaseData, A3DRootBaseGet);
if (sRootBaseData.m_pcName != NULL)
{
*m_ppcName = static_cast<A3DUTF8Char*>(malloc(strlen(sRootBaseData.m_pcName) + 1));
strncpy(*m_ppcName, sRootBaseData.m_pcName, strlen(sRootBaseData.m_pcName));
(*m_ppcName)[strlen(sRootBaseData.m_pcName)] = '\0';
}
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Gets the color values for a A3DRootBaseWithGraphics, then prints it to the console.
*/
A3DStatus stExtractColorFromGraphicData(
const A3DRootBaseWithGraphics* pRootBaseWithGraphics,
const A3DGraphStyleData& sGraphStyleData)
{
// Get its name
A3DUTF8Char* pcName = NULL;
const A3DStatus iRet = stGetName(pRootBaseWithGraphics, &pcName);
const MemoryGuard sGuard(pcName);
CHECK_RET(iRet);
// First get non-inherited color information
A3DRootBaseWithGraphicsData rbwgData;
A3D_INITIALIZE_DATA(A3DRootBaseWithGraphicsData, rbwgData);
A3DRootBaseWithGraphicsGet(pRootBaseWithGraphics, &rbwgData);
if (rbwgData.m_pGraphics != NULL)
{
// this entity has an attached graphics object
A3DGraphicsData graphicsData;
A3D_INITIALIZE_DATA(A3DGraphicsData, graphicsData);
A3DGraphicsGet(rbwgData.m_pGraphics, &graphicsData);
A3DGraphStyleData styleData;
A3D_INITIALIZE_DATA(A3DGraphStyleData, styleData);
A3DGlobalGetGraphStyleData(graphicsData.m_uiStyleIndex, &styleData);
A3DGraphRgbColorData sColorData;
A3D_INITIALIZE_DATA(A3DGraphRgbColorData, sColorData);
if (!sGraphStyleData.m_bMaterial)
{
if (A3DGlobalGetGraphRgbColorData(styleData.m_uiRgbColorIndex, &sColorData) == A3D_SUCCESS)
{
fprintf(
GetLogFile(),
"\tcolor without inheritance of %s: %f %f %f\n",
pcName,
sColorData.m_dRed,
sColorData.m_dGreen,
sColorData.m_dBlue);
}
A3DGlobalGetGraphRgbColorData(A3D_DEFAULT_COLOR_INDEX, &sColorData);
}
else
{
fprintf(
GetLogFile(),
"\t local material of %s: %u\n",
pcName,
sGraphStyleData.m_uiRgbColorIndex
);
}
A3DGlobalGetGraphStyleData(A3D_DEFAULT_STYLE_INDEX, &styleData);
A3DGraphicsGet(NULL, &graphicsData);
}
// Then get inherited color information
if (!sGraphStyleData.m_bMaterial)
{
A3DGraphRgbColorData sColorData;
A3D_INITIALIZE_DATA(A3DGraphRgbColorData, sColorData);
if (A3DGlobalGetGraphRgbColorData(sGraphStyleData.m_uiRgbColorIndex, &sColorData) == A3D_SUCCESS)
{
fprintf(
GetLogFile(),
"\tcolor with inheritance of %s: %f %f %f\n",
pcName,
sColorData.m_dRed,
sColorData.m_dGreen,
sColorData.m_dBlue);
}
A3DGlobalGetGraphRgbColorData(A3D_DEFAULT_COLOR_INDEX, &sColorData);
}
else
{
fprintf(
GetLogFile(),
"\t inheritance material of %s: %u\n",
pcName,
sGraphStyleData.m_uiRgbColorIndex
);
}
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Creates an A3DMiscCascadedAttributes structure and computes the attributes
* based on the input A3DRootBaseWithGraphics structure pBase.
*/
static A3DStatus stCreateAndPushCascadedAttributes(
const A3DRootBaseWithGraphics* pBase,
const A3DMiscCascadedAttributes* pFatherAttr,
A3DMiscCascadedAttributes** ppAttr,
A3DMiscCascadedAttributesData* psAttrData)
{
CHECK_RET(A3DMiscCascadedAttributesCreate(ppAttr));
CHECK_RET(A3DMiscCascadedAttributesPush(*ppAttr, pBase, pFatherAttr));
A3D_INITIALIZE_DATA(A3DMiscCascadedAttributesData, (*psAttrData));
CHECK_RET(A3DMiscCascadedAttributesGet(*ppAttr, psAttrData));
CHECK_RET(stExtractColorFromGraphicData(pBase, psAttrData->m_sStyle));
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Parses a face, then computes cascaded attributes for that face.
*/
static A3DStatus stParseFace(
const A3DTopoFace* pFace,
const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Face level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
CHECK_RET(stCreateAndPushCascadedAttributes(pFace, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Parses a shell, then calls stParseFace for each face found in the shell.
*/
static A3DStatus stParseShell(const A3DTopoShell* pShell, const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Shell level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
CHECK_RET(stCreateAndPushCascadedAttributes(pShell, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
A3DTopoShellData sTopoShellData;
A3D_INITIALIZE_DATA(A3DTopoShellData, sTopoShellData);
CHECK_RET(A3DTopoShellGet(pShell, &sTopoShellData));
const DATAGUARD(A3DTopoShell) sGuard(sTopoShellData, A3DTopoShellGet);
for (unsigned int ui = 0; ui < sTopoShellData.m_uiFaceSize; ++ui)
CHECK_RET(stParseFace(sTopoShellData.m_ppFaces[ui], pAttr));
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Parses a connex, then calls stParseShell for each shell found in the connex.
*/
static A3DStatus stParseConnex(
const A3DTopoConnex* pConnex,
const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Connex level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
CHECK_RET(stCreateAndPushCascadedAttributes(pConnex, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
A3DTopoConnexData sTopoConnexData;
A3D_INITIALIZE_DATA(A3DTopoConnexData, sTopoConnexData);
CHECK_RET(A3DTopoConnexGet(pConnex, &sTopoConnexData));
const DATAGUARD(A3DTopoConnex) sGuard(sTopoConnexData, A3DTopoConnexGet);
for (unsigned int ui = 0; ui < sTopoConnexData.m_uiShellSize; ++ui)
CHECK_RET(stParseShell(sTopoConnexData.m_ppShells[ui], pAttr));
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Parses a representation item and computes cascaded attributes for it.
* Calls stParseConnex for each connex in this representation item.
*/
static A3DStatus stParseRepresentationItem(
const A3DRiRepresentationItem* pRepItem,
const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Representation item level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
// Compute the cascaded attributes for this representation item
CHECK_RET(stCreateAndPushCascadedAttributes(pRepItem, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
A3DEEntityType eType = kA3DTypeUnknown;
CHECK_RET(A3DEntityGetType(pRepItem, &eType));
if(eType == kA3DTypeRiBrepModel)
{
const A3DRiBrepModel* pBrepModel = static_cast<const A3DRiBrepModel*>(pRepItem);
A3DRiBrepModelData sBrepModelData;
A3D_INITIALIZE_DATA(A3DRiBrepModelData, sBrepModelData);
CHECK_RET(A3DRiBrepModelGet(pBrepModel, &sBrepModelData));
const DATAGUARD(A3DRiBrepModel) sGuard1(sBrepModelData, A3DRiBrepModelGet);
A3DTopoBrepDataData sTopoBrepDataData;
A3D_INITIALIZE_DATA(A3DTopoBrepDataData, sTopoBrepDataData);
CHECK_RET(A3DTopoBrepDataGet(sBrepModelData.m_pBrepData, &sTopoBrepDataData));
const DATAGUARD(A3DTopoBrepData) sGuard2(sTopoBrepDataData, A3DTopoBrepDataGet);
for (unsigned int ui = 0; ui < sTopoBrepDataData.m_uiConnexSize; ++ui)
CHECK_RET(stParseConnex(sTopoBrepDataData.m_ppConnexes[ui], pAttr));
}
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Iterates over all the representation items in the part pPart, and calls
* stParseRepresentationItem on each one.
*/
static A3DStatus stParsePartDefinition(
const A3DAsmPartDefinition* pPart,
const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Part definition level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
CHECK_RET(stCreateAndPushCascadedAttributes(pPart, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
A3DAsmPartDefinitionData sPartData;
A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, sPartData);
CHECK_RET(A3DAsmPartDefinitionGet(pPart, &sPartData));
const DATAGUARD(A3DAsmPartDefinition) sGuard(sPartData, A3DAsmPartDefinitionGet);
for (unsigned int ui = 0; ui < sPartData.m_uiRepItemsSize; ++ui)
CHECK_RET(stParseRepresentationItem(sPartData.m_ppRepItems[ui], pAttr));
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Returns a part definition from a product occurrence. Part definition is returned as
* the out parameter ppPart.
*/
static A3DStatus stProductOccurrenceGetPart(
const A3DAsmProductOccurrenceData* psPOccData,
A3DAsmPartDefinition** ppPart)
{
if(psPOccData == NULL)
return A3D_ERROR;
*ppPart = NULL;
if(psPOccData->m_pPart != NULL)
{
*ppPart = psPOccData->m_pPart;
return A3D_SUCCESS;
}
A3DAsmProductOccurrence* pProductPrototype = psPOccData->m_pPrototype;
while(pProductPrototype != NULL)
{
A3DAsmProductOccurrenceData sProductPrototypeData;
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sProductPrototypeData);
CHECK_RET(A3DAsmProductOccurrenceGet(pProductPrototype, &sProductPrototypeData));
const DATAGUARD(A3DAsmProductOccurrence) sGuard(sProductPrototypeData, A3DAsmProductOccurrenceGet);
if(sProductPrototypeData.m_pPart != NULL)
{
*ppPart = sProductPrototypeData.m_pPart;
return A3D_SUCCESS;
}
else
pProductPrototype = sProductPrototypeData.m_pPrototype;
}
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Parses a product occurrence recursively. When a part
* definition is found, it is then passed to stParsePartDefinition.
*/
static A3DStatus stParseProductOccurrence(
const A3DAsmProductOccurrence* pOccurrence,
const A3DMiscCascadedAttributes* pFatherAttr)
{
PrintConstLogMessage("Product Occurrence level\n");
A3DMiscCascadedAttributes* pAttr;
A3DMiscCascadedAttributesData sAttrData;
CHECK_RET(stCreateAndPushCascadedAttributes(pOccurrence, pFatherAttr, &pAttr, &sAttrData));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
A3DAsmProductOccurrenceData sData;
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sData);
CHECK_RET(A3DAsmProductOccurrenceGet(pOccurrence, &sData));
const DATAGUARD(A3DAsmProductOccurrence) sGuard(sData, A3DAsmProductOccurrenceGet);
A3DAsmPartDefinition* pPart = NULL;
TEST_RET(stProductOccurrenceGetPart(&sData, &pPart));
if (pPart)
CHECK_RET(stParsePartDefinition(pPart, pAttr));
if (sData.m_uiPOccurrencesSize > 0)
{
for (unsigned int ui = 0; ui < sData.m_uiPOccurrencesSize; ui++)
{
CHECK_RET(stParseProductOccurrence(sData.m_ppPOccurrences[ui], pAttr));
}
}
return A3D_SUCCESS;
}
//######################################################################################################################
/*! Calls stParseProductOccurrence for each product occurrence in the input parameter pModelFile.
*/
A3DStatus stParseCascadedAttributes(const A3DAsmModelFile* pModelFile)
{
// allocate model file structure
A3DAsmModelFileData sData;
A3D_INITIALIZE_DATA(A3DAsmModelFileData, sData);
CHECK_RET(A3DAsmModelFileGet(pModelFile, &sData));
const DATAGUARD(A3DAsmModelFile) sGuard(sData, A3DAsmModelFileGet);
// allocate cascaded attributes
A3DMiscCascadedAttributes* pAttr;
CHECK_RET(A3DMiscCascadedAttributesCreate(&pAttr));
const MiscCascadedAttributesGuard sMCAttrGuard(pAttr);
for (A3DUns32 ui = 0; ui < sData.m_uiPOccurrencesSize; ++ui)
// traverse the model tree
CHECK_RET(stParseProductOccurrence(sData.m_ppPOccurrences[ui], pAttr));
return A3D_SUCCESS;
}
static MY_CHAR acSrcFileName[_MAX_PATH * 2];
static MY_CHAR acLogFileName[_MAX_PATH * 2];
//######################################################################################################################
// Main function
#ifdef _MSC_VER
int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv)
#else
int main(A3DInt32 iArgc, A3DUTF8Char** ppcArgv)
#endif
{
//
// ### COMMAND LINE ARGUMENTS
//
if (iArgc > 3)
{
MY_PRINTF2("Usage:\n %s [input CAD file] [output LOG file]\n", ppcArgv[0]);
MY_PRINTF(" Default output LOG file is [input CAD file]_Log.txt\n\n");
return A3D_ERROR;
}
if (iArgc > 1) MY_STRCPY(acSrcFileName, ppcArgv[1]);
else MY_STRCPY(acSrcFileName, DEFAULT_INPUT_CAD);
if (iArgc > 2) MY_STRCPY(acLogFileName, ppcArgv[2]);
else MY_SPRINTF(acLogFileName, "%s_Log.txt", acSrcFileName);
GetLogFile(acLogFileName); // Initialize log file
//
// ### INITIALIZE HOOPS EXCHANGE
//
A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY), HOOPS_LICENSE);
CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus);
CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError));
//
// ### PROCESS SAMPLE CODE
//
// Initialize importer
A3DImport sImport(acSrcFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters
A3DStatus iRet = sHoopsExchangeLoader.Import(sImport);
if (iRet != A3D_SUCCESS && iRet != A3D_LOAD_MISSING_COMPONENTS)
CHECK_RET(iRet);
// Parse model for cascaded attributes
CHECK_RET(stParseCascadedAttributes(sHoopsExchangeLoader.m_psModelFile));
//
// ### TERMINATE HOOPS EXCHANGE
//
// Check memory allocations
// Check memory allocations
return (int)ListLeaks();
}