BimCT SDK / WebGL2 Viewer
    Preparing search index...

    BimCT Getting Started - Angular + TypeScript

    🚀 Try it Now in Playground

    You can download a sample Angular project from here

    • Node.js (v16 or higher)
    • npm
    • Angular CLI installed globally (npm install -g @angular/cli)
    • BimCT npm registry access (contact Nomitech)

    This guide presumes you have already Node.js, npm and Angular CLI 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.

    Create a .npmrc file in your project root with the following content:

    @nomitech:registry=https://npm.nomitech.com/
    

    Login to the Nomitech npm registry:

    Contact Nomitech to request npm registry credentials, then login using:

    npm login --registry=https://npm.nomitech.com/ --scope=@nomitech
    

    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 = "wasm32"; // can also use wasm64 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) {
    const preference = "wasm32"; // can also use wasm64 and wasm-threads32
    await loadBimEngineScripts("/assets", preference);
    await initializeBimEngineCore({});
    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