###############
|HCNOW| for BIM
###############

.. program:: converter

.. toctree::
   :maxdepth: 1
   :caption: Table of Contents

   bcf-format
   floorplan-2d


In this chapter, we will discuss some of the features in |HCNOW| specific to the Building and Construction industry.


Supported formats
=================

A list of all supported formats of |HCNOW| can viewed in the :doc:`File Formats Reference Page </overview/supported-formats>`.

The file formats specifically relevant to BIM are:

* IFC
* Revit
* DWG 2D/3D and DXF



IFC
===

After an IFC file has been converted to the Stream Cache format, it can be viewed and interrogated in the HOOPS Web Viewer. The Model Tree in the case of an IFC model is derived from its structural building hierarchy (IFCBUILDING->IFCFLOOR->IFCSPACE…) with additional properties and attributes stored on the nodes of the model. The GlobalIDs of an IFC file are also stored among those attributes. More information on how to parse attributes in a model can be found :doc:`here </prog_guide/viewing/data_model/model-tree>`.

You can also export IFC data file to an XML file with the :option:`--output_xml_assemblytree` command line option which you can then use to parse that attribute data outside of the viewer.

.. image:: images/BIM_IFCWall.png

*Properties for a IFCWall element displayed in the HOOPS Web Viewer*


IFC types
---------

When loading a Stream Cache model converted from an IFC file into the HOOPS Web Viewer you can get a list of all IFC Types that exist in the model with the :ref:`getGenericTypes() <api_ref/viewing/classes/Communicator.Model:getgenerictypes>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_gettypes]
	:end-before: //! [webviewer_BIM_gettypes]

Result:
	
.. code-block:: none

	"IFCPROJECT"

	"IFCSITE"

	"IFCBUILDING"

	"IFCBUILDINGSTOREY"

	"IFCSPACE"

	"IFCSLAB"

	"IFCBEAM"

	"IFCRAMP"

	"IFCCOLUMN"

	...

Given the types above, you can get a list of nodes for a specific IFC type with the :doc:`getNodesByGenericType() </api_ref/viewing/classes/Communicator.Model:getnodesbygenerictype>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_getnodesbytype]
	:end-before: //! [webviewer_BIM_getnodesbytype]

To query the IFC type of an individual node, you can use the :doc:`getNodeGenericType() </api_ref/viewing/classes/Communicator.Model:getnodesbygenerictype>` function below:

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_getnodetype]
	:end-before: //! [webviewer_BIM_getnodetype]
	
.. image:: images/BIM_highlighted.png

*An IFC model with all elements of type IFCDOOR highlighted.*


Spatial Relationships
---------------------

|HCNOW| supports spatial relationships for BIM elements in IFC files. Each BIM element has an ID, represented as a string. Relationships must be imported when the CAD file is loaded. The following options are available:

**ifc_import_relationships**: If set, relationships set in an IFC CAD file will be imported. The default value is ``true``.

**ifc_import_openings**: If set, opening elements in the CAD file will be imported and seen as a node in the Viewer. The default value is ``false``.

.. admonition: Note

	Not all IFC elements correspond to an actual element in the model tree. For instance, if the option ``ifc_import_openings setting`` is ``false``, IFC opening elements are not converted and have no entry in the tree, no corresponding node ID.

Here's an example of how to get BIM information from a selection event:

.. code-block:: js

	var selection = selectionEvent.getSelection();
	var nodeId = selection.getNodeId();
	var bimId = hwv.model.getBimIdFromNode(nodeId);
	
	console.log("bimInfo == " + JSON.stringify(hwv.model.getBimInfoFromBimId(nodeId, bimId), null, 2));

Result:

.. code-block:: none

	bimInfo == {
		"name": "Basic Wall:Generic - 500mm:214590",
		"connected": true
	}
	
Using the ``bimId``, we can get the IDs of related elements. For example, to get the related element IDs for ``ContainedInSpatialStructure``:

.. code-block:: none

	containedInSpatialStructure = hwv.model.getBimIdRelatingElements(nodeId, bimId, Communicator.RelationshipType.ContainedInSpatialStructure);
	
	for (var i = 0; i < containedInSpatialStructure.length; i++) {
		console.log(JSON.stringify(containedInSpatialStructure[i]));
	}
	
In general, functions that end in "FromBimId" can be used to query the model using a BIM ID. For example: ``getNodeIdFromBimId(nodeId, bimId)``. Other useful functions:

* :js:func:`getBimIdFromNode <Communicator.Model.getBimIdFromNode(node)>`
* :js:func:`getBimIdsFromGenericId <Communicator.Model.getBimIdsFromGenericId(node)>`
* :js:func:`getNodeIdFromBimId <Communicator.Model.getNodeIdFromBimId(bimId)>`
* :js:func:`getGenericIdFromBimId <Communicator.Model.getGenericIdFromBimId(node, bimId)>`
* :js:func:`getRelationshipTypesFromBimId <Communicator.Model.getRelationshipTypesFromBimId(node, bimId)>`
* :js:func:`getBimIdRelatedElements <Communicator.Model.getBimIdRelatedElements(node, bimId, type)>`
* :js:func:`getBimIdRelatingElements <Communicator.Model.getBimIdRelatingElements(node, bimId, type)>`
* :js:func:`getBimIdConnectedElements <Communicator.Model.getBimIdConnectedElements(node, bimId, type)>`
* :js:func:`getBimInfoFromBimId <Communicator.Model.getBimInfoFromBimId(node, bimId)>`

The |HCNOW| demo UI also supports IFC relationships. In the image below, the window has been selected. The chart on the left (under the model tree) shows the elements related to the window: ``ContainedInSpatialStructure``, ``FillsElement``, and ``SpaceBoundary``.

