"use strict";
/*
 * @Description  : 挤压相关方法
 * @Author       : 赵耀圣
 * @QQ           : 549184003
 * @Date         : 2020-12-10 15:01:42
 * @LastEditTime : 2021-09-14 10:07:25
 * @FilePath     : \cesium-taji-dabaod:\github\cga.js\src\alg\extrude.ts
 */
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
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));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.extrudeNext = exports.EndType = exports.JoinType = exports.extrude_obsolete = exports.extrude = exports.linkSides = exports.linkSide = void 0;
var Vec3_1 = require("../math/Vec3");
var Vec2_1 = require("../math/Vec2");
var Quat_1 = require("../math/Quat");
var Path_1 = require("../struct/3d/Path");
var common_1 = require("./common");
var pointset_1 = require("./pointset");
var mesh_1 = require("../render/mesh");
var trianglution_1 = require("./trianglution");
var array_1 = require("../utils/array");
var types_1 = require("../utils/types");
var Mat4_1 = require("../math/Mat4");
var Math_1 = require("../math/Math");
var vector_1 = __importDefault(require("../math/vector"));
var distance_1 = require("../basic/distance");
/**
 *  常用shape几何操作
 */
/**
 * @description : 缝合两个边 不提供uv生成  uv有@linkSides 生成
 * @param        { ILinkSideOption } options
 * @returns      { Array<Vec3>} 三角形数组，每三个为一个三角形
 * @example     :
 */
function linkSide(options) {
    options = __assign({ shapeClosed: true, autoUV: true }, options);
    var side0 = options.side0;
    var side1 = options.side1;
    var shapeClosed = options.shapeClosed;
    if (side0.length !== side1.length)
        throw ("拉伸两边的点数量不一致  linkSide");
    if (side0.length < 2 || side1.length < 2)
        return [];
    var orgLen = side0.length;
    var length = shapeClosed ? side0.length : side0.length - 1;
    var triangles = [];
    if (side0[0] instanceof Number) {
        //索引三角形
        for (var i = 0; i < length; i++) {
            var v00 = side0[i];
            var v01 = side0[(i + 1) % orgLen];
            var v10 = side1[i];
            var v11 = side1[(i + 1) % orgLen];
            triangles.push(v00);
            triangles.push(v01);
            triangles.push(v11);
            triangles.push(v00);
            triangles.push(v11);
            triangles.push(v10);
        }
    }
    else {
        if ((0, types_1.isDefined)(side0[0].index)) {
            //含索引的顶点
            for (var i = 0; i < length; i++) {
                var v00 = side0[i];
                var v01 = side0[(i + 1) % orgLen];
                var v10 = side1[i];
                var v11 = side1[(i + 1) % orgLen];
                triangles.push(v00.index);
                triangles.push(v01.index);
                triangles.push(v11.index);
                triangles.push(v00.index);
                triangles.push(v11.index);
                triangles.push(v10.index);
            }
        }
        else {
            //三角形顶点
            for (var i = 0; i < length; i++) {
                var v00 = side0[i];
                var v01 = side0[(i + 1) % orgLen];
                var v10 = side1[i];
                var v11 = side1[(i + 1) % orgLen];
                triangles.push(v00);
                triangles.push(v01);
                triangles.push(v11);
                triangles.push(v00);
                triangles.push(v11);
                triangles.push(v10);
            }
        }
    }
    if (options.holes0 && options.holes1) {
        var holes0 = options.holes0;
        var holes1 = options.holes1;
        for (var h = 0; h < holes0.length; h++) {
            var holeTriangles = linkSide({ side0: holes0[h], side1: holes1[h] });
            holeTriangles.reverse();
            triangles.push.apply(triangles, holeTriangles);
        }
    }
    return triangles;
}
exports.linkSide = linkSide;
/**
 * @description : 链接多个shape 生成几何体
 * @param        {ILinkSideOptions} optionsILinkSideOptions {
 *   shapes: Array<Array<IVec3 | number | any>>;
 *   sealStart?: boolean,//开始封面
 *   sealEnd?: boolean;//结束封面
 *   shapeClosed?: boolean,//shape是否闭合
 *   pathClosed?: boolean,//路径是否闭合
 *   index?: { index: number },
 *   generateUV?: boolean
 *   }
 *
 * @return       {*}
 * @example     :
 *
 */
