xtorcga
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
307 lines (306 loc) • 12 kB
JavaScript
"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;