Source: math/MathUtils.js

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 };