/*********************************************************************************************************************** * * 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 #include #define INITIALIZE_A3D_API #include #include #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(); }