//
// $Id: IModelViewer.js 9716 2026-01-13 14:01:08Z jochen.hanff $
const selectionChanged = new CustomEvent("selection-changed");
const visibilityChanged = new CustomEvent("visibility-changed");
import { Context } from "../infohub/Context.js"
import { ApiResponse } from "../tools/ApiResponse.js";
/**
*
* @category Model Viewer
*
*/
export class ProjectContext {
project = null
scope = null
connectedby = null
constructor() { }
setScopeProject(scope, project, connectedby) {
this.project = project
this.scope = scope
this.connectedby = connectedby
}
}
/**
*
* @category Model Viewer
*
* @class
* @classdesc
* Common interface and base class for Model Viewers such as DESITE, COLNEO Pro, Web Viewer, etc.
*
* To create an instance of a ModelViewer use one of the Factory Methods of
* the specific service classes such as `COLNEOproAdapterServices`, etc.
*
* Example:
* ```js
* const { COLNEOproAdapterServices } = await import("./node_modules/@colneo/infohub-js-api/dist/adapter/AdapterColneoPro.js");
* Infohub.ModelViewer = await COLNEOproAdapterServices.createAdapter()
* ```
*
* If the user changes the selection or visibility of objects in the 3D-scene these events are thrown:
* ```js
* Event `selection-changed` when selection of objects in 3d view is changed
* Event `visibility-changed` when visibility of objects in 3d view is changed
* ```
*
* To connect to these events use {@link IModelViewer#connectModelViewer connectModelViewer()}.
*
*/
export class IModelViewer extends EventTarget {
apiName = null
viewerName = null
viewerVersion = null
static eDomain = {
GEO: "geo",
ACT: "act",
BOQ: "boq",
DOC: "doc",
TYP: "typ",
ISS: "iss",
RES: "res",
BST: "bst",
CST: "cst",
ALL: "all"
};
// infohub project context ( scope , project )
/* ProjectContext */ _infohub_project_ctx = null
constructor(t = 'unknow', n = 'unknown', v = '0.0.0') {
super()
this.apiName = t;
this.viewerName = n;
this.viewerVersion = v;
this._infohub_project_ctx = new ProjectContext()
}
get eDomain() {
return this.constructor.eDomain;
}
// ======== user, infohub context (scope,project) ========
/**
*
* @group Authentication
*
* @description
* Get 'user' and 'token' from ModelViewer.
*
* @returns {ApiResponse<Object>} response
*
* @example
* {
* "status" : 200,
* "data" : {
* "user": "JohnDoe",
* "token": "abc123"
* }
* }
*
* @param {function} cb Callback function
* @param {string} user Login this user (optional)
*
*/
loginUser(cb, user = null) {
return Promise.reject("No model viewer instantiated");
}
/**
* @category Authentication
*
* @description
* Logout user.
* Clear user and token.
*
* @param {function} cb Callback function
* @returns {ApiResponse<Object>} response
*
*/
logoutUser(cb) {
return Promise.reject("No model viewer instantiated");
}
/**
*
* Restore project context (scope,project) from model viewer (from current project)
* and store it in infohub context ctx.
*
* @param {Context} ctx
* @param {*} cb Call back
* @returns {Promise<ApiResponse>} Returns object with status and ProjectContext data
*/
async restoreProjectContext(ctx, cb) {
console.error(`ERROR in ${this.apiName}.getProjectInfo(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
async saveProjectContext(cb) {
console.error(`ERROR in ${this.apiName}.getProjectInfo(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
async getProjectContext() {
return this._infohub_project_ctx
}
/**
* Get name and version of the current ModelViewer.
*
* @returns {object} JSON object containing name and version.
* @example {
* "name" : "...",
* "type" : "...",
* "version" : ".."
* }
*
* @since 10.2025
*/
getInfo() {
return {
name: this.viewerName,
type: this.apiName,
version: this.viewerVersion
}
}
/**
*
* @param {object} settings {
* 'scope_id' : ' ... ',
* 'project_shortid' : ' ... ',
* 'connected_by' : ' ... '
* }
* @returns {ApiResponse<void>}
* complies with COLNEOpro-API, 2025-10-14, ar
*/
setInfohubSettings(settings) {
console.error(`ERROR in ${this.apiName}.setInfohubSettings(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* @returns {object} settings object
* @example {
* 'scope_id' : ' ... ',
* 'project_shortid' : ' ... ',
* 'connected_by' : ' ... '
* }
*/
getInfohubSettings() {
console.error(`ERROR in ${this.apiName}.getInfohubSettings(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Dump info to console
* @updated 12.01.2026, SW
*/
dump() {
console.log(JSON.stringify(this.getInfo(), null, 2))
}
/**
*
* @method
*
* @description
* Connect signals `selection changed` and `visibility changed` to given functions.
*
* @returns {Object}
* ```js
* {
* 'status' : ...
* }
* ```
*
* @param {function} on_sc Function to be called on selection changed, null to disconnect
* @param {function} on_vc Function to be called on visibility changed, null to disconnect
* @param {*} cb
*
*/
connectModelViewer(on_sc, on_vc, cb) {
this.addEventListener("selection-changed", on_sc)
this.addEventListener("visibility-changed", on_vc)
return cb({
'status': 200
})
}
/**
* add selection listener, no extra call back function
* @param {*} listener
* @returns {Promise<null>}
* @since 08.12.2025, ar
*/
addSelectionEventListener(listener) {
return this.addEventListener("selection-changed", listener)
}
/**
* add visibility listener, no extra call back function
* @param {*} listener
* @returns {Promise<null>}
* @since 08.12.2025, ar
*/
addVisibilityEventListener(listener) {
return this.addEventListener("visibility-changed", listener)
}
/**
* remove selection listener, no extra call back function
* @param {*} listener
* @returns {Promise<null>}
* @since 08.12.2025, ar
*/
removeSelectionEventListener(listener) {
return this.removeEventListener("selection-changed", listener)
}
/**
* remove visibility listener, no extra call back function
* @param {*} listener
* @returns {Promise<null>}
* @since 08.12.2025, ar
*/
removeVisibilityEventListener(listener) {
return this.removeEventListener("visibility-changed", listener)
}
/**
*
*/
onSelectionChanged() {
this.dispatchEvent(selectionChanged)
}
/**
*
*/
onVisibilityChanged() {
this.dispatchEvent(visibilityChanged)
}
// ======== Project Methods ========
/**
* Get project metadata
* @returns {ApiResponse<object>} //RM
* @since 10.2025
*/
getProjectInfo(projectId) {
console.error(`ERROR in ${this.apiName}.getProjectInfo(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get project id
* @since 12.2025
*/
getProjectId() {
console.error(`ERROR in ${this.apiName}.getProjectId(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get project directory
* @returns {ApiResponse<string>} file path
*/
getProjectDirectory(projectId) {
console.error(`ERROR in ${this.apiName}.getProjectDirectory(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Save current project, show SaveFileDialog if project was newly created and no file path is available.
* @returns {ApiResponse<boolean>} True if project was saved successfully.
*/
saveProject() {
console.error(`ERROR in ${this.apiName}.saveProject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Model Methods ========
/**
* Get model IDs for given domains.
* @param {eDomain[]} domains - Domain (e.g. 'all') or combination as array, e.g. ['geo', 'act'].
* @returns {ApiResponse<string[]>} Array of model IDs.
* @since 10.2025
* @updated 01.2026, SW - domains instead of domain
*/
getModelIds(domains) {
console.error(`ERROR in ${this.apiName}.getModelIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get metadata for given model.
* @param {string} modelId - Model ID.
* @returns {ApiResponse<object>}
* @since 10.2025
*/
getModelMetadata(modelId) {
console.error(`ERROR in ${this.apiName}.getModelMetadata(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create model. Synchronizes with Infohub.
* @param {string} name - Model name.
* @param {string} domain - Domain (e.g. 'geo')
* @param {object} settings - Model settings.
* @returns {ApiResponse<string>} ID of newly created model.
*/
createModel(name, domain, settings) {
console.error(`ERROR in ${this.apiName}.createModel(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Add model to coordination model. Synchronizes with Infohub.
* @param {string} modelId - Model ID.
* @returns {ApiResponse<boolean>} True if successfully added
* @updated 01.2026, SW modelId instead of filename
*/
importModel(modelId) {
console.error(`ERROR in ${this.apiName}.addModel(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* remove model from project. Synchronizes with Infohub.
* @param {string} modelId - Model ID.
* @returns {ApiResponse<boolean>} True if model was successfully removed.
*/
removeModel(modelId) {
console.error(`ERROR in ${this.apiName}.removeModel(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Object Methods ========
/**
* Get root object ID for given domain.
* @param {*} domain - Domain (e.g. 'geo')
* @returns {ApiResponse<string>} Root object ID
*/
getObjectsRootId(domain) {
console.error(`ERROR in ${this.apiName}.getObject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get object by ID. Synchronizes data with Infohub.
* @param {string} objId - ID of object.
* @returns {ApiResponse<cnObject>} returns object in GOM format
*/
getObject(objId, keys) {
return this.getObject([objId], keys)
}
/**
*
* Get objects in GOM format
*
* @param {Array<string>} objIdList Object Ids
* @param {*} opt
`
{
"properties" : { ... options ... } // if empty, return all
"geometry" : { ... options ... },
"relations" : {},
"nodes" : {}
}
`
*
*
* @example
* getObjects(
* ["obj1", "obj2"],
* {
* properties: {
* "propertytypes": [ // whitelist by default
* "cnName##xs:string",
* "MyNumber##xs:double"
* ]
* },
* geometry: {},
* relations: {},
* nodes: {}
* }
* );
*
*/
getObjects(objIdList, opt) {
console.error(`ERROR in ${this.apiName}.getObject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Collect object Ids contained in objects of objIdList, serach to depth of 'depth' or the
* complete hiererchy if depth is 0 (default)
*
* @param {*} objIdList Collect child ids from these root objects
* @param {*} depth [optional] Recursion depth, default = 0 (maximum depth)
*/
async getChildIds(objIdList, depth = 0) {
console.error(`ERROR in ${this.apiName}.getObject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create a new object. Synchronizes data with Infohub.
* @param {string} parentId - ID of parent object
* @param {object} data - Data for the new object in JSON notation
* @example {
info: {
object_type : "geo_container",
object_name : "MyObject"
},
properties: {
...
},
geometry: {
...
}
}
* @returns {ApiResponse<string>} ID of newly created object.
*/
createObject(parentId, data) {
console.error(`ERROR in ${this.apiName}.createObject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Delete objects by ID. Synchronizes data with Infohub.
* @param {string[]} objIds - IDs of objects to delete.
* @returns {ApiResponse<number>} Number of objects deleted.
*/
deleteObjects(objIds) {
console.error(`ERROR in ${this.apiName}.deleteObjects(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get all object IDs for given domains as list.
* @param {eDomain[]} domain Domain (e.g. 'all') or combination as array, e.g. ['geo', 'act'].
* @returns {ApiResponse<string[]>} Array of object IDs.
*/
getObjectIds(domain) {
console.error(`ERROR in ${this.apiName}.getObjectIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Filter objects by property values.
* @param {string[]} objIds - Object IDs of objects to filter.
* @param {any[]} filterExpression - Filter criteria.
* @example [ "$ifcEntity##xs:string" , "==" , "IfcWall" ]
* @example [ "$ifcEntity##xs:string" , "in" , ["IfcWall", "IfcWallStandardCase"]] , "and" , "$cnVolume##xs:double", ">=" , 2.5 ]]
* @example [ "$ifcEntity##xs:string" , "match" , "/^IfcWall/g"]]
* @returns {ApiResponse<string[]>} Filtered object IDs.
*/
filterObjectsByProperties(objIds, filterExpression) {
console.error(`ERROR in ${this.apiName}.filterObjectsByProperties(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Filter objects by status.
* @param {string[]} objIds - Object IDs of objects to filter.
* @param {string} statusCode - one of [ 'selected', 'visible', 'wired', 'locked'].
* @param {boolean} statusFlag - true: status, false: inverted status.
* @returns {ApiResponse<string[]>} Filtered object IDs.
*/
filterObjectsByStatus(objIds, statusCode, statusFlag) {
console.error(`ERROR in ${this.apiName}.filterObjectsByStatus(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Object Status Methods ========
/**
* Get IDs of currently visible objects in given domain/domains.
* @param {eDomain[]} domains - Domain (e.g. 'all') or combination as array, e.g. ['geo', 'act'].
* @returns {ApiResponse<string[]>} returns IDs of currently visible objects in given domain/domains
* @since 10.2025
*/
getVisibleObjectIds(domains) {
console.error(`ERROR in ${this.apiName}.getVisibleObjectIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set visibility of objects.
* @param {string[]} objIds - Object IDs.
* @param {boolean} flagOnOff - true: visible, false: hidden
* @param {boolean} exclusively - If the 'exclusivly' flag is set to true, the domains affected are determined by the specified objects.
* The remaining objects in these domains are set to the inverse status.
* @returns {ApiResponse<number>} Number of objects whose status changed.
* @since 10.2025
*
*/
setVisible(objIds, flagOnOff, exclusively) {
console.error(`ERROR in ${this.apiName}.setVisible(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set visibility of all objects of given domains.
* @param {eDomain[]} domains Array of domains to be taken into account
* @param {boolean} flagOnOff true = show, false = hide
* @returns {ApiResponse<void>}
* @example
*
* // assume a COLNEO pro adapter is instantiated (e.g. in index.js) ...
* const { COLNEOproAdapterServices } = await import("./node_modules/@colneo/infohub-js-api/dist/adapter/AdapterColneoPro.js");
* Infohub.ModelViewer = await COLNEOproAdapterServices.createAdapter( Infohub.Context )
*
* // set visibility for objects in domain 'geometry'
* Infohub.ModelViewer.setAllVisible( [ Infohub.ModelViewer.eDomain.GEO ], true )
*
* @since 01.12.2025, ar
*
*/
setAllVisible(domains, flagOnOff) {
console.error(`ERROR in ${this.apiName}.setAllVisible(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Toggle visibility of given objects.
* @param {string[]} objIds - Object IDs to toggle.
* @returns {ApiResponse<void>}
*/
toggleVisibility(objIds) {
console.error(`ERROR in ${this.apiName}.toggleVisibility(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Check if object is visible.
* @param {string} objId - Object ID.
* @returns {ApiResponse<boolean>} True if object is visible.
*/
isVisible(objId) {
console.error(`ERROR in ${this.apiName}.isVisible(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get IDs of currently selected objects.
* @param {eDomain[]} domains - Domain (e.g. 'all') or combination as array, e.g. ['geo', 'act'].
* @returns {ApiResponse<string[]>} returns IDs of currently selected objects
* @since 10.2025
*/
getSelectedObjectIds(domains) {
console.error(`ERROR in ${this.apiName}.getSelectedObjectIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set selection of objects.
*
* @param {string[]} objIds - Object IDs.
* @param {boolean} flagOnOff - Selection flag.
* @param {boolean} exclusively - If true, clear all other selections.
*
*
* @returns {ApiResponse<number>} Number of objects whose selection changed.
* @since 10.2025
*/
setSelected(objIds, flagOnOff, exclusively) {
console.error(`ERROR in ${this.apiName}.setSelected(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Toggle selection status of given objects.
* @param {string[]} objIds - Object IDs to toggle.
* @returns {ApiResponse<void>}
*/
toggleSelection(objIds) {
console.error(`ERROR in ${this.apiName}.toggleSelection(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Set all objects of specified domains as selected or deselected.
*
* Example:
*
* ```js
* // assume a COLNEO pro adapter is instantiated (e.g. in index.js) ...
* const { COLNEOproAdapterServices } = await import("./node_modules/@colneo/infohub-js-api/dist/adapter/AdapterColneoPro.js");
* Infohub.ModelViewer = await COLNEOproAdapterServices.createAdapter()
*
* // clear selection of objects in domain 'geometry'
* Infohub.ModelViewer.setAllSelected( [ Infohub.ModelViewer.eDomain.GEO ], false )
* ```
*
*
* @param {boolean} flagOnOff
* @param {string[]} domains
*
* @returns {ApiResponse<void>}
*/
setAllSelected(domains, flagOnOff) {
console.error(`ERROR in ${this.apiName}.setAllSelected(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Check if object is selected.
* @param {string} objId - Object ID.
* @returns {ApiResponse<boolean>} True if object is selected.
*/
isSelected(objId) {
console.error(`ERROR in ${this.apiName}.isSelected(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Hierarchy Methods ========
/**
* Get parent ID of object.
* @param {string} objId - Object ID.
* @returns {ApiResponse<string>} - ID of closest parent
* @since 10.2025
*/
getParentId(objId) {
console.error(`ERROR in ${this.apiName}.getParentId(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get root node of object trees for a given domain.
* @param {string} domain - Domain (e.g. 'geo')
* @returns {ApiResponse<string>} returns ID of root node of object trees for a given domain
* @since 10.2025
*/
getRootNodeId(domain) {
console.error(`ERROR in ${this.apiName}.getRootNodeId(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get root nodes of smartsets for given domain.
* @param {string} domain - Domain (e.g. 'geo')
* @returns {ApiResponse<string>}
* @since 10.2025
*/
getRootNodeIdOfSets(domain) {
console.error(`ERROR in ${this.apiName}.getRootNodeIdOfSets(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Property Methods ========
/**
* Get property value for object.
* @param {string} objId - Object ID.
* @param {string} ptKeyStr - Access key of property type in the format name##datatype.
* @returns {ApiResponse<any>} -alue of property, depending on the datatype
*/
getPropertyValue(objId, ptKeyStr) {
console.error(`ERROR in ${this.apiName}.getPropertyValue(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get property values for multiple objects.
* @param {string[]} objIds - Object IDs.
* @param {string} ptKeyStr - Access key of property type in the format name##datatype.
* @returns {ApiResponse<object[]>} Map with object IDs as keys.
* @example data: {
"id1" : {
"value": 1.234,
"comment": ""
},
...
}
*/
getPropertyValues(objIds, ptKeyStr) {
console.error(`ERROR in ${this.apiName}.getPropertyValues(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get unique property values for type.
* @param {string} ptKeyStr - Access key of property type in the format name##datatype.
* @param {object} options - Options for filtering.
* @example * // Example options object:
* const options = {
* objects: ['obj_1', 'obj_2'],
* precision: 0.0001,
* case_sensitive: true,
* interval_size: 2.0,
* interval_offset: 1.0,
* date_grouping: 'week',
* max_values: 0
* };
* @returns {ApiResponse<string[]>} returns list of unique property values
* @since 10.2025
*/
getPropertyTypeValues(ptKeyStr, options) {
console.error(`ERROR in ${this.apiName}.getPropertyTypeValues(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get all properties of object.
* @param {string} objId - Object ID.
* @param {boolean} inclPropsFromTypes - Include props from types.
* @param {object} filter - Filter criteria.
* @example * // Example filter object:
* const filter = {
* name: "MyPset:MyNumber*",
* datatype : ["xs:double", "xs:float"]
* };
* @returns {ApiResponse<object>}
* @example data: {
"MyPset:MyNumber##xs:double": "11",
"MyPset:MyNumberNew##xs:float": 42,
}
*/
getProperties(objId, inclPropsFromTypes, filter) {
console.error(`ERROR in ${this.apiName}.getProperties(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get property type metadata.
* @param {string} ptKeyStr - Access key of property type in the format name##datatype.
* @returns {ApiResponse<object|null>}
* @example data: {
name: "cnName",
displayName: "cn:Name",
datatype: "xs:string",
readonly: false,
...
}
*/
getPropertyTypeInfo(ptKeyStr) {
console.error(`ERROR in ${this.apiName}.getPropertyTypeInfo(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get property types used by object.
* @param {string} objId - Object ID.
* @param {object} filter - Filter criteria.
* @example * // Example filter object:
* const filter = {
* name: "MyPset:MyNumber*",
* datatype : ["xs:double", "xs:float"]
* readOnly: true
* };
* @returns {ApiResponse<object[]>}
* @example data: [
{
name: "MyPset:MyNumber",
displayName: "MyPset:MyNumber",
datatype: "xs:double",
readonly: true,
...
}
]
*
*/
getPropertyTypesByObject(objId, filter) {
console.error(`ERROR in ${this.apiName}.getPropertyTypesByObject(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get a list of all available property types matching filter.
* @param {object} filter - Filter criteria.
* @example * // Example filter object:
* const filter = {
* name: "MyPset:MyNumber*",
* datatype : ["xs:double", "xs:float"]
* readOnly: true
* };
* @returns {ApiResponse<string[]>}
*/
getPropertyTypes(filter) {
console.error(`ERROR in ${this.apiName}.getPropertyTypes(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set single property value. Synchronizes with Infohub.
* @param {string} objId - Object ID.
* @param {string} ptKeyStr - property typeidö in the format name##datatype.
* @param {string} value - New value.
* @returns {ApiResponse<boolean>}
*/
setPropertyValue(objId, ptKeyStr, value) {
console.error(`ERROR in ${this.apiName}.setPropertyValue(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Set multiple property values for each object in object list.
*
* @param {string[]} objIds - Array of Object IDs.
* @param {object} properties - Key/value pairs, key format name##datatype
*
* @example // Example properties object:
const properties = {
"myType##xs:string" : "ABC",
"myNumber##xs:double" : 1.234,
"myBoolean##xs:boolean" : true
};
* @returns {ApiResponse<boolean>}
*/
setProperties(objIds, properties) {
console.error(`ERROR in ${this.apiName}.setProperties(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set properties in a batch by a property map object -> properties
*
* @param {*} propertyMap {
*
* "object id 1" : {
* "proptypeid1" : value1,
* "proptypeid2" : value2
* },
* "object id 2" : {
* "proptypeid1" : value1,
* "proptypeid2" : value2,
* * "proptypeid3" : value3,
* },
* }
*
* @returns {ApiResponse<boolean>}
*
*/
setPropertiesByMap(propertyMap) {
console.error(`ERROR in ${this.apiName}.setProperties(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create or update property type. Synchronizes with Infohub.
* @param {object} propData - Property type definition.
* @example * // Example propData objects:
propData1 = {
name: "MyLength",
datatype: "xs:double",
unit: "m"
}
propData2 = {
name: "TrafficLight",
datatype: "xs:string",
values: ["red", "yellow", "green"]
readOnly: true
}
* @param {boolean} updateExisting - Whether to update existing type.
* @returns {ApiResponse<boolean>}
*/
createPropertyType(propData, updateExisting) {
console.error(`ERROR in ${this.apiName}.createPropertyType(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Delete exsisting property type. Synchronizes with Infohub.
*
* @param {string} ptKeyStr - Access key of property type in the format name##datatype.
*
* @returns {ApiResponse<boolean>}
*
*/
deletePropertyType(ptKeyStr) {
console.error(`ERROR in ${this.apiName}.deletePropertyType(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Reset camera to home viewpoint.
*
* If a home viewpoint does not exist, the camera and clipping planes are reset
*
* @example
* Infohub.ModelViewer.showHomeViewpoint()
* @returns {ApiResponse<void>}
*
* @since 01.2026
*
*/
async showHomeViewpoint() {
console.error(`ERROR in ${this.apiName}.showHomeViewpoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get list of all viewpoint ids.
*
* @returns {ApiResponse<string[]>}
*
* @since 10.2025
*/
getViewpointIds() {
console.error(`ERROR in ${this.apiName}.getViewpointIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create a new viewpoint.
* @param {string | null} parentId - ID of parent object
* @param {object} options
* @returns {ApiResponse<string>} ID of newly created viewpoint.
*/
createViewpoint(parentId, options) {
console.error(`ERROR in ${this.apiName}.createViewpoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Update existing viewpoint.
* @param {string} objId - Object ID
* @param {object} data - Data for the viewpoint in JSON notation
* @returns {ApiResponse<boolean>} True if update was successful.
* @since 10.2025
*/
updateViewpoint(objId, data) {
console.error(`ERROR in ${this.apiName}.updateViewpoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Activate a viewpoint.
* @param {string} objId - Object ID
* @returns {ApiResponse<boolean>} True if viewpoint was activated.
*/
activateViewpoint(objId) {
console.error(`ERROR in ${this.apiName}.activateViewpoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get viewpoint data.
* @param {string} objId - Object ID
* @returns {ApiResponse<object>} JSON object with viewpoint data.
*/
getViewpointData(objId) {
console.error(`ERROR in ${this.apiName}.getViewpointData(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Set viewpoint data.
* @param {string} objId - Object ID
* @param {object} viewpointData - Viewpoint data to set.
* @returns {ApiResponse<boolean>} True if viewpoint data was set.
*/
setViewpointData(objId, viewpointData) {
console.error(`ERROR in ${this.apiName}.setViewpointData(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Delete a viewpoint.
* @param {string} objId - Object ID
* @returns {ApiResponse<boolean>} True if viewpoint was deleted.
*/
deleteViewpoint(objId) {
console.error(`ERROR in ${this.apiName}.deleteViewpoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== Style / Material / Color Methods ========
/**
* Get list of Ids of all available styles.
* @returns {ApiResponse<string[]>} Array of style object Ids.
* @since 10.2025
*/
getStyleIds() {
console.error(`ERROR in ${this.apiName}.getStyleIds(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get styles / materials / colors applied to given objects.
* @param {string[]} objIDs - Object IDs.
* @returns {ApiResponse<object[]>} Array of applied style / material objects.
* @since 10.2025
*/
getStyles(objIDs) {
console.error(`ERROR in ${this.apiName}.getStyles(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Get information about specific style / material attributes.
* @param {string} styleId - Style ID.
* @param {string} key - If specified, only the corresponding attribute is returned, otherwise the entire object.
* @returns {ApiResponse<object|string>} Style attribute info.
* @since 10.2025
*/
getStyleData(styleId, key) {
console.error(`ERROR in ${this.apiName}.getStyleData(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create a new style / material.
* @param {object} styleData - Style definition.
* @example * // Example styleData:
* const styleData = {
* id: "12345", // optional
* name: "MyStyle", // not empty
* color: "#rrggbbaa" // valid color value in hexadecimal RGBA format
* }
* @returns {ApiResponse<string>} ID of newly created style.
*/
createStyle(styleData) {
console.error(`ERROR in ${this.apiName}.createStyle(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Update style / material.
* @param {string} styleId - Style ID.
* @param {object} styleData - Updated style data.
* @returns {ApiResponse<boolean>} True if style was updated.
*/
updateStyle(styleId, styleData) {
console.error(`ERROR in ${this.apiName}.updateStyle(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Delete styles / materials.
* @param {string[]} styleIds - IDs of styles to delete.
* @returns {ApiResponse<boolean>} True if styles deleted.
* @since 10.2025
*/
deleteStyles(styleIds) {
console.error(`ERROR in ${this.apiName}.deleteStyles(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Apply style to objects.
* @param {string} styleId - Style ID.
* @param {string[]} objIds - Object IDs.
* @returns {ApiResponse<boolean>} True if objects style has been changed
*/
applyStyleToObjects(styleId, objIds) {
console.error(`ERROR in ${this.apiName}.applyStyleToObjects(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Reset styles to default.
* @param {string[]} objIds - Object IDs.
* @returns {ApiResponse<boolean>} True if reset succeeded. styles reset to default
* @since 10.2025
*/
resetStylesOfObjects(objIds) {
console.error(`ERROR in ${this.apiName}.resetStylesOfObjects(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Reset styles (materials,colors) of all objects
*
* @returns {ApiResponse<void>}
*
* @example
* Infohub.ModelViewer.resetStyles( [ Infohub.ModelViewer.eDomain.GEO ] )
*
*/
async resetStyles(domains) {
console.error(`ERROR in ${this.apiName}.resetStylesOfObjects(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ======== SmartSet Methods ========
getSmartSetsRootId(domain) {
console.error(`ERROR in ${this.apiName}.getSmartSetsRootId(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Create new SmartSet.
*
* @param {string} parentId Id of parent or domain name (eDomain) for topmost
* @param {string} name Name of the SmartSet.
* @param {string[]} objectIds List of object IDs (root nodes, children will be automatically collected).
* If all objects should be taken into account, use getObjectsRootId(domain) to get ID of root node of domain
* and add root node of domain as SmartSet Object only. To add specific objects to a SmartSet (Set by enumeration)
* use objects which are leafs in the object hierarchy as SmartSet Objects.
* @param {object|null} options Additional options for SmartSet creation.
*
{
"filter": {
"skip_openings": true,
"skip_assembly_parts": false,
"visible_only": false
},
"group_by": {
"propertytypes": [
"ifcEntity##xs:string",
"cnVolume##xs:double"
],
"options": {
"decimal_precision": 4,
"case_sensitive": true,
"skip_null_values": true,
"interval_size": 5.0,
"interval_offset": 0.0,
"date_grouping": "week"
}
}
}
*
* @returns {ApiResponse<string>} ID of newly created SmartSet.
*
* @since 10.2025
* @update 09.12.2025, ar
*/
async createSmartSet(parentId, name, objectIds, options = null) {
console.error(`ERROR in ${this.apiName}.createSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Delete a SmartSet.
* @param {string} smartSetId - Id of SmartSet.
* @returns {ApiResponse<boolean>} True if deleted.
* @since 10.2025
*/
async deleteSmartSet(smartSetId) {
console.error(`ERROR in ${this.apiName}.deleteSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Add objects to SmartSet.
* @param {string} smartSetId - SmartSet ID.
* @param {string[]} objIds - Object IDs.
* @param {boolean} includeChildren true: tree structure, false: flat list
* @returns {ApiResponse<int>} Number of added objects
* @since 10.2025
*/
async addObjectsToSmartSet(smartSetId, objIds, includeChildren) {
console.error(`ERROR in ${this.apiName}.addObjectsToSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Remove objects from SmartSet.
* @param {string} smartSetId - SmartSet ID.
* @param {string[]} objIds - Object IDs to remove.
* @returns {ApiResponse<boolean>} True if objects effectivily removed
* @since 10.2025
*/
async removeObjectsFromSmartSet(smartSetId, objIds) {
console.error(`ERROR in ${this.apiName}.removeObjectsFromSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Create SmartSets from schema.
* @param {object} schema - Schema definition.
* @returns {ApiResponse<string[]>} Array of SmartSet IDs.
*/
createSmartSetsFromSchema(schema) {
console.error(`ERROR in ${this.apiName}.createSmartSetsFromSchema(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Update SmartSet. Synchronizes with Infohub.
* @param {string} smartSetId - SmartSet ID.
* @returns {ApiResponse<boolean>} True if SmartSet was updated.
*/
updateSmartSet(smartSetId) {
console.error(`ERROR in ${this.apiName}.updateSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Add style to SmartSet.
* @param {string} smartSetId - ID the SmartSet.
* @param {object} options
* @returns {ApiResponse<string>} ID of newly created style.
* @since 10.2025
*/
addStyleSchemaToSmartSet(smartSetId, options) {
console.error(`ERROR in ${this.apiName}.addStyleSchemaToSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Remove style from SmartSet.
* @param {string} smartSetId - ID the SmartSet.
* @returns {ApiResponse<boolean>} True if successfully removed.
* @since 10.2025
*/
removeStyleSchemaFromSmartSet(smartSetId) {
console.error(`ERROR in ${this.apiName}.removeStyleSchemaFromSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Activate style schema scheme.
* @param {string} smartSetId - ID the SmartSet.
* @returns {ApiResponse<boolean>} True if successfully activated.
* @since 10.2025
*/
activateStyleSchemaScheme(smartSetId) {
console.error(`ERROR in ${this.apiName}.activateStyleSchemaScheme(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Add viewpoint to SmartSet.
* @param {string} smartSetId - ID the SmartSet.
* @param {object} options
* @returns {ApiResponse<status>}
* @since 10.2025
*/
addViewpointToSmartSet(smartSetId, options) {
console.error(`ERROR in ${this.apiName}.addViewpointToSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* remove viewpoint to SmartSet.
* @param {string} smartSetId - ID the SmartSet.
* @returns {ApiResponse<boolean>} True if successfully removed.
* @since 10.2025
*/
removeViewpointFromSmartSet(smartSetId) {
console.error(`ERROR in ${this.apiName}.removeViewpointFromSmartSet(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Open URL/Link in Browser (target = null -> default browser )
*
* @param {*} url
* @param {*} target
*/
openUrl(url, target) {
console.error(`ERROR in ${this.apiName}.openUrl(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ------------
/**
*
* return {
'intern' : [ ix , iy , iz ],
'global' : [ x , y , z ]
}
*
*/
getPickedPoint() {
console.error(`ERROR in ${this.apiName}.getPickedPoint(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Rotate and Translate object.
*
* Rotation is executed first around point 'rotatePoint' with rotation matrix 'rotateMat6rix',
* then object is translated.
*
* if includeContained is true ont only the geometry of the object itself is transformed but
* also the included objects ('id' could be a model, a container or an assembly)
*
* @param {*} id
* @param {*} T = {
* 'move' : [],
* 'rotate' : {
* 'pivot' : [ x , y , z ],
* 'alpha' : val_deg
* }
* }
*
* @returns {ApiResponse}
*/
async transformObject(id, T, includeContained) {
console.error(`ERROR in ${this.apiName}.openUrl(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
// ------------
/**
* Check overlap of oriented bounding boxes (OBBs) for given IDs every object against every other object.
* Objects having no geometry are ignored.
* @param {string[]} idList
* @param {number} overlapAllowed - Minimum overlap to report (0.0 - 1.0), default: 0.1
* @param {function|null} statusCallback - Optional callback function to report progress status.
* @returns {ApiResponse<object[]>} data: Array of overlapping OBB pairs. [ {
id1: id1,
id2: id2,
maxOverlap: 0.9
}, ... ]
*/
checkOverlapObjectList(idList, overlapAllowed = 0.1, statusCallback = null) {
console.error(`ERROR in ${this.apiName}.checkOverlapObjectList(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Calculate optimized oriented bounding boxes (OBBs) for given object IDs.
* @param {string[]} objIds
* @returns {ApiResponse<object>} Number of affected objects
*/
async calcOptOBB(objIds) {
console.error(`ERROR in ${this.apiName}.checkOverlapObjectList(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* Calculate overlap of oriented bounding boxes (OBBs) for two given object IDs.
* @param {string} id1
* @param {string} id2
* @returns {ApiResponse<number>} max overlap. example: 0.9 for 90% overlap
*/
async checkOverlapObjects(id1, id2) {
console.error(`ERROR in ${this.apiName}.checkOverlapObjectList(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* Set viewer configuration. <br>
* Changes configuration partially!
*
* @param {*} cfg = {
* "edges" : bool,
* "grid" : {
* "show" : bool,
* "color" : #hex
* },
* "background" : {
* "color" : #hex
* }
* }
*
* @returns {Promise<ApiResponse>}
*
*/
async setConfig( cfg ) {
console.error(`ERROR in ${this.apiName}.checkOverlapObjectList(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* @returns {Promise<ApiResponse>}
*/
async getConfig() {
console.error(`ERROR in ${this.apiName}.checkOverlapObjectList(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
*
* DEPRECATED !
*
* @param {boolean} onOff
* @returns {ApiResponse}
* @since 28.11.2025, ar
*/
setDrawEdges(onOff) {
console.error(`ERROR in ${this.apiName}.setDrawEdges(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
/**
* DEPRECATED !
* @returns {ApiResponse<boolean>}
* @since 28.11.2025, ar
*/
getDrawEdges() {
console.error(`ERROR in ${this.apiName}.getDrawEdges(): No model viewer instantiated.`)
return Promise.reject("No model viewer instantiated");
}
}
Source