@ -1,16 +1,15 @@
import { Injectable , Inject , Injector } from '@angular/core' ;
import { Injectable , Injector } from '@angular/core' ;
import { XeokitServer } from "core-app/modules/bim/ifc_models/xeokit/xeokit-server" ;
import { XeokitServer } from 'core-app/modules/bim/ifc_models/xeokit/xeokit-server' ;
import { BcfViewpointInterface } from "core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface" ;
import { BcfViewpointInterface } from 'core-app/modules/bim/bcf/api/viewpoints/bcf-viewpoint.interface' ;
import { ViewerBridgeService } from "core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service" ;
import { ViewerBridgeService } from 'core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service' ;
import { BehaviorSubject , Observable , Subject , of } from "rxjs" ;
import { BehaviorSubject , Observable , of } from 'rxjs' ;
import { WorkPackageResource } from "core-app/modules/hal/resources/work-package-resource" ;
import { WorkPackageResource } from 'core-app/modules/hal/resources/work-package-resource' ;
import { PathHelperService } from "core-app/modules/common/path-helper/path-helper.service" ;
import { PathHelperService } from 'core-app/modules/common/path-helper/path-helper.service' ;
import { BcfApiService } from "core-app/modules/bim/bcf/api/bcf-api.service" ;
import { BcfApiService } from 'core-app/modules/bim/bcf/api/bcf-api.service' ;
import { InjectField } from "core-app/helpers/angular/inject-field.decorator" ;
import { InjectField } from 'core-app/helpers/angular/inject-field.decorator' ;
import { ViewpointsService } from "core-app/modules/bim/bcf/helper/viewpoints.service" ;
import { ViewpointsService } from 'core-app/modules/bim/bcf/helper/viewpoints.service' ;
import { CurrentProjectService } from "core-app/components/projects/current-project.service" ;
import { CurrentProjectService } from 'core-app/components/projects/current-project.service' ;
import { HttpClient } from "@angular/common/http" ;
import { HttpClient } from '@angular/common/http' ;
export interface XeokitElements {
export interface XeokitElements {
canvasElement :HTMLElement ;
canvasElement :HTMLElement ;
@ -21,16 +20,28 @@ export interface XeokitElements {
enableEditModels? :boolean ;
enableEditModels? :boolean ;
}
}
/ * *
* Options for saving current viewpoint in xeokit - bim - viewer .
* See : https : //xeokit.github.io/xeokit-bim-viewer/docs/class/src/BIMViewer.js~BIMViewer.html#instance-method-saveBCFViewpoint
* /
export interface BCFCreationOptions {
export interface BCFCreationOptions {
spacesVisible? :boolean ;
spacesVisible? :boolean ;
spaceBoundariesVisible? :boolean ;
spaceBoundariesVisible? :boolean ;
openingsVisible? :boolean ;
openingsVisible? :boolean ;
defaultInvisible? :boolean ;
reverseClippingPlanes? :boolean ;
}
}
/ * *
* Options for loading a viewpoint into xeokit - bim - viewer .
* See : https : //xeokit.github.io/xeokit-bim-viewer/docs/class/src/BIMViewer.js~BIMViewer.html#instance-method-loadBCFViewpoint
* /
export interface BCFLoadOptions {
export interface BCFLoadOptions {
rayCast? :boolean ;
rayCast? :boolean ;
immediate? :boolean ;
immediate? :boolean ;
duration? :number ;
duration? :number ;
updateCompositeObjects? :boolean ;
reverseClippingPlanes? :boolean ;
}
}
@Injectable ( )
@Injectable ( )
@ -49,7 +60,7 @@ export class IFCViewerService extends ViewerBridgeService {
super ( injector ) ;
super ( injector ) ;
}
}
public newViewer ( elements :XeokitElements , projects :any [ ] ) {
public newViewer ( elements :XeokitElements , projects :any [ ] ) : void {
import ( '@xeokit/xeokit-bim-viewer/dist/xeokit-bim-viewer.es' ) . then ( ( XeokitViewerModule :any ) = > {
import ( '@xeokit/xeokit-bim-viewer/dist/xeokit-bim-viewer.es' ) . then ( ( XeokitViewerModule :any ) = > {
const server = new XeokitServer ( this . pathHelper ) ;
const server = new XeokitServer ( this . pathHelper ) ;
const viewerUI = new XeokitViewerModule . BIMViewer ( server , elements ) ;
const viewerUI = new XeokitViewerModule . BIMViewer ( server , elements ) ;
@ -62,45 +73,44 @@ export class IFCViewerService extends ViewerBridgeService {
viewerUI . loadProject ( projects [ 0 ] [ "id" ] ) ;
viewerUI . loadProject ( projects [ 0 ] [ "id" ] ) ;
viewerUI . on ( "addModel" , ( event :Event ) = > { // "Add" selected in Models tab's context menu
viewerUI . on ( "addModel" , ( ) = > { // "Add" selected in Models tab's context menu
window . location . href = this . pathHelper . ifcModelsNewPath ( this . currentProjectService . identifier as string ) ;
window . location . href = this . pathHelper . ifcModelsNewPath ( this . currentProjectService . identifier as string ) ;
} ) ;
} ) ;
viewerUI . on ( "editModel" , ( event : { modelId :number | string } ) = > { // "Edit" selected in Models tab's context menu
viewerUI . on ( "editModel" , ( event : { modelId :number | string } ) = > { // "Edit" selected in Models tab's context menu
window . location . href = this . pathHelper . ifcModelsEditPath ( this . currentProjectService . identifier as string , event . modelId ) ;
window . location . href = this . pathHelper . ifcModelsEditPath (
this . currentProjectService . identifier as string , event . modelId ) ;
} ) ;
} ) ;
viewerUI . on ( "deleteModel" , ( event : { modelId :number | string } ) = > { // "Delete" selected in Models tab's context menu
viewerUI . on ( "deleteModel" , ( event : { modelId :number | string } ) = > {
// "Delete" selected in Models tab's context menu.
// We don't have an API for IFC models yet. We need to use the normal Rails form posts for deletion.
// We don't have an API for IFC models yet. We need to use the normal Rails form posts for deletion.
const formData = new FormData ( ) ;
const formData = new FormData ( ) ;
formData . append (
formData . append (
'authenticity_token' ,
'authenticity_token' ,
jQuery ( 'meta[name=csrf-token]' ) . attr ( 'content' ) as string
jQuery ( 'meta[name=csrf-token]' ) . attr ( 'content' ) as string ,
) ;
) ;
formData . append (
formData . append (
'_method' ,
'_method' ,
'delete'
'delete' ,
) ;
) ;
this . httpClient . post (
this . httpClient . post (
this . pathHelper . ifcModelsDeletePath (
this . pathHelper . ifcModelsDeletePath ( this . currentProjectService . identifier as string , event . modelId ) , formData )
this . currentProjectService . identifier as string , event . modelId ) ,
formData
)
. subscribe ( )
. subscribe ( )
. add ( ( ) = > {
. add ( ( ) = > {
// Ensure we reload after every request.
// Ensure we reload after every request.
// We need to reload to get a fresh CSRF token for a successive
// We need to reload to get a fresh CSRF token for a successive
// model deletion placed as a META element into the HTML HEAD.
// model deletion placed as a META element into the HTML HEAD.
window . location . reload ( )
window . location . reload ( ) ;
} )
} ) ;
} ) ;
} ) ;
this . viewer = viewerUI ;
this . viewer = viewerUI ;
} ) ;
} ) ;
}
}
public destroy() {
public destroy ( ) : void {
this . viewerVisible $ . complete ( ) ;
this . viewerVisible $ . complete ( ) ;
if ( ! this . viewer ) {
if ( ! this . viewer ) {
@ -111,7 +121,7 @@ export class IFCViewerService extends ViewerBridgeService {
this . viewer = undefined ;
this . viewer = undefined ;
}
}
public get viewer() {
public get viewer ( ) : any {
return this . _viewer ;
return this . _viewer ;
}
}
@ -119,12 +129,13 @@ export class IFCViewerService extends ViewerBridgeService {
this . _viewer = viewer ;
this . _viewer = viewer ;
}
}
public setKeyboardEnabled ( val :boolean ) {
public setKeyboardEnabled ( val :boolean ) : void {
this . viewer . setKeyboardEnabled ( val ) ;
this . viewer . setKeyboardEnabled ( val ) ;
}
}
public getViewpoint $ ( ) : Observable < BcfViewpointInterface > {
public getViewpoint $ ( ) : Observable < BcfViewpointInterface > {
const viewpoint = this . viewer . saveBCFViewpoint ( { spacesVisible : true } ) ;
const opts :BCFCreationOptions = { spacesVisible : true , reverseClippingPlanes : true } ;
const viewpoint = this . viewer . saveBCFViewpoint ( opts ) ;
// The backend rejects viewpoints with bitmaps
// The backend rejects viewpoints with bitmaps
delete viewpoint . bitmaps ;
delete viewpoint . bitmaps ;
@ -132,15 +143,15 @@ export class IFCViewerService extends ViewerBridgeService {
return of ( viewpoint ) ;
return of ( viewpoint ) ;
}
}
public showViewpoint ( workPackage :WorkPackageResource , index :number ) {
public showViewpoint ( workPackage :WorkPackageResource , index :number ) : void {
// Avoid reload the app when there is a place to show the viewer
// Avoid reload the app when there is a place to show the viewer
// ('bim.partitioned.split')
// ('bim.partitioned.split')
if ( this . routeWithViewer ) {
if ( this . routeWithViewer ) {
if ( this . viewer ) {
if ( this . viewer ) {
let viewpoint Options = { updateCompositeObjects : true } ;
const opts :BCFLoad Options = { updateCompositeObjects : true , reverseClippingPlane s : true } ;
this . viewpointsService
this . viewpointsService
. getViewPoint $ ( workPackage , index )
. getViewPoint $ ( workPackage , index )
. subscribe ( viewpoint = > this . viewer . loadBCFViewpoint ( viewpoint , viewp ointO ption s) ) ;
. subscribe ( viewpoint = > this . viewer . loadBCFViewpoint ( viewpoint , opts ) ) ;
}
}
} else {
} else {
// Reload the whole app to get the correct menus and GON data
// Reload the whole app to get the correct menus and GON data
@ -149,7 +160,7 @@ export class IFCViewerService extends ViewerBridgeService {
window . location . href = this . pathHelper . bimDetailsPath (
window . location . href = this . pathHelper . bimDetailsPath (
workPackage . project . idFromLink ,
workPackage . project . idFromLink ,
workPackage . id ! ,
workPackage . id ! ,
index
index ,
) ;
) ;
}
}
}
}