src/viewer/scene/metriqs/Metriqs.js
//----------------------------------------------------------------------------------------------------------------------
// This file is named "Metriqs.js" because "Metrics.js" is blocked by uBlock Origin (https://en.wikipedia.org/wiki/UBlock_Origin)
//----------------------------------------------------------------------------------------------------------------------
import {Component} from "../Component.js";
import {math} from "../math/math.js";
const unitsInfo = {
meters: {
abbrev: "m"
},
metres: {
abbrev: "m"
},
centimeters: {
abbrev: "cm"
},
centimetres: {
abbrev: "cm"
},
millimeters: {
abbrev: "mm"
},
millimetres: {
abbrev: "mm"
},
yards: {
abbrev: "yd"
},
feet: {
abbrev: "ft"
},
inches: {
abbrev: "in"
}
};
/**
* @desc Configures its {@link Scene}'s measurement unit and mapping between the Real-space and World-space 3D Cartesian coordinate systems.
*
*
* ## Overview
*
* * Located at {@link Scene#metrics}.
* * {@link Metrics#units} configures the Real-space unit type, which is ````"meters"```` by default.
* * {@link Metrics#scale} configures the number of Real-space units represented by each unit within the World-space 3D coordinate system. This is ````1.0```` by default.
* * {@link Metrics#origin} configures the 3D Real-space origin, in current Real-space units, at which this {@link Scene}'s World-space coordinate origin sits, This is ````[0,0,0]```` by default.
*
* ## Usage
*
* Let's load a model using an {@link XKTLoaderPlugin}, then configure the Real-space unit type and the coordinate
* mapping between the Real-space and World-space 3D coordinate systems.
*
* ````JavaScript
* import {Viewer, XKTLoaderPlugin} from "xeokit-sdk.es.js";
*
* const viewer = new Viewer({
* canvasId: "myCanvas"
* });
*
* viewer.scene.camera.eye = [-2.37, 18.97, -26.12];
* viewer.scene.camera.look = [10.97, 5.82, -11.22];
* viewer.scene.camera.up = [0.36, 0.83, 0.40];
*
* const xktLoader = new XKTLoaderPlugin(viewer);
*
* const model = xktLoader.load({
* src: "./models/xkt/duplex/duplex.xkt"
* });
*
* const metrics = viewer.scene.metrics;
*
* metrics.units = "meters";
* metrics.scale = 10.0;
* metrics.origin = [100.0, 0.0, 200.0];
* ````
*/
class Metrics extends Component {
/**
* @constructor
* @private
*/
constructor(owner, cfg = {}) {
super(owner, cfg);
this._units = "meters";
this._scale = 1.0;
this._origin = math.vec3([0, 0, 0]);
this.units = cfg.units;
this.scale = cfg.scale;
this.origin = cfg.origin;
}
/**
* Gets info about the supported Real-space unit types.
*
* This will be:
*
* ````javascript
* {
* {
* meters: {
* abbrev: "m"
* },
* metres: {
* abbrev: "m"
* },
* centimeters: {
* abbrev: "cm"
* },
* centimetres: {
* abbrev: "cm"
* },
* millimeters: {
* abbrev: "mm"
* },
* millimetres: {
* abbrev: "mm"
* },
* yards: {
* abbrev: "yd"
* },
* feet: {
* abbrev: "ft"
* },
* inches: {
* abbrev: "in"
* }
* }
* }
* ````
*
* @type {*}
*/
get unitsInfo() {
return unitsInfo;
}
/**
* Sets the {@link Scene}'s Real-space unit type.
*
* Accepted values are ````"meters"````, ````"centimeters"````, ````"millimeters"````, ````"metres"````, ````"centimetres"````, ````"millimetres"````, ````"yards"````, ````"feet"```` and ````"inches"````.
*
* @emits ````"units"```` event on change, with the value of this property.
* @type {String}
*/
set units(value) {
if (!value) {
value = "meters";
}
const info = unitsInfo[value];
if (!info) {
this.error("Unsupported value for 'units': " + value + " defaulting to 'meters'");
value = "meters";
}
this._units = value;
this.fire("units", this._units);
}
/**
* Gets the {@link Scene}'s Real-space unit type.
*
* @type {String}
*/
get units() {
return this._units;
}
/**
* Sets the number of Real-space units represented by each unit of the {@link Scene}'s World-space coordinate system.
*
* For example, if {@link Metrics#units} is ````"meters"````, and there are ten meters per World-space coordinate system unit, then ````scale```` would have a value of ````10.0````.
*
* @emits ````"scale"```` event on change, with the value of this property.
* @type {Number}
*/
set scale(value) {
value = value || 1;
if (value <= 0) {
this.error("scale value should be larger than zero");
return;
}
this._scale = value;
this.fire("scale", this._scale);
}
/**
* Gets the number of Real-space units represented by each unit of the {@link Scene}'s World-space coordinate system.
*
* @type {Number}
*/
get scale() {
return this._scale;
}
/**
* Sets the Real-space 3D origin, in Real-space units, at which this {@link Scene}'s World-space coordinate origin ````[0,0,0]```` sits.
*
* @emits "origin" event on change, with the value of this property.
* @type {Number[]}
*/
set origin(value) {
if (!value) {
this._origin[0] = 0;
this._origin[1] = 0;
this._origin[2] = 0;
return;
}
this._origin[0] = value[0];
this._origin[1] = value[1];
this._origin[2] = value[2];
this.fire("origin", this._origin);
}
/**
* Gets the 3D Real-space origin, in Real-space units, at which this {@link Scene}'s World-space coordinate origin ````[0,0,0]```` sits.
*
* @type {Number[]}
*/
get origin() {
return this._origin;
}
/**
* Converts a 3D position from World-space to Real-space.
*
* This is equivalent to ````realPos = #origin + (worldPos * #scale)````.
*
* @param {Number[]} worldPos World-space 3D position, in World coordinate system units.
* @param {Number[]} [realPos] Destination for Real-space 3D position.
* @returns {Number[]} Real-space 3D position, in units indicated by {@link Metrics#units}.
*/
worldToRealPos(worldPos, realPos = math.vec3(3)) {
realPos[0] = this._origin[0] + (this._scale * worldPos[0]);
realPos[1] = this._origin[1] + (this._scale * worldPos[1]);
realPos[2] = this._origin[2] + (this._scale * worldPos[2]);
}
/**
* Converts a 3D position from Real-space to World-space.
*
* This is equivalent to ````worldPos = (worldPos - #origin) / #scale````.
*
* @param {Number[]} realPos Real-space 3D position.
* @param {Number[]} [worldPos] Destination for World-space 3D position.
* @returns {Number[]} World-space 3D position.
*/
realToWorldPos(realPos, worldPos = math.vec3(3)) {
worldPos[0] = (realPos[0] - this._origin[0]) / this._scale;
worldPos[1] = (realPos[1] - this._origin[1]) / this._scale;
worldPos[2] = (realPos[2] - this._origin[2]) / this._scale;
return worldPos;
}
}
export {Metrics};