"use strict";
/**
 * 当向量以数组的方式出现，一个计算单元库
 * @Description  : 向量数组
 * @Author       : 赵耀圣
 * @QQ           : 549184003
 * @Date         : 2021-08-02 15:09:33
 * @LastEditTime : 2021-08-02 15:50:16
 * @FilePath     : \cga.js\src\math\VecArray.ts
 */
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.vecs = void 0;
var Polygon_1 = require("../struct/3d/Polygon");
var Polyline_1 = require("../struct/3d/Polyline");
var Vec2_1 = require("./Vec2");
var Vec3_1 = require("./Vec3");
var Vec4_1 = require("./Vec4");
var Math_1 = require("./Math");
var Quat_1 = require("./Quat");
var _vec21 = new Vec2_1.Vec2();
var _vec31 = new Vec3_1.Vec3();
var _vec41 = new Vec4_1.Vec4();
var ckeckVec = function (vs, component) {
    if (vs.length % component !== 0)
        throw ("向量组件数量不一样");
};
/**
 * 矢量几何操作，数字数组/矢量数组，常用工具集合
 */
var vecs = /** @class */ (function () {
    function vecs() {
    }
    /**
     * 去除相邻的重复向量
     * @param vs 矢量集合
     * @param delta 误差
     * @returns
     */
    vecs.uniqueNeighborVecs = function (vs, delta) {
        if (delta === void 0) { delta = Math_1.delta4; }
        for (var i = 0; i < vs.length - 1; i++) {
            var lenSq = vs[i].distanceTo(vs[i + 1]);
            if (lenSq < delta)
                vs.splice(i, 1);
        }
        return vs;
    };
    /**
     * 找到最大值
     * @param array
     * @returns
     */
    vecs.max = function (array) {
        if (array.length === 0)
            return -Infinity;
        var max = array[0];
        for (var i = 1, l = array.length; i < l; ++i) {
            if (array[i] > max)
                max = array[i];
        }
        return max;
    };
    /**
    * 找到最小值
    * @param array
    * @returns
    */
    vecs.min = function (array) {
        if (array.length === 0)
            return -Infinity;
        var min = array[0];
        for (var i = 1, l = array.length; i < l; ++i) {
            if (array[i] < min)
                min = array[i];
        }
        return min;
    };
    /**
     * 去除相邻没有重复点
     */
    vecs.uniqueNeighbor = function (vs, component, delta) {
        if (component === void 0) { component = 3; }
        if (delta === void 0) { delta = Math_1.delta4; }
        for (var i = 0; i < vs.length; i += component) {
            for (var j = i + 3; j < vs.length;) {
                var lensq = 0;
                for (var c = 0; c < component; c++) {
                    lensq += (vs[i + c] - vs[j + c]) * (vs[i + c] - vs[j + c]);
                }
                if (Math.sqrt(lensq) < delta)
                    vs.splice(j, component);
                else
                    break;
            }
        }
        return vs;
    };
    /**
     * 去除任意重复点
     * @param vs 向量数组
     * @param component 向量组件数量
     * @returns 无重复向量数组
     */
    vecs.unique = function (vs, component) {
        if (component === void 0) { component = 3; }
        for (var i = 0; i < vs.length; i += component) {
            for (var j = i + 3; j < vs.length;) {
                var lensq = 0;
                for (var c = 0; c < component; c++) {
                    lensq += (vs[i + c] - vs[j + c]) * (vs[i + c] - vs[j + c]);
                }
                if (Math.sqrt(lensq) < 1e-5)
                    vs.splice(j, component);
                else
                    j += component;
            }
        }
        return vs;
    };
    /**
     *  翻转向量数组
     * @param vecs 向量数组
     * @param component  组件数量
     * @returns
     */
    vecs.reverse = function (vecs, component) {
        if (component === void 0) { component = 3; }
        ckeckVec(vecs, component);
        var length = vecs.length;
        for (var i = 0; i < length; i += component) {
            vecs.unshift.apply(vecs, vecs.splice(i, component));
        }
        return vecs;
    };
    /**
     * 点积
     * @param vecs
     * @returns
     */
    vecs.dot = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        if (vecs.length % 2 !== 0)
            throw ("两个向量组件数量不一样");
        var len = vecs.length / 2;
        var dot = 0;
        for (var i = 0; i < len; i++) {
            dot += vecs[i] * vecs[len + i];
        }
        return dot;
    };
    /**
     * 长度平方
     * @param vecs
     * @returns
     */
    vecs.distanceSq = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        if (vecs.length % 2 !== 0)
            throw ("向量组件数量不一样");
        var len = vecs.length / 2;
        var lenSq = 0;
        for (var i = 0; i < len; i++) {
            var d = (vecs[i] - vecs[len + i]);
            lenSq += d * d;
        }
        return lenSq;
    };
    /**
     * 长度
     * @param vecs
     * @returns
     */
    vecs.distance = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        return Math.sqrt(this.distanceSq.apply(this, vecs));
    };
    /**
     * 相加
     * @param vecs
     * @returns
     */
    vecs.add = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        if (vecs.length % 2 !== 0)
            throw ("两个向量组件数量不一样");
        if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) {
            for (var i = 0; i < vecs[0].length; i++) {
                vecs[0][i] += vecs[1][i];
            }
            return vecs[0];
        }
        if (vecs.length % 2 !== 0)
            console.error("VecArray:distanceSq  向量错误!!!");
        var len = vecs.length / 2;
        var res = [];
        for (var i = 0; i < len; i++) {
            res[i] = res[len + i] + res[i];
        }
        return res;
    };
    /**
     * 相减
     * @param vecs
     * @returns
     */
    vecs.sub = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        ckeckVec(vecs, 2);
        if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) {
            for (var i = 0; i < vecs[0].length; i++) {
                vecs[0][i] -= vecs[1][i];
            }
            return vecs[0];
        }
        if (vecs.length % 2 !== 0)
            console.error("VecArray:distanceSq  向量错误!!!");
        var len = vecs.length / 2;
        var res = [];
        for (var i = 0; i < len; i++) {
            res[i] = res[i] - res[len + i];
        }
        return res;
    };
    /**
     * 相乘
     * @param vecs
     * @returns
     */
    vecs.mul = function () {
        var vecs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            vecs[_i] = arguments[_i];
        }
        ckeckVec(vecs, 2);
        if (Array.isArray(vecs[0]) && Array.isArray(vecs[1])) {
            for (var i = 0; i < vecs[0].length; i++) {
                vecs[0][i] *= vecs[1][i];
            }
            return vecs[0];
        }
        if (vecs.length % 2 !== 0)
            console.error("VecArray:distanceSq  向量错误!!!");
        var len = vecs.length / 2;
        var res = [];
        for (var i = 0; i < len; i++) {
            res[i] = res[i] * res[len + i];
        }
        return res;
    };
    /**
     * 获取矢量数组的i个矢量
     * @param vecs
     * @param i
     * @param component
     * @returns
     */
    vecs.getVecAt = function (vecs, i, component) {
        if (component === void 0) { component = 3; }
        return [vecs[3 * i], vecs[3 * i + 1], vecs[3 * i + 2]];
    };
    /**
     * 在第 i 个位置插入一个向量
     * @param vecs
     * @param i
     * @param vec
     */
    vecs.insertAt = function (vecs, i) {
        var vec = [];
        for (var _i = 2; _i < arguments.length; _i++) {
            vec[_i - 2] = arguments[_i];
        }
        vecs.splice.apply(vecs, __spreadArray([i * vecs.length, 0], vecs, false));
    };
    //
    /**
     * 是否逆时针
     * counterclockwise
     */
    vecs.isCCW = function (shape, component) {
        if (component === void 0) { component = 3; }
        var d = 0;
        if (shape instanceof Polyline_1.Polyline || shape instanceof Polygon_1.Polygon)
            for (var i = 0; i < shape.length; i++) {
                var pt = shape.get(i);
                var ptnext = shape.get((i + 1) % shape.length);
                d += -0.5 * (ptnext.y + pt.y) * (ptnext.x - pt.x);
            }
        else if (Array.isArray(shape) && shape.length > 0) {
            if (shape[0] instanceof Vec3_1.Vec3 || shape[0] instanceof Vec2_1.Vec2) {
                for (var i = 0; i < shape.length; i++) {
                    var pt = shape[i];
                    var ptnext = shape[(i + 1) % shape.length];
                    d += -0.5 * (ptnext.y + pt.y) * (ptnext.x - pt.x);
                }
            }
            else if (!isNaN(shape[0])) {
                for (var i = 0; i < shape.length; i += component) {
                    var ptx = shape[i];
                    var pty = shape[(i + 1) % shape.length];
                    var ptnextx = shape[(i + 3) % shape.length];
                    var ptnexty = shape[(i + 4) % shape.length];
                    d += -0.5 * (ptnexty + pty) * (ptnextx - ptx);
                }
            }
        }
        return d > 0;
    };
    /**
     * 将向量深度拆解为数字
     * @param {Array} Array<Vec4 | Vec3 | Vec2 | any> | any
     * @param {String} comSort  'x','y','z','w' 按顺序选取后自由组合
     * @returns {Array<Number>} 数字数组
     */
    vecs.verctorToNumbers = function (vectors, comSort) {
        if (comSort === void 0) { comSort = "xyz"; }
        if (!(vectors instanceof Array)) {
            console.error("传入参数必须是数组");
            return [];
        }
        var numbers = [];
        if (vectors[0].x !== undefined && vectors[0].y !== undefined && vectors[0].z !== undefined && vectors[0].w !== undefined) {
            comSort = comSort.length !== 4 ? 'xyzw' : comSort;
            for (var i = 0; i < vectors.length; i++) {
                for (var j = 0; j < comSort.length; j++) {
                    numbers.push(vectors[i][comSort[j]]);
                }
            }
        }
        if (vectors[0].x !== undefined && vectors[0].y !== undefined && vectors[0].z !== undefined) {
            comSort = comSort.length !== 3 ? 'xyz' : comSort;
            for (var i = 0; i < vectors.length; i++) {
                for (var j = 0; j < comSort.length; j++) {
                    numbers.push(vectors[i][comSort[j]]);
                }
            }
        }
        else if (vectors[0].x !== undefined && vectors[0].y !== undefined) {
            comSort = comSort.length !== 2 ? 'xy' : comSort;
            for (var i = 0; i < vectors.length; i++) {
                for (var j = 0; j < comSort.length; j++) {
                    numbers.push(vectors[i][comSort[j]]);
                }
            }
        }
        else if (vectors[0] instanceof Array) {
            for (var i = 0; i < vectors.length; i++) {
                numbers = numbers.concat(vecs.verctorToNumbers(vectors[i]));
            }
        }
        else {
            console.error("数组内部的元素不是向量");
        }
        return numbers;
    };
    vecs.vec = function (component) {
        if (component === void 0) { component = 3; }
        if (component === 2)
            return new Vec2_1.Vec2;
        if (component === 3)
            return new Vec3_1.Vec3;
        if (component === 4)
            return new Vec4_1.Vec4;
        throw ('暂时不支持4维以上的矢量');
    };
    /**
     * 数字数组 转 适量数组
     * @param vss  数字数组
     * @param component 矢量维度，默认为3
     * @returns
     */
    vecs.numbersToVecs = function (vss, component) {
        if (component === void 0) { component = 3; }
        var result = [];
        for (var i = 0, length_1 = vss.length; i < length_1; i += component) {
            var vec = vecs.vec(component);
            vec.fromArray(vss, i);
            result.push(vec);
        }
        return result;
    };
    vecs.applyQuat = function (vss, quat, component) {
        if (component === void 0) { component = 3; }
        var vec;
        if (component === 3)
            vec = _vec31;
        else if (component === 2)
            vec = _vec21;
        else if (component === 4)
            vec = _vec41;
        for (var i = 0; i < vss.length; i += component) {
            vec.fromArray(vss, i)
                .applyQuat(quat)
                .toArray(vss, i);
        }
    };
    vecs.applyMat4 = function (vss, mat, component) {
        if (component === void 0) { component = 3; }
        var vec;
        if (component === 3)
            vec = _vec31;
        else if (component === 2)
            vec = _vec21;
        else if (component === 4)
            vec = _vec41;
        for (var i = 0; i < vss.length; i += component) {
            vec.fromArray(vss, i)
                .applyMat4(mat)
                .toArray(vss, i);
        }
    };
    vecs.translate = function (vss, distance, component) {
        if (component === void 0) { component = 3; }
        for (var i = 0; i < vss.length; i += component) {
            for (var j = 0; j < component; j++) {
                vss[i + j] += distance[j];
            }
        }
    };
    vecs.rotate = function (vss, axis, angle) {
        vecs.applyQuat(vss, new Quat_1.Quat().setFromAxisAngle(axis, angle));
    };
    vecs.scale = function (vss, _scale, component) {
        if (component === void 0) { component = 3; }
        for (var i = 0; i < vss.length; i += component) {
            for (var j = 0; j < component; j++) {
                vss[i + j] *= _scale[j];
            }
        }
    };
    return vecs;
}());
exports.vecs = vecs;