function linkSides(options) {
    options = __assign({ sealEnd: true, sealStart: true, shapeClosed: true, pathClosed: false, generateUV: true, autoIndex: true, axisPlane: trianglution_1.AxisPlane.XY }, options);
    if (options.autoIndex)
        options.index = options.index || { index: 0 };
    var shapes = options.shapes;
    var holess = options.holes;
    var hasHole = !!(holess && holess.length > 0);
    var length = options.pathClosed ? shapes.length : shapes.length - 1;
    var triangles = [];
    var index = options.index;
    var allVertics = [shapes];
    if (hasHole)
        allVertics.push(holess);
    var orgShape = options.orgShape || shapes[0];
    var orgHoles = options.orgHoles || (holess && holess[0]);
    if (index)
        (0, mesh_1.indexable)(allVertics, index);
    for (var i = 0; i < length; i++) {
        if (holess)
            triangles.push.apply(triangles, linkSide({ side0: shapes[i], side1: shapes[(i + 1) % shapes.length], holes0: holess[i], holes1: holess[(i + 1) % shapes.length], shapeClosed: options.shapeClosed }));
        else
            triangles.push.apply(triangles, linkSide({ side0: shapes[i], side1: shapes[(i + 1) % shapes.length], shapeClosed: options.shapeClosed }));
    }
    if (options.sealStart) {
        var startShape = (0, common_1.clone)(shapes[0]);
        allVertics.push(startShape);
        if (holess && holess[0]) {
            var startHoles = (0, common_1.clone)(holess[0]);
            allVertics.push(startHoles);
        }
        var startTris = (0, trianglution_1.triangulation)(orgShape, orgHoles, { feature: trianglution_1.AxisPlane.XYZ });
        if (index) {
            startTris.forEach(function (v, i) {
                startTris[i] = v + (index === null || index === void 0 ? void 0 : index.index);
            });
            index.index += startShape.length;
            if (holess && holess[0])
                startHoles.forEach(function (h) {
                    index.index += h.length;
                });
        }
        triangles.push.apply(triangles, startTris.reverse());
    }
    if (options.sealEnd) {
        var endShape = (0, common_1.clone)(shapes[shapes.length - 1]);
        allVertics.push(endShape);
        if (holess && holess[0]) {
            var endHoles = (0, common_1.clone)((0, common_1.clone)(holess[holess.length - 1]));
            allVertics.push(endHoles);
        }
        var endTris = (0, trianglution_1.triangulation)(orgShape, orgHoles, { feature: trianglution_1.AxisPlane.XYZ });
        if (index) {
            endTris.forEach(function (v, i) {
                endTris[i] = v + (index === null || index === void 0 ? void 0 : index.index);
            });
            index.index += endShape.length;
            if (holess && holess[0])
                endHoles.forEach(function (h) {
                    index.index += h.length;
                });
        }
        triangles.push.apply(triangles, endTris);
    }
    triangles.shapes = allVertics;
    var uvs = [];
    if (options.generateUV) {
        //生成UV 
        // let uBasicScalar = new Array(shapes[0].length).fill(0);
        var uBasicScalar = 0;
        for (var i_1 = 0; i_1 < shapes.length; i_1++) {
            var shape = shapes[i_1];
            var lastshape = shapes[i_1 - 1];
            if (isNaN(shape[0])) {
                //不是索引才生产纹理，其他都是顶点
                var vScalar = Path_1.Path.getPerMileages(shape, false);
                var uScalar = 0;
                // if (i > 0)
                //     uScalar = uBasicScalar.map((e, k) => {
                //         return e + shape[k].distanceTo(lastshape[k]);
                //     });
                // else
                //     uScalar = new Array(shapes[0].length).fill(0);
                if (i_1 > 0)
                    uScalar = uBasicScalar + shape[0].distanceTo(lastshape[0]);
                for (var l = 0; l < shape.length; l++) {
                    uvs.push(uScalar, vScalar[l]);
                }
                uBasicScalar = uScalar;
            }
            else
                console.error("索引无法生成纹理");
        }
        if (holess) {
            uBasicScalar = 0;
            for (var i_2 = 0; i_2 < holess.length; i_2++) {
                var holes = holess[i_2];
                var lastHole = holess[i_2 - 1];
                var uScalar = 0;
                if (i_2 > 0)
                    uScalar = uBasicScalar + holes[0][0].distanceTo(lastHole[0][0]);
                for (var j = 0; j < holes.length; j++) {
                    var hole = holes[j];
                    var vScalar = Path_1.Path.getPerMileages(hole, false);
                    for (var l = 0; l < hole.length; l++) {
                        uvs.push(uScalar, vScalar[l]);
                    }
                }
                uBasicScalar = uScalar;
            }
        }
        //前后纹理
        var sealUvs = [];
        switch (options.axisPlane) {
            case trianglution_1.AxisPlane.XY:
                orgShape.map(function (e) {
                    sealUvs.push(e.x, e.y);
                });
                if (orgHoles)
                    orgHoles.forEach(function (h) {
                        h.forEach(function (e) {
                            sealUvs.push(e.x, e.y);
                        });
                    });
                break;
            case trianglution_1.AxisPlane.XZ:
                orgShape.map(function (e) {
                    sealUvs.push(e.x, e.z);
                });
                if (orgHoles)
                    orgHoles.forEach(function (h) {
                        h.forEach(function (e) {
                            sealUvs.push(e.x, e.z);
                        });
                    });
                break;
            case trianglution_1.AxisPlane.YZ:
                orgShape.map(function (e) {
                    sealUvs.push(e.y, e.z);
                });
                if (orgHoles)
                    orgHoles.forEach(function (h) {
                        h.forEach(function (e) {
                            sealUvs.push(e.y, e.z);
                        });
                    });
                break;
            default:
                break;
        }
        uvs.push.apply(uvs, __spreadArray(__spreadArray([], sealUvs, false), sealUvs, false));
    }
    var indices = triangles || [];
    // if (isDefined(shapes[0][0].index)) {
    //     //收集索引
    //     for (let i = 0; i < shapes.length; i++) {
    //         const shape = shapes[i];
    //         for (let j = 0; j < shape.length; j++) {
    //             const v = shape[j];
    //             indices.push(v.index);
    //         }
    //     }
    // }
    var positions = vector_1.default.verctorToNumbers(allVertics);
    shapes.pop();
    shapes.pop();
    return { position: positions, index: indices, uv: uvs };
}
exports.linkSides = linkSides;
var defaultExtrudeOption = {
    textureEnable: true,
    textureScale: new Vec2_1.Vec2(1, 1),
    smoothAngle: Math.PI / 180 * 30,
    sealStart: false,
    sealEnd: false,
    normal: Vec3_1.Vec3.UnitZ,
};
var _matrix = (0, Mat4_1.m4)();
var _matrix1 = (0, Mat4_1.m4)();
var _quat = (0, Quat_1.quat)();
var _quat1 = (0, Quat_1.quat)();
var _vec1 = (0, Vec3_1.v3)();
var _vec2 = (0, Vec3_1.v3)();
/**
 * @description : 挤压形状生成几何体
 * @param        {IExtrudeOptionsEx} options
 *   IExtrudeOptionsEx {
 *    shape: Array<Vec3 | IVec3 | Vec2 | IVec2>;//shape默认的矩阵为正交矩阵
 *    path: Array<Vec3 | IVec3>;//挤压路径
 *    ups?: Array<Vec3 | IVec3>;
 *    up?: Vec3 | IVec3;
 *    shapeClosed?: boolean;//闭合为多边形 界面
 *    pathClosed?: boolean;//首尾闭合为圈
 *    textureEnable?: boolean;
 *    smoothAngle?: number;
 *    sealStart?: boolean;
 *    sealEnd?: boolean;
 *    normal?: Vec3,//面的法线
 *    autoIndex?: boolean,
 *    index?: { index: number }
 *    holes?: Array<Vec3 | IVec3 | Vec2 | IVec2>[]
 *}
 * @return       {IGeometry}
 * @example     :
 *
 */
