/*********************************************************************************************************************** * * Copyright (c) 2010 - 2022 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 DemoDataModelData.cpp Demonstrates how to create a table in which the table data is linked to the model data. ***********************************************************************************************************************/ // Do not define INITIALIZE_A3D_API here. It should be only included once in a project. #define HOOPS_PRODUCT_PUBLISH_ADVANCED #include #include "../common.hpp" #include #include #include #include #include #include std::string intToString(int i) { std::ostringstream oss; oss << i; return oss.str(); } //###################################################################################################################### //###################################################################################################################### A3DVoid mallocAndSetString(const A3DUTF8Char* srcString, A3DUTF8Char*& destString) { // we return empty strings rather than NULL because some strings usages crash with NULL values // (for example std::string xx = NULL crashes !) unsigned int uiSize = (unsigned int)(srcString ? strlen(srcString) : 0); destString = (A3DUTF8Char*)malloc((uiSize + 1) * sizeof(A3DUTF8Char)); if (uiSize > 0) { strcpy(destString, srcString); } destString[uiSize] = 0; } //###################################################################################################################### // cleaning functions void stFreeTable(A3DPDFDataTableData &sTableData) { for (A3DUns32 ir = 0; ir < sTableData.m_iNbRows ; ir++) { for(A3DUns32 ic = 0; ic < sTableData.m_iNbCols ; ic++) free(sTableData.m_ppcTexts[ir*sTableData.m_iNbCols+ic]); } free(sTableData.m_ppcTexts); } void stFreeTable3DViews(A3DPDFTable3DViewsData &sTable3DViewsData) { if (sTable3DViewsData.m_piViewIndexes) free(sTable3DViewsData.m_piViewIndexes); if (sTable3DViewsData.m_ppcViewLabels) { for(A3DUns32 ic = 0; ic < sTable3DViewsData.m_iNbViews ; ic++) if (sTable3DViewsData.m_ppcViewLabels[ic]) free(sTable3DViewsData.m_ppcViewLabels[ic]); free(sTable3DViewsData.m_ppcViewLabels); } if (sTable3DViewsData.m_ppImages) free(sTable3DViewsData.m_ppImages); if (sTable3DViewsData.m_pDataTableData) { for (A3DUns32 ir = 0; ir < sTable3DViewsData.m_pDataTableData->m_iNbRows ; ir++) { for(A3DUns32 ic = 0; ic < sTable3DViewsData.m_pDataTableData->m_iNbCols ; ic++) free(sTable3DViewsData.m_pDataTableData->m_ppcTexts[ir*sTable3DViewsData.m_pDataTableData->m_iNbCols+ic]); } free(sTable3DViewsData.m_pDataTableData->m_ppcTexts); } } void stFreeRelationship(A3DPDFDataRelationshipData &sRelationshipData) { free(sRelationshipData.m_pMapIndexes); } //###################################################################################################################### A3DStatus stCreateTable(A3DPDFDocument* pDoc, const std::vector > &aRows, A3DPDFDataTable*& pDataTable) { A3DStatus iRet = A3D_SUCCESS; A3DUns32 iNbRows = (A3DUns32)aRows.size(); A3DUns32 iNbCols = (A3DUns32)aRows[0].size(); A3DPDFDataTableData sTableData; A3D_INITIALIZE_DATA(A3DPDFDataTableData, sTableData); sTableData.m_iNbRows = iNbRows; sTableData.m_iNbCols = iNbCols; sTableData.m_ppcTexts = (A3DUTF8Char**)malloc(iNbRows * iNbCols * A3DUns32(sizeof(A3DUTF8Char*))); for (A3DUns32 ir = 0; ir < iNbRows; ir++) { for (A3DUns32 ic = 0; ic < iNbCols; ic++) mallocAndSetString( aRows[ir][ic].c_str(), // src sTableData.m_ppcTexts[ir*iNbCols + ic]); // dest } CHECK_RET(A3DPDFDataTableCreate(pDoc, &sTableData, &pDataTable)); stFreeTable(sTableData); return iRet; } A3DStatus stCreateRelationship(A3DPDFDocument* pDoc, std::vector< std::pair > &aMapIndexes, A3DPDFDataTable* pDataTableSource, A3DPDFDataTable* pDataTableTarget) { A3DStatus iRet = A3D_SUCCESS; A3DUns32 iNbRows = (A3DUns32)aMapIndexes.size(); A3DPDFDataRelationshipData sRelationshipData; A3D_INITIALIZE_DATA(A3DPDFDataRelationshipData, sRelationshipData); sRelationshipData.m_iSizeMap = iNbRows; sRelationshipData.m_pDataTableSource = pDataTableSource; sRelationshipData.m_pDataTableTarget = pDataTableTarget; sRelationshipData.m_pMapIndexes = (A3DPDFMapIndexData *)malloc(iNbRows * sizeof(A3DPDFMapIndexData)); memset(sRelationshipData.m_pMapIndexes, 0, iNbRows * sizeof(A3DPDFMapIndexData)); for (A3DUns32 ir = 0; ir < iNbRows; ir++) { sRelationshipData.m_pMapIndexes[ir].m_aiIndexes[0] = (A3DInt32)(aMapIndexes[ir].first); sRelationshipData.m_pMapIndexes[ir].m_aiIndexes[1] = (A3DInt32)(aMapIndexes[ir].second); } CHECK_RET(A3DPDFDataRelationshipCreate(pDoc, &sRelationshipData)); stFreeRelationship(sRelationshipData); return iRet; } std::string stStoreIcon(A3DPDFDocument* pDoc, std::string sFileName) { A3DStatus iRet = A3D_SUCCESS; std::string sIconId; // icons must primarily be stored into the document A3DPDFImage* pImage = nullptr; iRet = A3DPDFImageCreateFromFile(pDoc, sFileName.c_str(), kA3DPDFImageFormatUnknown, // not defined -> format is deducted from file extension &pImage); if (iRet == A3D_SUCCESS) { A3DUTF8Char* pcIconId = NULL; iRet = A3DPDFDocumentAddImageAsIcon2(pDoc, pImage, nullptr, // pcIconId : not defined -> a unique id is automatically generated; see last argument for retrieving. &pcIconId); if (pcIconId) { sIconId = pcIconId; A3DPDFDocumentAddImageAsIcon2(nullptr, nullptr, nullptr,&pcIconId); } } else std::cout << "Can't create image from file " << sFileName << ". Error number=" << iRet << std::endl; return sIconId; } //###################################################################################################################### A3DStatus PageGetTextField( A3DPDFPage* pPage, const std::string& sFieldId, A3DPDFTextField** ppField) { A3DStatus iRet = A3D_SUCCESS; *ppField = NULL; A3DPDFField* pField = NULL; CHECK_RET(A3DPDFPageGetField(pPage, sFieldId.c_str(), &pField)); A3DPDFEWidgetType eWidgetType; CHECK_RET(A3DPDFWidgetGetType((A3DPDFWidget*)pField, &eWidgetType)); if (eWidgetType!=kA3DTypeFieldText) iRet = A3D_INVALID_ENTITY_TYPE; else *ppField = (A3DPDFTextField*)pField; return iRet; } A3DStatus PageGetButtonField(A3DPDFPage* pPage, const std::string& sFieldId, A3DPDFButton** ppField) { A3DStatus iRet = A3D_SUCCESS; *ppField = NULL; A3DPDFField* pField = NULL; CHECK_RET(A3DPDFPageGetField(pPage, sFieldId.c_str(), &pField)); A3DPDFEWidgetType eWidgetType; CHECK_RET(A3DPDFWidgetGetType((A3DPDFWidget*)pField, &eWidgetType)); if (eWidgetType != kA3DTypeFieldButton) iRet = A3D_INVALID_ENTITY_TYPE; else *ppField = (A3DPDFButton*)pField; return iRet; } A3DStatus PageGetListBoxField(A3DPDFPage* pPage, const std::string& sFieldId, A3DPDFListBox** ppField) { A3DStatus iRet = A3D_SUCCESS; *ppField = NULL; A3DPDFField* pField = NULL; CHECK_RET(A3DPDFPageGetField(pPage, sFieldId.c_str(), &pField)); A3DPDFEWidgetType eWidgetType; CHECK_RET(A3DPDFWidgetGetType((A3DPDFWidget*)pField, &eWidgetType)); if (eWidgetType!=kA3DTypeFieldListBox) iRet = A3D_INVALID_ENTITY_TYPE; else *ppField = (A3DPDFListBox*)pField; return iRet; } A3DStatus PageGetDropDownListField(A3DPDFPage* pPage, const std::string& sFieldId, A3DPDFDropDownList** ppField) { A3DStatus iRet = A3D_SUCCESS; *ppField = NULL; A3DPDFField* pField = NULL; CHECK_RET(A3DPDFPageGetField(pPage, sFieldId.c_str(), &pField)); A3DPDFEWidgetType eWidgetType; CHECK_RET(A3DPDFWidgetGetType((A3DPDFWidget*)pField, &eWidgetType)); if (eWidgetType!=kA3DTypeFieldDropDownList) iRet = A3D_INVALID_ENTITY_TYPE; else *ppField = (A3DPDFDropDownList*)pField; return iRet; } //###################################################################################################################### class BomElement { public: BomElement() : m_iQty(0), m_PtrPRCEntity(NULL) {} BomElement(const BomElement& other) : m_attrib(other.m_attrib), m_name(other.m_name), m_bIsRepresentationItem(other.m_bIsRepresentationItem), m_PtrPRCEntity(other.m_PtrPRCEntity), m_iQty(other.m_iQty), m_keyAttribValue(other.m_keyAttribValue){}; static bool isInMapByKeyAttrib(const std::vector mapBomElements, const std::string& sKeyAttrib, size_t& idxinbommap); static bool isInMapByName(const std::vector mapBomElements, const std::string& sName, size_t& idxinbommap); std::string m_attrib; std::string m_name; bool m_bIsRepresentationItem; void* m_PtrPRCEntity; int m_iQty; std::string m_keyAttribValue; std::vector m_NodeIndexes; }; bool BomElement::isInMapByKeyAttrib( const std::vector mapBomElements, const std::string& sKeyAttribValue, size_t& idxinbommap) { // find in map size_t imap; bool bFoundIdxinbommap = false; for (imap = 0; !bFoundIdxinbommap && imap < mapBomElements.size(); imap++) { if (mapBomElements[imap].m_keyAttribValue == sKeyAttribValue) { idxinbommap = imap; bFoundIdxinbommap = true; } } return bFoundIdxinbommap; } bool BomElement::isInMapByName( const std::vector mapBomElements, const std::string& sName, size_t& idxinbommap) { // find in map size_t imap; bool bFoundIdxinbommap = false; for (imap = 0; !bFoundIdxinbommap && imap < mapBomElements.size(); imap++) { if (mapBomElements[imap].m_name == sName) { idxinbommap = imap; bFoundIdxinbommap = true; } } return bFoundIdxinbommap; } //###################################################################################################################### A3DStatus CreateTable_Sple1_Statics(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable_Statics) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; // TABLE Statics aRows.clear(); aOneRow.clear(); aOneRow.push_back("CRANK"); aOneRow.push_back("23/07/2017"); aOneRow.push_back("Joe"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable_Statics); } A3DStatus CreateTable_Sple1_Manufacturers(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; aRows.clear(); aOneRow.clear(); aOneRow.push_back("Tech Soft 3D"); aOneRow.push_back("US"); aOneRow.push_back("Joe Bill"); aOneRow.push_back("931 Ashby Ave.\nBerkeley\nCA 94710-2805\nUSA"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Tetra4D"); aOneRow.push_back("US"); aOneRow.push_back("James Orning"); aOneRow.push_back("1567 SW Chandler Ave,\nSuite 100, Bend, OR 97702\nUSA"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Adden"); aOneRow.push_back("UK"); aOneRow.push_back("David Grival"); aOneRow.push_back("River Mill, Staveley Mill Yard,\nStaveley Cumbria LA8 9LR\nUK"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Hart"); aOneRow.push_back("Germany"); aOneRow.push_back("Martin Zucher"); aOneRow.push_back("Schonwalder Allee 30\nEckernforde\nSchleswig-Holstein\n24334"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Dynamics"); aOneRow.push_back("Japan"); aOneRow.push_back("Tetsuo Taniguchi"); aOneRow.push_back("Yokohama ST Bldg. 7F 1-11-15\nKitasaiwai, Nishi-ku, Yokohama, Kanagawa\n220-0004 Japan"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Prendergast"); aOneRow.push_back("US"); aOneRow.push_back("Alexandru Pintilie"); aOneRow.push_back("4010 Executive Park Dr, Suite 250\nCincinnati, OH 45241\nUSA"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Vector Solutions"); aOneRow.push_back("France"); aOneRow.push_back("Jean François Marchand"); aOneRow.push_back("200 ave Jean Jaures\n69007 Lyon\nFrance"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Rimmer"); aOneRow.push_back("Belgium"); aOneRow.push_back("Johan Groeningen"); aOneRow.push_back("Rue des Honnelles 495\nZeebrugge\nWest Flanders\n8380"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable); } A3DStatus CreateTable_Sple1_3DModel_Bom(A3DPDFDocument* pDoc, A3DAsmModelFile* pModelFile, A3DRWParamsPrcWriteHelper* pPRCWriteHelper, const std::string& sPathIcons, int& iKeyNode3dUID, int& iKeyNode3dName, int& iKeyNode3dInstance, int& iKeyBomNumArt, int& iKeyBomNamePart, int& iKeyBomQty, int& iKeyBomMaterial, int& iKeyBomIcon, A3DPDFDataTable*& pDataTable3D, A3DPDFDataTable*& pDataTableBom, A3DPDFDataTable* pDataTableManufacturers) { A3DStatus iRet = A3D_SUCCESS; pDataTable3D = NULL; pDataTableBom = NULL; // structure for Tables definitions std::vector > aTable3DRows; std::vector > aTableBomRows; // structure for Relationships definitions std::vector< std::pair > aMapIndexes_3dToBom; std::vector< std::pair > aMapIndexes_BomTo3D; std::vector< std::pair > aMapIndexes_BomToManufacturers; std::vector mapBomElements; // parse the 3D PDF nodes A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL; CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pPRCWriteHelper, &pModelFileNodesInfo)); std::map mapOfNames; int iFirstNode = 2; // for this sample, we don't take the 2 first nodes (node 0 is for the root, and node 1 doesn't exist) for (size_t inodein3d = iFirstNode; inodein3d < (size_t)pModelFileNodesInfo->m_iNbNodes; inodein3d++) { A3DPDFNodeData* nodeInfos = pModelFileNodesInfo->m_ppNodes[inodein3d]; // in this sample, the 3D nodes involved in datamodel are the Product Occurences // the product name is the key to bom entry if (nodeInfos->m_eNodeType == kA3DPDFNodeProductOccurrence) { std::string sNodeName = nodeInfos->m_pcName; // instance number std::map::iterator it = mapOfNames.find(sNodeName); int iIbnstanceNb = 0; if (it != mapOfNames.end()) // found : increment second { it->second++; iIbnstanceNb = it->second; } else // not found : create entry { mapOfNames.insert(std::make_pair(sNodeName, 1)); iIbnstanceNb = 1; } std::vector aOneRow; aOneRow.push_back(nodeInfos->m_pcNodeUid); iKeyNode3dUID = (int)aOneRow.size() - 1; aOneRow.push_back(sNodeName); iKeyNode3dName = (int)aOneRow.size() - 1; aOneRow.push_back(intToString(iIbnstanceNb)); iKeyNode3dInstance = (int)aOneRow.size() - 1; aTable3DRows.push_back(aOneRow); // Build Bom map entry size_t idxinbommap = 0; bool bFoundIdxinbommap = BomElement::isInMapByName(mapBomElements, sNodeName, idxinbommap); if (!bFoundIdxinbommap) { // node not found in map, put it BomElement bomElement; bomElement.m_iQty = 1; bomElement.m_name = nodeInfos->m_pcName; mapBomElements.push_back(bomElement); idxinbommap = (int)mapBomElements.size() - 1; } else { // node is already in map // only count mesh nodes ? not needed in this sample as we go here only for productoccurence // if (nodeInfos->m_bIsRepresentationItem) mapBomElements[idxinbommap].m_iQty++; mapBomElements[idxinbommap].m_NodeIndexes.push_back(inodein3d); } // create relationship between 3d node and bom entry size_t iThisNodein3d = aTable3DRows.size()-1; aMapIndexes_3dToBom.push_back(std::make_pair(iThisNodein3d, idxinbommap)); aMapIndexes_BomTo3D.push_back(std::make_pair(idxinbommap, iThisNodein3d)); } } CHECK_RET(A3DPDFGetModelFileNodes(nullptr, nullptr, &pModelFileNodesInfo)); // Build BOM table for (size_t imap = 0; imap < mapBomElements.size(); imap++) { // hard coded section for adding corresponding icons and materials // typically, these information would be stored as attribute, or extracted from a PLM std::string sMaterial; std::string sIconId; if (mapBomElements[imap].m_name == "01-2_CRANKSHAFT") { sMaterial = "Steel"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_crankshaft.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 0)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 4)); } else if (mapBomElements[imap].m_name == "CONNECTING_ROD") { sMaterial = "Copper"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_connectingrod.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 3)); } else if (mapBomElements[imap].m_name == "CONNECTING_ROD_CAP") { sMaterial = "Chrome"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_connectingrod_cap.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 0)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); } else if (mapBomElements[imap].m_name == "CONNECTING_ROD_BUSHING") { sMaterial = "Nickel"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_connectingrod_bushing.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 3)); } else if (mapBomElements[imap].m_name == "CONNECTING_ROD_BOLT") { sMaterial = "Aluminium"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_connectingrod_bolt.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 0)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); } else if (mapBomElements[imap].m_name == "CONNECTING_ROD_BOLT_NUT") { sMaterial = "Copper"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_connectingrod_boltnut.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 3)); } else if (mapBomElements[imap].m_name == "01-2_PISTON") { sMaterial = "Chrome"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_piston.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 4)); } else if (mapBomElements[imap].m_name == "01-2_PISTON_PIN") { sMaterial = "Nickel"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_pistonpin.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 0)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 4)); } else if (mapBomElements[imap].m_name == "01-2_PISTON_RETAINER") { sMaterial = "Aluminium"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_pistonretainer.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 4)); } else if (mapBomElements[imap].m_name == "01-2_PISTON_TOP_COMP<01-2_PISTON_RING>") { sMaterial = "Aluminium"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_pistonring.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); } else if (mapBomElements[imap].m_name == "PISTON_BOT_COMP<01-2_PISTON_RING>") { sMaterial = "Aluminium"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_pistonring.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); } else if (mapBomElements[imap].m_name == "PISTON_OIL_COMP<01-2_PISTON_RING>") { sMaterial = "Aluminium"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_pistonring.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 2)); } else if (mapBomElements[imap].m_name == "01-2_VALVE_TIMING_SPROCKET") { sMaterial = "Iron"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_valve.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 3)); } else if (mapBomElements[imap].m_name == "01-2_DAMPER_PULLEY") { sMaterial = "Iron"; sIconId = stStoreIcon(pDoc, sPathIcons + "crank_damper.jpg"); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 1)); aMapIndexes_BomToManufacturers.push_back(std::make_pair(imap, 3)); } else { sMaterial = ""; sIconId = ""; } std::vector aOneRow; aOneRow.push_back(intToString((int)imap)); iKeyBomNumArt = (int)aOneRow.size() - 1; aOneRow.push_back(mapBomElements[imap].m_name); iKeyBomNamePart = (int)aOneRow.size() - 1; aOneRow.push_back(sMaterial); iKeyBomMaterial = (int)aOneRow.size() - 1; aOneRow.push_back(sIconId); iKeyBomIcon = (int)aOneRow.size() - 1; aOneRow.push_back(intToString(mapBomElements[imap].m_iQty)); iKeyBomQty = (int)aOneRow.size() - 1; aTableBomRows.push_back(aOneRow); } iRet = stCreateTable(pDoc, aTable3DRows, pDataTable3D); iRet = stCreateTable(pDoc, aTableBomRows, pDataTableBom); iRet = stCreateRelationship(pDoc, aMapIndexes_3dToBom, pDataTable3D, pDataTableBom); iRet = stCreateRelationship(pDoc, aMapIndexes_BomTo3D, pDataTableBom, pDataTable3D); iRet = stCreateRelationship(pDoc, aMapIndexes_BomToManufacturers, pDataTableBom, pDataTableManufacturers); return iRet; } A3DStatus CreateTable_Sple1_CBFILTER(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; aRows.clear(); aOneRow.clear(); aOneRow.push_back("Central parts"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Connectors"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("Pistons"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable); } A3DStatus CreateRelationship_Sple1_CBFILTER_To_Bom(A3DPDFDocument* pDoc, A3DPDFDataTable* pDataTable_Source, A3DPDFDataTable* pDataTable_Target) { // structure for Relationships definitions std::vector< std::pair > aMapIndexes; // This is a hard-coded section working only for the 3D part provided with this sample // filter 1 isolates a subset of parts ; here we want the central parts aMapIndexes.push_back(std::make_pair (0, 1)); aMapIndexes.push_back(std::make_pair (0, 12)); aMapIndexes.push_back(std::make_pair (0, 13)); // filter 2 isolates a second subset of parts ; here we want the parts referring to connectors aMapIndexes.push_back(std::make_pair(1, 1)); aMapIndexes.push_back(std::make_pair(1, 2)); aMapIndexes.push_back(std::make_pair(1, 3)); aMapIndexes.push_back(std::make_pair(1, 4)); aMapIndexes.push_back(std::make_pair (1, 5)); // filter 3 isolates a second subset of parts ; here we want the parts referring to pistons aMapIndexes.push_back(std::make_pair(2, 6)); aMapIndexes.push_back(std::make_pair(2, 7)); aMapIndexes.push_back(std::make_pair(2, 8)); aMapIndexes.push_back(std::make_pair(2, 9)); aMapIndexes.push_back(std::make_pair(2, 10)); aMapIndexes.push_back(std::make_pair(2, 11)); return stCreateRelationship(pDoc, aMapIndexes, pDataTable_Source, pDataTable_Target); } //###################################################################################################################### A3DStatus CreateTable_Sple2_Statics(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable_Statics) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; // TABLE Statics aRows.clear(); aOneRow.clear(); aOneRow.push_back("INSPECTION REPORT"); aOneRow.push_back("23/07/2017"); aOneRow.push_back("Bill"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable_Statics); } A3DStatus CreateTable_Sple2_ViewNames(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; aRows.clear(); aOneRow.clear(); aOneRow.push_back("View 1"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("View 2"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable); } A3DStatus CreateTable_Sple2_3DModel(A3DPDFDocument* pDoc, A3DAsmModelFile* pModelFile, A3DRWParamsPrcWriteHelper* pPRCWriteHelper, int& iKeyNode3dUID, int& iKeyPmiName, int& iKeyPmiType, int& iKeyPmiValue, int& iKeyPmiTol, A3DPDFDataTable*& pDataTable3D, A3DPDFDataTable*& pDataTablePmis) { A3DStatus iRet = A3D_SUCCESS; pDataTable3D = NULL; // structure for Tables definitions std::vector > aTable3DRows; std::vector > aTablePmis; // structure for Relationships definitions std::vector< std::pair > aMapIndexes_3dToPmis; std::vector< std::pair > aMapIndexes_PmisTo3d; // parse the 3D PDF nodes A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL; CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pPRCWriteHelper, &pModelFileNodesInfo)); std::map mapOfNames; for (size_t inodein3d = 0; inodein3d < (size_t)pModelFileNodesInfo->m_iNbNodes; inodein3d++) { A3DPDFNodeData* nodeInfos = pModelFileNodesInfo->m_ppNodes[inodein3d]; // in this sample, the 3D nodes involved in datamodel are the Pmis // the pmi name is the key to bom entry if (nodeInfos->m_eNodeType == kA3DPDFNodePMI) { std::string sNodeName = nodeInfos->m_pcName; // hard coded section for adding corresponding icons and materials // typically, these information would be stored as attribute, or extracted from a PLM std::string sType; std::string sValue; std::string sTol; if (sNodeName == "Chamfer 1") { sType = "Chamfer"; sValue = "Not specified"; sTol = "Not specified"; } else if (sNodeName == "Chamfer 2") { sType = "Chamfer"; sValue = "Not specified"; sTol = "Not specified"; } else if (sNodeName == "Roughness") { sType = "Roughness"; sValue = "Not specified"; sTol = "Not specified"; } else if (sNodeName == "Datum A") { sType = "Datum"; sValue = "A"; sTol = "Not specified"; } else if (sNodeName == "Datum B") { sType = "Datum"; sValue = "B"; sTol = "Not specified"; } else if (sNodeName == "Perpendicularity 1") { sType = "Perpendicularity"; sValue = "Not specified"; sTol = "0.01"; } else if (sNodeName == "Concentricity") { sType = "Concentricity"; sValue = "Not specified"; sTol = "0.01"; } else if (sNodeName == "Linear Size.1") { sType = "Diameter Cylinder"; sValue = "50"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Dimension.5") { sType = "Length"; sValue = "50"; sTol = "H6/f7"; } else if (sNodeName == "Dimension.6") { sType = "Length"; sValue = "35"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Linear Size.2") { sType = "Diameter Cylinder"; sValue = "35"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Linear Size.3") { sType = "Diameter Cylinder"; sValue = "35"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Dimension.4") { sType = "Distance"; sValue = "5"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Dimension.2") { sType = "Distance"; sValue = "40"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Dimension.1") { sType = "Distance"; sValue = "15"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Dimension.3") { sType = "Distance"; sValue = "5"; sTol = "-0.1 / 0.1"; } else if (sNodeName == "Datum C") { sType = "Datum"; sValue = "C"; sTol = "Not specified"; } else if (sNodeName == "Parallelism") { sType = "Parallelism"; sValue = "Not specified"; sTol = "0.01"; } else if (sNodeName == "Perpendicularity 2") { sType = "Perpendicularity"; sValue = "Not specified"; sTol = "0.01"; } else if (sNodeName == "Linear Size.4") { sType = "Diameter Cylinder"; sValue = "10"; sTol = "-0.1 / 0.1"; } std::vector aOneRow3d; aOneRow3d.push_back(nodeInfos->m_pcNodeUid); iKeyNode3dUID = (int)aOneRow3d.size() - 1; aTable3DRows.push_back(aOneRow3d); std::vector aOneRowPmi; aOneRowPmi.push_back(sNodeName); iKeyPmiName = (int)aOneRowPmi.size() - 1; aOneRowPmi.push_back(sType); iKeyPmiType = (int)aOneRowPmi.size() - 1; aOneRowPmi.push_back(sValue); iKeyPmiValue = (int)aOneRowPmi.size() - 1; aOneRowPmi.push_back(sTol); iKeyPmiTol = (int)aOneRowPmi.size() - 1; aTablePmis.push_back(aOneRowPmi); // create relationship between 3d node and pmi entry size_t iThisIndex = aTable3DRows.size() - 1; aMapIndexes_3dToPmis.push_back(std::make_pair(iThisIndex, iThisIndex)); aMapIndexes_PmisTo3d.push_back(std::make_pair(iThisIndex, iThisIndex)); } } iRet = stCreateTable(pDoc, aTable3DRows, pDataTable3D); iRet = stCreateTable(pDoc, aTablePmis, pDataTablePmis); iRet = stCreateRelationship(pDoc, aMapIndexes_3dToPmis, pDataTable3D, pDataTablePmis); iRet = stCreateRelationship(pDoc, aMapIndexes_PmisTo3d, pDataTablePmis, pDataTable3D); CHECK_RET(A3DPDFGetModelFileNodes(nullptr, nullptr, &pModelFileNodesInfo)); return iRet; } /* hard coded version A3DStatus CreateTable_Sple2_3DViews(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; aRows.clear(); aOneRow.clear(); aOneRow.push_back("0"); aOneRow.push_back("Front View.1"); aOneRow.push_back("This is first view"); aRows.push_back(aOneRow); aOneRow.clear(); aOneRow.push_back("1"); aOneRow.push_back("Front View.2"); aOneRow.push_back("This is second view"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable); } */ A3DStatus CreateTable_Sple2_3DViews_WithCarousel(A3DPDFDocument* pDoc, A3DPDF3DArtwork* p3DArtwork, A3DAsmModelFile* pModelFile, A3DPDFDataTable3DViews*& pDataTable) { A3DStatus iRet = A3D_SUCCESS; A3DUns32 uiNbViews = 0; A3DPDFView** ppViews = NULL; pDataTable = NULL; // first get views from the 3D model: do we really need a carousel iRet = A3DPDF3DArtworkGetViews(p3DArtwork, &uiNbViews, &ppViews); // the last view is the automatic view, automatically created by HOOPS Publish to be the default view. // we consider in this sample that this view is not in the CAD tool, so we don't want it in the carousel if(uiNbViews > 0) uiNbViews--; // if no views after that, no use to write a carousel ! if (uiNbViews == 0) return A3D_SUCCESS; // columns to add to the table for views int iNbAddedCols = 2; std::vector > aAddedAttribs; std::vector aOneRow; aAddedAttribs.clear(); for (unsigned int ir = 0; ir < uiNbViews; ir++) { aOneRow.clear(); aOneRow.push_back("v" + intToString((int)ir) + " - info A"); aOneRow.push_back("v" + intToString((int)ir) + " - info B"); aAddedAttribs.push_back(aOneRow); } A3DInt32 *piViewIndexes = (A3DInt32 *)malloc(uiNbViews*sizeof(A3DInt32)); A3DUTF8Char* *ppcViewLabels = (A3DUTF8Char* *)malloc(uiNbViews*sizeof(A3DUTF8Char*)); A3DPDFImage* *ppImages = (A3DPDFImage* *)malloc(uiNbViews*sizeof(A3DPDFImage*)); A3DPDFDataTableData sTableAddedData; A3D_INITIALIZE_DATA(A3DPDFDataTableData, sTableAddedData); sTableAddedData.m_iNbRows = uiNbViews; sTableAddedData.m_iNbCols = iNbAddedCols; sTableAddedData.m_ppcTexts = (A3DUTF8Char**) malloc(uiNbViews * iNbAddedCols * A3DUns32(sizeof(A3DUTF8Char*))); for (unsigned int ir = 0; ir < uiNbViews; ir++) { // get the view name. might be useful if there's a need to filter values depending on view name A3DUTF8Char* pcViewId = NULL; A3DPDFViewGetExternalName(ppViews[ir], &pcViewId); std::string sViewId = pcViewId; A3DPDFViewGetExternalName(nullptr, &pcViewId); piViewIndexes[ir] = ir;// index in list view, ordered as in A3DPDF3DArtworkGetViews //optional code: labels for carousel buttons. if null, view name are used. if (sViewId == "Front View.1") mallocAndSetString("VIEW 1", ppcViewLabels[ir]); else if (sViewId == "Front View.2") mallocAndSetString("VIEW 2", ppcViewLabels[ir]); else mallocAndSetString("VIEW UNKNOWN", ppcViewLabels[ir]); // icon for view. if kA3DPDFTableFor3DViewsComputePosters, the image is automatically generated if needed for carousel. ppImages[ir] = NULL; // additional table columns: will be stored in the table starting from column position [2] for(int ic = 0; ic < iNbAddedCols ; ic++) mallocAndSetString( aAddedAttribs[ir][ic].c_str(), // src sTableAddedData.m_ppcTexts[ir*iNbAddedCols+ic]); // dest } A3DPDFTable3DViewsData sTable3DViewsData; A3D_INITIALIZE_DATA(A3DPDFTable3DViewsData, sTable3DViewsData); sTable3DViewsData.m_iNbViews = uiNbViews; sTable3DViewsData.m_piViewIndexes = piViewIndexes; sTable3DViewsData.m_ppcViewLabels = ppcViewLabels; sTable3DViewsData.m_ppImages = ppImages; // not useful if kA3DPDFTableFor3DViewsComputePosters is specified sTable3DViewsData.m_pDataTableData = &sTableAddedData; CHECK_RET(A3DPDFDataTable3DViewsCreate(pDoc, p3DArtwork,pModelFile, kA3DPDFTableFor3DViewsCustom | kA3DPDFTableFor3DViewsComputePosters, // kA3DPDFTableFor3DViewsComputePosters to automatically compute posters for all views specified &sTable3DViewsData, &pDataTable)); // clean stFreeTable3DViews(sTable3DViewsData); iRet = A3DPDF3DArtworkGetViews(NULL, NULL, &ppViews); return iRet; } A3DStatus CreateTable_Sple2_3DViews_WithCarousel_Simple(A3DPDFDocument* pDoc, A3DPDF3DArtwork* p3DArtwork, A3DAsmModelFile* pModelFile, A3DPDFDataTable3DViews*& pDataTable) { A3DStatus iRet = A3D_SUCCESS; A3DUns32 uiNbViews = 0; A3DPDFView** ppViews = NULL; pDataTable = NULL; // first get views from the 3D model: do we really need a carousel iRet = A3DPDF3DArtworkGetViews(p3DArtwork, &uiNbViews, &ppViews); // the last view is the automatic view, automatically created by HOOPS Publish to be the default view. // we consider in this sample that this view is not in the CAD tool, so we don't want it in the carousel if(uiNbViews > 0) uiNbViews--; // if no views after that, no use to write a carousel ! if (uiNbViews == 0) return A3D_SUCCESS; A3DInt32 *piViewIndexes = (A3DInt32 *)malloc(uiNbViews*sizeof(A3DInt32)); A3DUTF8Char* *ppcViewLabels = (A3DUTF8Char* *)malloc(uiNbViews*sizeof(A3DUTF8Char*)); A3DPDFImage* *ppImages = (A3DPDFImage* *)malloc(uiNbViews*sizeof(A3DPDFImage*)); for (unsigned int ir = 0; ir < uiNbViews; ir++) { piViewIndexes[ir] = ir;// index in list view, ordered as in A3DPDF3DArtworkGetViews //optional: labels for carousel buttons. if null, view name are used. ppcViewLabels[ir] = NULL; ppImages[ir] = NULL; // icon for view. if kA3DPDFTableFor3DViewsComputePosters, the image is automatically generated if needed for carousel. } CHECK_RET(A3DPDFDataTable3DViewsCreate(pDoc, p3DArtwork,pModelFile, kA3DPDFTableFor3DViewsCustom | kA3DPDFTableFor3DViewsComputePosters, // kA3DPDFTableFor3DViewsComputePosters to automatically compute posters for all views specified NULL, &pDataTable)); // clean free(piViewIndexes); free(ppcViewLabels); free(ppImages); iRet = A3DPDF3DArtworkGetViews(NULL, NULL, &ppViews); return iRet; } A3DStatus CreateTable_Sple2_3DViews(A3DPDFDocument* pDoc, A3DPDF3DArtwork* p3DArtwork, A3DPDFDataTable3DViews*& pDataTable) { A3DStatus iRet = A3D_SUCCESS; pDataTable = NULL; CHECK_RET(A3DPDFDataTable3DViewsCreate(pDoc, p3DArtwork,NULL, kA3DPDFTableFor3DViewsAll, NULL, // views specification unused as we want all views and no predefined posters &pDataTable)); return iRet; } A3DStatus CreateRelationship_Sple2_ViewNames_To_Views(A3DPDFDocument* pDoc, A3DPDFDataTable* pDataTable_ViewNames, A3DPDFDataTable* pDataTable_Views) { // structure for Relationships definitions std::vector< std::pair > aMapIndexes; aMapIndexes.push_back( std::make_pair (0, 0) ); aMapIndexes.push_back( std::make_pair (1, 1) ); stCreateRelationship(pDoc, aMapIndexes, pDataTable_ViewNames, pDataTable_Views); stCreateRelationship(pDoc, aMapIndexes, pDataTable_Views, pDataTable_ViewNames); return A3D_SUCCESS; } A3DStatus CreateRelationship_Sple2_View_To_Pmis(A3DPDFDocument* pDoc, A3DPDFDataTable* pDataTable_Source, A3DPDFDataTable* pDataTable_Target) { // structure for Relationships definitions std::vector< std::pair > aMapIndexes; // This is a hard-coded section working only for the 3D part provided with this sample // view 1 aMapIndexes.push_back( std::make_pair (0, 0) ); aMapIndexes.push_back( std::make_pair (0, 1) ); aMapIndexes.push_back( std::make_pair (0, 2) ); aMapIndexes.push_back( std::make_pair (0, 3) ); aMapIndexes.push_back( std::make_pair (0, 4) ); aMapIndexes.push_back( std::make_pair (0, 5) ); aMapIndexes.push_back( std::make_pair (0, 6) ); aMapIndexes.push_back( std::make_pair (0, 7) ); aMapIndexes.push_back( std::make_pair (0, 8) ); aMapIndexes.push_back( std::make_pair (0, 9) ); aMapIndexes.push_back( std::make_pair (0, 10) ); aMapIndexes.push_back( std::make_pair (0, 11) ); aMapIndexes.push_back( std::make_pair (0, 12) ); aMapIndexes.push_back( std::make_pair (0, 13) ); aMapIndexes.push_back( std::make_pair (0, 14) ); aMapIndexes.push_back( std::make_pair (0, 15) ); // view 2 aMapIndexes.push_back( std::make_pair (1, 16) ); aMapIndexes.push_back( std::make_pair (1, 17) ); aMapIndexes.push_back( std::make_pair (1, 18) ); aMapIndexes.push_back( std::make_pair (1, 19) ); return stCreateRelationship(pDoc, aMapIndexes, pDataTable_Source, pDataTable_Target); } //###################################################################################################################### A3DStatus CreateTable_Sple3_Statics(A3DPDFDocument* pDoc, A3DPDFDataTable*& pDataTable_Statics) { // structure for Tables definitions std::vector > aRows; std::vector aOneRow; // TABLE Statics aRows.clear(); aOneRow.clear(); aOneRow.push_back("CRANK FOR BOM"); aOneRow.push_back("12/09/2014"); aOneRow.push_back("James"); aRows.push_back(aOneRow); return stCreateTable(pDoc, aRows, pDataTable_Statics); } A3DStatus CreateTable_Sple3_3DModel_Bom(A3DPDFDocument* pDoc, A3DAsmModelFile* pModelFile, A3DRWParamsPrcWriteHelper* pHelper, const std::string& sPathIcons, int& iKeyNode3dUID, int& iKeyNode3dInstanceName, int& iKeyBomNumArt, int& iKeyBomNamePart, int& iKeyBomQty, int& iKeyBomIcon, A3DPDFDataTable*& pDataTable3D, A3DPDFDataTable*& pDataTableBom) { A3DStatus iRet = A3D_SUCCESS; pDataTable3D = NULL; pDataTableBom = NULL; // structure for Tables definitions std::vector > aTable3DRows; std::vector > aTableBomRows; // structure for Relationships definitions std::vector< std::pair > aMapIndexes_3dToBom; std::vector< std::pair > aMapIndexes_BomTo3D; std::vector mapBomElements; // use API to parse the 3D PDF nodes A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL; CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pHelper, &pModelFileNodesInfo)); for (size_t inodein3d = 0; inodein3d < (size_t)pModelFileNodesInfo->m_iNbNodes; inodein3d++) { std::vector aOneRow; A3DPDFNodeData* nodeInfos = pModelFileNodesInfo->m_ppNodes[inodein3d]; // in this sample, the 3D nodes involved in datamodel are all the ndoes // the attribute 'PartNumber' is the key to bom entry aOneRow.push_back(nodeInfos->m_pcNodeUid); iKeyNode3dUID = (int)aOneRow.size()-1; //char acPtrPRCEntity[1024]; sprintf(acPtrPRCEntity, "%p", nodeInfos->m_pEntity); //aOneRow.push_back(acPtrPRCEntity); aOneRow.push_back(nodeInfos->m_pcName); if (nodeInfos->m_eNodeType==kA3DPDFNodeProductOccurrence) aOneRow.push_back("PO"); else if (nodeInfos->m_eNodeType==kA3DPDFNodeRepresentationItem) aOneRow.push_back("RI"); else if (nodeInfos->m_eNodeType==kA3DPDFNodePMI) aOneRow.push_back("PMI"); //aOneRow.push_back(nodeInfos->m_pcFilePath); //aOneRow.push_back(nodeInfos->m_pcOriginalFilePath); // looking for a key attribute that defines the attribute which identifies a bom entry // in this sample, this is the attribute 'PartNumber' char pcAttribKeyForMap[] = "PartNumber" ; char pcAttribKeyForNode3dInstance[] = "InstanceName" ; A3DPDFNodeAttributeData* attribKey = NULL; A3DPDFNodeAttributeData* attribKeyForNode3dInstance = NULL; for (int j = 0; j < nodeInfos->m_iNbAttributes; j++) { A3DPDFNodeAttributeData* attrib = nodeInfos->m_ppAttributes[j]; if (strcmp (attrib->m_pcType, pcAttribKeyForMap)==0) attribKey = attrib; if (strcmp (attrib->m_pcType, pcAttribKeyForNode3dInstance)==0) attribKeyForNode3dInstance = attrib; } aOneRow.push_back(attribKey ? attribKey->m_pcValue : ""); aOneRow.push_back(attribKeyForNode3dInstance ? attribKeyForNode3dInstance->m_pcValue : "");iKeyNode3dInstanceName = (int)aOneRow.size()-1; aTable3DRows.push_back(aOneRow); if (attribKey) { // the node has the key attribute, put it into Bom map // find in map size_t imap = 0; size_t idxinbommap = 0; bool bFoundIdxinbommap = false; for (imap = 0; !bFoundIdxinbommap && imap < mapBomElements.size(); imap++) { if (mapBomElements[imap].m_keyAttribValue == std::string(attribKey->m_pcValue)) { idxinbommap = imap; bFoundIdxinbommap = true; } } if (!bFoundIdxinbommap) { // node not found in map, put it BomElement bomElement; bomElement.m_keyAttribValue = (attribKey ? attribKey->m_pcValue : ""); bomElement.m_iQty = 1; bomElement.m_name = nodeInfos->m_pcName; bomElement.m_attrib = (attribKey ? attribKey->m_pcValue : ""); mapBomElements.push_back(bomElement); idxinbommap = (int)mapBomElements.size()-1; } else { // node is already in map // only count mesh nodes ? not needed in this sample as we go here only for productoccurence // if (nodeInfos->m_bIsRepresentationItem) mapBomElements[idxinbommap].m_iQty++; mapBomElements[idxinbommap].m_NodeIndexes.push_back(inodein3d); } // create relationship between 3d node and bom entry aMapIndexes_3dToBom.push_back( std::make_pair (inodein3d, idxinbommap) ); aMapIndexes_BomTo3D.push_back( std::make_pair (idxinbommap, inodein3d) ); } else { // the key attribute was not found on the node // note: with this sample prc, the attrib key is not found on repitems ; the attrib is only stored onto the prodocc father // in case where the attribute is not found on repitems, we consider that the prodoccurence father was found, // and we connect this father node to the bom entry if (nodeInfos->m_iPocFatherIndex != -1 && nodeInfos->m_iPocFatherIndex<(A3DInt32)aMapIndexes_3dToBom.size()) { // get bom map entry related to m_iPocFatherIndex size_t idxinbommap = aMapIndexes_3dToBom[nodeInfos->m_iPocFatherIndex].second; // create relationship between 3d node and bom entry aMapIndexes_3dToBom.push_back(std::make_pair(inodein3d, idxinbommap)); } } } // Build BOM table for (size_t imap = 0; imap < mapBomElements.size(); imap++) { // hard coded section for adding corresponding icons // typically, these information would be stored as attribute, or extracted from a PLM std::string sIconId; if (mapBomElements[imap].m_attrib == "HOUSING") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_housing.jpg"); else if (mapBomElements[imap].m_attrib == "CYLINDER LINER") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_cylinderliner.jpg"); else if (mapBomElements[imap].m_attrib == "HOUSING TOP") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_housingtop.jpg"); else if (mapBomElements[imap].m_attrib == "MOBILE PART") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_mobilepart.jpg"); else if (mapBomElements[imap].m_attrib == "PUSH ROD") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_pushrod.jpg"); else if (mapBomElements[imap].m_attrib == "BEARING PR DW") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_bearing_prdw.jpg"); else if (mapBomElements[imap].m_attrib == "BEARING PR UP") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_bearing_prup.jpg"); else if (mapBomElements[imap].m_attrib == "AXE") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_axe.jpg"); else if (mapBomElements[imap].m_attrib == "PISTON") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_piston.jpg"); else if (mapBomElements[imap].m_attrib == "CRANKSHAFT") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_crankshaft.jpg"); else if (mapBomElements[imap].m_attrib == "BEARING CS") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_bearingcs.jpg"); else if (mapBomElements[imap].m_attrib == "HOUSING BACK") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_housingback.jpg"); else if (mapBomElements[imap].m_attrib == "HOUSING FRONT") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_housingfront.jpg"); else if (mapBomElements[imap].m_attrib == "SCREW BACK") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_screwback.jpg"); else if (mapBomElements[imap].m_attrib == "SCREW TOP") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_screwtop.jpg"); else if (mapBomElements[imap].m_attrib == "CARBURETOR") sIconId = stStoreIcon(pDoc, sPathIcons + "microengine_carburetor.jpg"); else sIconId = ""; std::vector aOneRow; aOneRow.push_back(intToString((int)imap)); iKeyBomNumArt = (int)aOneRow.size() - 1; aOneRow.push_back(mapBomElements[imap].m_name); aOneRow.push_back(mapBomElements[imap].m_attrib); iKeyBomNamePart = (int)aOneRow.size() - 1; aOneRow.push_back(sIconId); iKeyBomIcon = (int)aOneRow.size() - 1; aOneRow.push_back(intToString(mapBomElements[imap].m_iQty)); iKeyBomQty = (int)aOneRow.size() - 1; aTableBomRows.push_back(aOneRow); } iRet = stCreateTable(pDoc, aTable3DRows, pDataTable3D); iRet = stCreateTable(pDoc, aTableBomRows, pDataTableBom); iRet = stCreateRelationship(pDoc, aMapIndexes_3dToBom, pDataTable3D, pDataTableBom); iRet = stCreateRelationship(pDoc, aMapIndexes_BomTo3D, pDataTableBom, pDataTable3D); CHECK_RET(A3DPDFGetModelFileNodes(nullptr, nullptr, &pModelFileNodesInfo)); return iRet; }