You can download a sample Angular project from here

Create a new Project

This guide presumes you have already Nodejs, Npm and Angular installed as a global package

Create a new folder and execute the following command in powershell

ng new bimct-viewer-app

The command will prompt you for some questions on how to create the project. The answers depend on the scope of your application.

For this guide just accept the defaults by pressing enter.

After the command is finished a new folder will be created with a skeleton angular application.

Note: All the commands and files mentioned from now and on should be run/edited on the newly created bimct-viewer-app folder.

Setup npm registry

To download Nomitech's propriaty packages you need to setup

To do so on the newly created folder create a file named .npmrc with the following contents

@nomitech:registry=https://repo.nomitech.com/repository/npm-bimct-viewer/

To login to this registry run the following command on Powershell

npm login --registry=https://repo.nomitech.com/repository/npm-bimct-viewer/

This will create a .npmrc file in your home folder with the following contents

  //repo.nomitech.com/repository/npm-bimct-viewer:_authToken=NpmToken.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

Add bimct-viewer package

Run the following command to install the latest version of bimct-viewer

npm install @nomitech/bimct-viewer --save

Setup angular.json

Edit the file angular.json and perform the following changes

Find the following path in this json file

projects["bimct-viewer-app"].architect.build.options

Change the assets property so that it looks like this

"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*",
"input": "./node_modules/@nomitech/bimct-viewer/dist/assets",
"output": "./assets",
"ignore": ["wasm/*", "assets/fonts"]
},
{
"glob": "**/*",
"input": "./node_modules/@nomitech/bimct-viewer/dist/assets/fonts",
"output": "./assets/assets/fonts"
},
{
"glob": "bimct-viewer.css",
"input": "./node_modules/@nomitech/bimct-viewer/dist",
"output": "./assets"
},
{
"glob": "**/*",
"input": "./node_modules/cesium/Build/Cesium/Workers",
"output": "./assets/cesium/Workers"
},
{
"glob": "**/*",
"input": "./node_modules/cesium/Build/Cesium/ThirdParty",
"output": "./assets/cesium/ThirdParty"
},
{
"glob": "**/*",
"input": "./node_modules/cesium/Build/Cesium/Assets",
"output": "./assets/cesium/Assets"
},
{
"glob": "**/*",
"input": "./node_modules/cesium/Build/Cesium/Widgets",
"output": "./assets/cesium/Widgets"
}
],

The assets configiration tell the angular compiler to copy files to the assets directory of the application

Additionally change the main.ts file to include the cesium base url for the maps to work, so add the following line before the call to bootstrapApplication function:

(window as any).CESIUM_BASE_URL = '/assets/cesium';

Setup index.html

Edit the file src/index.html

Add the following line inside the head tag

<link rel="stylesheet" href="assets/bimct-viewer.css" />

This will load globaly the bimct-viewer.css

Setup the app components

Setup the HTML

Edit the src/app/app.component.html

Replace the contents of the file with the following

<div class="content" role="main">
<div #bimctViewer id="bimct-viewer">
</div>
</div>

Setup the CSS

Edit the src/app/app.components.css

Replace the contents of the file with the following

:host {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}

.content {
flex-grow: 1;
display: flex;
}

#bimct-viewer {
flex-grow: 1;
}

This will make the bimct-viewer element to fill the whole page

Note: The div must have non-zero width and height for the application to work correctly

Setup the Code

Edit the src/app/app.component.ts

Replace the contents of the file with the following

import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { initializeBimEngineCore, BimCTWebGL2Renderer, RendererInititializationOptions, MEASUREMENT_SYSTEM, MAP_TILE_TYPE, MAP_SERVER } from '@nomitech/bimct-viewer'
import { MAP_SEARCH_SERVICE } from '@nomitech/bimct-viewer/dist/lib/webservices/geosearch';

let isEngineInitialized = false;