function extrude(options) {
    options = __assign({ sealEnd: true, sealStart: true, shapeClosed: true, pathClosed: false, generateUV: true, autoIndex: true, axisPlane: trianglution_1.AxisPlane.XY, up: Vec3_1.Vec3.Up, smoothAngle: 30 * Math_1.RADIANS_PER_DEGREE, enableSmooth: false }, options);
    if (!vector_1.default.isCCW(options.shape))
        options.shape.reverse();
    if (options.holes)
        options.holes.forEach(function (hole) {
            if (!vector_1.default.isCCW(hole))
                hole.reverse();
        });
    var path = new Path_1.Path(options.path);
    var shapes = [];
    var shape = options.shape;
    if (options.shapeClosed && !shape[0].equals(shape[shape.length - 1]))
        shape.push(shape[0].clone());
    var shapePath = new Path_1.Path(shape, options.shapeClosed);
    if (options.enableSmooth)
        for (var i = 1; i < shapePath.length; i++) { //大角度插入点 角度过大为了呈现flat shader的效果
            if (shapePath.get(i).direction.dot(shapePath.get((i + 1) % shapePath.length).direction) < Math.cos(options.smoothAngle)) {
                shapePath.splice(i + 1, 0, shapePath.get(i).clone());
                i++;
            }
        }
    var ups = options.ups || [];
    if ((0, types_1.isUndefined)(shapePath.first.z)) {
        shapePath.array = shapePath.array.map(function (e) { return (0, Vec3_1.v3)(e.x, e.y, 0); });
        options.normal = options.normal || Vec3_1.Vec3.UnitZ;
    }
    var up = options.up;
    var right = options.right;
    var newholes = [];
    for (var i = 0; i < options.path.length; i++) {
        var point = path.get(i);
        var direction = point.direction;
        var upi = void 0;
        upi = ups[i] || up || (0, Vec3_1.v3)().crossVecs(right, direction);
        var righti = right;
        if (!right)
            righti = (0, Vec3_1.v3)().crossVecs(upi, direction).normalize();
        _matrix.makeBasis(righti, upi, direction);
        _matrix.setPosition(point);
        var new_shape = shapePath.clone();
        new_shape.applyMat4(_matrix);
        shapes.push(new_shape);
        if (options.holes) {
            var mholes = (0, pointset_1.applyMat4)(options.holes, _matrix, false);
            newholes.push(mholes);
        }
    }
    var geo = linkSides({
        shapes: shapes.map(function (e) { return e._array; }),
        holes: newholes,
        orgShape: shapePath._array,
        orgHoles: options.holes,
        sealStart: options.sealStart,
        sealEnd: options.sealEnd,
        shapeClosed: options.shapeClosed,
        pathClosed: options.pathClosed,
        axisPlane: options.axisPlane,
        autoIndex: options.autoIndex,
        generateUV: options.generateUV,
    });
    return geo;
}
exports.extrude = extrude;
/**
 * 挤压
 * @param {Polygon|Array<Point|Vec3> }  shape   多边形或顶点数组
 * @param {Path|Array<Point|Vec3> } path  路径或者或顶点数组
 * @param {Object} options {
 *      isClosed: false,闭合为多边形 界面
 *      isClosed2: false, 闭合为圈
 *      textureEnable: true, 计算纹理坐标
 *      textureScale: new Vec2(1, 1),纹理坐标缩放
 *      smoothAngle: Math.PI / 180 * 30,大于这个角度则不平滑
 *      sealStart: true, 是否密封开始面
 *      sealEnd: true,是否密封结束面}
 */
