You can download a sample Angular project from here
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.
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
Run the following command to install the latest version of bimct-viewer
npm install @nomitech/bimct-viewer --save
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';
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
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>
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
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;
}
}
}
Copy the file InstituteProps.bimct to the folder src/assets/
Run the following command
ng build
This will build everything on the dist folder
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
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