UNPKG

xtorcga

Version:

Xtor Compute Geometry Algorithm Libary 计算几何算法库

307 lines (306 loc) 12 kB
"use strict"; /* * @Author : 赵耀圣 * @Date : 2020-12-10 15:01:42 * @QQ : 549184003 * @LastEditTime : 2021-09-07 15:40:10 * @FilePath : \cesium-taji-dabaod:\github\cga.js\src\struct\3d\Path.ts */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Path = void 0; var Vec3_1 = require("../../math/Vec3"); var Math_1 = require("../../math/Math"); var types_1 = require("../../utils/types"); var ArrayList_1 = require("../data/ArrayList"); var pointset_1 = require("../../alg/pointset"); var common_1 = require("../../alg/common"); var Path = /** @class */ (function (_super) { __extends(Path, _super); /** * * @param vs 假定是没有重复的点集 * @param closed * @param calcNormal */ function Path(vs, closed, calcNormal) { if (closed === void 0) { closed = false; } if (calcNormal === void 0) { calcNormal = false; } var _this = _super.call(this, vs) || this; _this._calcNoraml = false; _this._closed = closed; _this.init(calcNormal); return _this; } Path.prototype.init = function (calcNormal) { if (this.length === 0) return; this.get(0).len = 0; this.get(0).tlen = 0; var end = this.length; for (var i = 0; i < end; i++) { var e = this.get(i); if (i !== 0) { e.len = this.get(i).distanceTo(this.get(i - 1)); e.tlen = this.get(i - 1).tlen + e.len; } this.get(i).direction = this.get((i + 1) % this.length).clone().sub(this.get(i)).normalize(); } if (!this._closed) { this.get(-1).direction.copy(this.get(-2).direction); } if (calcNormal) { for (var i = 0; i < end; i++) { var d1 = this.get(i - 1).direction; var d2 = this.get(i).direction; // if (Math.abs(d1.dot(d2) - 1) > delta6) { //应该同时考虑长度差 //normal是两条线段所在的平面的法线 //bdirection是两条方向线的等分线 //TODO var normal = new Vec3_1.Vec3(); normal.crossVecs(d1, d2).normalize(); this.get(i).normal = normal; var bdir = Vec3_1.v3().addVecs(d1, d2).normalize(); this.get(i).bdirection = bdir; this.get(i).bnormal = Vec3_1.v3().crossVecs(bdir, normal).normalize(); // } } if (!this._closed) { //不闭合路径 最后一个点没有 this.get(-1).bdirection = Vec3_1.v3(); this.get(-1).normal = Vec3_1.v3(); this.get(-1).bnormal = Vec3_1.v3(); } if (!this._closed) { // 不闭合的情况下怎么样去计算端点的up和normal this.get(0).normal.copy(this.get(1).normal); this.get(0).bdirection.copy(this.get(0).direction); var bdir = this.get(0).bdirection; this.get(0).bnormal.crossVecs(bdir, this.get(0).normal); this.get(-1).normal.copy(this.get(-2).normal); this.get(-1).bdirection.copy(this.get(-1).direction); bdir = this.get(-1).bdirection; this.get(-1).bnormal.crossVecs(bdir, this.get(-1).normal).normalize(); } } }; Object.defineProperty(Path.prototype, "closed", { get: function () { return this._closed; }, set: function (val) { this._closed = val; }, enumerable: false, configurable: true }); Object.defineProperty(Path.prototype, "tlen", { get: function () { if (this.length === 0) return 0; return Math.max(this.get(-1).tlen, this.get(0).tlen); }, enumerable: false, configurable: true }); Path.prototype.applyMat4 = function (mat4) { pointset_1.applyMat4(this._array, mat4); }; Path.prototype.scale = function (x, y, z) { common_1.scale(this._array, Vec3_1.v3(x, y, z), true); }; /** * 截取一段从from到to的path * @param {Number} from * @param {Number} to */ Path.prototype.splitByFromToDistance = function (from, to) { if (from === void 0) { from = 0; } if (to === void 0) { to = 0; } if (to <= from) return null; var newPath = new Path([]); for (var i = 0; i < this.length - 1; i++) { var pt = this.get(i); var ptnext = this.get(i + 1); if (pt.tlen <= from && ptnext.tlen >= from) { var v3 = new Vec3_1.Vec3().lerpVecs(pt, ptnext, (from - pt.tlen) / (ptnext.tlen - pt.tlen)); newPath.add(v3); } if (pt.tlen > from && pt.tlen < to) { newPath.add(pt.clone()); } if (pt.tlen <= to && ptnext.tlen >= to) { var v3 = new Vec3_1.Vec3().lerpVecs(pt, ptnext, (to - pt.tlen) / (ptnext.tlen - pt.tlen)); newPath.add(v3); return newPath; } } return newPath; }; /** * 从起点出发到距离等于distance位置 的坐标 二分查找 * @param {Number} distance */ Path.prototype.getPointByDistance = function (arg_distance, left, right) { if (left === void 0) { left = 0; } if (right === void 0) { right = this.length - 1; } var distance = Math_1.clamp(arg_distance, 0, this.get(-1).tlen); if (distance !== arg_distance) return null; if (right - left === 1) { return { isNode: false, point: new Vec3_1.Vec3().lerpVecs(this.get(left), this.get(right), (distance - this.get(left).tlen) / this.get(right).len), direction: this.get(left).diretion, }; } var mid = (left + right) >> 1; if (this.get(mid).tlen > distance) return this.getPointByDistance(distance, left, mid); else if (this.get(mid).tlen < distance) return this.getPointByDistance(distance, mid, right); else return { isNode: true, point: new Vec3_1.Vec3().lerpVecs(this.get(left), this.get(right), (distance - this.get(left).tlen) / this.get(right).len), direction: this.get(left).direction }; }; /** * 从起点出发到距离等于distance位置 的坐标 二分查找 * @param {Number} distance */ Path.prototype.getPointByDistancePure = function (arg_distance, left, right) { if (left === void 0) { left = 0; } if (right === void 0) { right = this.length - 1; } var distance = Math_1.clamp(arg_distance, 0, this.get(-1).tlen); if (distance !== arg_distance) return null; if (right - left === 1) { return new Vec3_1.Vec3().lerpVecs(this.get(left), this.get(right), (distance - this.get(left).tlen) / this.get(right).len); } var mid = (left + right) >> 1; if (this.get(mid).tlen > distance) return this.getPointByDistancePure(distance, left, mid); else if (this.get(mid).tlen < distance) return this.getPointByDistancePure(distance, mid, right); else return this.get(mid).clone(); }; /** * 平均切割为 splitCount 段 * @param {Number} splitCount * @returns {Path} 新的path */ Path.prototype.splitAverage = function (splitCount) { var tlen = this.last.tlen; var perlen = tlen / splitCount; var res = []; var curJ = 0; for (var i = 0; i <= splitCount; i++) { var plen = i * perlen; for (var j = curJ; j < this.length - 1; j++) { if (this.get(j).tlen <= plen && this.get(j + 1).tlen >= plen) { var p = new Vec3_1.Vec3().lerpVecs(this.get(j), this.get(j + 1), (plen - this.get(j).tlen) / (this.get(j + 1).len)); res.push(p); curJ = j; break; } } } return new Path(res); }; /** * 通过测试 * 平均切割为 splitCount 段 * @param {Number} splitCount * @param {Boolean} integer 是否取整 * @returns {Path} 新的path */ Path.prototype.splitAverageLength = function (splitLength, integer) { if (integer === void 0) { integer = true; } var tlen = this.last.tlen; var count = tlen / splitLength; if (integer) count = Math.round(count); return this.splitAverage(count); }; /** * * @param {...any} ps */ Path.prototype.add = function () { var ps = []; for (var _i = 0; _i < arguments.length; _i++) { ps[_i] = arguments[_i]; } if (this.length == 0) { var firstpt = ps.shift(); this.push(firstpt); this.get(0).len = 0; this.get(0).tlen = 0; } for (var i = 0; i < ps.length; i++) { var pt = ps[i]; pt.len = pt.distanceTo(this.get(-1)); pt.tlen = this.get(-1).tlen + pt.len; pt.direction = pt.clone().sub(this.get(-1)).normalize(); if (!this.get(-1).direction) this.get(-1).direction = pt.clone().sub(this.get(-1)).normalize(); else this.get(-1).direction.copy(pt.direction); this.push(pt); } }; /** * @description : 计算一段线段的总长度 * @param {ArrayLike} ps * @return {number} 总长度 */ Path.totalMileages = function (ps) { var alldisance = 0; for (var i = 0, len = ps.length - 1; i < len; i++) { alldisance += ps[i + 1].distanceTo(ps[i]); } return alldisance; }; /** * @description : 获取没一点的里程 里程是指从第一个点出发的长度 * @param {ArrayLike} ps 里程上的点集 * @param {boolean} normalize 是否归一化 * @return {number[]} 每一个点的里程数组 * @example : */ Path.getPerMileages = function (ps, normalize, totalMileage) { if (normalize === void 0) { normalize = false; } var res = []; var mileages = 0; res.push(mileages); for (var i = 0, len = ps.length - 1; i < len; i++) { mileages += ps[i + 1].distanceTo(ps[i]); res.push(mileages); } if (normalize) { var tl = types_1.isDefined(totalMileage) ? totalMileage : this.totalMileages(ps); for (var i = 0, len = ps.length; i < len; i++) { res[i] /= tl; } } return res; }; return Path; }(ArrayList_1.ArrayList)); exports.Path = Path;