Files
Hoops_Exchange/publish/publishsource/DemoDataModel/DemoDataModelData.cpp
2025-12-15 22:10:55 +08:00

1341 lines
46 KiB
C++
Raw Permalink Blame History

/***********************************************************************************************************************
*
* 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 <A3DSDKIncludes.h>
#include "../common.hpp"
#include <cstdlib>
#include <sstream>
#include <ostream>
#include <iostream>
#include <vector>
#include <map>
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<std::vector<std::string> > &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 <size_t, size_t> > &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<BomElement> mapBomElements, const std::string& sKeyAttrib, size_t& idxinbommap);
static bool isInMapByName(const std::vector<BomElement> 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<size_t> m_NodeIndexes;
};
bool BomElement::isInMapByKeyAttrib(
const std::vector<BomElement> 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<BomElement> 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<61>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<std::vector<std::string> > aTable3DRows;
std::vector<std::vector<std::string> > aTableBomRows;
// structure for Relationships definitions
std::vector< std::pair <size_t, size_t> > aMapIndexes_3dToBom;
std::vector< std::pair <size_t, size_t> > aMapIndexes_BomTo3D;
std::vector< std::pair <size_t, size_t> > aMapIndexes_BomToManufacturers;
std::vector<BomElement> mapBomElements;
// parse the 3D PDF nodes
A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL;
CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pPRCWriteHelper, &pModelFileNodesInfo));
std::map<std::string, int> 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<std::string, int>::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<std::string> 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<std::string> 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<std::vector<std::string> > aRows;
std::vector<std::string> 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 <size_t, size_t> > 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<std::vector<std::string> > aTable3DRows;
std::vector<std::vector<std::string> > aTablePmis;
// structure for Relationships definitions
std::vector< std::pair <size_t, size_t> > aMapIndexes_3dToPmis;
std::vector< std::pair <size_t, size_t> > aMapIndexes_PmisTo3d;
// parse the 3D PDF nodes
A3DPDFModelFileNodesData* pModelFileNodesInfo = NULL;
CHECK_RET(A3DPDFGetModelFileNodes(pModelFile, pPRCWriteHelper, &pModelFileNodesInfo));
std::map<std::string, int> 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<std::string> aOneRow3d;
aOneRow3d.push_back(nodeInfos->m_pcNodeUid); iKeyNode3dUID = (int)aOneRow3d.size() - 1;
aTable3DRows.push_back(aOneRow3d);
std::vector<std::string> 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<std::vector<std::string> > aAddedAttribs;
std::vector<std::string> 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 <size_t, size_t> > 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 <size_t, size_t> > 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<std::vector<std::string> > aRows;
std::vector<std::string> 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<std::vector<std::string> > aTable3DRows;
std::vector<std::vector<std::string> > aTableBomRows;
// structure for Relationships definitions
std::vector< std::pair <size_t, size_t> > aMapIndexes_3dToBom;
std::vector< std::pair <size_t, size_t> > aMapIndexes_BomTo3D;
std::vector<BomElement> 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<std::string> 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<std::string> 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;
}