import { Utils } from '../common/Utils'
import { MathUtils } from '../math/MathUtils';
import { PlanePointsHelperComponent } from '../components/PlanePointsHelperComponent';
import { BaseDynamicPoints } from './BaseDynamicPoints';
const registerComponentParam = { isResident: true };
/**
* @class BasePlanePoints
* The base plane points object.
* @memberof THING
* @extends THING.BaseDynamicPoints
* @public
*/
class BasePlanePoints extends BaseDynamicPoints {
/**
* 基础平面点对象类,负责管理平面上的点数据和区域属性
* @param {object} param 初始化参数
*/
constructor(param = {}) {
super(param);
}
// #region Private Functions
/**
* Refresh holes.
* @private
*/
_refreshHoles() {
let selfPlaneHoles = this.selfPlaneHoles;
this.bodyNode.setHoles(selfPlaneHoles);
if (this.hasComponent('helper')) {
this.helper.refresh();
}
}
/**
* Get the outline points in self space in plane.
* @returns {Array<Array<number>>}
* @private
*/
_getOutlinePoints() {
let planePoints = this.onGetSelfPoints(this.selfPoints);
return MathUtils.getOutlinePoints(planePoints);
}
// #endregion
// #region Overrides
onSetupResource(param) {
// 读取点数据,写到参数里传给父类处理
const selfPlanePoints = param['selfPlanePoints'];
if (selfPlanePoints) {
param['selfPoints'] = convertPlanePoints(selfPlanePoints);
}
// 读取洞数据
const selfPlaneHoles = param['selfPlaneHoles'];
if (selfPlaneHoles) {
this._selfHoles = convertPlaneHolesPoints(selfPlaneHoles);
}
else if (param['selfHoles']) {
this._selfHoles = param['selfHoles'];
}
else if (param['holes']) {
this._selfHoles = param['holes'].map(hole => {
return hole.map(_hole => {
return this.worldToSelf(_hole);
});
});
}
else {
this._selfHoles = [];
}
super.onSetupResource(param);
}
onSetupBodyNode(node) {
super.onSetupBodyNode(node);
const holes = this.selfPlaneHoles;
if (holes) {
node.setHoles(holes);
}
}
onExportExternalData() {
let external = Object.assign({}, super.onExportExternalData());
Utils.setAttributeIfExist(external, 'selfPlanePoints', this);
Utils.setAttributeIfExist(external, 'selfPlaneHoles', this);
Utils.setAttributeIfExist(external, 'selfHoles', this);
return external;
}
onSetupComponent(param) {
super.onSetupComponent(param);
this.addComponent(PlanePointsHelperComponent, 'helper', registerComponentParam);
}
onSetupTransform(param) {
// Auto calculate the position when it do not provide any positions
let position = param['position'] || param['localPosition'];
if (!position) {
let points = param['points'];
if (points && points.length) {
// Get the height
let height = points.reduce((value, point) => {
return value + point[1];
}, 0) / points.length;
// Make label position as default position
param['position'] = MathUtils.getLabelPosition(points, param['holes'], height);
}
}
super.onSetupTransform(param);
}
onGetSelfPoints(selfPoints) {
return selfPoints.map(point => {
return [point[0], point[2]];
});
}
onBeforeSetBodyPoints(selfPoints) {
}
onRefresh() {
this._refreshHoles();
super.onRefresh();
}
// #endregion
// #region Accessor
/**
* 设置/获取 自身平面坐标系下(2D)区域空洞坐标
* @type {Array<Array<Array<number>>>}
* @public
*/
get selfPlaneHoles() {
return this._selfHoles.map(hole => {
return hole.map(_hole => {
return [_hole[0], _hole[2]];
});
});
}
set selfPlaneHoles(value) {
this._selfHoles = value.map(hole => {
return hole.map(_hole => {
return [_hole[0], 0, _hole[1]];
});
});
this._refreshHoles();
}
/**
* 设置/获取 自身坐标系下(3D)区域空洞坐标
* @type {Array<Array<Array<number>>>}
* @public
*/
get selfHoles() {
return this._selfHoles;
}
set selfHoles(value = []) {
this._selfHoles = value.slice(0);
this._refreshHoles();
}
/**
* 设置/获取 世界坐标系下(3D)区域空洞坐标
* @type {Array<Array<Array<number>>>}
* @public
*/
get holes() {
return this._selfHoles.map(hole => {
return hole.map(_hole => {
return this.selfToWorld(_hole);
});
});
}
set holes(value = []) {
this._selfHoles = value.map(hole => {
return hole.map(_hole => {
return this.worldToSelf(_hole);
});
});
this._refreshHoles();
}
/**
* 设置/获取 自身平面坐标系下(2D)区域外轮廓坐标
* @type {Array<Array<Array<number>>>}
* @public
*/
get selfPlanePoints() {
return this.points.map(point => {
let selfPoint = this.worldToSelf(point);
return [selfPoint[0], selfPoint[2]];
});
}
set selfPlanePoints(value = []) {
if (!MathUtils.isClockWise(value)) {
const reversedArr = value.slice().reverse();
this.points = (reversedArr).map(point => {
return this.selfToWorld([point[0], 0, point[1]]);
});
}
else {
this.points = (value).map(point => {
return this.selfToWorld([point[0], 0, point[1]]);
});
}
}
/**
* 获取区域面积(计算中会减去洞的面积)
* @type {number}
* @public
*/
get area() {
let outlinePoints = this._getOutlinePoints();
let area = Math.abs(MathUtils.getArea(outlinePoints));
// Sub holes area
this.selfPlaneHoles.forEach(holes => {
let holeArea = MathUtils.getArea(holes);
area -= holeArea;
});
return area;
}
/**
* 获取区域周长
* @type {number}
* @public
*/
get perimeter() {
let outlinePoints = this.outlinePoints;
return MathUtils.getDistanceFromPoints(outlinePoints, true);
}
/**
* 获取世界坐标系下区域的标注位置(一般是在区域中心)
* @type {Array<number>}
* @public
*/
get labelPosition() {
let outlinePoints = this._getOutlinePoints();
let labelPos = MathUtils.getLabelPosition(outlinePoints);
return this.selfToWorld(labelPos);
}
/**
* 获取自身平面空间(2D)下区域外轮廓点位
* @type {Array<Array<number>>}
* @public
*/
get outlinePoints() {
let planePoints = this._getOutlinePoints();
return planePoints.map(point => {
return this.selfToWorld([point[0], 0, point[1]]);
});
}
// #endregion
}
export { BasePlanePoints }
function convertPlanePoints(value) {
if (!MathUtils.isClockWise(value)) {
const reversedArr = value.slice().reverse();
return (reversedArr).map(point => {
return [point[0], 0, point[1]];
});
}
else {
return (value).map(point => {
return [point[0], 0, point[1]];
});
}
}
function convertPlaneHolesPoints(value) {
return value.map(hole => {
return hole.map(_hole => {
return [_hole[0], 0, _hole[1]];
});
});
}