###################
Exchange SC mapping
###################

.. program:: converter

**Please note, this functionality is not publicly exposed in the Exchange API -- please** :doc:`contact us </contact_us>` **if you are interested in using this feature.**

While the Stream Cache (SC) format used in HC is very rich and retains a lot of the data that is associated with a typical CAD model, it is sometimes desirable to have even deeper access to the precise B-rep and attribute data as well as perform calculations that HC does not support directly. Connecting an HC viewing session to Exchange on the server is one way to accomplish this. We currently offer a beta version of the bidirectional StreamCache-Exchange mapping functionality that facilitates these types of workflows. 

The following steps are currently required for this feature to work:

#. When converting the original CAD model to the SC format via Converter, the :option:`--export_exchange_ids` command line options has to be set to ``true``. This step will generate Exchange IDs for every node in the model which can be queried in the WebViewer with a call to ``model.getNodeExchangeId()``.

#. On the server, the :doc:`PRC </prog_guide/viewing/data_model/stream_cache/sc-and-prc>` file associated with the SC model being viewed should be loaded into Exchange via the function ``A3DPrcIdMapCreate()``. The resulting map can then be used to find the Exchange entity associated with the Exchange ID that the viewer has passed to the server. 


Matching conversion parameters
------------------------------

In order for the SC-Exchange mapping to work, the SC file and PRC file must be generated as part of the same conversion process. So, when you run a source model through Converter, you will be generating the SC/SCS file(s) and a PRC file. Additionally, the :option:`--export_exchange_ids` Converter option must be ``true`` and you must also include HOOPS Publish using:

.. code-block:: cpp

	#define HOOPS_PRODUCT_PUBLISH_ADVANCED // needed for A3DPrcIdMap functions

If any of these are left out, the link will not work.

The following code snippet for loading a file in Exchange corresponds with the default parameters from Converter:

.. code-block:: cpp

	A3DAsmModelFile* model_file = nullptr;

	// Set your path to the PRC file generated alongside the SC file from conversion
	auto const input_file = "micro engine.prc";

	A3DStatus load_status = A3DAsmModelFileLoadFromPrcFile(input_file, nullptr, &model_file); // Use this function to load PRC file with Exchange IDs

	A3DPrcIdMap* map = nullptr;

	A3DPrcIdMapCreate(model_file, &map));

Once the CAD file has been loaded, you can get the Exchange ID from the generated XML file, or using ``Model.getNodeExchangeId(nodeId)``. Then, you call ``A3DPrcIdMapFindId()`` to retrieve the corresponding ``A3DEntity`` from your Exchange model. For example:

.. code-block:: cpp

	A3DEntity* exchange_entity = nullptr, * exchange_entity_father = nullptr;

	A3DStatus status = A3DPrcIdMapFindEntity(map,
		"HOUSING(HOUSING.1).c84d3a3194fa594fcda02a26a7f1644da02900" // retrieved this from XML file generated with Converter, this entity is a known "product occurrence" type
		, &exchange_entity, &exchange_entity_father);

	if (A3D_SUCCESS == status) {
		std::cout << "ID found!" << std::endl;
	}
	else {
		std::cerr << "No id found" << std::endl;
		return -1;
	}

The process of parsing an Exchange entity to retrieve data is beyond the scope of this document and will largely depend on your file conversion configuration and the type of data you'd like to extract.


Relationships between entity types
----------------------------------

.. image:: images/entity_mapping_1200px.png


Product occurrences
-------------------

Exchange product occurrences directly correspond to product occurrences in HC.


Representation items
--------------------

To avoid storing the same geometry structure multiple times, Exchange uses the concept of prototypes. When we parse the tree we generate a unique ``exchangeId`` for all traversed entities, so instances of the same prototype representation items will have a unique ``exchangeID``.


Selecting a server framework for HOOPS Exchange
-----------------------------------------------

Currently, HOOPS Communicator provides no functionality to directly communicate with Exchange or to pass ID's to the server. This should be handled by your WebApp directly - for example, via HTTP requests or websocket connections originating from your Javascript client application, passed via REST or some other method to a server running Exchange.

Since most users integrate their applications with Exchange in C++, it's probably most expedient to find a web server framework that can call directly into C++ code. `Restbed <https://github.com/Corvusoft/restbed>`_ is one example.
