##############################
Creating Topology PRC Entities
##############################

The Exchange API Reference groups the PRC entities that specify topology into the topology module.
The topology module uses a hierarchy of faces to define the shapes of 3D objects.

* Create a null pointer to a topology B-rep data entity.

.. code-block:: c

   A3DTopoBrepData* pTopoBrepData = NULL;

.. note::

   Do not confuse the `A3DTopoBrepData` entity with the `A3DTopoBrepDataData` structure.

The former references a PRC entity (an opaque type), while the latter reveals the data in that entity.

* For each topology connex data in the B-rep data entity, create a pointer that references a populated topology connex (See :doc:`building_prc_4`). In the following example, `createTopoConnex` is a private function that returns a reference to a populated topology connex entity.

.. code-block:: c

   A3DTopoConnex* p = createTopoConnex();

* If the B-rep representation item references multiple topology connex entities, allocate memory for an array of references to the topology connexes in the B-rep data entity.

* Declare and initialize a :struct:`A3DTopoBrepDataData` structure. Set the `m_ppConnexes` member to reference the array of topology connex entities, and set the `m_uiConnexSize` member to the number of entries in the array.

.. code-block:: c

   A3DTopoBrepDataData sData = A3D_MAKE_DATA(A3DTopoBrepDataData);

   sData.m_ppConnexes = &p;
   sData.m_uiConnexSize = 1;

* Package the :struct:`A3DTopoBrepDataData` structure as a PRC entity by invoking the :struct:`A3DAsmPartDefinitionCreate` function.
  The first argument is a pointer to the B-rep-data data structure (:func:`A3DTopoBrepDataData`), and the second is the pointer to the B-rep data entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoBrepDataCreate(&sData, &pTopoBrepData);

* Declare a pointer to a topology connex entity.

.. code-block:: c

   A3DTopoConnex* pTopoConnex = NULL;

* For each topology shell in the topology connex entity, create a pointer that references a populated topology shell entity. (See :doc:`building_prc_4`.) In the following example, `createTopoShell` is a private function that returns a reference to a populated topology shell entity.

.. code-block:: c

   A3DTopoShell* p = createTopoShell();

* If the topology connex entity references multiple topology shell entities, allocate memory for an array to accommodate each topology shell entity pointer.

* For each topology shell in the topology connex entity, create a pointer that references a populated topology shell entity. (See :doc:`building_prc_4`.) In the following example, `createTopoShell` is a private function that returns a reference to a populated topology shell entity.

.. code-block:: c

   A3DTopoShell* p = createTopoShell();

* Declare and initialize an :struct:`A3DTopoConnexData` structure.
  Set the `m_ppShells` member to reference the array that contains the pointers, and set the `m_uiShellSize` member to the number of pointers.

.. code-block:: c

   A3DTopoConnexData sData = A3D_MAKE_DATA(A3DTopoConnexData);

   sData.m_ppShells = &p;
   sData.m_uiShellSize = 1;

* Package the topology connex data as a PRC entity by invoking the `A3DTopoConnexCreate` function. The first argument is a pointer to the B-rep-data data structure (`A3DTopoBrepDataData`), and the second is the pointer to the topology connex entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoConnexCreate(&sData, &pTopoConnex);

* Declare a null pointer to a topology shell entity.

.. code-block:: c

   A3DTopoShell* pTopoShell = NULL;

* If the topology shell references multiple topology face entities, create an array to accommodate each pointer.

* For each topology face in the topology shell, create a pointer that references a populated topology face entity. (See :doc:`building_prc_4`.) In the following example, `createTopoFace` is a private function that returns a reference to a populated topology shell entity.

.. code-block:: c

   A3DTopoFace* p = createTopoFace();

* Declare and initialize an `A3DTopoShellData` structure. Set the `m_ppFaces` member to reference the array of topology face entities, and set the `m_uiFaceSize` member to the number of topology shell face entities.

.. code-block:: c

   A3DTopoShellData sData = A3D_MAKE_DATA(A3DTopoShellData);

   sData.m_ppFaces = &p;
   sData.m_uiFaceSize = 1;

* Set the :func:`A3DTopoShellData` structure's `m_pucOrientationWithShell` member to reference an A3DUns8 integer that specifies the orientation of the surface normal with respect to the shell normal.
  If the shell is closed and otherwise arbitrary, the shell normal points outside the material. The following example specifies that the surface normal has the same orientation as the face and shell.

.. note::

   Despite the simplicity of the values it expresses, the `m_pucOrientationWithShell` is a pointer to an `A3DUns8` integer; it is not itself an `A3DUns8` integer.

.. code-block:: c

   A3DUns8 orient = 1;
   sData.m_pucOrientationWithShell = &orient;

* Package the topology shell data as a PRC entity by invoking the :func:`A3DTopoShellCreate` function.
  The first argument is a pointer to the topology shell data, and the second is the pointer to the topology shell entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoShellCreate(&sData, &pTopoShell);

The example described here UV-maps onto a cylinder surface a topology loop representing a circular band.

* Declare a null pointer to a topology face entity.

.. code-block:: c

   A3DTopoFace* pTopoFace = NULL;

* If the topology face references multiple loop entities, declare an array to accommodate each pointer.

* For each loop in the topology face, create a pointer that references a populated loop entity.
  (See :doc:`building_prc_4`). In the following example, `createTopoLoop` is a private function that returns a reference to a populated loop entity.

