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 };
/**
* CellSpace - 空间
*
* 提供处理对象的空间关系能力,可进行包含、相交和相离等空间计算。
* @class CellSpace
* @memberof THING
* @extends THING.Object3D
* @public
* @example
const space = new THING.CellSpace({
size: [5, 3, 5],
position: [0, 1.5, 0],
});
*/
class CellSpace extends Object3D {
static defaultTagArray = ['CellSpace'];
/**
提供处理对象的空间关系的能力。空间是具有一定体积的三维对象,可进行空间计算。
</br>空间可以包含子空间和实体,实体也可以包含空间。空间关系可以分为包含、相交和相离。
</br>空间计算时是以物体自身包围盒进行计算
* @param {object} param The initial parameters. 除Object3D构造方法中的参数之外,还可以传size
* @param {number[]} param.size 三个方向的尺寸
* @constructor
* @public
*/
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);
}
/**
判读包含关系
* @param {object} obj 当前物体是否包含该参数传入的物体
* @param {boolean} recursive 空间计算是否包含obj的子对象
* @returns {boolean}
* @example
* let result = this.contains(obj, false);
* console.log(result);
* @public
*/
contains(obj, recursive = true) {
return this._calcRelationByCondition(obj, recursive, relation.contains);
}
/**
判读相交关系
* @param {object} obj 当前物体是否与该参数传入的物体相交
* @param {boolean} recursive 空间计算是否包含obj的子对象
* @returns {boolean}
* @example
* let result = this.intersects(obj, false);
* console.log(result);
* @public
*/
intersects(obj, recursive = true) {
return this._calcRelationByCondition(obj, recursive, relation.intersects);
}
/**
判读相离关系 相离代表两个物体之间没有交集
* @param {object} obj 当前物体是否与该参数传入的物体不相交
* @param {boolean} recursive 空间计算是否包含obj的子对象
* @returns {boolean}
* @example
* let result = this.disjoint(obj, false);
* console.log(result);
* @public
*/
disjoint(obj, recursive = true) {
return this._calcRelationByCondition(obj, recursive, relation.disjoint);
}
/**
显示包围盒
* @param {boolean} value 是否显示
* @example
* space.showBounding();
* @public
*/
showBounding(value = true) {
let _private = this[__.private];
if (!_private.size && !this.children.length) {
Utils.warn('CellSpace no size!');
return;
}
this.traverse((object) => {
if (object.isCellSpace && object.size) {
object.spaceHelper.showBounding(value);
}
});
}
// calc relation by condition
_calcRelationByCondition(obj, cascade, condition) {
let spaces = [];
this.traverse((object) => {
if (object.isCellSpace && 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;
}
}
/**
获取对象三个方向的尺寸
* @type {Array<number>}
*/
get size() {
let _private = this[__.private];
return _private.size;
}
/**
Check whether it's CellSpace type or inherit from it.
* @type {boolean}
*/
get isCellSpace() {
return true;
}
get isSpace3D() {
console.warn('Plase use isCellSpace instead of isSpace3D');
return true;
}
}
export { CellSpace }