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
*/
class BasePlanePoints extends BaseDynamicPoints {
_selfHoles = [];
/**
* The base points object in plane.
* @param {Object} param The initial parameters.
*/
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
onSyncOptions(param) {
super.onSyncOptions(param);
Utils.syncOptions(this, [
'selfPlanePoints',
'selfPlaneHoles',
'selfHoles',
'holes'
], param, param['extras'] || param['external']);
}
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
/**
* Get/Set the plane holes in self space.
* @type {Array<Array<Array<Number>>>}
* @private
*/
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();
}
/**
* Get/Set the holes in self space.
* @type {Array<Array<Array<Number>>>}
* @private
*/
get selfHoles() {
return this._selfHoles;
}
set selfHoles(value = []) {
this._selfHoles = value.slice(0);
this._refreshHoles();
}
/**
* Get/Set the holes in world space.
* @type {Array<Array<Array<Number>>>}
*/
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();
}
/**
* Get/Set the plane points in self space.
* @type {Array<Array<Array<Number>>>}
* @private
*/
get selfPlanePoints() {
return this.points.map(point => {
let selfPoint = this.worldToSelf(point);
return [selfPoint[0], selfPoint[2]];
});
}
set selfPlanePoints(value = []) {
this.points = MathUtils.makeClockWisePoints(value).map(point => {
return this.selfToWorld([point[0], 0, point[1]]);
});
}
/**
* Get the area.
* @type {Number}
*/
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;
}
/**
* Get the perimeter.
* @type {Number}
*/
get perimeter() {
let outlinePoints = this.outlinePoints;
return MathUtils.getDistanceFromPoints(outlinePoints, true);
}
/**
* Get the label position in world space.
* @type {Array<Number>}
*/
get labelPosition() {
let outlinePoints = this._getOutlinePoints();
let labelPos = MathUtils.getLabelPosition(outlinePoints);
return this.selfToWorld(labelPos);
}
/**
* Get the outline points in plane.
* @type {Array<Array<Number>>}
*/
get outlinePoints() {
let planePoints = this._getOutlinePoints();
return planePoints.map(point => {
return this.selfToWorld([point[0], 0, point[1]]);
});
}
// #endregion
}
export { BasePlanePoints }