import { MathUtils as BaseMathUtils } from "@uino/base-thing";
import polylabel from 'polylabel';
/**
* @class
* The math utils.
* @memberof THING
*/
class MathUtils extends BaseMathUtils {
/**
* Fix scale factor.
* @param {Array<Number>} value The scale factor.
* @returns {Array<Number>}
* @private
*/
static fixScaleFactor(value) {
if (value[0] === 0) { value[0] = Number.EPSILON; }
if (value[1] === 0) { value[1] = Number.EPSILON; }
if (value[2] === 0) { value[2] = Number.EPSILON; }
return value;
}
/**
* Get outline points.
* @param {Array<Array<Number>>} points The points in plane.
* @returns {Array<Number>}
* @private
*/
static getOutlinePoints(points) {
// Thanks for sharing code: https://stackoverflow.com/questions/41654535/find-outline-using-2d-point-map
let pLen, p, s, hull, i, p1, j, len;
let isRight = (a, b, c) => 0 <= (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
points.sort((a, b) => (a[0] + a[1] / 10000) - (b[0] + b[1] / 10000));
pLen = points.length - 1;
p = points;
s = [];
hull = [];
s.push(p[0], p[1]);
for (j = 0; j < 2; j++) {
for (i = 2; i <= pLen; i++) {
p1 = j === 0 ? p[i] : p[pLen - i];
len = s.length;
while (len > 1 && !isRight(s[len - 2], s[len - 1], p1)) {
s.pop();
len = s.length;
}
s.push(p1);
}
hull.push(...s);
s.length = 0;
s.push(p[pLen], p[pLen - 1]);
}
return MathUtils.toUniquePoints(hull.slice(1));
}
/**
* Get label position.
* @param {Array<Array<Number>>} points The points in plane.
* @param {Array<Array<Array<Number>>>} holes The hole points in plane.
* @param {Number} height The height, default is 0.
* @returns {Array<Number>}
* @private
*/
static getLabelPosition(points, holes = null, height = 0) {
let _points = [];
_points.push(MathUtils.toPlanePoints(points));
if (holes) {
holes.forEach(_holes => {
_points.push(MathUtils.toPlanePoints(_holes));
});
}
let labelPos = new polylabel(_points);
return [labelPos[0], height, labelPos[1]];
}
}
export { MathUtils };