.. image:: images/spatial_relationships.png


IFC Layers
----------

|HCNOW| will convert all `IFCPRESENTATIONLAYERASSIGNMENT`` elements in IFC models to layers that can be queried in the HOOPS Web Viewer. To find out more about layers please refer to this :doc:`Programming Guide entry </prog_guide/viewing/data_model/layers-filters>`.


IFC GlobalID
------------

When an IFC model is converted to a Stream Cache the IFC ``GlobalId`` attribute of an entity is not only available by querying the properties of the node but can also be accessed directly via the :ref:`getNodeGenericId() <api_ref/viewing/classes/Communicator.Model:getnodegenericid>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_getGenericID]
	:end-before: //! [webviewer_BIM_getGenericID]
	
Result:

.. code-block::

	"06MIg93QbEyhsz9Us1N2lq" 

To retrieve a list of nodes ids based on their generic id you can use the :ref:`getNodeIdsByGenericIds() <api_ref/viewing/classes/Communicator.Model:getnodeidsbygenericids>` function, which takes a list of generic IDs and returns their corresponding :ref:`NodeIds <api_ref/viewing/modules/Communicator:nodeid>`.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_getNodeIdsGenericID]
	:end-before: //! [webviewer_BIM_getNodeIdsGenericID]
	
Result:

.. code-block:: none

	[8813]


IFC Walk Operator
-----------------

When loading a Stream Cache Model converted from an IFC file, the keyboard-based walk operator uses a set of predefined IFC types to determine walls and floors in a model. Based on that information it can perform collision detection as the user navigates through the model, automatically adjusting the height of the camera to the floor and blocking movement through walls.

To activate the keyboard-based walk operator and enable collision detection please see the code below:

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_walk]
	:end-before: //! [webviewer_BIM_walk]

Please note that activating collision detection can affect performance with larger models.

See below for the default keys when using keyboard-based walk: 

.. image:: images/BIM_default_keys.png

*Properties for a IFCWall element displayed in the HOOPS Web Viewer*



Revit
=====

Revit support has been officially introduced with |HCTHEN| 2019 and has seen constant improvements. Currently, it offers support for:

* Node attributes
* 3D views
* Layers
* Textures and colors
* Linked views

Support for 2D Views (elevation views, etc) and other enhancements are planned for a future release.

.. image:: images/BIM_revit_example.png

*Revit example model with part properties*


DWG
===

|HCNOW| supports 2D and 3D content within a DWG file with the ability to display each sheet in a DWG file as well as the 3D geometry.


.. _overview_importing_dwg:

Importing DWGs
--------------

When importing DWG files you can specify if you are only interested in the 2D (drawing) content, the 3D data within a DWG file or both with the :option:`--drawings_mode` Converter command line option.
If you choose both then the sheet tab in the model browser will contain all sheets as well as the 3D model.


Sheets
------

When a DWG file has been imported with drawings enabled then each sheet will be visible in the Sheet tab in the model browser. By clicking on a sheet in the model browser the HOOPS Web Viewer will switch to the new sheet.

To find all sheets in a model when writing your UI programmatically you can use the :ref:`getSheetIds() <api_ref/viewing/classes/Communicator.WebViewer:getsheetids>` function which returns a list of ``NodeIds`` for each sheet representing the top-level node for each sheet.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_findsheets]
	:end-before: //! [webviewer_BIM_findsheets]
	
Results:

.. code-block:: none

	[4, 56706]

You can also get the NodeId of the currently active sheet with the :ref:`getActiveSheetId() <api_ref/viewing/classes/Communicator.WebViewer:getactivesheetid>` function.

To switch to a new sheet you can use the :ref:`setActiveSheetId() <api_ref/viewing/classes/Communicator.WebViewer:setactivesheetid>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_BIM_setsheet]
	:end-before: //! [webviewer_BIM_setsheet]
	
When a 2D sheet is activated the HOOPS Web Viewer will automatically switch to "drawing mode", ensuring that camera manipulation is constrained, and a drawing background is added to the model.

.. image:: images/BIM_DWG_file.png

*Properties for an IFCWall element displayed in the HOOPS Web Viewer*

By default, the HOOPS Web Viewer will display a drawing sheet on a white background with a dark grey shadow effect on top of a grey window background. You can change the color of both backgrounds and the shadow with the :ref:`setSheetColors() <api_ref/viewing/classes/Communicator.WebViewer:setsheetcolors>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_bim_sheetcolors]
	:end-before: //! [webviewer_bim_sheetcolors]

You can also choose to turn off the sheet background altogether with the :ref:`setBackgroundSheetEnabled() <api_ref/viewing/classes/Communicator.WebViewer:setbackgroundsheetenabled>` function.

.. literalinclude:: /../../applications/client/docs/PG_BIM_Overview.ts
	:start-after: //! [webviewer_bim_sheetbackgroundisabled]
	:end-before: //! [webviewer_bim_sheetbackgroundisabled]

.. image:: images/BIM_model_no_sheet_background.png

*Properties for a IFCWall element displayed in the HOOPS Web Viewer*


Federated models in BIM
=======================

A common concept in BIM is to break up large building projects into multiple disciplines (Architectural, Plumbing, Mechanical, etc.)  each worked on by different teams and often represented by their model files. To support this workflow |HCNOW| allows you to easily aggregate models in the HOOPS Web Viewer using the loadSubtree functionality.

For more information about model aggregation please see the :doc:`Loading Subtrees Programming Guide </prog_guide/viewing/data_model/stream_cache/loading-subtrees>`.
