import { Utils } from '../common/Utils';
import { MathUtils } from '../math/MathUtils';
import { Object3D } from './Object3D';
/**
* @class BasePoints
* The base points object.
* @memberof THING
* @extends THING.Object3D
*/
class BasePoints extends Object3D {
_selfPoints = [];
_autoAdjustPosition = false;
/**
* The base points object.
* @param {Object} param The initial parameters.
*/
constructor(param = {}) {
super(param);
}
// #region Private
_adjustPosition(points) {
let center = MathUtils.getCenterFromPoints(points);
this.position = center;
}
// #endregion
// #region Overrides
onSyncOptions(param) {
Utils.syncOptions(this, [
'autoAdjustPosition',
'selfPoints',
'points'
], param, param['extras'] || param['external']);
}
onExportExternalData() {
let external = Object.assign({}, super.onExportExternalData());
Utils.setAttributeIfExist(external, 'autoAdjustPosition', this);
Utils.setAttributeIfExist(external, 'selfPoints', this);
return external;
}
onSetupPosition(param) {
if (param['localPosition'] || param['position']) {
super.onSetupPosition(param);
}
// Auto set center of points as line position
else if (param['points']) {
let center = MathUtils.getCenterFromPoints(param['points']);
this.position = center;
}
else {
super.onSetupPosition(param);
}
}
/**
* When get self points callback function.
* @param {Array<Array<Number>>} selfPoints The self points.
* @returns {Array<Array<Number>>}
* @private
*/
onGetSelfPoints(selfPoints) {
return selfPoints;
}
/**
* Before set body self points.
* @param {Array<Array<Number>>} selfPoints The self points.
* @private
*/
onBeforeSetBodyPoints(selfPoints) {
}
/**
* After set body self points.
* @private
*/
onAfterSetBodyPoints() {
}
onRefresh() {
this.onRefreshPoints();
this.onRefreshAttributes();
}
/**
* When refresh points.
* @returns {Array<Array<Number>>}
* @private
*/
onRefreshPoints() {
this.onBeforeSetBodyPoints(this._selfPoints);
let selfPoints = this.onGetSelfPoints(this._selfPoints);
this.bodyNode.setPoints(selfPoints);
this.onAfterSetBodyPoints();
return selfPoints;
}
/**
* When refresh attributes.
* @private
*/
onRefreshAttributes() {
}
// #endregion
/**
* Clear all points.
* @example
* let point = new THING.Points();
* let ret = point.points.length == 0;
* // @expect(ret == true);
* point.addPoint([1,1,1]);
* ret = point.points.length == 1;
* // @expect(ret == true);
* point.clearPoints();
* ret = point.points.length == 0;
* // @expect(ret == true);
*/
clearPoints() {
this._selfPoints = [];
this.bodyNode.setPoints([]);
}
/**
* Insert point by index in world space.
* @param {Number} index The index.
* @param {Array<Number>} position The world position.
* @example
* let point = new THING.Points();
* point.addPoint([1,1,1]);
* point.insertPoint(0,[10,10,10]);
* ret = point.points[0][0] == 10;
* // @expect(ret == true);
*/
insertPoint(index, position) {
let selfPoints = this._selfPoints;
selfPoints._insert(index, this.worldToSelf(position));
this.onRefreshPoints();
}
/**
* Add point in world space.
* @param {Array<Number>} position The world position.
* @example
* let point = new THING.Points();
* let ret = point.points.length == 0;
* // @expect(ret == true);
* point.addPoint([1,1,1]);
* ret = point.points.length == 1;
* // @expect(ret == true);
*/
addPoint(position) {
let selfPoints = this._selfPoints;
selfPoints.push(this.worldToSelf(position));
this.onRefreshPoints();
}
/**
* Add points in world space.
* @param {Array<Array<Number>>} points The points in world space.
* @example
* let point = new THING.Points();
* let ret = point.points.length == 0;
* // @expect(ret == true);
* point.addPoints([[1,1,1],[2,2,2]]);
* ret = point.points.length == 2;
* // @expect(ret == true);
*/
addPoints(points) {
let selfPoints = this._selfPoints;
points.forEach(point => {
selfPoints.push(this.worldToSelf(point));
});
this.onRefreshPoints();
}
/**
* Remove point by index.
* @param {Number} index The index.
* @example
* let point = new THING.Points();
* let ret = point.points.length == 0;
* // @expect(ret == true);
* point.addPoints([[1,1,1],[2,2,2]]);
* ret = point.points[0][0] == 1;
* // @expect(ret == true);
* point.removePoint(0);
* ret = point.points[0][0] == 2;
* // @expect(ret == true);
*/
removePoint(index) {
let selfPoints = this._selfPoints;
selfPoints._removeAt(index);
this.onRefreshPoints();
}
/**
* Set the point by index in world space.
* @param {Number} index The index.
* @param {Array<Number>} position The world position.
* @example
* let point = new THING.Points();
* let ret = point.points.length == 0;
* // @expect(ret == true);
* point.addPoints([[1,1,1],[2,2,2]]);
* ret = point.points[0][0] == 1;
* // @expect(ret == true);
* point.setPoint(0,[10,10,10]);
* ret = point.points[0][0] == 10;
* // @expect(ret == true);
*/
setPoint(index, position) {
let selfPoints = this._selfPoints;
selfPoints[index] = this.worldToSelf(position);
this.onRefreshPoints();
}
// #region Accessor
/**
* Get the number of points.
* @type {Number}
* @example
* let point = new THING.Points();
* let ret = point.number == 0;
* // @expect(ret == true);
* point.addPoints([[1,1,1],[2,2,2]]);
* ret = point.number == 2;
* // @expect(ret == true);
*/
get number() {
return this.points.length;
}
/**
* Get/Set the auto adjust position flag, default is false.
* If the relative position of point(s) is too large, there will be a problem of precision loss (object drawing will shake).
* @type {Boolean}
* @example
* let point = new THING.Points();
* let ret = point.autoAdjustPosition == false;
* // @expect(ret == true);
* point.autoAdjustPosition = true;
* ret = point.autoAdjustPosition == true;
* // @expect(ret == true);
*/
get autoAdjustPosition() {
return this._autoAdjustPosition;
}
set autoAdjustPosition(value) {
this._autoAdjustPosition = value;
}
/**
* Get/Set the points in self space.
* @type {Array<Array<Number>>}
* @example
* let point = new THING.Points();
* point.selfPoints = [[1,1,1],[2,2,2]];
* ret = point.selfPoints[1][1] == 2;
* // @expect(ret == true);
*/
get selfPoints() {
return this._selfPoints;
}
set selfPoints(value) {
this._selfPoints = value ? value.slice(0) : [];
this.onRefreshPoints();
}
/**
* Get/Set the points in world space.
* @type {Array<Array<Number>>}
* @example
* let point = new THING.Points();
* point.points = [[1,1,1],[2,2,2]];
* ret = point.points[1][1] == 2;
* // @expect(ret == true);
*/
get points() {
return this._selfPoints.map(point => {
return this.selfToWorld(point);
});
}
set points(value) {
if (value) {
if (this._autoAdjustPosition) {
this._adjustPosition(value);
}
this._selfPoints = value.map(point => {
return this.worldToSelf(point);
});
this.onRefreshPoints();
}
else {
this.clearPoints();
}
}
/**
* Get/Set the points in local space.
* @type {Array<Array<Number>>}
* @example
* let point = new THING.Points();
* point.localPoints = [[1,1,1],[2,2,2]];
* ret = point.localPoints[1][1] == 2;
* // @expect(ret == true);
*/
get localPoints() {
return this._selfPoints.map(point => {
return this.selfToLocal(point);
});
}
set localPoints(value) {
if (value) {
this._selfPoints = value.map(point => {
return this.localToSelf(point);
});
this.onRefreshPoints();
}
else {
this.clearPoints();
}
}
/**
* Get the length of points.
* @type {Number}
* @example
* let point = new THING.Points();
* point.localPoints = [[0,0,0],[3,0,0],[0,4,0]];
* ret = point.length == 8;
* // @expect(ret == true);
*/
get length() {
return MathUtils.getDistanceFromPoints(this.points);
}
// #endregion
}
export { BasePoints }