:orphan:
##################################
Product Occurrences -- Code Sample
##################################

The following diagram and code are provided to assist with parsing Product Occurrences in Exchange.
Please see the \ref product_occurrence "Programming Guide" for more information.

.. image:: /_assets/images/prc_traverse.png
   :align: center

.. code-block:: c

   /*
   * This template traverses all PO / RI / BREP / Connex / Shell / Face / Loop / Co Edge / Edge

   #include <stdio.h>
   #include <iostream>

   #define INITIALIZE_A3D_API
   #include <A3DSDKIncludes.h>

   //##############################
   #define CHECK_RET(function_call) {\
           iRet = function_call; if(iRet != A3D_SUCCESS) { std::cout << "Error number=" << iRet << std::endl; return iRet; }\
   }

   // #############################
   // Analyze BREP
   A3DStatus traverseCoEdge(const A3DTopoCoEdge* pTopoCoEdge)
   {
       A3DStatus iRet = A3D_SUCCESS;
       A3DTopoCoEdgeData sTopoCoEdgeData = A3D_MAKE_DATA(A3DTopoCoEdgeData);
       CHECK_RET(A3DTopoCoEdgeGet(pTopoCoEdge, &sTopoCoEdgeData));

       // Here is the edge
       // sTopoCoEdgeData.m_pEdge;

       return iRet;
   }

   A3DStatus traverseLoop(const A3DTopoLoop* pTopoLoop)
   {
       A3DStatus iRet = A3D_SUCCESS;
       A3DTopoLoopData sTopoLoopData = A3D_MAKE_DATA(A3DTopoLoopData);
       CHECK_RET(A3DTopoLoopGet(pTopoLoop, &sTopoLoopData));

       for (int i = 0; i < sTopoLoopData.m_uiCoEdgeSize; ++i)
       {
           traverseCoEdge(sTopoLoopData.m_ppCoEdges[i]);
       }

       return iRet;
   }

   A3DStatus traverseFace(const A3DTopoFace* pTopoFace)
   {
       A3DStatus iRet = A3D_SUCCESS;
       A3DTopoFaceData sTopoFaceData = A3D_MAKE_DATA(A3DTopoFaceData);
       CHECK_RET(A3DTopoFaceGet(pTopoFace, &sTopoFaceData));

       for (int i = 0; i < sTopoFaceData.m_uiLoopSize; ++i)
       {
           traverseLoop(sTopoFaceData.m_ppLoops[i]);
       }

       return iRet;
   }

   A3DStatus traverseShell(const A3DTopoShell* pTopoShell)
   {
       A3DStatus iRet = A3D_SUCCESS;
       A3DTopoShellData sTopoShellData = A3D_MAKE_DATA(A3DTopoShellData);
       CHECK_RET(A3DTopoShellGet(pTopoShell, &sTopoShellData));

       for (int i = 0; i < sTopoShellData.m_uiFaceSize; ++i)
       {
           traverseFace(sTopoShellData.m_ppFaces[i]);
       }

       return iRet;
   }

   A3DStatus traverseConnex(const A3DTopoConnex* pTopoConnex)
   {
       A3DStatus iRet = A3D_SUCCESS;
       A3DTopoConnexData sTopoConnexData = A3D_MAKE_DATA(A3DTopoConnexData);
       CHECK_RET(A3DTopoConnexGet(pTopoConnex, &sTopoConnexData));

       for (int i = 0; i < sTopoConnexData.m_uiShellSize; ++i)
       {
           traverseShell(sTopoConnexData.m_ppShells[i]);
       }

       return iRet;
   }

   A3DStatus traverseBREPModel(const A3DRiBrepModel* pBrepModel)
   {
       A3DStatus iRet = A3D_SUCCESS;

       A3DRiBrepModelData sBREPData = A3D_MAKE_DATA(A3DRiBrepModelData);
       CHECK_RET(A3DRiBrepModelGet(pBrepModel, &sBREPData));

       A3DTopoBrepDataData sTopoBrepDataData = A3D_MAKE_DATA(A3DTopoBrepDataData);
       CHECK_RET(A3DTopoBrepDataGet(sBREPData.m_pBrepData, &sTopoBrepDataData));

       for (int i = 0; i < sTopoBrepDataData.m_uiConnexSize; ++i)
       {
           traverseConnex(sTopoBrepDataData.m_ppConnexes[i]);
       }

       return iRet;
   }

   // ######################################################################################################################
   // Traverse Representation Item
   A3DStatus traverseRI(const A3DRiRepresentationItem* pRI)
   {
       A3DStatus iRet = A3D_SUCCESS;

       A3DRiRepresentationItemData sRIData;

       A3DEEntityType eType;
       CHECK_RET(A3DEntityGetType(pRI, &eType));
       if (eType == kA3DTypeRiBrepModel)
       {
           traverseBREPModel(pRI);
       }
       else if (eType == kA3DTypeRiSet)
       {
           A3DRiSetData sRiSetData = A3D_MAKE_DATA(A3DRiSetData);
           CHECK_RET(A3DRiSetGet(pRI, &sRiSetData));

           for (int i = 0; i < sRiSetData.m_uiRepItemsSize; ++i)
           {
               traverseRI(sRiSetData.m_ppRepItems[i]);
           }
       }

       return iRet;
   }

   // ######################################################################################################################
   // Traverse part
   A3DStatus traversePart(const A3DAsmPartDefinition* pPart)
   {
       A3DStatus iRet = A3D_SUCCESS;

       A3DAsmPartDefinitionData sPartData = A3D_MAKE_DATA(A3DAsmPartDefinitionData);
       A3DAsmPartDefinitionGet(pPart, &sPartData);

       for (int i = 0; i < sPartData.m_uiRepItemsSize; i++)
       {
           CHECK_RET(traverseRI(sPartData.m_ppRepItems[i]));
       }

       return iRet;
   }

   // ######################################################################################################################
   // Traverse PO Recursively
   A3DStatus traversePO(const A3DAsmProductOccurrence* pPO)
   {
       A3DStatus iRet = A3D_SUCCESS;

       A3DAsmProductOccurrenceData sPOData = A3D_MAKE_DATA(A3DAsmProductOccurrenceData);
       A3DAsmProductOccurrenceGet(pPO, &sPOData);

       if (sPOData.m_pPart)
       {
           CHECK_RET(traversePart(sPOData.m_pPart));
       }

       for (int i = 0; i < sPOData.m_uiPOccurrencesSize; i++)
       {
           CHECK_RET(traversePO(sPOData.m_ppPOccurrences[i]));
       }

       if (sPOData.m_pPrototype && sPOData.m_uiPOccurrencesSize == 0)
       {
           CHECK_RET(traversePO(sPOData.m_pPrototype));
       }

       return iRet;
   }

   // ######################################################################################################################
   #ifdef _MSC_VER
   int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv)
   #else
   int main(int iArgc, A3DUTF8Char** ppcArgv)
   #endif
   {
       A3DStatus iRet = A3D_SUCCESS;

       if (iArgc != 2)
       {
   #ifdef _MSC_VER
           _tprintf(_T("Usage:\n %s <CAD input file>\n"), ppcArgv[0]);
   #else
           printf("Usage:\n %s <CAD input file>\n", ppcArgv[0]);
   #endif
           return A3D_ERROR;
       }

   #ifdef _MSC_VER
   #	ifdef _WIN64
       const TCHAR* pcLibPath = _T("..\\..\\..\\..\\bin\\win64\\");
   #	else
       const TCHAR* pcLibPath = _T("..\\..\\..\\..\\bin\\win32\\");
   #	endif
   #else
   #	ifdef __APPLE__
       const A3DUTF8Char* pcLibPath = "../../../../bin/osx64";
   #	elif defined(X32)
       const A3DUTF8Char* pcLibPath = "../../../../bin/linux32";
   #	else
       const A3DUTF8Char* pcLibPath = "../../../../bin/linux64";
   #	endif
   #endif

       A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(pcLibPath);
       if (sHoopsExchangeLoader.m_eSDKStatus != A3D_SUCCESS)
           return sHoopsExchangeLoader.m_eSDKStatus;

       A3DImport sImport(ppcArgv[1]);
       sHoopsExchangeLoader.Import(sImport);

       // get Model File
       A3DAsmModelFileData sModelFileData = A3D_MAKE_DATA(A3DAsmModelFileData);
       CHECK_RET(A3DAsmModelFileGet(sHoopsExchangeLoader.m_psModelFile, &sModelFileData));

       // Traverse each PO in Model File
       for (int i = 0; i < sModelFileData.m_uiPOccurrencesSize; ++i)
       {
           CHECK_RET(traversePO(sModelFileData.m_ppPOccurrences[i]));
       }

       return iRet;
   }