const options: RendererInititializationOptions = {
// Auto-pause the drawing loop after 5 seconds of inactivity:
ecoRenderingOn: true,
// Use a skymap ('grass', 'dessert' or null)
skymapId: 'desert',
// Enable Sunlight (realistic mode only)
sunLight: true,
// Enable Shadows from Sunlight (realistic mode only)
shadowMaps: true,
// Use BimCT UIs (can turn anything on off):
gui: {
useContextMenu: true, // right click menu
useToolbar: true, // bottom line toolbar
useLeftToolbar: true, // tools toolbar on the left
useHomeToolbar: true, // home toolbar (below camera cube)
useSettingsWindow: true, // settings window
useDesignTreeWindow: true, // design tree window
useSnapshotWindow: true, // snapshot/screenshots enabling window
useViewsWindows: true, // snapshot window
useMessageBoxes: true, // enable message oxes with messageBox function
usePropertiesWindow: true, // properties window
useFilterElementsWindow: true, // filter elements window
useTouchWidget: true, // use Touch 'Thumb Widget' on mobile devices
useWebXRWindow: true, // use window for showing and enabling WebXR (Virtual Reality)
useQuantitiesLabel: true, // show a label on the top left area of the screen when picking elements or faces or lines or measurements
map: {
visible: true, // show map initially
}
},
//enhancedSilhouettes: false, // enable enahnced silhouettes
snappingEnabled: true, // use this to enable O-Snaps
preloadProperties: false, // preload properties to the javascript memory (warn increases memory)
measurementSystem: MEASUREMENT_SYSTEM.METRIC, // either imperial (USA) or metric (Rest of World)
logging: { // Enable BimCT logging
console: {
comments: false,
debug: false,
errors: true,
warnings: true
}
},
maps: {
allowed: [MAP_SERVER.ESRI, MAP_SERVER.BING, MAP_SERVER.OSM],
default: { server: MAP_SERVER.ESRI, type: MAP_TILE_TYPE.HYBRID },
search: {
service: MAP_SEARCH_SERVICE.NOMINATIM,
},
},
}

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit, AfterViewInit {
@ViewChild("bimctViewer") bimctViewerElement!: ElementRef;
private renderer!: BimCTWebGL2Renderer;


title = 'bimct-viewer-app';

async ngOnInit() {
//
}

async ngAfterViewInit() {
await this.initializeEngine();
this.renderer = new BimCTWebGL2Renderer(this.bimctViewerElement.nativeElement, options);
await this.renderer.init();
this.renderer.selectionChangeEvent.subscribe((renderer, elements) => {
console.log('Elements selected: ', elements);
});
await this.renderer.loadModelFromUrl("assets/InstituteProps.bimct");
this.renderer.beginDrawLoop();
}

async initializeEngine() {
if (!isEngineInitialized) {
const preference = "wasm64"; // can alos use wasm32 and wasm-threads32
await loadBimEngineScripts("/assets", preference);
await initializeBimEngineCore({});
isEngineInitialized = true;
}
}
}

Setup the sample BIM file

Copy the file InstituteProps.bimct to the folder src/assets/

Build the application

Run the following command

ng build

This will build everything on the dist folder

Test the application

Run the following command

ng serve

This will start a server on a port, usually 4200. Check the output of the command to see the port number.

Open your browser on http://localhost:4200/ to use the application

Typescript code explanation

let isEngineInitialized = false;

async initializeEngine(){
if (!isEngineInitialized) {
await initializeBimEngineCore({ wasmBinaryUrl: "assets/BIMEngine-Core.wasm" });
isEngineInitialized = true;
}
}

The engine must be initialized exactly one time before a renderer is created. To make sure that this is the case we have created a variable outside the class that will keep the initialization state.

  <div #bimctViewer id="bimct-viewer">
</div>
@ViewChild("bimctViewer") bimctViewerElement!: ElementRef;

Here we get a reference for the bimct-viewer div from html to Typescript

const options: RendererInititializationOptions = {
...
}

This are the initialization options of the renderer. See the renderer reference for all options

this.renderer = new BimCTWebGL2Renderer(this.bimctViewerElement.nativeElement, options);
await this.renderer.init();
...
this.renderer.beginDrawLoop();

Create a renderer object using the bimctViewer element injected above, as well the defined options and then initialize the renderer. Finally tell the renderer to start the animation.

    this.renderer.selectionChangeEvent.subscribe((renderer, elements) => {
console.log('Elements selected: ', elements);
});

Subscribe to one of the renderer events.

    await this.renderer.loadModelFromUrl("assets/InstituteProps.bimct");

Load a model to the renderer