import { MathUtils } from '../math/MathUtils';
import { Object3D } from './Object3D';
import { Utils } from '../common/Utils';
import { SpaceRelationComponent } from '../components/SpaceRelationComponent';
import { SpaceHelperComponent } from '../components/SpaceHelperComponent';
const __ = {
private: Symbol('private'),
}
const relation = {
contains: 'contains',
intersects: 'intersects',
disjoint: 'disjoint'
}
const registerComponentParam = { isResident: true };
/**
* @class Space3D
* The space3D object.
* @memberof THING
* @extends THING.Object3D
* @public
*/
class Space3D extends Object3D {
static defaultTagArray = ['Space3D'];
/**
* The space3D object.
* @param {Object} param The initial parameters.
*/
constructor(param = {}) {
super(param);
this[__.private] = {};
let _private = this[__.private];
_private.size = param['size'];
// init local bounding box
if (_private.size) {
this.initialLocalBoundingBox = {
center: [0, 0, 0],
halfSize: MathUtils.divideVector(_private.size, 2)
};
}
}
clearInitialLocalBoundingBox() { }
onSetupComponent(param) {
super.onSetupComponent(param);
this.addComponent(SpaceRelationComponent, 'spaceCalculation', registerComponentParam);
this.addComponent(SpaceHelperComponent, 'spaceHelper', registerComponentParam);
}
/**
* contains relation
* @param {Object} obj THe relation object.
* @param {Boolean} cascade The cascade.
* @returns {Boolean}
* @example
* let result = this.contains(obj, false);
* console.log(result);
* @public
*/
contains(obj, cascade = true) {
return this._calcRelationByCondition(obj, cascade, relation.contains);
}
/**
* intersects relation
* @param {Object} obj THe relation object.
* @param {Boolean} cascade The cascade.
* @returns {Boolean}
* @example
* let result = this.intersects(obj, false);
* console.log(result);
* @public
*/
intersects(obj, cascade = true) {
return this._calcRelationByCondition(obj, cascade, relation.intersects);
}
/**
* disjoint relation
* @param {Object} obj THe relation object.
* @param {Boolean} cascade The cascade.
* @returns {Boolean}
* @example
* let result = this.disjoint(obj, false);
* console.log(result);
* @public
*/
disjoint(obj, cascade = true) {
return this._calcRelationByCondition(obj, cascade, relation.disjoint);
}
/**
* show bounding
* @param {Boolean} value The value, default is true.
* @example
* space.showBounding();
* @public
*/
showBounding(value = true) {
let _private = this[__.private];
if (!_private.size && !this.children.length) {
Utils.warn('Space3D no size!');
return;
}
this.traverse((object) => {
if (object.isSpace3D && object.size) {
object.spaceHelper.showBounding(value);
}
});
}
// calc relation by condition
_calcRelationByCondition(obj, cascade, condition) {
let spaces = [];
this.traverse((object) => {
if (object.isSpace3D && object.size) {
spaces.push(object);
}
});
switch (condition) {
case relation.contains:
case relation.intersects:
return _calcRelation(true);
case relation.disjoint:
return _calcRelation(false);
}
function _calcRelation(bool) {
for (let i = 0; i < spaces.length; i++) {
const space = spaces[i];
if (space.spaceCalculation[condition](obj, cascade) === bool) {
return bool;
}
}
return !bool;
}
}
/**
* The object size
* @type {Array<Number>}
*/
get size() {
let _private = this[__.private];
return _private.size;
}
/**
* Check whether it's Space3D type or inherit from it.
* @type {Boolean}
*/
get isSpace3D() {
return true;
}
}
export { Space3D }