.. code-block:: c

   A3DDouble outerradius = 0.5;
   A3DDouble innerradius = 0.4;
   A3DTopoLoop* loops[2];
   loops[0] = createTopoLoop(outerradius);
   loops[1] = createTopoLoop(innerradius);

* Declare and initialize an :struct:`A3DTopoFaceData` structure. Set the `m_ppLoops` member to reference the array of loop entity pointers, and set the `m_uiLoopSize` member to the number of loop entities in the array. Set the `m_uiOuterLoopIndex` member to the array index of the topology loop that describes the outer loop. If unknown, set that member to `A3D_LOOP_UNKNOWN_OUTER_INDEX`.

In the following example, `m_uiOuterLoopIndex` indicates that the outer loop is the first entry in the loops array.

.. code-block:: c

   A3DTopoFaceData sData = A3D_MAKE_DATA(A3DTopoFaceData);
   sData.m_ppLoops = loops;
   sData.m_uiLoopSize = 2;
   sData.m_uiOuterLoopIndex = 0;

* Declare a pointer that references a populated surface base entity. (:doc:`building_prc_5`) Set the `m_pSurface` member of the `A3DTopoFaceData` structure to reference the populated surface. In the following example, `createSurface`  is a private function that returns a reference to a populated cylinder surface entity.
  The returned value is cast as a pointer to a surface base.

.. code-block:: c

   A3DSurfBase * p = createSurface();
   sData.m_pSurface = p;

* Package the topology face data as a PRC entity by invoking the `A3DTopoFaceCreate` function. The first argument is a pointer to the topology face data, and the second is the pointer to the topology face entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoFaceCreate(&sData, &pTopoFace);

A loop is a connected series of co-edges and describes the boundary of a face.
Generally, loops are closed, having no start or end point.

* Declare a null pointer to a topology loop entity.

.. code-block:: c

   A3DTopoLoop* pTopoLoop = NULL;

* If the topology loop references multiple co-edge entities, declare an array to accommodate each pointer.
* For each co-edge in the loop, do the following:

  * Create a pointer that references a populated circle entity with a given radius. (:doc:`building_prc_5`)
  * Create a pointer that references a populated co-edge entity with a given curve. (:doc:`building_prc_6`)

In the following example, `createCircle` is a private function that takes a radius and returns a reference to a populated circular curve entity, and `createTopoCoEdge` is a private function that takes a pointer to a circle entity and returns a reference to a populated co-edge entity. The circle-entity describes a curve.

.. code-block:: c

   A3DCrvBase* p = createCircle(radius);
   A3DTopoCoEdge* q = createTopoCoEdge(p);

* Declare and initialize an `A3DTopoLoopData` structure. Set the `m_ppCoEdges` member to reference the array of co-edge entity pointers, and set the `m_uiCoEdgeSize` member to the number of entities in the array.

.. code-block:: c

   A3DTopoLoopData sData = A3D_MAKE_DATA(A3DTopoLoopData);
   sData.m_ppCoEdges = &q;
   sData.m_uiCoEdgeSize = 1;

* Set the `A3DTopoLoopData` structure's `m_ucOrientationWithSurface` member to specify the orientation of the loop relative to the surface normal vector. The following example specifies that the orientation is perpendicular to the surface normal vector (or parallel with the surface).

.. code-block:: c

   sData.m_ucOrientationWithSurface = 1;

* Package the topology face data as a PRC entity by invoking the `A3DTopoLoopCreate` function. The first argument is a pointer to the topology loop data, and the second is the pointer to the topology loop entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet=A3DTopoLoopCreate(&sData, &pTopoLoop);

A co-edge is a directed edge.
The two co-edges related to an edge point in the same or opposite directions along the edge.
Each co-edge is associated with a loop of one of the two neighboring/adjacent faces.

* Create a pointer to a populated `A3DTopoEdge` entity. (See :doc:`building_prc_4`.)

* Declare and initialize a topology co-edge data entity.

* Set the m_pUVCurve member of the data entity to reference the circle entity created earlier (see :doc:`building_prc_4`).
  Set the `m_pEdge` member to the edge entity created in Step 1.

NOTE: To set the value of the m_pUVCurve member using meaningful data, you need your own modeler.

.. code-block:: c

   A3DTopoCoEdgeData sData = A3D_MAKE_DATA(A3DTopoCoEdgeData);
   sData.m_pUVCurve = p;
   sData.m_pEdge = q;

* Set the `m_ucOrientationWithLoop` member to indicate the relative orientation of the loop.

.. code-block:: c

   sData.m_ucOrientationWithLoop = 1;	 /* Same orientation as the adjacent co-edge */
   sData.m_ucOrientationUVWithLoop = 1;

* Package the co-edge data as a PRC entity by invoking the `A3DTopoEdgeCreate` function. The first argument is a pointer to the topology loop data, and the second is the pointer to the topology edge entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoCoEdgeCreate(&sData, &pp);

* Declare a null pointer to a topology edge entity.

.. code-block:: c

   A3DTopoEdge* pTopoEdge = NULL;

* Declare and initialize a topology edge data structure.

.. code-block:: c

   A3DTopoEdgeData sData = A3D_MAKE_DATA(A3DTopoEdgeData);

* Populate the members with data.

* Package the topology face data as a PRC entity by invoking the `A3DTopoEdgeCreate` function. The first argument is a pointer to the topology loop data, and the second is the pointer to the topology edge entity created in Step 1.

.. code-block:: c

   A3DInt32 iRet = A3DTopoEdgeCreate(&sData, &pTopoEdge);