function extrude_obsolete(shape, arg_path, options) {
    var _a, _b;
    if (options === void 0) { options = defaultExtrudeOption; }
    options = __assign(__assign({}, defaultExtrudeOption), options);
    if (arg_path.length < 2) {
        throw ("路径节点数必须大于2");
    }
    var isCCW = vector_1.default.isCCW(shape);
    if (!isCCW)
        shape.reverse();
    var normal = options.normal;
    var startSeal = (0, common_1.clone)(shape);
    var shapepath = new Path_1.Path(shape);
    var insertNum = 0;
    for (var i = 1; i < shapepath.length - 1; i++) { //大角度插入点 角度过大为了呈现flat shader的效果
        if (Math.acos(shapepath.get(i).tangent.dot(shapepath.get(i + 1).tangent)) > options.smoothAngle)
            shape.splice(i + insertNum++, 0, shapepath.get(i).clone());
    }
    if (options.shapeClosed) {
        var dir1 = shapepath.get(-1).clone().sub(shapepath.get(-2)).normalize();
        var dir2 = shapepath.get(0).clone().sub(shapepath.get(-1)).normalize();
        if (Math.acos(dir1.dot(dir2)) > options.smoothAngle)
            shape.push(shape.get(-1).clone());
        //新加起始点纹理拉伸
        shape.unshift(shape.first.clone());
    }
    var path = arg_path;
    if (!(path instanceof Path_1.Path) && path instanceof Array)
        path = new Path_1.Path(arg_path);
    var shapeArray = [];
    for (var i = 0; i < path.length; i++) {
        var node = path[i];
        var dir = node.tangent;
        var newShape = (0, common_1.clone)(shape);
        (0, common_1.rotateByUnitVectors)(newShape, normal, dir);
        if (options.fixedY) {
            var v = Vec3_1.Vec3.UnitX;
            (0, common_1.rotateByUnitVectors)([v], normal, dir);
            var v1 = v.clone();
            v1.y = 0;
            (0, common_1.rotateByUnitVectors)(newShape, v, v1);
        }
        (0, pointset_1.translate)(newShape, node);
        shapeArray.push(newShape);
    }
    var gindex = { index: 0 };
    var vertices = (0, array_1.flat)(shapeArray);
    (0, mesh_1.indexable)(vertices, gindex);
    var index = linkSides({ shapes: shapeArray, shapeClosed: options.shapeClosed, pathClosed: options.isClosed2, orgShape: shape }).index;
    shapepath = new Path_1.Path(shape);
    var uvs = [];
    for (var i = 0; i < path.length; i++) {
        for (var j = 0; j < shapepath.length; j++) {
            uvs.push(shapepath.get(j).tlen * options.textureScale.x, path.get(i).tlen * options.textureScale.y);
        }
    }
    var sealUv = (0, common_1.clone)(startSeal);
    if (normal.dot(Vec3_1.Vec3.UnitZ) < 1 - 1e-4)
        (0, common_1.rotateByUnitVectors)(sealUv, normal, Vec3_1.Vec3.UnitZ);
    var endSeal = (0, common_1.clone)(startSeal);
    (0, common_1.rotateByUnitVectors)(startSeal, normal, path[0].tangent);
    if (options.fixedY) {
        var v = Vec3_1.Vec3.UnitX;
        (0, common_1.rotateByUnitVectors)([v], normal, path[0].tangent);
        var v1 = v.clone();
        v1.y = 0;
        (0, common_1.rotateByUnitVectors)(startSeal, v, v1);
    }
    (0, pointset_1.translate)(startSeal, path[0]);
    (0, common_1.rotateByUnitVectors)(endSeal, normal, path.get(-1).tangent);
    if (options.fixedY) {
        var v = Vec3_1.Vec3.UnitX;
        (0, common_1.rotateByUnitVectors)([v], normal, path.get(-1).tangent);
        var v1 = v.clone();
        v1.y = 0;
        (0, common_1.rotateByUnitVectors)(endSeal, v, v1);
    }
    (0, pointset_1.translate)(endSeal, path.get(-1));
    var sealStartTris = (0, trianglution_1.triangulation)(sealUv, [], { normal: normal });
    sealStartTris.reverse();
    if (options.sealStart)
        (0, mesh_1.indexable)(startSeal, gindex);
    if (options.sealEnd)
        (0, mesh_1.indexable)(endSeal, gindex);
    var sealEndTris = [];
    var hasVLen = vertices.length;
    if (options.sealStart)
        for (var i = 0; i < sealStartTris.length; i++) {
            sealStartTris[i] += hasVLen;
        }
    if (options.sealEnd && !options.sealStart)
        for (var i = 0; i < sealStartTris.length; i++) {
            sealEndTris[i] = sealStartTris[i] + hasVLen;
        }
    if (options.sealEnd && options.sealStart) {
        for (var i = 0; i < sealStartTris.length; i++) {
            sealEndTris[i] = sealStartTris[i] + startSeal.length;
        }
    }
    if (options.sealStart) {
        vertices.push.apply(vertices, startSeal);
        (_a = index).push.apply(_a, sealStartTris);
        for (var i = 0; i < sealUv.length; i++)
            uvs.push(sealUv[i].x, sealUv[i].y);
    }
    if (options.sealEnd) {
        vertices.push.apply(vertices, endSeal);
        sealEndTris.reverse();
        (_b = index).push.apply(_b, sealEndTris);
        for (var i = 0; i < sealUv.length; i++)
            uvs.push(sealUv[i].x, sealUv[i].y);
    }
    return {
        vertices: vertices,
        index: index,
        uvs: uvs
    };
}
exports.extrude_obsolete = extrude_obsolete;
var JoinType;
(function (JoinType) {
    JoinType[JoinType["Square"] = 0] = "Square";
    JoinType[JoinType["Round"] = 1] = "Round";
    JoinType[JoinType["Miter"] = 2] = "Miter";
    JoinType[JoinType["Bevel"] = 0] = "Bevel";
})(JoinType = exports.JoinType || (exports.JoinType = {}));
var EndType;
(function (EndType) {
    EndType[EndType["Square"] = 0] = "Square";
    EndType[EndType["Round"] = 1] = "Round";
    EndType[EndType["Butt"] = 2] = "Butt";
    EndType[EndType["etClosedLine"] = 3] = "etClosedLine";
    EndType[EndType["etClosedPolygon"] = 4] = "etClosedPolygon";
    EndType[EndType["etOpenButt"] = 5] = "etOpenButt";
    EndType[EndType["etOpenSquare"] = 6] = "etOpenSquare";
})(EndType = exports.EndType || (exports.EndType = {}));
/**
 * 将路径看做挤压操作中心
 *
 * @param shape
 * @param followPath
 * @param options
 */
function extrudeNext(options) {
    options = __assign({ sealEnd: true, sealStart: true, shapeClosed: true, pathClosed: false, generateUV: true, autoIndex: true, axisPlane: trianglution_1.AxisPlane.XY, smoothAngle: 30 * Math_1.RADIANS_PER_DEGREE, enableSmooth: false }, options);
    var path = options.shapeCenter ? (0, pointset_1.translate)(options.path, options.shapeCenter, false) : options.path;
    var shape = options.shape;
    (0, array_1.unique)(path, function (a, b) { return a.equals(b); });
    (0, array_1.unique)(shape, function (a, b) { return a.equals(b); });
    var pathPath = new Path_1.Path(path, options.pathClosed, true);
    var starti = options.shapeClosed ? 0 : 1;
    var shapePath = new Path_1.Path(shape, options.shapeClosed);
    if (options.enableSmooth)
        for (var i = 1; i < shapePath.length; i++) { //大角度插入点 角度过大为了呈现flat shader的效果
            if (shapePath.get(i).direction.dot(shapePath.get((i + 1) % shapePath.length).direction) < options.smoothAngle) {
                shapePath.splice(i + 1, 0, shapePath.get(i).clone());
                i++;
            }
        }
    options.normal = options.normal || Vec3_1.Vec3.UnitZ;
    if ((0, types_1.isUndefined)(shapePath.first.z)) {
        shapePath.array = shapePath.array.map(function (e) { return (0, Vec3_1.v3)(e.x, e.y, 0); });
    }
    var up = options.up;
    var right = options.right;
    var shapes = [], newholes = [];
    var accMat = (0, Mat4_1.m4)();
    /**
     * 如果路径闭合  要考虑首尾shape矩阵变化后还能一致吻合
     */
    switch (options.jtType) {
        case JoinType.Square: //切角
            break;
        case JoinType.Round: //圆角
            /**
             * 原理，计算所有交点处的平分面，
             * 两条相接不共线的的线段可以确定一个平面，平面法线与
             */
            for (var i = 0; i < pathPath.length; i++) {
                var p = pathPath.get(i);
                var pLast = pathPath.get(i - 1);
                var pNext = pathPath.get(i + 1);
                var dir = p.direction;
                //两个外向
                var bdir = p.bdirection;
                var bnormal = p.bnormal;
                var normal = p.normal;
                //相邻两个向量发生的旋转
                if (i === 0) {
                    _quat.setFromUnitVecs(Vec3_1.Vec3.UnitZ, dir);
                }
                else {
                    _quat.setFromUnitVecs(pathPath.get(i - 1).direction, dir);
                }
                var new_shape = shapePath.clone();
                //旋转 
                _quat.setFromUnitVecs(dir, bdir);
                _matrix.makeRotationFromQuat(_quat);
                _matrix.multiply(accMat);
                //位置
                _matrix.setPosition(p);
                new_shape.applyMat4(_matrix);
                // 找出最近一个点  绕此点旋转 
                var min = Infinity;
                var anchor = 0;
                for (var i_3 = 0; i_3 < new_shape.array.length; i_3++) {
                    var p_1 = new_shape.get(i_3);
                    var tdot = bdir.dot(_vec1.copy(p_1).sub(new_shape.get(0)));
                    if (tdot < min) {
                        min = tdot;
                        anchor = i_3;
                    }
                }
                var minPoint = new_shape.get(anchor);
                //找出距离连个线段最近的点
                // 垂直的两个点  这两个点与
                if (i !== 0 && i !== pathPath.length - 1) {
                    var P0 = distance_1.Distance.Point2Line_Vec3(minPoint, pLast, _vec1.copy(p).sub(pLast).normalize());
                    var P1 = distance_1.Distance.Point2Line_Vec3(minPoint, p, _vec1.copy(pNext).sub(p).normalize());
                    _vec1.copy(P0).sub(minPoint);
                    _vec2.copy(P1).sub(minPoint);
                    var angle_1 = _vec1.angleTo(_vec2, normal);
                    var seg = Math.ceil(angle_1 / 0.1);
                    var perAngle = angle_1 / seg;
                    for (var i_4 = 0; i_4 <= seg; i_4++) {
                        var cAngle = i_4 * perAngle;
                        for (var j = 0; j < new_shape.length; j++) {
                            var np = new_shape.get(j);
                            var v = new Vec3_1.Vec3().slerpVecs(_vec1, _vec2, cAngle);
                            var t = np.clone().sub(minPoint);
                        }
                    }
                    // if (options.holes) {
                    //     const mholes = applyMat4(options.holes, _matrix1, false);
                    //     applyMat4(mholes, _matrix, true);
                    //     newholes.push(mholes);
                    // } 
                }
                shapes.push(new_shape);
            }
            break;
        case JoinType.Miter: //直角
            for (var i = 0; i < pathPath.length; i++) {
                var p = pathPath.get(i);
                var dir = p.direction;
                var bdir = p.bdirection;
                var bnormal = p.bnormal;
                var normal = p.normal;
                //相邻两个向量发生的旋转
                if (i === 0) {
                    _quat.setFromUnitVecs(Vec3_1.Vec3.UnitZ, dir);
                }
                else {
                    _quat.setFromUnitVecs(pathPath.get(i - 1).direction, dir);
                }
                var new_shape = shapePath.clone();
                //旋转
                _matrix.makeRotationFromQuat(_quat);
                accMat.premultiply(_matrix);
                _quat.setFromUnitVecs(dir, bdir);
                _matrix.makeRotationFromQuat(_quat);
                _matrix.multiply(accMat);
                // /旋转到原地缩放----开始-----------------------
                var cosA = dir.dot(bdir);
                var shear = 1 / cosA;
                _vec1.crossVecs(normal, bdir);
                _matrix1.copy(_matrix);
                _matrix1.invert();
                _vec1.applyMat4(_matrix1);
                _quat.setFromUnitVecs(_vec1, Vec3_1.Vec3.Up);
                _matrix1.makeRotationFromQuat(_quat);
                new_shape.applyMat4(_matrix1);
                new_shape.scale(1, shear, 1);
                new_shape.applyMat4(_matrix1.invert());
                // /旋转到原地缩放----结束-----------------------
                //位置
                _matrix.setPosition(p);
                new_shape.applyMat4(_matrix);
                // if (options.holes) {
                //     const mholes = applyMat4(options.holes, _matrix1, false);
                //     applyMat4(mholes, _matrix, true);
                //     newholes.push(mholes);
                // }  
                shapes.push(new_shape);
            }
            break;
        default:
            break;
    }
    var geo = linkSides({
        shapes: shapes.map(function (e) { return e.array; }),
        holes: newholes,
        orgShape: shapePath._array,
        orgHoles: options.holes,
        sealStart: options.sealStart,
        sealEnd: options.sealEnd,
        shapeClosed: options.shapeClosed,
        pathClosed: options.pathClosed,
        axisPlane: options.axisPlane,
        autoIndex: options.autoIndex,
        generateUV: options.generateUV,
    });
    return geo;
}
exports.extrudeNext = extrudeNext;
