Files
Hoops_Exchange/exchange/exchangesource/CreatePRCBrepWithGeometry/CreatePRCBrepWithGeometry.cpp
2025-12-15 23:22:33 +08:00

480 lines
14 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 CreatePRCBrepWithGeometry.cpp
This file demonstrates how to programmatically create a PRC file using HOOPS Exchange.
The only input is the file path where the program will write the output PRC file.
The program generates a PRC file which contains a warped circle with a thick edge.
***********************************************************************************************************************/
#define _CRT_SECURE_NO_DEPRECATE 1
#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
#define INITIALIZE_A3D_API
#include <A3DSDKIncludes.h>
#include <hoops_license.h>
#include "../common.hpp"
//######################################################################################################################
/*! Creates a surface based on the parameters supplied to m_sUVDomain
*/
A3DSurfCylinder* stCreateSurface()
{
A3DSurfCylinderData sData;
A3D_INITIALIZE_DATA(A3DSurfCylinderData, sData);
sData.m_dRadius = 10.0;
// A 40 mm high closed cylinder (360°)
// Make the cylinder parameterized between -1 and +1 in both directions ((0, 0) is the center)
// The sUVDomain indicates the domain you want to use
// Coefficients have to be set so that computed parameters are defined
// inside classical parameterization for cylinders [0.0, 360.0]
sData.m_sParam.m_sUVDomain.m_sMin.m_dX = -1.0;
sData.m_sParam.m_sUVDomain.m_sMin.m_dY = -1.0;
sData.m_sParam.m_sUVDomain.m_sMax.m_dX = 1.0;
sData.m_sParam.m_sUVDomain.m_sMax.m_dY = 1.0;
A3DDouble dX = sData.m_sParam.m_sUVDomain.m_sMax.m_dX - sData.m_sParam.m_sUVDomain.m_sMin.m_dX;
sData.m_sParam.m_dUCoeffA = 2*M_PI/dX;
sData.m_sParam.m_dUCoeffB = 0;
sData.m_sParam.m_dVCoeffA = 20;
sData.m_sParam.m_dVCoeffB = 0;
sData.m_sParam.m_bSwapUV = false;
sData.m_sTrsf.m_ucBehaviour = kA3DTransformationIdentity;
A3DSurfCylinder* pp = NULL;
A3DSurfCylinderCreate(&sData, &pp);
return pp;
}
//######################################################################################################################
/*! Creates a NURBS circle.
*/
A3DCrvNurbs* stCreateCircle(A3DDouble radius)
{
A3DCrvNurbsData sData;
A3D_INITIALIZE_DATA(A3DCrvNurbsData, sData);
double dSqrt2_2 = sqrt(2.0) / 2.0;
/****************************************************************************
Definition of a NURBS representing a circle in the parametric space:
Radius must be comprised between 0 and 1
Degree = 2, Dimension = 2
9 control points (first and last are identical)
9 weights
12 knots
3 |2 1
+--------+--------+
| | |
| | |
4| | |0
--+--------+--------+--
| | |8
| | |
| | |
+--------+--------+
5 6 7
****************************************************************************/
double adCtrlPoints[18] =
{
1.0, 0.0, // 0
1.0, 1.0, // 1
0.0, 1.0, // 2
-1.0, 1.0, // 3
-1.0, 0.0, // 4
-1.0, -1.0, // 5
0.0, -1.0, // 6
1.0, -1.0, // 7
1.0, 0.0 // 8
};
double adWeights[9] =
{
1.0, // 0
dSqrt2_2, // 1
1.0, // 2
dSqrt2_2, // 3
1.0, // 4
dSqrt2_2, // 5
1.0, // 6
dSqrt2_2, // 7
1.0 // 8
};
double adKnots[12] =
{
0.0, 0.0, 0.0,
0.25, 0.25,
0.50, 0.50,
0.75, 0.75,
1.00, 1.00, 1.00
};
A3DVector3dData asControlPoints[9];
A3DInt32 i;
for(i = 0; i < 9; ++i)
A3D_INITIALIZE_DATA(A3DVector3dData, asControlPoints[i]);
for(i = 0; i < 9; ++i)
{
asControlPoints[i].m_dX = adCtrlPoints[i * 2] * radius;
asControlPoints[i].m_dY = adCtrlPoints[i * 2 + 1] * radius;
asControlPoints[i].m_dZ = 0;
}
sData.m_bIs2D = 2;
sData.m_bRational = true;
sData.m_uiDegree = 2;
sData.m_uiCtrlSize = 9;
sData.m_pCtrlPts = asControlPoints;
sData.m_uiWeightSize = 9;
sData.m_pdWeights = adWeights;
sData.m_uiKnotSize = 12;
sData.m_pdKnots = adKnots;
sData.m_eCurveForm = kA3DBSplineCurveFormCircularArc;
sData.m_eKnotType = kA3DKnotTypeUnspecified;
A3DCrvNurbs* pp = NULL;
A3DCrvNurbsCreate(&sData, &pp);
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoEdge based on topo edges created from A3DTopoEdgeCreate.
*/
A3DTopoEdge* stCreateTopoEdge()
{
A3DTopoEdgeData sData;
A3D_INITIALIZE_DATA(A3DTopoEdgeData, sData);
A3DTopoEdge* pp = NULL;
A3DTopoEdgeCreate(&sData, &pp);
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoCoEdge based on data returned from stCreateTopoEdge().
*/
A3DTopoCoEdge* stCreateTopoCoEdge(A3DCrvBase* p)
{
A3DTopoCoEdge* pp = NULL;
A3DTopoCoEdge* q = stCreateTopoEdge();
if(p != NULL && q != NULL)
{
A3DTopoCoEdgeData sData;
A3D_INITIALIZE_DATA(A3DTopoCoEdgeData, sData);
sData.m_pUVCurve = p;
sData.m_pEdge = q;
sData.m_ucOrientationWithLoop = 1;
sData.m_ucOrientationUVWithLoop = 1;
A3DTopoCoEdgeCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoLoop based on data returned from stCreateCircle() and stCreateTopoCoEdge().
*/
A3DTopoLoop* stCreateTopoLoop(A3DDouble radius)
{
A3DTopoLoopData sData;
A3D_INITIALIZE_DATA(A3DTopoLoopData, sData);
A3DCrvBase* p = stCreateCircle(radius);
A3DTopoCoEdge* q = stCreateTopoCoEdge(p);
sData.m_ppCoEdges = &q;
sData.m_uiCoEdgeSize = 1;
sData.m_ucOrientationWithSurface = 1;
A3DTopoLoop* pp = NULL;
A3DTopoLoopCreate(&sData, &pp);
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoFace and creates a surface from stCreateSurface().
*/
A3DTopoFace* stCreateTopoFace()
{
A3DDouble outerradius = 0.5;
A3DDouble innerradius = 0.4;
A3DTopoLoop* loops[2];
loops[0] = stCreateTopoLoop(outerradius);
loops[1] = stCreateTopoLoop(innerradius);
A3DTopoFaceData sData;
A3D_INITIALIZE_DATA(A3DTopoFaceData, sData);
sData.m_pSurface = stCreateSurface();
sData.m_ppLoops = loops;
sData.m_uiLoopSize = 2;
sData.m_uiOuterLoopIndex = 0;
A3DTopoFace* pp = NULL;
A3DTopoFaceCreate(&sData, &pp);
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoShell and populates it with an A3DTopoFace from stCreateTopoFace().
*/
A3DTopoShell* stCreateTopoShell()
{
A3DTopoShell* pp = NULL;
A3DTopoFace* p = stCreateTopoFace();
if(p != NULL)
{
A3DTopoShellData sData;
A3D_INITIALIZE_DATA(A3DTopoShellData, sData);
A3DUns8 orient = 1;
sData.m_bClosed = false;
sData.m_ppFaces = &p;
sData.m_uiFaceSize = 1;
sData.m_pucOrientationWithShell = &orient;
A3DTopoShellCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoConnex and populates it with an A3DTopoShell from A3DTopoConnexCreate().
*/
A3DTopoConnex* stCreateTopoConnex()
{
A3DTopoConnex* pp = NULL;
A3DTopoShell* p = stCreateTopoShell();
if(p != NULL)
{
A3DTopoConnexData sData;
A3D_INITIALIZE_DATA(A3DTopoConnexData, sData);
sData.m_ppShells = &p;
sData.m_uiShellSize = 1;
A3DTopoConnexCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates an A3DTopoBrepData and populates it with an A3DTopoConnex from stCreateTopoConnex().
*/
A3DTopoBrepData* stCreateTopoBrep()
{
A3DTopoBrepData* pp = NULL;
A3DTopoConnex* p = stCreateTopoConnex();
if(p != NULL)
{
A3DTopoBrepDataData sData;
A3D_INITIALIZE_DATA(A3DTopoBrepDataData, sData);
sData.m_ppConnexes = &p;
sData.m_uiConnexSize = 1;
A3DTopoBrepDataCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates a representation item and populates it with an A3DTopoBrepData from stCreateTopoBrep().
*/
A3DRiRepresentationItem* stCreateRIBrep()
{
A3DRiBrepModel* pp = NULL;
A3DTopoBrepData* p = stCreateTopoBrep();
if(p != NULL)
{
A3DRiBrepModelData sData;
A3D_INITIALIZE_DATA(A3DRiBrepModelData, sData);
sData.m_pBrepData = p;
sData.m_bSolid = false;
A3DRiBrepModelCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates a part definition and populates it with a representation item from stCreateRIBrep().
*/
A3DAsmPartDefinition* stCreatePart()
{
A3DAsmPartDefinition* pp = NULL;
A3DRiRepresentationItem* p = stCreateRIBrep();
if(p != NULL)
{
A3DAsmPartDefinitionData sData;
A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, sData);
sData.m_uiRepItemsSize = 1;
sData.m_ppRepItems = &p;
A3DAsmPartDefinitionCreate(&sData, &pp);
}
return pp;
}
//######################################################################################################################
/*! Creates attributes for the entity parameter p, then assigns the attributes to p.
*/
A3DVoid stSetAttributes(A3DEntity* p)
{
A3DMiscAttribute* pAttr[3];
A3DMiscSingleAttributeData Single;
A3D_INITIALIZE_DATA(A3DMiscSingleAttributeData, Single);
Single.m_eType = kA3DModellerAttributeTypeString;
Single.m_pcTitle = (char*) "Title";
Single.m_pcData = (char*) "Simple B-rep building demonstration";
A3DMiscAttributeData sAttribs;
A3D_INITIALIZE_DATA(A3DMiscAttributeData, sAttribs);
sAttribs.m_pcTitle = Single.m_pcTitle;
sAttribs.m_asSingleAttributesData = &Single;
sAttribs.m_uiSize = 1;
A3DMiscAttributeCreate(&sAttribs, &pAttr[0]);
Single.m_pcTitle = (char*) "Author";
Single.m_pcData = (char*) "HOOPS Exchange";
sAttribs.m_pcTitle = Single.m_pcTitle;
A3DMiscAttributeCreate(&sAttribs, &pAttr[1]);
Single.m_pcTitle = (char*) "Company";
Single.m_pcData = (char*) "Tech Soft 3D";
sAttribs.m_pcTitle = Single.m_pcTitle;
A3DMiscAttributeCreate(&sAttribs, &pAttr[2]);
A3DRootBaseData sRootData;
A3D_INITIALIZE_DATA(A3DRootBaseData, sRootData);
sRootData.m_pcName = (char*) "Trimmed surface";
sRootData.m_ppAttributes = pAttr;
sRootData.m_uiSize = 3;
A3DRootBaseSet(p, &sRootData);
// cleaning up the allocated attributes
for(A3DUns32 i = 0; i < sRootData.m_uiSize; ++i)
A3DEntityDelete(sRootData.m_ppAttributes[i]);
}
//######################################################################################################################
/*! Creates the product occurrence and populates it with the part definition created by stCreatePart.
*/
A3DAsmProductOccurrence* stCreateOccurrence()
{
A3DAsmProductOccurrence* pp = NULL;
A3DAsmPartDefinition* p = stCreatePart();
if(p != NULL)
{
A3DAsmProductOccurrenceData sData;
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, sData);
sData.m_pPart = p;
A3DInt32 iRet = A3DAsmProductOccurrenceCreate(&sData, &pp);
if(iRet == A3D_SUCCESS)
stSetAttributes(pp);
}
return pp;
}
//######################################################################################################################
/*! Create model file structure, build the model, and return the model file
*/
A3DAsmModelFile* stCreateModel()
{
// Create the product occurrence
A3DAsmModelFile* pp = NULL;
A3DAsmProductOccurrence* p = stCreateOccurrence();
if(p != NULL)
{
A3DAsmModelFileData sData;
A3D_INITIALIZE_DATA(A3DAsmModelFileData, sData);
// In this model there will be only one product occurrence
sData.m_uiPOccurrencesSize = 1;
sData.m_dUnit = 1.0;
sData.m_ppPOccurrences = &p;
A3DAsmModelFileCreate(&sData, &pp);
}
return pp;
}
static MY_CHAR acDstFileName[_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 || iArgc < 2)
{
MY_PRINTF2("Usage:\n %s [output PRC file] [output LOG file]\n", ppcArgv[0]);
MY_PRINTF(" Default output LOG file is [output PRC file]_Log.txt\n\n");
return A3D_ERROR;
}
MY_STRCPY(acDstFileName, ppcArgv[1]);
if (iArgc > 2) MY_STRCPY(acLogFileName, ppcArgv[2]);
else MY_SPRINTF(acLogFileName, "%s_Log.txt", acDstFileName);
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
//
// Model file is created programmatically
sHoopsExchangeLoader.m_psModelFile = stCreateModel();
// The command line argument ppcArgv[1] is the file name for the exported file
A3DExport sExport(acDstFileName); // see A3DSDKInternalConvert.hxx for import and export detailed parameters
// Export the model
CHECK_RET(sHoopsExchangeLoader.Export(sExport));
//
// ### TERMINATE HOOPS EXCHANGE
//
// Check memory allocations
return (int)ListLeaks();
}