480 lines
14 KiB
C++
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();
|
|
}
|