0.0.23 • Published 2 years ago

ngx-ifc-viewer v0.0.23

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

IFC-viewer for Angular

Creator: Mads Holten Rasmussen

The library includes my take on an IFC viewer for Angular based on IFC.js.

Install to Angular project

The library uses Angular Material Design, so please install this package beforehand.

npm i --save ngx-ifc-viewer npm i --save three web-ifc-three camera-controls three-fatline npm i --save-dev @types/three

Add to app.module.ts

import { IfcViewerModule } from 'ngx-ifc-viewer';

@NgModule({
  imports: [
    ...,
    IfcViewerModule
  ]
})

Use

See examples of use in the LD-BIM viewer.

Install to non-Angular project

npm i --save ngx-ifc-viewer

Add to HTML body

<ifc-viewer></ifc-viewer>

Copy the files web-ifc.wasm and web-ifc-mt.wasm from the folder node_modules/web-ifc/ to a new folder assets/ifcjs. Add the files IFCWorker.js and IFCWorker.js.map from node_modules/web-ifc-three/.

Add some global styling to buttons that will also affect the buttons in the IFC-viewer (styles.scss):

.btn {
    background-color: DodgerBlue;
    border: none;
    color: white;
    padding: 12px 16px;
    font-size: 16px;
    cursor: pointer;
}

/* Darker background on mouse-over */
.btn:hover {
    background-color: RoyalBlue;
}

Use

See examples of use in the LD-BIM viewer.

Viewer

The viewer inherits the size of its parent div, so the example below will give us a full screen viewer.

<div style="width: 100%; height: 100%">
    <ifc-viewer></ifc-viewer>
</div>

The viewer per default has a button to upload a model, but it is also possible to do that from outside using the IFCModelLoaderService. This service takes a file and returns an observable that first shows the status of the loading process and once finished has the resulting model attached. This model can then be passed to the IFCViewerService or other services such as the Linked Building Data (LBD) toolset. The viewer service can at any time be used to access all the models that have been loaded.

import { IFCModelLoaderService, IFCViewerService } from 'ngx-ifc-viewer';
import { IFCModel } from 'web-ifc-three/IFC/components/IFCModel';

@Component({
  selector: 'app-component',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  public models: IFCModel[] = [];

  constructor(
    private: _modelLoader: IFCModelLoaderService,
    private _viewer: IFCViewerService
  ){}

  uploadFile(files: FileList){

    this._modelLoader.loadModel(files[0]).subscribe(async (status: LoadingStatus) => {

        // Load finished
        if(status.result != undefined){

          const model = status.result;

          // Add to array of models
          this.models.push(model);

          // Append model to scene
          this._viewer.appendModel(model);

        }

      }, 
      err => console.log(err))

  }
}

Input

NameDescription
settingsAn instance of the MenuPanelSettings class which holds all settings for the viewer

Output

  • elementClick
  • canvasClick

Menu panel

The content displayed in the menu panel can be limited by specifying so in the viewer settings.

The top menu panel can be extended by placing HTML content between the <ifc-viewer>-tags. To display this content in the top menu after a model is loaded in the scene, use the menuPostLoadContent-selector as demonstrated below.

<div style="width: 100%; height: 100%">
    <ifc-viewer>

      <!-- MENU PANEL ADDITIONAL BUTTONS -->
      <ng-container menuPostLoadContent>

        <!-- My function -->
        <button class="btn" *ngIf="rdfParsed" (click)="myFunction()" matTooltip="Do something cool">
            <fa-icon [icon]="faUnicorn"></fa-icon>
        </button>

      </ng-container>

    </ifc-viewer>
</div>

In the above example we append a font-awesome icon with a unicorn. This requires the icon to also be loaded from the @fortawesome/free-solid-svg-icons package:

import { faUnicorn } from '@fortawesome/free-solid-svg-icons';

@Component({
  ...
})
export class AppComponent {
  public faUnicorn = faUnicorn;
  ...
}

Context menu

The content displayed in the context menu on element click can be limited by specifying so in the viewer settings.

The context menu can also be extended with custom items by placing HTML content between the <ifc-viewer>-tags. To display this content in the top menu after a model is loaded in the scene, use the contextMenu-selector as demonstrated below.

This requires MatMenuModule and MatButtonModule to be imported in the app module.

<div style="width: 100%; height: 100%">
    <ifc-viewer (elementClick)="lastClicekedElement = $event">

      <!-- CONTEXT MENU ADDITIONAL BUTTONS -->
      <ng-container contextMenu>
        <button mat-menu-item (click)="colorElement()">Color element</button>
      </ng-container>

    </ifc-viewer>
</div>

Coloring

In the context menu example we define a "color element" function. Implementing this functionality is quite simple using the ColorService. In the example below we make use of the lastClickedElement which is defined by element clicks in the model using the elementClick-output of the viewer (se context menu HTML snippet). From this we can access the expressID of the element and feed it to the colorSubset-method of the color service. We also provide it with a stringified version of the expressID as the customID. The customID is used by the color service to know that it already exists in the scene, and therefore clicking and coloring the same element again will toggle the color off.

import { ColorService, ElementClickEvent } from 'ngx-ifc-viewer';

@Component({
  ...
})
export class AppComponent {
  ...
  public lastClicekedElement?: ElementClickEvent;

  constructor(
    private _color: ColorService
  ){}

  colorElement(){
    if(this.lastClickedElement == undefined) return;
    const expressID = this.lastClickedElement.expressID;
    this._color.colorSubset([expressID], "red", expressID.toString());
  }
}

The color service also has a function that applies color to groups of elements. Simply feed it with a nested array of expressIDs (an array per group) and the service will apply colors and return the colors used. The default color pallette has 10 colors.

import { ColorService, IFCModelLoaderService } from 'ngx-ifc-viewer';

@Component({
  ...
})
export class AppComponent {
  ...
  constructor(
    private _modelLoader: IFCModelLoaderService,
    private _color: ColorService
  ){}

  colorGroups(){
    const wallIDs = await this._modelLoader.ifc.getAllItemsOfType(modelID, IFCWALLSTANDARDCASE, false);
    const windowIDs = await this._modelLoader.ifc.getAllItemsOfType(modelID, IFCWINDOW, false);
    const doorIDs = await this._modelLoader.ifc.getAllItemsOfType(modelID, IFCDOOR, false);
    const colors = await this._color.colorByGroup([wallIDs, windowIDs, doorIDs]);
    console.log(colors);
  }
}
0.0.20

2 years ago

0.0.21

2 years ago

0.0.22

2 years ago

0.0.23

2 years ago

0.0.19

2 years ago

0.0.17

2 years ago

0.0.18

2 years ago

0.0.11

2 years ago

0.0.12

2 years ago

0.0.13

2 years ago

0.0.14

2 years ago

0.0.15

2 years ago

0.0.16

2 years ago

0.0.10

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago