import { Object3D, Style } from '@uino/thing';
import { Utils } from '../../common/Utils.js';
/**
* @class Boundary
* @summary 围栏类,用于在三维场景中创建多边形围栏/边界墙,支持自定义高度和纹理贴图。
* 通过指定世界坐标点集或局部坐标点集定义围栏路径,配合高度参数生成三维墙体。
* 高度支持数组形式为不同顶点分别指定高度,样式支持纹理贴图,
* 适用于场地围栏、安全区域边界、道路护栏等可视化场景。
* @memberof THING
* @public
* @example
* // 创建一个半透明纹理围栏
* const fence = new THING.EXTEND.Boundary({
* points: [
* [-10, 0, -10],
* [-10, 0, 10],
* [10, 0, 10],
* [10, 0, -10]
* ],
* height: 3,
* style: {
* color: [0, 0.6, 1, 0.5],
* map: new THING.ImageTexture('./images/fence.png')
* }
* });
* fence.isAcceptLight = false;
*/
class Boundary extends Object3D {
/**
* 构造函数
* @param {object} param 参数对象
* @param {Number|Number[]} param.height 围栏高度 支持数组 长度需要和points或者selfPoints一致
* @param {Boolean} param.isAcceptLight 是否接受光照
* @param {Array<number>} param.points 点集合
* @param {Array<number>} param.selfPoints 自身坐标系下的点集合
* @param {Style} param.style 围栏样式
* @example
* // 创建一个围栏
const boundary = new THING.EXTEND.Boundary({
points: [
[1,0,-1],
[1,0,1],
[1,0,2],
],
height: 5,
style: {
map: new THING.ImageTexture('./images/signboard-top/image1.png'),
}
});
*/
constructor(param = {}) {
super(param);
this._syncOptions(param);
if (this._points) {
this._convertPointsAndSelfPoints('points');
}
if (this._selfPoints) {
this._convertPointsAndSelfPoints('selfPoints');
}
this._updateRenderNode();
}
_syncOptions(param) {
Utils.syncOptions(this, [
'height',
'points',
'selfPoints',
'isAcceptLight',
], param, param['extras'] || param['external']);
}
/**
* 更新渲染节点
* @private
* @ignore
*/
_updateRenderNode() {
// create render node
if (this._selfPoints) {
const geometryResource = Utils._createBoundaryGeometryResource({
data: this._selfPoints,
extrudeHeight: this._height //支持数组 长度需要和points一致
});
const node = Utils.createObject('BoundaryNode', { uScene: this.node._uScene, geometryResource: geometryResource });
this.body.setNode(node);
}
}
/**
* 在点和自身点之间进行转换
* @private
* @ignore
*/
_convertPointsAndSelfPoints(flag) {
// convert points to selfPoints
if (this._points && flag === 'points') {
let localPoints = [];
for (let i = 0; i < this._points.length; i++) {
localPoints[i] = this.worldToSelf(this._points[i]);
}
this._selfPoints = localPoints;
}
// convert selfPoints to points
if (this._selfPoints && flag === 'selfPoints') {
let worldPoints = [];
for (let i = 0; i < this._selfPoints.length; i++) {
worldPoints[i] = this.selfToWorld(this._selfPoints[i]);
}
this._points = worldPoints;
}
}
onExportExternalData() {
let external = Object.assign({}, super.onExportExternalData());
Utils.setAttributeIfExist(external, 'selfPoints', this);
Utils.setAttributeIfExist(external, 'height', this);
Utils.setAttributeIfExist(external, 'isAcceptLight', this);
return external;
}
/**
* 获取/设置点集合
* @type {Number[]}
* @public
*/
get points() {
return this._points;
}
set points(value) {
this._points = value;
this._convertPointsAndSelfPoints('points');
this._updateRenderNode();
}
/**
* 获取/设置自身坐标系下的点集合
* @type {Number[]}
* @public
*/
get selfPoints() {
return this._selfPoints;
}
set selfPoints(value) {
this._selfPoints = value;
this._convertPointsAndSelfPoints('selfPoints');
this._updateRenderNode();
}
/**
* 获取/设置高度 支持数组
* @type {Number|Number[]}
* @public
*/
get height() {
return this._height;
}
set height(value) {
this._height = value;
this._updateRenderNode();
}
/**
* 获取/设置是否接受光照
* @type {Boolean}
* @public
*/
set isAcceptLight(value) {
this._isAcceptLight = value
this.style.setAttribute('Lights', value)
}
get isAcceptLight() {
return this._isAcceptLight
}
onDestroy() {
this._selfPoints = null;
this._points = null;
this._height = null;
super.onDestroy()
}
copy(source) {
super.copy(source);
this._points = source._points;
this._selfPoints = source._selfPoints;
this._height = source._height;
if (this._points) {
this._convertPointsAndSelfPoints('points');
}
if (this._selfPoints) {
this._convertPointsAndSelfPoints('selfPoints');
}
this._updateRenderNode();
return this;
}
clone() {
return new this.constructor().copy(this);
}
}
export { Boundary }