Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@antv/g-math

Package Overview
Dependencies
Maintainers
64
Versions
155
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@antv/g-math - npm Package Compare versions

Comparing version 1.7.49 to 1.8.0-alpha.1

dist/index.esm.js.map

56

dist/arc.d.ts

@@ -1,49 +0,9 @@

import type { Point, BBox } from './types';
declare const _default: {
/**
* 计算包围盒
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @return {object} 包围盒对象
*/
box(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number): BBox;
/**
* 获取圆弧的长度,计算圆弧长度时不考虑旋转角度,
* 仅跟 rx, ry, startAngle, endAngle 相关
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
*/
length(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number): void;
/**
* 获取指定点到圆弧的最近距离的点
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @param {number} x0 指定点的 x
* @param {number} y0 指定点的 y
* @return {object} 到指定点最近距离的点
*/
nearestPoint(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, x0: number, y0: number): {
x: number;
y: number;
};
pointDistance(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, x0: number, y0: number): number;
pointAt(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, t: number): Point;
tangentAngle(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, t: number): number;
import type { BBox, Point } from './types';
export declare function box(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number): BBox;
export declare function nearestPoint(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, x0: number, y0: number): {
x: number;
y: number;
};
export default _default;
//# sourceMappingURL=arc.d.ts.map
export declare function pointDistance(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, x0: number, y0: number): number;
export declare function pointAt(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, t: number): Point;
export declare function tangentAngle(cx: number, cy: number, rx: number, ry: number, xRotation: number, startAngle: number, endAngle: number, t: number): number;

@@ -12,2 +12,1 @@ import type { Point } from './types';

export declare function snapLength(xArr: number[], yArr: number[]): number;
//# sourceMappingURL=bezier.d.ts.map
import type { Point } from './types';
declare function cubicAt(p0: number, p1: number, p2: number, p3: number, t: number): number;
declare function extrema(p0: number, p1: number, p2: number, p3: number): any[];
declare const _default: {
extrema: typeof extrema;
box(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): import("./types").BBox;
length(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): number;
nearestPoint(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, x0: number, y0: number, length?: number): Point;
pointDistance(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, x0: number, y0: number, length?: number): number;
interpolationAt: typeof cubicAt;
pointAt(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): Point;
divide(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): [number, number, number, number, number, number, number, number][];
tangentAngle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): number;
};
export default _default;
//# sourceMappingURL=cubic.d.ts.map
export declare function box(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): import("./types").BBox;
export declare function length(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): number;
export declare function nearestPoint(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, x0: number, y0: number, length?: number): Point;
export declare function pointDistance(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, x0: number, y0: number, length?: number): number;
export declare function pointAt(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): Point;
export declare function divide(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): [number, number, number, number, number, number, number, number][];
export declare function tangentAngle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, t: number): number;

@@ -1,74 +0,10 @@

/**
* @fileoverview 椭圆的一些计算,
* - 周长计算参考:https://www.mathsisfun.com/geometry/ellipse-perimeter.html
* - 距离计算参考:https://wet-robots.ghost.io/simple-method-for-distance-to-ellipse/
* @author dxq613@gmail.com
*/
import type { Point, BBox } from './types';
declare const _default: {
/**
* 包围盒计算
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {object} 包围盒
*/
box(x: number, y: number, rx: number, ry: number): BBox;
/**
* 计算周长,使用近似法
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {number} 椭圆周长
*/
length(x: number, y: number, rx: number, ry: number): number;
/**
* 距离椭圆最近的点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {object} 椭圆上距离指定点最近的点
*/
nearestPoint(x: number, y: number, rx: number, ry: number, x0: number, y0: number): {
x: number;
y: number;
};
/**
* 点到椭圆最近的距离
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {number} 点到椭圆的距离
*/
pointDistance(x: number, y: number, rx: number, ry: number, x0: number, y0: number): number;
/**
* 根据比例获取点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例,x轴方向为 0
* @return {object} 点
*/
pointAt(x: number, y: number, rx: number, ry: number, t: number): Point;
/**
* 根据比例计算切线角度
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例 0 - 1 之间,x轴方向为 0。在 0-1 范围之外是循环还是返回 null,还需要调整
* @return {number} 角度,在 0 - 2PI 之间
*/
tangentAngle(x: number, y: number, rx: number, ry: number, t: number): number;
import type { BBox, Point } from './types';
export declare function box(x: number, y: number, rx: number, ry: number): BBox;
export declare function length(x: number, y: number, rx: number, ry: number): number;
export declare function nearestPoint(x: number, y: number, rx: number, ry: number, x0: number, y0: number): {
x: number;
y: number;
};
export default _default;
//# sourceMappingURL=ellipse.d.ts.map
export declare function pointDistance(x: number, y: number, rx: number, ry: number, x0: number, y0: number): number;
export declare function pointAt(x: number, y: number, rx: number, ry: number, t: number): Point;
export declare function tangentAngle(x: number, y: number, rx: number, ry: number, t: number): number;

@@ -1,9 +0,8 @@

import Quad from './quadratic';
import Cubic from './cubic';
import Arc from './arc';
import Line from './line';
import Polygon from './polygon';
import Polyline from './polyline';
import * as Util from './util';
export { Quad, Cubic, Arc, Line, Polygon, Polyline, Util };
//# sourceMappingURL=index.d.ts.map
import { box as arcBox, nearestPoint as arcNearestPoint, tangentAngle as arcTangentAngle } from './arc';
import { box as cubicBox, length as cubicLength, nearestPoint as cubicNearestPoint, pointAt as cubicPointAt, pointDistance as cubicPointDistance, tangentAngle as cubicTangentAngle } from './cubic';
import { box as lineBox, length as lineLength, pointAt as linePointAt, pointDistance as linePointDistance, pointToLine as linePointToLine, tangentAngle as lineTangentAngle } from './line';
import { box as polygonBox, length as polygonLength, pointAt as polygonPointAt, pointDistance as polygonPointDistance, tangentAngle as polygonTangentAngle } from './polygon';
import { box as polylineBox, length as polylineLength, pointAt as polylinePointAt, pointDistance as polylinePointDistance, tangentAngle as polylineTangentAngle } from './polyline';
import { box as quadBox, length as quadLength, nearestPoint as quadNearestPoint, pointDistance as quadPointDistance } from './quadratic';
import { distance } from './util';
export { distance, quadBox, quadLength, quadPointDistance, quadNearestPoint, cubicBox, cubicLength, cubicNearestPoint, cubicPointDistance, cubicPointAt, cubicTangentAngle, polygonBox, polygonLength, polygonPointDistance, polygonPointAt, polygonTangentAngle, polylineBox, polylineLength, polylinePointDistance, polylinePointAt, polylineTangentAngle, lineBox, lineLength, linePointDistance, linePointAt, linePointToLine, lineTangentAngle, arcBox, arcTangentAngle, arcNearestPoint, };

@@ -0,473 +1,33 @@

import { __spreadArray, __read } from 'tslib';
import { vec2 } from 'gl-matrix';
/**
* 两点之间的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
function distance(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function isNumberEqual(v1, v2) {
return Math.abs(v1 - v2) < 0.001;
return Math.abs(v1 - v2) < 0.001;
}
function getBBoxByArray(xArr, yArr) {
var minX = Math.min.apply(Math, xArr);
var minY = Math.min.apply(Math, yArr);
var maxX = Math.max.apply(Math, xArr);
var maxY = Math.max.apply(Math, yArr);
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
};
}
function getBBoxRange(x1, y1, x2, y2) {
return {
minX: Math.min(x1, x2),
maxX: Math.max(x1, x2),
minY: Math.min(y1, y2),
maxY: Math.max(y1, y2)
};
}
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
var util = /*#__PURE__*/Object.freeze({
__proto__: null,
distance: distance,
isNumberEqual: isNumberEqual,
getBBoxByArray: getBBoxByArray,
getBBoxRange: getBBoxRange,
piMod: piMod
});
var line = {
/**
* 计算线段的包围盒
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {object} 包围盒对象
*/
box: function box(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
},
/**
* 线段的长度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
length: function length(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
},
/**
* 根据比例获取点
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} t 指定比例
* @return {object} 包含 x, y 的点
*/
pointAt: function pointAt(x1, y1, x2, y2, t) {
var minX = Math.min.apply(Math, __spreadArray([], __read(xArr), false));
var minY = Math.min.apply(Math, __spreadArray([], __read(yArr), false));
var maxX = Math.max.apply(Math, __spreadArray([], __read(xArr), false));
var maxY = Math.max.apply(Math, __spreadArray([], __read(yArr), false));
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
};
},
/**
* 点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointDistance: function pointDistance(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
},
/**
* 点到直线的距离,而不是点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointToLine: function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (vec2.exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
vec2.normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(vec2.dot(a, u));
},
/**
* 线段的角度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 导数
*/
tangentAngle: function tangentAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
};
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [tCallback.apply(void 0, xArr.concat([_t])), tCallback.apply(void 0, yArr.concat([_t]))];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0]
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1]
};
}
d = Infinity;
for (var _i = 0; _i < 32; _i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var _v = [tCallback.apply(void 0, xArr.concat([prev])), tCallback.apply(void 0, yArr.concat([prev]))];
var _d = distance(v0[0], v0[1], _v[0], _v[1]);
if (prev >= 0 && _d < d) {
t = prev;
d = _d;
} else {
var v2 = [tCallback.apply(void 0, xArr.concat([next])), tCallback.apply(void 0, yArr.concat([next]))];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
} else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, xArr.concat([t])),
y: tCallback.apply(void 0, yArr.concat([t]))
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
function derivativeAt(p0, p1, p2, t) {
return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = line.pointAt(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = line.pointAt(x2, y2, x3, y3, t);
return [[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt], [xt, yt, controlPoint2.x, controlPoint2.y, x3, y3]];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return (distance(x1, y1, x2, y2) + distance(x2, y2, x3, y3) + distance(x1, y1, x3, y3)) / 2;
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, left) + quadraticLength.apply(void 0, right);
}
var quadratic = {
box: function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: quadraticAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, t) {
return {
x: quadraticAt(x1, x2, x3, t),
y: quadraticAt(y1, y2, y3, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, t) {
return divideQuadratic(x1, y1, x2, y2, x3, y3, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, t) {
var dx = derivativeAt(x1, x2, x3, t);
var dy = derivativeAt(y1, y2, y3, t);
var angle = Math.atan2(dy, dx);
return piMod(angle);
}
};
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return onet * onet * onet * p0 + 3 * p1 * t * onet * onet + 3 * p2 * t * t * onet + p3 * t * t * t;
}
function derivativeAt$1(p0, p1, p2, p3, t) {
var onet = 1 - t;
return 3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
} else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
} else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = line.pointAt(x1, y1, x2, y2, t);
var c2 = line.pointAt(x2, y2, x3, y3, t);
var c3 = line.pointAt(x3, y3, x4, y4, t);
var c12 = line.pointAt(c1.x, c1.y, c2.x, c2.y, t);
var c23 = line.pointAt(c2.x, c2.y, c3.x, c3.y, t);
return [[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt], [xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4]];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = [].concat(cubics[0], [iterationCount - 1]);
var right = [].concat(cubics[1], [iterationCount - 1]);
return cubicLength.apply(void 0, left) + cubicLength.apply(void 0, right);
}
var cubic = {
extrema: extrema$1,
box: function box(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var _i = 0; _i < yExtrema.length; _i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[_i]));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: cubicAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt$1(x1, x2, x3, x4, t);
var dy = derivativeAt$1(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
};
/**
* @fileoverview 椭圆的一些计算,
* - 周长计算参考:https://www.mathsisfun.com/geometry/ellipse-perimeter.html
* - 距离计算参考:https://wet-robots.ghost.io/simple-method-for-distance-to-ellipse/
* @author dxq613@gmail.com
*/
function copysign(v1, v2) {
var absv = Math.abs(v1);
return v2 > 0 ? absv : absv * -1;
var absv = Math.abs(v1);
return v2 > 0 ? absv : absv * -1;
}
var ellipse = {
/**
* 包围盒计算
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {object} 包围盒
*/
box: function box(x, y, rx, ry) {
return {
x: x - rx,
y: y - ry,
width: rx * 2,
height: ry * 2
};
},
/**
* 计算周长,使用近似法
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {number} 椭圆周长
*/
length: function length(x, y, rx, ry) {
return Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
},
/**
* 距离椭圆最近的点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {object} 椭圆上距离指定点最近的点
*/
nearestPoint: function nearestPoint(x, y, rx, ry, x0, y0) {
function nearestPoint$4(x, y, rx, ry, x0, y0) {
var a = rx;

@@ -477,6 +37,6 @@ var b = ry;

if (a === 0 || b === 0) {
return {
x: x,
y: y
};
return {
x: x,
y: y,
};
}

@@ -496,131 +56,74 @@ // 转换成 0, 0 为中心的椭圆计算

for (var i = 0; i < 4; i++) {
nearestX = a * Math.cos(t);
nearestY = b * Math.sin(t);
var ex = (squareA - squareB) * Math.pow(Math.cos(t), 3) / a;
var ey = (squareB - squareA) * Math.pow(Math.sin(t), 3) / b;
var rx1 = nearestX - ex;
var ry1 = nearestY - ey;
var qx = px - ex;
var qy = py - ey;
var r = Math.hypot(ry1, rx1);
var q = Math.hypot(qy, qx);
var delta_c = r * Math.asin((rx1 * qy - ry1 * qx) / (r * q));
var delta_t = delta_c / Math.sqrt(squareA + squareB - nearestX * nearestX - nearestY * nearestY);
t += delta_t;
t = Math.min(Math.PI / 2, Math.max(0, t));
nearestX = a * Math.cos(t);
nearestY = b * Math.sin(t);
var ex = ((squareA - squareB) * Math.pow(Math.cos(t), 3)) / a;
var ey = ((squareB - squareA) * Math.pow(Math.sin(t), 3)) / b;
var rx1 = nearestX - ex;
var ry1 = nearestY - ey;
var qx = px - ex;
var qy = py - ey;
var r = Math.hypot(ry1, rx1);
var q = Math.hypot(qy, qx);
var delta_c = r * Math.asin((rx1 * qy - ry1 * qx) / (r * q));
var delta_t = delta_c /
Math.sqrt(squareA + squareB - nearestX * nearestX - nearestY * nearestY);
t += delta_t;
t = Math.min(Math.PI / 2, Math.max(0, t));
}
return {
x: x + copysign(nearestX, relativeX),
y: y + copysign(nearestY, relativeY)
x: x + copysign(nearestX, relativeX),
y: y + copysign(nearestY, relativeY),
};
},
/**
* 点到椭圆最近的距离
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {number} 点到椭圆的距离
*/
pointDistance: function pointDistance(x, y, rx, ry, x0, y0) {
var nearestPoint = this.nearestPoint(x, y, rx, ry, x0, y0);
return distance(nearestPoint.x, nearestPoint.y, x0, y0);
},
/**
* 根据比例获取点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例,x轴方向为 0
* @return {object} 点
*/
pointAt: function pointAt(x, y, rx, ry, t) {
var angle = 2 * Math.PI * t; // 按照角度进行计算,而不按照周长计算
return {
x: x + rx * Math.cos(angle),
y: y + ry * Math.sin(angle)
};
},
/**
* 根据比例计算切线角度
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例 0 - 1 之间,x轴方向为 0。在 0-1 范围之外是循环还是返回 null,还需要调整
* @return {number} 角度,在 0 - 2PI 之间
*/
tangentAngle: function tangentAngle(x, y, rx, ry, t) {
var angle = 2 * Math.PI * t; // 按照角度进行计算,而不按照周长计算
// 直接使用 x,y 的导数计算, x' = -rx * sin(t); y' = ry * cos(t);
var tangentAngle = Math.atan2(ry * Math.cos(angle), -rx * Math.sin(angle));
// 也可以使用指定点的切线方程计算,成本有些高
// const point = this.pointAt(0, 0, rx, ry, t); // 椭圆的切线同椭圆的中心不相关
// let tangentAngle = -1 * Math.atan((ry * ry * point.x) / (rx * rx * point.y));
// if (angle >= 0 && angle <= Math.PI) {
// tangentAngle += Math.PI;
// }
return piMod(tangentAngle);
}
};
}
// 偏导数 x
function derivativeXAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle) {
return -1 * rx * Math.cos(xRotation) * Math.sin(angle) - ry * Math.sin(xRotation) * Math.cos(angle);
return (-1 * rx * Math.cos(xRotation) * Math.sin(angle) -
ry * Math.sin(xRotation) * Math.cos(angle));
}
// 偏导数 y
function derivativeYAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle) {
return -1 * rx * Math.sin(xRotation) * Math.sin(angle) + ry * Math.cos(xRotation) * Math.cos(angle);
return (-1 * rx * Math.sin(xRotation) * Math.sin(angle) +
ry * Math.cos(xRotation) * Math.cos(angle));
}
// x 的极值
function xExtrema(rx, ry, xRotation) {
return Math.atan(-ry / rx * Math.tan(xRotation));
return Math.atan((-ry / rx) * Math.tan(xRotation));
}
// y 的极值
function yExtrema(rx, ry, xRotation) {
return Math.atan(ry / (rx * Math.tan(xRotation)));
return Math.atan(ry / (rx * Math.tan(xRotation)));
}
// 根据角度求 x 坐标
function xAt(cx, cy, rx, ry, xRotation, angle) {
return rx * Math.cos(xRotation) * Math.cos(angle) - ry * Math.sin(xRotation) * Math.sin(angle) + cx;
return (rx * Math.cos(xRotation) * Math.cos(angle) -
ry * Math.sin(xRotation) * Math.sin(angle) +
cx);
}
// 根据角度求 y 坐标
function yAt(cx, cy, rx, ry, xRotation, angle) {
return rx * Math.sin(xRotation) * Math.cos(angle) + ry * Math.cos(xRotation) * Math.sin(angle) + cy;
return (rx * Math.sin(xRotation) * Math.cos(angle) +
ry * Math.cos(xRotation) * Math.sin(angle) +
cy);
}
// 获取点在椭圆上的角度
function getAngle(rx, ry, x0, y0) {
var angle = Math.atan2(y0 * rx, x0 * ry);
// 转换到 0 - 2PI 内
return (angle + Math.PI * 2) % (Math.PI * 2);
var angle = Math.atan2(y0 * rx, x0 * ry);
// 转换到 0 - 2PI 内
return (angle + Math.PI * 2) % (Math.PI * 2);
}
// 根据角度获取,x,y
function getPoint(rx, ry, angle) {
return {
x: rx * Math.cos(angle),
y: ry * Math.sin(angle)
};
return {
x: rx * Math.cos(angle),
y: ry * Math.sin(angle),
};
}
// 旋转
function rotate(x, y, angle) {
var cos = Math.cos(angle);
var sin = Math.sin(angle);
return [x * cos - y * sin, x * sin + y * cos];
var cos = Math.cos(angle);
var sin = Math.sin(angle);
return [x * cos - y * sin, x * sin + y * cos];
}
var arc = {
/**
* 计算包围盒
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @return {object} 包围盒对象
*/
box: function box(cx, cy, rx, ry, xRotation, startAngle, endAngle) {
function box$5(cx, cy, rx, ry, xRotation, startAngle, endAngle) {
var xDim = xExtrema(rx, ry, xRotation);

@@ -631,21 +134,22 @@ var minX = Infinity;

for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
var xAngle = xDim + i;
if (startAngle < endAngle) {
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
var xAngle = xDim + i;
if (startAngle < endAngle) {
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
}
}
} else {
if (endAngle < xAngle && xAngle < startAngle) {
xs.push(xAngle);
else {
if (endAngle < xAngle && xAngle < startAngle) {
xs.push(xAngle);
}
}
}
}
for (var _i = 0; _i < xs.length; _i++) {
var x = xAt(cx, cy, rx, ry, xRotation, xs[_i]);
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
for (var i = 0; i < xs.length; i++) {
var x = xAt(cx, cy, rx, ry, xRotation, xs[i]);
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
}

@@ -656,62 +160,37 @@ var yDim = yExtrema(rx, ry, xRotation);

var ys = [startAngle, endAngle];
for (var _i2 = -Math.PI * 2; _i2 <= Math.PI * 2; _i2 += Math.PI) {
var yAngle = yDim + _i2;
if (startAngle < endAngle) {
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
var yAngle = yDim + i;
if (startAngle < endAngle) {
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
}
}
} else {
if (endAngle < yAngle && yAngle < startAngle) {
ys.push(yAngle);
else {
if (endAngle < yAngle && yAngle < startAngle) {
ys.push(yAngle);
}
}
}
}
for (var _i3 = 0; _i3 < ys.length; _i3++) {
var y = yAt(cx, cy, rx, ry, xRotation, ys[_i3]);
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
for (var i = 0; i < ys.length; i++) {
var y = yAt(cx, cy, rx, ry, xRotation, ys[i]);
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
}
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
};
},
/**
* 获取圆弧的长度,计算圆弧长度时不考虑旋转角度,
* 仅跟 rx, ry, startAngle, endAngle 相关
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
*/
length: function length(cx, cy, rx, ry, xRotation, startAngle, endAngle) {},
/**
* 获取指定点到圆弧的最近距离的点
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @param {number} x0 指定点的 x
* @param {number} y0 指定点的 y
* @return {object} 到指定点最近距离的点
*/
nearestPoint: function nearestPoint(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
}
function nearestPoint$3(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
// 将最近距离问题转换成到椭圆中心 0,0 没有旋转的椭圆问题
var relativeVector = rotate(x0 - cx, y0 - cy, -xRotation);
var x1 = relativeVector[0],
y1 = relativeVector[1];
var _a = __read(relativeVector, 2), x1 = _a[0], y1 = _a[1];
// 计算点到椭圆的最近的点
var relativePoint = ellipse.nearestPoint(0, 0, rx, ry, x1, y1);
var relativePoint = nearestPoint$4(0, 0, rx, ry, x1, y1);
// 获取点在椭圆上的角度

@@ -721,66 +200,295 @@ var angle = getAngle(rx, ry, relativePoint.x, relativePoint.y);

if (angle < startAngle) {
// 小于起始圆弧
relativePoint = getPoint(rx, ry, startAngle);
} else if (angle > endAngle) {
// 大于结束圆弧
relativePoint = getPoint(rx, ry, endAngle);
// 小于起始圆弧
relativePoint = getPoint(rx, ry, startAngle);
}
else if (angle > endAngle) {
// 大于结束圆弧
relativePoint = getPoint(rx, ry, endAngle);
}
// 旋转到 xRotation 的角度
var vector = rotate(relativePoint.x, relativePoint.y, xRotation);
return {
x: vector[0] + cx,
y: vector[1] + cy
x: vector[0] + cx,
y: vector[1] + cy,
};
},
pointDistance: function pointDistance(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
var nearestPoint = this.nearestPoint(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0);
return distance(nearestPoint.x, nearestPoint.y, x0, y0);
},
pointAt: function pointAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
}
function tangentAngle$4(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
var angle = (endAngle - startAngle) * t + startAngle;
return {
x: xAt(cx, cy, rx, ry, xRotation, angle),
y: yAt(cx, cy, rx, ry, xRotation, angle)
};
},
tangentAngle: function tangentAngle(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
var angle = (endAngle - startAngle) * t + startAngle;
var dx = derivativeXAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle);
var dy = derivativeYAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle);
return piMod(Math.atan2(dy, dx));
}
};
}
function analyzePoints(points) {
// 计算每段的长度和总的长度
var totalLength = 0;
var segments = [];
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
var length = distance(from[0], from[1], to[0], to[1]);
var seg = {
from: from,
to: to,
length: length
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint$2(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [
tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([_t])), false)),
tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([_t])), false)),
];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0],
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1],
};
}
d = Infinity;
for (var i = 0; i < 32; i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var v1 = [
tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([prev])), false)),
tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([prev])), false)),
];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (prev >= 0 && d1 < d) {
t = prev;
d = d1;
}
else {
var v2 = [
tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([next])), false)),
tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([next])), false)),
];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
}
else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([t])), false)),
y: tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([t])), false)),
};
segments.push(seg);
totalLength += length;
}
return {
segments: segments,
totalLength: totalLength
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
}
function box$4(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
}
function length$4(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
}
function pointAt$3(x1, y1, x2, y2, t) {
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2,
};
}
function pointDistance$4(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
}
function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (vec2.exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
vec2.normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(vec2.dot(a, u));
}
function tangentAngle$3(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return (onet * onet * onet * p0 +
3 * p1 * t * onet * onet +
3 * p2 * t * t * onet +
p3 * t * t * t);
}
function derivativeAt(p0, p1, p2, p3, t) {
var onet = 1 - t;
return (3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2)));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
}
else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
}
else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = pointAt$3(x1, y1, x2, y2, t);
var c2 = pointAt$3(x2, y2, x3, y3, t);
var c3 = pointAt$3(x3, y3, x4, y4, t);
var c12 = pointAt$3(c1.x, c1.y, c2.x, c2.y, t);
var c23 = pointAt$3(c2.x, c2.y, c3.x, c3.y, t);
return [
[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt],
[xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4],
];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = __spreadArray(__spreadArray([], __read(cubics[0]), false), [iterationCount - 1], false);
var right = __spreadArray(__spreadArray([], __read(cubics[1]), false), [iterationCount - 1], false);
return cubicLength.apply(void 0, __spreadArray([], __read(left), false)) + cubicLength.apply(void 0, __spreadArray([], __read(right), false));
}
function box$3(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var i = 0; i < yExtrema.length; i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[i]));
}
return getBBoxByArray(xArr, yArr);
}
function length$3(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
}
function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint$2([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
}
function pointDistance$3(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
}
function pointAt$2(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t),
};
}
function tangentAngle$2(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt(x1, x2, x3, x4, t);
var dy = derivativeAt(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
function analyzePoints(points) {
// 计算每段的长度和总的长度
var totalLength = 0;
var segments = [];
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
var length_1 = distance(from[0], from[1], to[0], to[1]);
var seg = {
from: from,
to: to,
length: length_1,
};
segments.push(seg);
totalLength += length_1;
}
return { segments: segments, totalLength: totalLength };
}
function lengthOfSegment(points) {
if (points.length < 2) {
return 0;
}
var totalLength = 0;
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
totalLength += distance(from[0], from[1], to[0], to[1]);
}
return totalLength;
if (points.length < 2) {
return 0;
}
var totalLength = 0;
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
totalLength += distance(from[0], from[1], to[0], to[1]);
}
return totalLength;
}

@@ -794,32 +502,29 @@ /**

function pointAtSegments(points, t) {
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return null;
}
var _analyzePoints = analyzePoints(points),
segments = _analyzePoints.segments,
totalLength = _analyzePoints.totalLength;
// 多个点有可能重合
if (totalLength === 0) {
return {
x: points[0][0],
y: points[0][1]
};
}
// 计算比例
var startRatio = 0;
var point = null;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from,
to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
var localRatio = (t - startRatio) / currentRatio;
point = line.pointAt(from[0], from[1], to[0], to[1], localRatio);
break;
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return null;
}
startRatio += currentRatio;
}
return point;
var _a = analyzePoints(points), segments = _a.segments, totalLength = _a.totalLength;
// 多个点有可能重合
if (totalLength === 0) {
return {
x: points[0][0],
y: points[0][1],
};
}
// 计算比例
var startRatio = 0;
var point = null;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from, to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
var localRatio = (t - startRatio) / currentRatio;
point = pointAt$3(from[0], from[1], to[0], to[1], localRatio);
break;
}
startRatio += currentRatio;
}
return point;
}

@@ -832,146 +537,153 @@ /**

function angleAtSegments(points, t) {
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return 0;
}
var _analyzePoints2 = analyzePoints(points),
segments = _analyzePoints2.segments,
totalLength = _analyzePoints2.totalLength;
// 计算比例
var startRatio = 0;
var angle = 0;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from,
to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
break;
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return 0;
}
startRatio += currentRatio;
}
return angle;
var _a = analyzePoints(points), segments = _a.segments, totalLength = _a.totalLength;
// 计算比例
var startRatio = 0;
var angle = 0;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from, to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
break;
}
startRatio += currentRatio;
}
return angle;
}
function distanceAtSegment(points, x, y) {
var minDistance = Infinity;
for (var i = 0; i < points.length - 1; i++) {
var point = points[i];
var nextPoint = points[i + 1];
var _distance = line.pointDistance(point[0], point[1], nextPoint[0], nextPoint[1], x, y);
if (_distance < minDistance) {
minDistance = _distance;
var minDistance = Infinity;
for (var i = 0; i < points.length - 1; i++) {
var point = points[i];
var nextPoint = points[i + 1];
var distance_1 = pointDistance$4(point[0], point[1], nextPoint[0], nextPoint[1], x, y);
if (distance_1 < minDistance) {
minDistance = distance_1;
}
}
}
return minDistance;
return minDistance;
}
var polyline = {
/**
* 计算多折线的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box: function box(points) {
function box$2(points) {
var xArr = [];
var yArr = [];
for (var i = 0; i < points.length; i++) {
var point = points[i];
xArr.push(point[0]);
yArr.push(point[1]);
var point = points[i];
xArr.push(point[0]);
yArr.push(point[1]);
}
return getBBoxByArray(xArr, yArr);
},
/**
* 计算多折线的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多条边的长度
*/
length: function length(points) {
}
function length$2(points) {
return lengthOfSegment(points);
},
/**
* 根据比例获取多折线的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt: function pointAt(points, t) {
}
function pointAt$1(points, t) {
return pointAtSegments(points, t);
},
/**
* 指定点到多折线的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多折线的距离
*/
pointDistance: function pointDistance(points, x, y) {
}
function pointDistance$2(points, x, y) {
return distanceAtSegment(points, x, y);
},
/**
* 根据比例获取多折线的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle: function tangentAngle(points, t) {
}
function tangentAngle$1(points, t) {
return angleAtSegments(points, t);
}
};
}
function getAllPoints(points) {
var tmp = points.slice(0);
if (points.length) {
tmp.push(points[0]);
}
return tmp;
var tmp = points.slice(0);
if (points.length) {
tmp.push(points[0]);
}
return tmp;
}
var polygon = {
/**
* 计算多边形的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box: function box(points) {
return polyline.box(points);
},
/**
* 计算多边形的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多边形边的长度
*/
length: function length(points) {
function box$1(points) {
return box$2(points);
}
function length$1(points) {
return lengthOfSegment(getAllPoints(points));
},
/**
* 根据比例获取多边形的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt: function pointAt(points, t) {
}
function pointAt(points, t) {
return pointAtSegments(getAllPoints(points), t);
},
/**
* 指定点到多边形的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多边形的距离
*/
pointDistance: function pointDistance(points, x, y) {
}
function pointDistance$1(points, x, y) {
return distanceAtSegment(getAllPoints(points), x, y);
},
/**
* 根据比例获取多边形的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle: function tangentAngle(points, t) {
}
function tangentAngle(points, t) {
return angleAtSegments(getAllPoints(points), t);
}
};
}
export { arc as Arc, cubic as Cubic, line as Line, polygon as Polygon, polyline as Polyline, quadratic as Quad, util as Util };
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = pointAt$3(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = pointAt$3(x2, y2, x3, y3, t);
return [
[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt],
[xt, yt, controlPoint2.x, controlPoint2.y, x3, y3],
];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return ((distance(x1, y1, x2, y2) +
distance(x2, y2, x3, y3) +
distance(x1, y1, x3, y3)) /
2);
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, __spreadArray([], __read(left), false)) + quadraticLength.apply(void 0, __spreadArray([], __read(right), false));
}
function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
}
function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
}
function nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint$2([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
}
function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
}
export { box$5 as arcBox, nearestPoint$3 as arcNearestPoint, tangentAngle$4 as arcTangentAngle, box$3 as cubicBox, length$3 as cubicLength, nearestPoint$1 as cubicNearestPoint, pointAt$2 as cubicPointAt, pointDistance$3 as cubicPointDistance, tangentAngle$2 as cubicTangentAngle, distance, box$4 as lineBox, length$4 as lineLength, pointAt$3 as linePointAt, pointDistance$4 as linePointDistance, pointToLine as linePointToLine, tangentAngle$3 as lineTangentAngle, box$1 as polygonBox, length$1 as polygonLength, pointAt as polygonPointAt, pointDistance$1 as polygonPointDistance, tangentAngle as polygonTangentAngle, box$2 as polylineBox, length$2 as polylineLength, pointAt$1 as polylinePointAt, pointDistance$2 as polylinePointDistance, tangentAngle$1 as polylineTangentAngle, box as quadBox, length as quadLength, nearestPoint as quadNearestPoint, pointDistance as quadPointDistance };
//# sourceMappingURL=index.esm.js.map
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var glMatrix = require('gl-matrix');
/**
* 两点之间的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
function distance(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function isNumberEqual(v1, v2) {
return Math.abs(v1 - v2) < 0.001;
return Math.abs(v1 - v2) < 0.001;
}
function getBBoxByArray(xArr, yArr) {
var minX = Math.min.apply(Math, xArr);
var minY = Math.min.apply(Math, yArr);
var maxX = Math.max.apply(Math, xArr);
var maxY = Math.max.apply(Math, yArr);
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
};
}
function getBBoxRange(x1, y1, x2, y2) {
return {
minX: Math.min(x1, x2),
maxX: Math.max(x1, x2),
minY: Math.min(y1, y2),
maxY: Math.max(y1, y2)
};
}
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
var util = /*#__PURE__*/Object.freeze({
__proto__: null,
distance: distance,
isNumberEqual: isNumberEqual,
getBBoxByArray: getBBoxByArray,
getBBoxRange: getBBoxRange,
piMod: piMod
});
var line = {
/**
* 计算线段的包围盒
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {object} 包围盒对象
*/
box: function box(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
},
/**
* 线段的长度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
length: function length(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
},
/**
* 根据比例获取点
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} t 指定比例
* @return {object} 包含 x, y 的点
*/
pointAt: function pointAt(x1, y1, x2, y2, t) {
var minX = Math.min.apply(Math, tslib.__spreadArray([], tslib.__read(xArr), false));
var minY = Math.min.apply(Math, tslib.__spreadArray([], tslib.__read(yArr), false));
var maxX = Math.max.apply(Math, tslib.__spreadArray([], tslib.__read(xArr), false));
var maxY = Math.max.apply(Math, tslib.__spreadArray([], tslib.__read(yArr), false));
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
};
},
/**
* 点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointDistance: function pointDistance(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
},
/**
* 点到直线的距离,而不是点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointToLine: function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (glMatrix.vec2.exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
glMatrix.vec2.normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(glMatrix.vec2.dot(a, u));
},
/**
* 线段的角度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 导数
*/
tangentAngle: function tangentAngle(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
};
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [tCallback.apply(void 0, xArr.concat([_t])), tCallback.apply(void 0, yArr.concat([_t]))];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0]
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1]
};
}
d = Infinity;
for (var _i = 0; _i < 32; _i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var _v = [tCallback.apply(void 0, xArr.concat([prev])), tCallback.apply(void 0, yArr.concat([prev]))];
var _d = distance(v0[0], v0[1], _v[0], _v[1]);
if (prev >= 0 && _d < d) {
t = prev;
d = _d;
} else {
var v2 = [tCallback.apply(void 0, xArr.concat([next])), tCallback.apply(void 0, yArr.concat([next]))];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
} else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, xArr.concat([t])),
y: tCallback.apply(void 0, yArr.concat([t]))
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
function piMod(angle) {
return (angle + Math.PI * 2) % (Math.PI * 2);
}
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
function derivativeAt(p0, p1, p2, t) {
return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = line.pointAt(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = line.pointAt(x2, y2, x3, y3, t);
return [[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt], [xt, yt, controlPoint2.x, controlPoint2.y, x3, y3]];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return (distance(x1, y1, x2, y2) + distance(x2, y2, x3, y3) + distance(x1, y1, x3, y3)) / 2;
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, left) + quadraticLength.apply(void 0, right);
}
var quadratic = {
box: function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: quadraticAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, t) {
return {
x: quadraticAt(x1, x2, x3, t),
y: quadraticAt(y1, y2, y3, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, t) {
return divideQuadratic(x1, y1, x2, y2, x3, y3, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, t) {
var dx = derivativeAt(x1, x2, x3, t);
var dy = derivativeAt(y1, y2, y3, t);
var angle = Math.atan2(dy, dx);
return piMod(angle);
}
};
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return onet * onet * onet * p0 + 3 * p1 * t * onet * onet + 3 * p2 * t * t * onet + p3 * t * t * t;
}
function derivativeAt$1(p0, p1, p2, p3, t) {
var onet = 1 - t;
return 3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
} else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
} else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = line.pointAt(x1, y1, x2, y2, t);
var c2 = line.pointAt(x2, y2, x3, y3, t);
var c3 = line.pointAt(x3, y3, x4, y4, t);
var c12 = line.pointAt(c1.x, c1.y, c2.x, c2.y, t);
var c23 = line.pointAt(c2.x, c2.y, c3.x, c3.y, t);
return [[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt], [xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4]];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = [].concat(cubics[0], [iterationCount - 1]);
var right = [].concat(cubics[1], [iterationCount - 1]);
return cubicLength.apply(void 0, left) + cubicLength.apply(void 0, right);
}
var cubic = {
extrema: extrema$1,
box: function box(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var _i = 0; _i < yExtrema.length; _i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[_i]));
}
return getBBoxByArray(xArr, yArr);
},
length: function length(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
},
nearestPoint: function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
},
pointDistance: function pointDistance(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
},
interpolationAt: cubicAt,
pointAt: function pointAt(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t)
};
},
divide: function divide(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t);
},
tangentAngle: function tangentAngle(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt$1(x1, x2, x3, x4, t);
var dy = derivativeAt$1(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
};
/**
* @fileoverview 椭圆的一些计算,
* - 周长计算参考:https://www.mathsisfun.com/geometry/ellipse-perimeter.html
* - 距离计算参考:https://wet-robots.ghost.io/simple-method-for-distance-to-ellipse/
* @author dxq613@gmail.com
*/
function copysign(v1, v2) {
var absv = Math.abs(v1);
return v2 > 0 ? absv : absv * -1;
var absv = Math.abs(v1);
return v2 > 0 ? absv : absv * -1;
}
var ellipse = {
/**
* 包围盒计算
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {object} 包围盒
*/
box: function box(x, y, rx, ry) {
return {
x: x - rx,
y: y - ry,
width: rx * 2,
height: ry * 2
};
},
/**
* 计算周长,使用近似法
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @return {number} 椭圆周长
*/
length: function length(x, y, rx, ry) {
return Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
},
/**
* 距离椭圆最近的点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {object} 椭圆上距离指定点最近的点
*/
nearestPoint: function nearestPoint(x, y, rx, ry, x0, y0) {
function nearestPoint$4(x, y, rx, ry, x0, y0) {
var a = rx;

@@ -481,6 +39,6 @@ var b = ry;

if (a === 0 || b === 0) {
return {
x: x,
y: y
};
return {
x: x,
y: y,
};
}

@@ -500,131 +58,74 @@ // 转换成 0, 0 为中心的椭圆计算

for (var i = 0; i < 4; i++) {
nearestX = a * Math.cos(t);
nearestY = b * Math.sin(t);
var ex = (squareA - squareB) * Math.pow(Math.cos(t), 3) / a;
var ey = (squareB - squareA) * Math.pow(Math.sin(t), 3) / b;
var rx1 = nearestX - ex;
var ry1 = nearestY - ey;
var qx = px - ex;
var qy = py - ey;
var r = Math.hypot(ry1, rx1);
var q = Math.hypot(qy, qx);
var delta_c = r * Math.asin((rx1 * qy - ry1 * qx) / (r * q));
var delta_t = delta_c / Math.sqrt(squareA + squareB - nearestX * nearestX - nearestY * nearestY);
t += delta_t;
t = Math.min(Math.PI / 2, Math.max(0, t));
nearestX = a * Math.cos(t);
nearestY = b * Math.sin(t);
var ex = ((squareA - squareB) * Math.pow(Math.cos(t), 3)) / a;
var ey = ((squareB - squareA) * Math.pow(Math.sin(t), 3)) / b;
var rx1 = nearestX - ex;
var ry1 = nearestY - ey;
var qx = px - ex;
var qy = py - ey;
var r = Math.hypot(ry1, rx1);
var q = Math.hypot(qy, qx);
var delta_c = r * Math.asin((rx1 * qy - ry1 * qx) / (r * q));
var delta_t = delta_c /
Math.sqrt(squareA + squareB - nearestX * nearestX - nearestY * nearestY);
t += delta_t;
t = Math.min(Math.PI / 2, Math.max(0, t));
}
return {
x: x + copysign(nearestX, relativeX),
y: y + copysign(nearestY, relativeY)
x: x + copysign(nearestX, relativeX),
y: y + copysign(nearestY, relativeY),
};
},
/**
* 点到椭圆最近的距离
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} x0 指定的点 x
* @param {number} y0 指定的点 y
* @return {number} 点到椭圆的距离
*/
pointDistance: function pointDistance(x, y, rx, ry, x0, y0) {
var nearestPoint = this.nearestPoint(x, y, rx, ry, x0, y0);
return distance(nearestPoint.x, nearestPoint.y, x0, y0);
},
/**
* 根据比例获取点
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例,x轴方向为 0
* @return {object} 点
*/
pointAt: function pointAt(x, y, rx, ry, t) {
var angle = 2 * Math.PI * t; // 按照角度进行计算,而不按照周长计算
return {
x: x + rx * Math.cos(angle),
y: y + ry * Math.sin(angle)
};
},
/**
* 根据比例计算切线角度
* @param {number} x 椭圆中心 x
* @param {number} y 椭圆中心 y
* @param {number} rx 椭圆 x 方向半径
* @param {number} ry 椭圆 y 方向半径
* @param {number} t 指定比例 0 - 1 之间,x轴方向为 0。在 0-1 范围之外是循环还是返回 null,还需要调整
* @return {number} 角度,在 0 - 2PI 之间
*/
tangentAngle: function tangentAngle(x, y, rx, ry, t) {
var angle = 2 * Math.PI * t; // 按照角度进行计算,而不按照周长计算
// 直接使用 x,y 的导数计算, x' = -rx * sin(t); y' = ry * cos(t);
var tangentAngle = Math.atan2(ry * Math.cos(angle), -rx * Math.sin(angle));
// 也可以使用指定点的切线方程计算,成本有些高
// const point = this.pointAt(0, 0, rx, ry, t); // 椭圆的切线同椭圆的中心不相关
// let tangentAngle = -1 * Math.atan((ry * ry * point.x) / (rx * rx * point.y));
// if (angle >= 0 && angle <= Math.PI) {
// tangentAngle += Math.PI;
// }
return piMod(tangentAngle);
}
};
}
// 偏导数 x
function derivativeXAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle) {
return -1 * rx * Math.cos(xRotation) * Math.sin(angle) - ry * Math.sin(xRotation) * Math.cos(angle);
return (-1 * rx * Math.cos(xRotation) * Math.sin(angle) -
ry * Math.sin(xRotation) * Math.cos(angle));
}
// 偏导数 y
function derivativeYAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle) {
return -1 * rx * Math.sin(xRotation) * Math.sin(angle) + ry * Math.cos(xRotation) * Math.cos(angle);
return (-1 * rx * Math.sin(xRotation) * Math.sin(angle) +
ry * Math.cos(xRotation) * Math.cos(angle));
}
// x 的极值
function xExtrema(rx, ry, xRotation) {
return Math.atan(-ry / rx * Math.tan(xRotation));
return Math.atan((-ry / rx) * Math.tan(xRotation));
}
// y 的极值
function yExtrema(rx, ry, xRotation) {
return Math.atan(ry / (rx * Math.tan(xRotation)));
return Math.atan(ry / (rx * Math.tan(xRotation)));
}
// 根据角度求 x 坐标
function xAt(cx, cy, rx, ry, xRotation, angle) {
return rx * Math.cos(xRotation) * Math.cos(angle) - ry * Math.sin(xRotation) * Math.sin(angle) + cx;
return (rx * Math.cos(xRotation) * Math.cos(angle) -
ry * Math.sin(xRotation) * Math.sin(angle) +
cx);
}
// 根据角度求 y 坐标
function yAt(cx, cy, rx, ry, xRotation, angle) {
return rx * Math.sin(xRotation) * Math.cos(angle) + ry * Math.cos(xRotation) * Math.sin(angle) + cy;
return (rx * Math.sin(xRotation) * Math.cos(angle) +
ry * Math.cos(xRotation) * Math.sin(angle) +
cy);
}
// 获取点在椭圆上的角度
function getAngle(rx, ry, x0, y0) {
var angle = Math.atan2(y0 * rx, x0 * ry);
// 转换到 0 - 2PI 内
return (angle + Math.PI * 2) % (Math.PI * 2);
var angle = Math.atan2(y0 * rx, x0 * ry);
// 转换到 0 - 2PI 内
return (angle + Math.PI * 2) % (Math.PI * 2);
}
// 根据角度获取,x,y
function getPoint(rx, ry, angle) {
return {
x: rx * Math.cos(angle),
y: ry * Math.sin(angle)
};
return {
x: rx * Math.cos(angle),
y: ry * Math.sin(angle),
};
}
// 旋转
function rotate(x, y, angle) {
var cos = Math.cos(angle);
var sin = Math.sin(angle);
return [x * cos - y * sin, x * sin + y * cos];
var cos = Math.cos(angle);
var sin = Math.sin(angle);
return [x * cos - y * sin, x * sin + y * cos];
}
var arc = {
/**
* 计算包围盒
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @return {object} 包围盒对象
*/
box: function box(cx, cy, rx, ry, xRotation, startAngle, endAngle) {
function box$5(cx, cy, rx, ry, xRotation, startAngle, endAngle) {
var xDim = xExtrema(rx, ry, xRotation);

@@ -635,21 +136,22 @@ var minX = Infinity;

for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
var xAngle = xDim + i;
if (startAngle < endAngle) {
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
var xAngle = xDim + i;
if (startAngle < endAngle) {
if (startAngle < xAngle && xAngle < endAngle) {
xs.push(xAngle);
}
}
} else {
if (endAngle < xAngle && xAngle < startAngle) {
xs.push(xAngle);
else {
if (endAngle < xAngle && xAngle < startAngle) {
xs.push(xAngle);
}
}
}
}
for (var _i = 0; _i < xs.length; _i++) {
var x = xAt(cx, cy, rx, ry, xRotation, xs[_i]);
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
for (var i = 0; i < xs.length; i++) {
var x = xAt(cx, cy, rx, ry, xRotation, xs[i]);
if (x < minX) {
minX = x;
}
if (x > maxX) {
maxX = x;
}
}

@@ -660,62 +162,37 @@ var yDim = yExtrema(rx, ry, xRotation);

var ys = [startAngle, endAngle];
for (var _i2 = -Math.PI * 2; _i2 <= Math.PI * 2; _i2 += Math.PI) {
var yAngle = yDim + _i2;
if (startAngle < endAngle) {
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
var yAngle = yDim + i;
if (startAngle < endAngle) {
if (startAngle < yAngle && yAngle < endAngle) {
ys.push(yAngle);
}
}
} else {
if (endAngle < yAngle && yAngle < startAngle) {
ys.push(yAngle);
else {
if (endAngle < yAngle && yAngle < startAngle) {
ys.push(yAngle);
}
}
}
}
for (var _i3 = 0; _i3 < ys.length; _i3++) {
var y = yAt(cx, cy, rx, ry, xRotation, ys[_i3]);
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
for (var i = 0; i < ys.length; i++) {
var y = yAt(cx, cy, rx, ry, xRotation, ys[i]);
if (y < minY) {
minY = y;
}
if (y > maxY) {
maxY = y;
}
}
return {
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
};
},
/**
* 获取圆弧的长度,计算圆弧长度时不考虑旋转角度,
* 仅跟 rx, ry, startAngle, endAngle 相关
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
*/
length: function length(cx, cy, rx, ry, xRotation, startAngle, endAngle) {},
/**
* 获取指定点到圆弧的最近距离的点
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} rx x 轴方向的半径
* @param {number} ry y 轴方向的半径
* @param {number} xRotation 旋转角度
* @param {number} startAngle 起始角度
* @param {number} endAngle 结束角度
* @param {number} x0 指定点的 x
* @param {number} y0 指定点的 y
* @return {object} 到指定点最近距离的点
*/
nearestPoint: function nearestPoint(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
}
function nearestPoint$3(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
// 将最近距离问题转换成到椭圆中心 0,0 没有旋转的椭圆问题
var relativeVector = rotate(x0 - cx, y0 - cy, -xRotation);
var x1 = relativeVector[0],
y1 = relativeVector[1];
var _a = tslib.__read(relativeVector, 2), x1 = _a[0], y1 = _a[1];
// 计算点到椭圆的最近的点
var relativePoint = ellipse.nearestPoint(0, 0, rx, ry, x1, y1);
var relativePoint = nearestPoint$4(0, 0, rx, ry, x1, y1);
// 获取点在椭圆上的角度

@@ -725,66 +202,295 @@ var angle = getAngle(rx, ry, relativePoint.x, relativePoint.y);

if (angle < startAngle) {
// 小于起始圆弧
relativePoint = getPoint(rx, ry, startAngle);
} else if (angle > endAngle) {
// 大于结束圆弧
relativePoint = getPoint(rx, ry, endAngle);
// 小于起始圆弧
relativePoint = getPoint(rx, ry, startAngle);
}
else if (angle > endAngle) {
// 大于结束圆弧
relativePoint = getPoint(rx, ry, endAngle);
}
// 旋转到 xRotation 的角度
var vector = rotate(relativePoint.x, relativePoint.y, xRotation);
return {
x: vector[0] + cx,
y: vector[1] + cy
x: vector[0] + cx,
y: vector[1] + cy,
};
},
pointDistance: function pointDistance(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0) {
var nearestPoint = this.nearestPoint(cx, cy, rx, ry, xRotation, startAngle, endAngle, x0, y0);
return distance(nearestPoint.x, nearestPoint.y, x0, y0);
},
pointAt: function pointAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
}
function tangentAngle$4(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
var angle = (endAngle - startAngle) * t + startAngle;
return {
x: xAt(cx, cy, rx, ry, xRotation, angle),
y: yAt(cx, cy, rx, ry, xRotation, angle)
};
},
tangentAngle: function tangentAngle(cx, cy, rx, ry, xRotation, startAngle, endAngle, t) {
var angle = (endAngle - startAngle) * t + startAngle;
var dx = derivativeXAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle);
var dy = derivativeYAt(cx, cy, rx, ry, xRotation, startAngle, endAngle, angle);
return piMod(Math.atan2(dy, dx));
}
};
}
function analyzePoints(points) {
// 计算每段的长度和总的长度
var totalLength = 0;
var segments = [];
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
var length = distance(from[0], from[1], to[0], to[1]);
var seg = {
from: from,
to: to,
length: length
var EPSILON = 0.0001;
/**
* 使用牛顿切割法求最近的点
* @param {number[]} xArr 点的 x 数组
* @param {number[]} yArr 点的 y 数组
* @param {number} x 指定的点 x
* @param {number} y 指定的点 y
* @param {Function} tCallback 差值函数
*/
function nearestPoint$2(xArr, yArr, x, y, tCallback, length) {
var t = -1;
var d = Infinity;
var v0 = [x, y];
var segNum = 20;
if (length && length > 200) {
segNum = length / 10;
}
var increaseRate = 1 / segNum;
var interval = increaseRate / 10;
for (var i = 0; i <= segNum; i++) {
var _t = i * increaseRate;
var v1 = [
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(xArr.concat([_t])), false)),
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(yArr.concat([_t])), false)),
];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (d1 < d) {
t = _t;
d = d1;
}
}
// 提前终止
if (t === 0) {
return {
x: xArr[0],
y: yArr[0],
};
}
if (t === 1) {
var count = xArr.length;
return {
x: xArr[count - 1],
y: yArr[count - 1],
};
}
d = Infinity;
for (var i = 0; i < 32; i++) {
if (interval < EPSILON) {
break;
}
var prev = t - interval;
var next = t + interval;
var v1 = [
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(xArr.concat([prev])), false)),
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(yArr.concat([prev])), false)),
];
var d1 = distance(v0[0], v0[1], v1[0], v1[1]);
if (prev >= 0 && d1 < d) {
t = prev;
d = d1;
}
else {
var v2 = [
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(xArr.concat([next])), false)),
tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(yArr.concat([next])), false)),
];
var d2 = distance(v0[0], v0[1], v2[0], v2[1]);
if (next <= 1 && d2 < d) {
t = next;
d = d2;
}
else {
interval *= 0.5;
}
}
}
return {
x: tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(xArr.concat([t])), false)),
y: tCallback.apply(void 0, tslib.__spreadArray([], tslib.__read(yArr.concat([t])), false)),
};
segments.push(seg);
totalLength += length;
}
return {
segments: segments,
totalLength: totalLength
};
}
// 近似求解 https://community.khronos.org/t/3d-cubic-bezier-segment-length/62363/2
function snapLength(xArr, yArr) {
var totalLength = 0;
var count = xArr.length;
for (var i = 0; i < count; i++) {
var x = xArr[i];
var y = yArr[i];
var nextX = xArr[(i + 1) % count];
var nextY = yArr[(i + 1) % count];
totalLength += distance(x, y, nextX, nextY);
}
return totalLength / 2;
}
function box$4(x1, y1, x2, y2) {
return getBBoxByArray([x1, x2], [y1, y2]);
}
function length$4(x1, y1, x2, y2) {
return distance(x1, y1, x2, y2);
}
function pointAt$3(x1, y1, x2, y2, t) {
return {
x: (1 - t) * x1 + t * x2,
y: (1 - t) * y1 + t * y2,
};
}
function pointDistance$4(x1, y1, x2, y2, x, y) {
// 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a
// p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量)
var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
if (cross < 0) {
return distance(x1, y1, x, y);
}
var lengthSquare = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
if (cross > lengthSquare) {
return distance(x2, y2, x, y);
}
return this.pointToLine(x1, y1, x2, y2, x, y);
}
function pointToLine(x1, y1, x2, y2, x, y) {
var d = [x2 - x1, y2 - y1];
// 如果端点相等,则判定点到点的距离
if (glMatrix.vec2.exactEquals(d, [0, 0])) {
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
}
var u = [-d[1], d[0]];
glMatrix.vec2.normalize(u, u);
var a = [x - x1, y - y1];
return Math.abs(glMatrix.vec2.dot(a, u));
}
function tangentAngle$3(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
function cubicAt(p0, p1, p2, p3, t) {
var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
return (onet * onet * onet * p0 +
3 * p1 * t * onet * onet +
3 * p2 * t * t * onet +
p3 * t * t * t);
}
function derivativeAt(p0, p1, p2, p3, t) {
var onet = 1 - t;
return (3 * (onet * onet * (p1 - p0) + 2 * onet * t * (p2 - p1) + t * t * (p3 - p2)));
}
function extrema$1(p0, p1, p2, p3) {
var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
var b = 6 * p0 - 12 * p1 + 6 * p2;
var c = 3 * p1 - 3 * p0;
var extremas = [];
var t1;
var t2;
var discSqrt;
if (isNumberEqual(a, 0)) {
if (!isNumberEqual(b, 0)) {
t1 = -c / b;
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
}
}
else {
var disc = b * b - 4 * a * c;
if (isNumberEqual(disc, 0)) {
extremas.push(-b / (2 * a));
}
else if (disc > 0) {
discSqrt = Math.sqrt(disc);
t1 = (-b + discSqrt) / (2 * a);
t2 = (-b - discSqrt) / (2 * a);
if (t1 >= 0 && t1 <= 1) {
extremas.push(t1);
}
if (t2 >= 0 && t2 <= 1) {
extremas.push(t2);
}
}
}
return extremas;
}
// 分割贝塞尔曲线
function divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, t) {
// 划分点
var xt = cubicAt(x1, x2, x3, x4, t);
var yt = cubicAt(y1, y2, y3, y4, t);
// 计算两点之间的差值点
var c1 = pointAt$3(x1, y1, x2, y2, t);
var c2 = pointAt$3(x2, y2, x3, y3, t);
var c3 = pointAt$3(x3, y3, x4, y4, t);
var c12 = pointAt$3(c1.x, c1.y, c2.x, c2.y, t);
var c23 = pointAt$3(c2.x, c2.y, c3.x, c3.y, t);
return [
[x1, y1, c1.x, c1.y, c12.x, c12.y, xt, yt],
[xt, yt, c23.x, c23.y, c3.x, c3.y, x4, y4],
];
}
// 使用迭代法取贝塞尔曲线的长度,二阶和三阶分开写,更清晰和便于调试
function cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, iterationCount) {
if (iterationCount === 0) {
return snapLength([x1, x2, x3, x4], [y1, y2, y3, y4]);
}
var cubics = divideCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0.5);
var left = tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(cubics[0]), false), [iterationCount - 1], false);
var right = tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(cubics[1]), false), [iterationCount - 1], false);
return cubicLength.apply(void 0, tslib.__spreadArray([], tslib.__read(left), false)) + cubicLength.apply(void 0, tslib.__spreadArray([], tslib.__read(right), false));
}
function box$3(x1, y1, x2, y2, x3, y3, x4, y4) {
var xArr = [x1, x4];
var yArr = [y1, y4];
var xExtrema = extrema$1(x1, x2, x3, x4);
var yExtrema = extrema$1(y1, y2, y3, y4);
for (var i = 0; i < xExtrema.length; i++) {
xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
}
for (var i = 0; i < yExtrema.length; i++) {
yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[i]));
}
return getBBoxByArray(xArr, yArr);
}
function length$3(x1, y1, x2, y2, x3, y3, x4, y4) {
// 迭代三次,划分成 8 段求长度
return cubicLength(x1, y1, x2, y2, x3, y3, x4, y4, 3);
}
function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
return nearestPoint$2([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
}
function pointDistance$3(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
return distance(point.x, point.y, x0, y0);
}
function pointAt$2(x1, y1, x2, y2, x3, y3, x4, y4, t) {
return {
x: cubicAt(x1, x2, x3, x4, t),
y: cubicAt(y1, y2, y3, y4, t),
};
}
function tangentAngle$2(x1, y1, x2, y2, x3, y3, x4, y4, t) {
var dx = derivativeAt(x1, x2, x3, x4, t);
var dy = derivativeAt(y1, y2, y3, y4, t);
return piMod(Math.atan2(dy, dx));
}
function analyzePoints(points) {
// 计算每段的长度和总的长度
var totalLength = 0;
var segments = [];
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
var length_1 = distance(from[0], from[1], to[0], to[1]);
var seg = {
from: from,
to: to,
length: length_1,
};
segments.push(seg);
totalLength += length_1;
}
return { segments: segments, totalLength: totalLength };
}
function lengthOfSegment(points) {
if (points.length < 2) {
return 0;
}
var totalLength = 0;
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
totalLength += distance(from[0], from[1], to[0], to[1]);
}
return totalLength;
if (points.length < 2) {
return 0;
}
var totalLength = 0;
for (var i = 0; i < points.length - 1; i++) {
var from = points[i];
var to = points[i + 1];
totalLength += distance(from[0], from[1], to[0], to[1]);
}
return totalLength;
}

@@ -798,32 +504,29 @@ /**

function pointAtSegments(points, t) {
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return null;
}
var _analyzePoints = analyzePoints(points),
segments = _analyzePoints.segments,
totalLength = _analyzePoints.totalLength;
// 多个点有可能重合
if (totalLength === 0) {
return {
x: points[0][0],
y: points[0][1]
};
}
// 计算比例
var startRatio = 0;
var point = null;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from,
to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
var localRatio = (t - startRatio) / currentRatio;
point = line.pointAt(from[0], from[1], to[0], to[1], localRatio);
break;
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return null;
}
startRatio += currentRatio;
}
return point;
var _a = analyzePoints(points), segments = _a.segments, totalLength = _a.totalLength;
// 多个点有可能重合
if (totalLength === 0) {
return {
x: points[0][0],
y: points[0][1],
};
}
// 计算比例
var startRatio = 0;
var point = null;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from, to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
var localRatio = (t - startRatio) / currentRatio;
point = pointAt$3(from[0], from[1], to[0], to[1], localRatio);
break;
}
startRatio += currentRatio;
}
return point;
}

@@ -836,152 +539,182 @@ /**

function angleAtSegments(points, t) {
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return 0;
}
var _analyzePoints2 = analyzePoints(points),
segments = _analyzePoints2.segments,
totalLength = _analyzePoints2.totalLength;
// 计算比例
var startRatio = 0;
var angle = 0;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from,
to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
break;
// 边界判断
if (t > 1 || t < 0 || points.length < 2) {
return 0;
}
startRatio += currentRatio;
}
return angle;
var _a = analyzePoints(points), segments = _a.segments, totalLength = _a.totalLength;
// 计算比例
var startRatio = 0;
var angle = 0;
for (var i = 0; i < segments.length; i++) {
var seg = segments[i];
var from = seg.from, to = seg.to;
var currentRatio = seg.length / totalLength;
if (t >= startRatio && t <= startRatio + currentRatio) {
angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
break;
}
startRatio += currentRatio;
}
return angle;
}
function distanceAtSegment(points, x, y) {
var minDistance = Infinity;
for (var i = 0; i < points.length - 1; i++) {
var point = points[i];
var nextPoint = points[i + 1];
var _distance = line.pointDistance(point[0], point[1], nextPoint[0], nextPoint[1], x, y);
if (_distance < minDistance) {
minDistance = _distance;
var minDistance = Infinity;
for (var i = 0; i < points.length - 1; i++) {
var point = points[i];
var nextPoint = points[i + 1];
var distance_1 = pointDistance$4(point[0], point[1], nextPoint[0], nextPoint[1], x, y);
if (distance_1 < minDistance) {
minDistance = distance_1;
}
}
}
return minDistance;
return minDistance;
}
var polyline = {
/**
* 计算多折线的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box: function box(points) {
function box$2(points) {
var xArr = [];
var yArr = [];
for (var i = 0; i < points.length; i++) {
var point = points[i];
xArr.push(point[0]);
yArr.push(point[1]);
var point = points[i];
xArr.push(point[0]);
yArr.push(point[1]);
}
return getBBoxByArray(xArr, yArr);
},
/**
* 计算多折线的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多条边的长度
*/
length: function length(points) {
}
function length$2(points) {
return lengthOfSegment(points);
},
/**
* 根据比例获取多折线的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt: function pointAt(points, t) {
}
function pointAt$1(points, t) {
return pointAtSegments(points, t);
},
/**
* 指定点到多折线的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多折线的距离
*/
pointDistance: function pointDistance(points, x, y) {
}
function pointDistance$2(points, x, y) {
return distanceAtSegment(points, x, y);
},
/**
* 根据比例获取多折线的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle: function tangentAngle(points, t) {
}
function tangentAngle$1(points, t) {
return angleAtSegments(points, t);
}
};
}
function getAllPoints(points) {
var tmp = points.slice(0);
if (points.length) {
tmp.push(points[0]);
}
return tmp;
var tmp = points.slice(0);
if (points.length) {
tmp.push(points[0]);
}
return tmp;
}
var polygon = {
/**
* 计算多边形的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box: function box(points) {
return polyline.box(points);
},
/**
* 计算多边形的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多边形边的长度
*/
length: function length(points) {
function box$1(points) {
return box$2(points);
}
function length$1(points) {
return lengthOfSegment(getAllPoints(points));
},
/**
* 根据比例获取多边形的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt: function pointAt(points, t) {
}
function pointAt(points, t) {
return pointAtSegments(getAllPoints(points), t);
},
/**
* 指定点到多边形的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多边形的距离
*/
pointDistance: function pointDistance(points, x, y) {
}
function pointDistance$1(points, x, y) {
return distanceAtSegment(getAllPoints(points), x, y);
},
/**
* 根据比例获取多边形的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle: function tangentAngle(points, t) {
}
function tangentAngle(points, t) {
return angleAtSegments(getAllPoints(points), t);
}
};
}
exports.Arc = arc;
exports.Cubic = cubic;
exports.Line = line;
exports.Polygon = polygon;
exports.Polyline = polyline;
exports.Quad = quadratic;
exports.Util = util;
// 差值公式
function quadraticAt(p0, p1, p2, t) {
var onet = 1 - t;
return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
}
// 求极值
function extrema(p0, p1, p2) {
var a = p0 + p2 - 2 * p1;
if (isNumberEqual(a, 0)) {
return [0.5];
}
var rst = (p0 - p1) / a;
if (rst <= 1 && rst >= 0) {
return [rst];
}
return [];
}
// 分割贝塞尔曲线
function divideQuadratic(x1, y1, x2, y2, x3, y3, t) {
// 划分点
var xt = quadraticAt(x1, x2, x3, t);
var yt = quadraticAt(y1, y2, y3, t);
// 分割的第一条曲线的控制点
var controlPoint1 = pointAt$3(x1, y1, x2, y2, t);
// 分割的第二条曲线的控制点
var controlPoint2 = pointAt$3(x2, y2, x3, y3, t);
return [
[x1, y1, controlPoint1.x, controlPoint1.y, xt, yt],
[xt, yt, controlPoint2.x, controlPoint2.y, x3, y3],
];
}
// 使用迭代法取贝塞尔曲线的长度
function quadraticLength(x1, y1, x2, y2, x3, y3, iterationCount) {
if (iterationCount === 0) {
return ((distance(x1, y1, x2, y2) +
distance(x2, y2, x3, y3) +
distance(x1, y1, x3, y3)) /
2);
}
var quadratics = divideQuadratic(x1, y1, x2, y2, x3, y3, 0.5);
var left = quadratics[0];
var right = quadratics[1];
left.push(iterationCount - 1);
right.push(iterationCount - 1);
return quadraticLength.apply(void 0, tslib.__spreadArray([], tslib.__read(left), false)) + quadraticLength.apply(void 0, tslib.__spreadArray([], tslib.__read(right), false));
}
function box(x1, y1, x2, y2, x3, y3) {
var xExtrema = extrema(x1, x2, x3)[0];
var yExtrema = extrema(y1, y2, y3)[0];
// 控制点不加入 box 的计算
var xArr = [x1, x3];
var yArr = [y1, y3];
if (xExtrema !== undefined) {
xArr.push(quadraticAt(x1, x2, x3, xExtrema));
}
if (yExtrema !== undefined) {
yArr.push(quadraticAt(y1, y2, y3, yExtrema));
}
return getBBoxByArray(xArr, yArr);
}
function length(x1, y1, x2, y2, x3, y3) {
return quadraticLength(x1, y1, x2, y2, x3, y3, 3);
}
function nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0) {
return nearestPoint$2([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
}
function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
var point = this.nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
return distance(point.x, point.y, x0, y0);
}
exports.arcBox = box$5;
exports.arcNearestPoint = nearestPoint$3;
exports.arcTangentAngle = tangentAngle$4;
exports.cubicBox = box$3;
exports.cubicLength = length$3;
exports.cubicNearestPoint = nearestPoint$1;
exports.cubicPointAt = pointAt$2;
exports.cubicPointDistance = pointDistance$3;
exports.cubicTangentAngle = tangentAngle$2;
exports.distance = distance;
exports.lineBox = box$4;
exports.lineLength = length$4;
exports.linePointAt = pointAt$3;
exports.linePointDistance = pointDistance$4;
exports.linePointToLine = pointToLine;
exports.lineTangentAngle = tangentAngle$3;
exports.polygonBox = box$1;
exports.polygonLength = length$1;
exports.polygonPointAt = pointAt;
exports.polygonPointDistance = pointDistance$1;
exports.polygonTangentAngle = tangentAngle;
exports.polylineBox = box$2;
exports.polylineLength = length$2;
exports.polylinePointAt = pointAt$1;
exports.polylinePointDistance = pointDistance$2;
exports.polylineTangentAngle = tangentAngle$1;
exports.quadBox = box;
exports.quadLength = length;
exports.quadNearestPoint = nearestPoint;
exports.quadPointDistance = pointDistance;
//# sourceMappingURL=index.js.map

@@ -1,1 +0,2 @@

!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(((t="undefined"!=typeof globalThis?globalThis:t||self).G=t.G||{},t.G.Math={}))}(this,(function(t){"use strict";function n(t,n,r,a){var o=t-r,e=n-a;return Math.sqrt(o*o+e*e)}function r(t,n){return.001>Math.abs(t-n)}function a(t,n){var r=Math.min.apply(Math,t),a=Math.min.apply(Math,n);return{x:r,y:a,width:Math.max.apply(Math,t)-r,height:Math.max.apply(Math,n)-a}}function o(t){return(t+2*Math.PI)%(2*Math.PI)}var e=Object.freeze({__proto__:null,distance:n,isNumberEqual:r,getBBoxByArray:a,getBBoxRange:function(t,n,r,a){return{minX:Math.min(t,r),maxX:Math.max(t,r),minY:Math.min(n,a),maxY:Math.max(n,a)}},piMod:o}),i="undefined"!=typeof Float32Array?Float32Array:Array;Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});u=new i(2),i!=Float32Array&&(u[0]=0,u[1]=0),h=u;var u,h,f={box:function(t,n,r,o){return a([t,r],[n,o])},length:function(t,r,a,o){return n(t,r,a,o)},pointAt:function(t,n,r,a,o){return{x:(1-o)*t+o*r,y:(1-o)*n+o*a}},pointDistance:function(t,r,a,o,e,i){var u=(a-t)*(e-t)+(o-r)*(i-r);return 0>u?n(t,r,e,i):u>(a-t)*(a-t)+(o-r)*(o-r)?n(a,o,e,i):this.pointToLine(t,r,a,o,e,i)},pointToLine:function(t,n,r,a,o,e){var i=[r-t,a-n];if(function(t,n){return t[0]===n[0]&&t[1]===n[1]}(i,[0,0]))return Math.sqrt((o-t)*(o-t)+(e-n)*(e-n));var u=[-i[1],i[0]];return function(t,n){var r=n[0],a=n[1],o=r*r+a*a;o>0&&(o=1/Math.sqrt(o)),t[0]=n[0]*o,t[1]=n[1]*o}(u,u),Math.abs(function(t,n){return t[0]*n[0]+t[1]*n[1]}([o-t,e-n],u))},tangentAngle:function(t,n,r,a){return Math.atan2(a-n,r-t)}};function c(t,r,a,o,e,i){var u=-1,h=1/0,f=[a,o],c=20;i&&i>200&&(c=i/10);for(var p=1/c,s=p/10,v=0;c>=v;v++){var M=v*p,l=[e.apply(void 0,t.concat([M])),e.apply(void 0,r.concat([M]))],y=n(f[0],f[1],l[0],l[1]);h>y&&(u=M,h=y)}if(0===u)return{x:t[0],y:r[0]};if(1===u){var g=t.length;return{x:t[g-1],y:r[g-1]}}h=1/0;for(var x=0;32>x&&1e-4<=s;x++){var d=u-s,A=u+s,m=[e.apply(void 0,t.concat([d])),e.apply(void 0,r.concat([d]))],b=n(f[0],f[1],m[0],m[1]);if(d>=0&&h>b)u=d,h=b;else{var P=[e.apply(void 0,t.concat([A])),e.apply(void 0,r.concat([A]))],I=n(f[0],f[1],P[0],P[1]);1>=A&&h>I?(u=A,h=I):s*=.5}}return{x:e.apply(void 0,t.concat([u])),y:e.apply(void 0,r.concat([u]))}}function p(t,n,r,a){var o=1-a;return o*o*t+2*a*o*n+a*a*r}function s(t,n,a){var o=t+a-2*n;if(r(o,0))return[.5];var e=(t-n)/o;return e>1||0>e?[]:[e]}function v(t,n,r,a){return 2*(1-a)*(n-t)+2*a*(r-n)}function M(t,n,r,a,o,e,i){var u=p(t,r,o,i),h=p(n,a,e,i),c=f.pointAt(t,n,r,a,i),s=f.pointAt(r,a,o,e,i);return[[t,n,c.x,c.y,u,h],[u,h,s.x,s.y,o,e]]}function l(t,r,a,o,e,i,u){if(0===u)return(n(t,r,a,o)+n(a,o,e,i)+n(t,r,e,i))/2;var h=M(t,r,a,o,e,i,.5),f=h[0],c=h[1];return f.push(u-1),c.push(u-1),l.apply(void 0,f)+l.apply(void 0,c)}var y={box:function(t,n,r,o,e,i){var u=s(t,r,e)[0],h=s(n,o,i)[0],f=[t,e],c=[n,i];return void 0!==u&&f.push(p(t,r,e,u)),void 0!==h&&c.push(p(n,o,i,h)),a(f,c)},length:function(t,n,r,a,o,e){return l(t,n,r,a,o,e,3)},nearestPoint:function(t,n,r,a,o,e,i,u){return c([t,r,o],[n,a,e],i,u,p)},pointDistance:function(t,r,a,o,e,i,u,h){var f=this.nearestPoint(t,r,a,o,e,i,u,h);return n(f.x,f.y,u,h)},interpolationAt:p,pointAt:function(t,n,r,a,o,e,i){return{x:p(t,r,o,i),y:p(n,a,e,i)}},divide:function(t,n,r,a,o,e,i){return M(t,n,r,a,o,e,i)},tangentAngle:function(t,n,r,a,e,i,u){var h=v(t,r,e,u),f=v(n,a,i,u);return o(Math.atan2(f,h))}};function g(t,n,r,a,o){var e=1-o;return e*e*e*t+3*n*o*e*e+3*r*o*o*e+a*o*o*o}function x(t,n,r,a,o){var e=1-o;return 3*(e*e*(n-t)+2*e*o*(r-n)+o*o*(a-r))}function d(t,n,a,o){var e,i,u,h=-3*t+9*n-9*a+3*o,f=6*t-12*n+6*a,c=3*n-3*t,p=[];if(r(h,0))r(f,0)||0>(e=-c/f)||e>1||p.push(e);else{var s=f*f-4*h*c;r(s,0)?p.push(-f/(2*h)):s>0&&(i=(-f-(u=Math.sqrt(s)))/(2*h),0>(e=(-f+u)/(2*h))||e>1||p.push(e),0>i||i>1||p.push(i))}return p}function A(t,n,r,a,o,e,i,u,h){var c=g(t,r,o,i,h),p=g(n,a,e,u,h),s=f.pointAt(t,n,r,a,h),v=f.pointAt(r,a,o,e,h),M=f.pointAt(o,e,i,u,h),l=f.pointAt(s.x,s.y,v.x,v.y,h),y=f.pointAt(v.x,v.y,M.x,M.y,h);return[[t,n,s.x,s.y,l.x,l.y,c,p],[c,p,y.x,y.y,M.x,M.y,i,u]]}function m(t,r,a,o,e,i,u,h,f){if(0===f)return function(t,r){for(var a=0,o=t.length,e=0;o>e;e++)a+=n(t[e],r[e],t[(e+1)%o],r[(e+1)%o]);return a/2}([t,a,e,u],[r,o,i,h]);var c=A(t,r,a,o,e,i,u,h,.5),p=[].concat(c[0],[f-1]),s=[].concat(c[1],[f-1]);return m.apply(void 0,p)+m.apply(void 0,s)}var b={extrema:d,box:function(t,n,r,o,e,i,u,h){for(var f=[t,u],c=[n,h],p=d(t,r,e,u),s=d(n,o,i,h),v=0;p.length>v;v++)f.push(g(t,r,e,u,p[v]));for(var M=0;s.length>M;M++)c.push(g(n,o,i,h,s[M]));return a(f,c)},length:function(t,n,r,a,o,e,i,u){return m(t,n,r,a,o,e,i,u,3)},nearestPoint:function(t,n,r,a,o,e,i,u,h,f,p){return c([t,r,o,i],[n,a,e,u],h,f,g,p)},pointDistance:function(t,r,a,o,e,i,u,h,f,c,p){var s=this.nearestPoint(t,r,a,o,e,i,u,h,f,c,p);return n(s.x,s.y,f,c)},interpolationAt:g,pointAt:function(t,n,r,a,o,e,i,u,h){return{x:g(t,r,o,i,h),y:g(n,a,e,u,h)}},divide:function(t,n,r,a,o,e,i,u,h){return A(t,n,r,a,o,e,i,u,h)},tangentAngle:function(t,n,r,a,e,i,u,h,f){var c=x(t,r,e,u,f),p=x(n,a,i,h,f);return o(Math.atan2(p,c))}};function P(t,n){var r=Math.abs(t);return n>0?r:-1*r}var I=function(t,n,r,a,o,e){var i=r,u=a;if(0===i||0===u)return{x:t,y:n};for(var h=o-t,f=e-n,c=Math.abs(h),p=Math.abs(f),s=i*i,v=u*u,M=Math.PI/4,l=0,y=0,g=0;4>g;g++){l=i*Math.cos(M),y=u*Math.sin(M);var x=(s-v)*Math.pow(Math.cos(M),3)/i,d=(v-s)*Math.pow(Math.sin(M),3)/u,A=l-x,m=y-d,b=c-x,I=p-d,q=Math.hypot(m,A),D=Math.hypot(I,b);M=Math.min(Math.PI/2,Math.max(0,M+=q*Math.asin((A*I-m*b)/(q*D))/Math.sqrt(s+v-l*l-y*y)))}return{x:t+P(l,h),y:n+P(y,f)}};function q(t,n,r,a,o,e){return r*Math.cos(o)*Math.cos(e)-a*Math.sin(o)*Math.sin(e)+t}function D(t,n,r,a,o,e){return r*Math.sin(o)*Math.cos(e)+a*Math.cos(o)*Math.sin(e)+n}function L(t,n,r){return{x:t*Math.cos(r),y:n*Math.sin(r)}}function _(t,n,r){var a=Math.cos(r),o=Math.sin(r);return[t*a-n*o,t*o+n*a]}var w={box:function(t,n,r,a,o,e,i){for(var u=function(t,n,r){return Math.atan(-n/t*Math.tan(r))}(r,a,o),h=1/0,f=-1/0,c=[e,i],p=2*-Math.PI;2*Math.PI>=p;p+=Math.PI){var s=u+p;i>e?s>e&&i>s&&c.push(s):s>i&&e>s&&c.push(s)}for(var v=0;c.length>v;v++){var M=q(t,0,r,a,o,c[v]);h>M&&(h=M),M>f&&(f=M)}for(var l=function(t,n,r){return Math.atan(n/(t*Math.tan(r)))}(r,a,o),y=1/0,g=-1/0,x=[e,i],d=2*-Math.PI;2*Math.PI>=d;d+=Math.PI){var A=l+d;i>e?A>e&&i>A&&x.push(A):A>i&&e>A&&x.push(A)}for(var m=0;x.length>m;m++){var b=D(0,n,r,a,o,x[m]);y>b&&(y=b),b>g&&(g=b)}return{x:h,y:y,width:f-h,height:g-y}},length:function(t,n,r,a,o,e,i){},nearestPoint:function(t,n,r,a,o,e,i,u,h){var f=_(u-t,h-n,-o),c=I(0,0,r,a,f[0],f[1]),p=function(t,n,r,a){return(Math.atan2(a*t,r*n)+2*Math.PI)%(2*Math.PI)}(r,a,c.x,c.y);e>p?c=L(r,a,e):p>i&&(c=L(r,a,i));var s=_(c.x,c.y,o);return{x:s[0]+t,y:s[1]+n}},pointDistance:function(t,r,a,o,e,i,u,h,f){var c=this.nearestPoint(t,r,a,o,e,i,u,h,f);return n(c.x,c.y,h,f)},pointAt:function(t,n,r,a,o,e,i,u){var h=(i-e)*u+e;return{x:q(t,0,r,a,o,h),y:D(0,n,r,a,o,h)}},tangentAngle:function(t,n,r,a,e,i,u,h){var f=(u-i)*h+i,c=function(t,n,r,a,o,e,i,u){return-1*r*Math.cos(o)*Math.sin(u)-a*Math.sin(o)*Math.cos(u)}(0,0,r,a,e,0,0,f),p=function(t,n,r,a,o,e,i,u){return-1*r*Math.sin(o)*Math.sin(u)+a*Math.cos(o)*Math.cos(u)}(0,0,r,a,e,0,0,f);return o(Math.atan2(p,c))}};function B(t){for(var r=0,a=[],o=0;t.length-1>o;o++){var e=t[o],i=t[o+1],u=n(e[0],e[1],i[0],i[1]);a.push({from:e,to:i,length:u}),r+=u}return{segments:a,totalLength:r}}function T(t){if(2>t.length)return 0;for(var r=0,a=0;t.length-1>a;a++){var o=t[a],e=t[a+1];r+=n(o[0],o[1],e[0],e[1])}return r}function j(t,n){if(n>1||0>n||2>t.length)return null;var r=B(t),a=r.segments,o=r.totalLength;if(0===o)return{x:t[0][0],y:t[0][1]};for(var e=0,i=null,u=0;a.length>u;u++){var h=a[u],c=h.from,p=h.to,s=h.length/o;if(n>=e&&e+s>=n){i=f.pointAt(c[0],c[1],p[0],p[1],(n-e)/s);break}e+=s}return i}function F(t,n){if(n>1||0>n||2>t.length)return 0;for(var r=B(t),a=r.segments,o=r.totalLength,e=0,i=0,u=0;a.length>u;u++){var h=a[u],f=h.from,c=h.to,p=h.length/o;if(n>=e&&e+p>=n){i=Math.atan2(c[1]-f[1],c[0]-f[0]);break}e+=p}return i}function G(t,n,r){for(var a=1/0,o=0;t.length-1>o;o++){var e=t[o],i=t[o+1],u=f.pointDistance(e[0],e[1],i[0],i[1],n,r);a>u&&(a=u)}return a}var k={box:function(t){for(var n=[],r=[],o=0;t.length>o;o++){var e=t[o];n.push(e[0]),r.push(e[1])}return a(n,r)},length:function(t){return T(t)},pointAt:function(t,n){return j(t,n)},pointDistance:function(t,n,r){return G(t,n,r)},tangentAngle:function(t,n){return F(t,n)}};function O(t){var n=t.slice(0);return t.length&&n.push(t[0]),n}var X={box:function(t){return k.box(t)},length:function(t){return T(O(t))},pointAt:function(t,n){return j(O(t),n)},pointDistance:function(t,n,r){return G(O(t),n,r)},tangentAngle:function(t,n){return F(O(t),n)}};t.Arc=w,t.Cubic=b,t.Line=f,t.Polygon=X,t.Polyline=k,t.Quad=y,t.Util=e,Object.defineProperty(t,"__esModule",{value:!0})}));
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(((t="undefined"!=typeof globalThis?globalThis:t||self).G=t.G||{},t.G.Math={}))}(this,(function(t){"use strict";function n(t,n){var r="function"==typeof Symbol&&t[Symbol.iterator];if(!r)return t;var a,o,e=r.call(t),u=[];try{for(;(void 0===n||n-- >0)&&!(a=e.next()).done;)u.push(a.value)}catch(t){o={error:t}}finally{try{a&&!a.done&&(r=e.return)&&r.call(e)}finally{if(o)throw o.error}}return u}function r(t,n,r){if(r||2===arguments.length)for(var a,o=0,e=n.length;e>o;o++)!a&&o in n||(a||(a=Array.prototype.slice.call(n,0,o)),a[o]=n[o]);return t.concat(a||Array.prototype.slice.call(n))}function a(t,n,r,a){var o=t-r,e=n-a;return Math.sqrt(o*o+e*e)}function o(t,n){return.001>Math.abs(t-n)}function e(t,a){var o=Math.min.apply(Math,r([],n(t),!1)),e=Math.min.apply(Math,r([],n(a),!1));return{x:o,y:e,width:Math.max.apply(Math,r([],n(t),!1))-o,height:Math.max.apply(Math,r([],n(a),!1))-e}}function u(t){return(t+2*Math.PI)%(2*Math.PI)}function i(t,n){var r=Math.abs(t);return n>0?r:-1*r}function h(t,n,r,a,o,e){return r*Math.cos(o)*Math.cos(e)-a*Math.sin(o)*Math.sin(e)+t}function c(t,n,r,a,o,e){return r*Math.sin(o)*Math.cos(e)+a*Math.cos(o)*Math.sin(e)+n}function f(t,n,r){return{x:t*Math.cos(r),y:n*Math.sin(r)}}function l(t,n,r){var a=Math.cos(r),o=Math.sin(r);return[t*a-n*o,t*o+n*a]}var s=1e-4;function p(t,o,e,u,i,h){var c=-1,f=1/0,l=[e,u],p=20;h&&h>200&&(p=h/10);for(var v=1/p,y=v/10,M=0;p>=M;M++){var g=M*v,x=[i.apply(void 0,r([],n(t.concat([g])),!1)),i.apply(void 0,r([],n(o.concat([g])),!1))];f>(m=a(l[0],l[1],x[0],x[1]))&&(c=g,f=m)}if(0===c)return{x:t[0],y:o[0]};if(1===c){var d=t.length;return{x:t[d-1],y:o[d-1]}}f=1/0;for(M=0;32>M&&s<=y;M++){var P=c-y,b=c+y,m=(x=[i.apply(void 0,r([],n(t.concat([P])),!1)),i.apply(void 0,r([],n(o.concat([P])),!1))],a(l[0],l[1],x[0],x[1]));if(P>=0&&f>m)c=P,f=m;else{var A=[i.apply(void 0,r([],n(t.concat([b])),!1)),i.apply(void 0,r([],n(o.concat([b])),!1))],I=a(l[0],l[1],A[0],A[1]);1>=b&&f>I?(c=b,f=I):y*=.5}}return{x:i.apply(void 0,r([],n(t.concat([c])),!1)),y:i.apply(void 0,r([],n(o.concat([c])),!1))}}var v,y="undefined"!=typeof Float32Array?Float32Array:Array;function M(t,n,r,a,o){return{x:(1-o)*t+o*r,y:(1-o)*n+o*a}}function g(t,n,r,o,e,u){var i=(r-t)*(e-t)+(o-n)*(u-n);return 0>i?a(t,n,e,u):i>(r-t)*(r-t)+(o-n)*(o-n)?a(r,o,e,u):this.pointToLine(t,n,r,o,e,u)}function x(t,n,r,a,o){var e=1-o;return e*e*e*t+3*n*o*e*e+3*r*o*o*e+a*o*o*o}function d(t,n,r,a,o){var e=1-o;return 3*(e*e*(n-t)+2*e*o*(r-n)+o*o*(a-r))}function P(t,n,r,a){var e,u,i,h=-3*t+9*n-9*r+3*a,c=6*t-12*n+6*r,f=3*n-3*t,l=[];if(o(h,0))o(c,0)||0>(e=-f/c)||e>1||l.push(e);else{var s=c*c-4*h*f;o(s,0)?l.push(-c/(2*h)):s>0&&(u=(-c-(i=Math.sqrt(s)))/(2*h),0>(e=(-c+i)/(2*h))||e>1||l.push(e),0>u||u>1||l.push(u))}return l}function b(t,o,e,u,i,h,c,f,l){if(0===l)return function(t,n){for(var r=0,o=t.length,e=0;o>e;e++)r+=a(t[e],n[e],t[(e+1)%o],n[(e+1)%o]);return r/2}([t,e,i,c],[o,u,h,f]);var s=function(t,n,r,a,o,e,u,i,h){var c=x(t,r,o,u,h),f=x(n,a,e,i,h),l=M(t,n,r,a,h),s=M(r,a,o,e,h),p=M(o,e,u,i,h),v=M(l.x,l.y,s.x,s.y,h),y=M(s.x,s.y,p.x,p.y,h);return[[t,n,l.x,l.y,v.x,v.y,c,f],[c,f,y.x,y.y,p.x,p.y,u,i]]}(t,o,e,u,i,h,c,f,.5),p=r(r([],n(s[0]),!1),[l-1],!1),v=r(r([],n(s[1]),!1),[l-1],!1);return b.apply(void 0,r([],n(p),!1))+b.apply(void 0,r([],n(v),!1))}function m(t){for(var n=0,r=[],o=0;t.length-1>o;o++){var e=t[o],u=t[o+1],i=a(e[0],e[1],u[0],u[1]);r.push({from:e,to:u,length:i}),n+=i}return{segments:r,totalLength:n}}function A(t){if(2>t.length)return 0;for(var n=0,r=0;t.length-1>r;r++){var o=t[r],e=t[r+1];n+=a(o[0],o[1],e[0],e[1])}return n}function I(t,n){if(n>1||0>n||2>t.length)return null;var r=m(t),a=r.segments,o=r.totalLength;if(0===o)return{x:t[0][0],y:t[0][1]};for(var e=0,u=null,i=0;a.length>i;i++){var h=a[i],c=h.from,f=h.to,l=h.length/o;if(n>=e&&e+l>=n){u=M(c[0],c[1],f[0],f[1],(n-e)/l);break}e+=l}return u}function q(t,n){if(n>1||0>n||2>t.length)return 0;for(var r=m(t),a=r.segments,o=r.totalLength,e=0,u=0,i=0;a.length>i;i++){var h=a[i],c=h.from,f=h.to,l=h.length/o;if(n>=e&&e+l>=n){u=Math.atan2(f[1]-c[1],f[0]-c[0]);break}e+=l}return u}function L(t,n,r){for(var a=1/0,o=0;t.length-1>o;o++){var e=t[o],u=t[o+1],i=g(e[0],e[1],u[0],u[1],n,r);a>i&&(a=i)}return a}function T(t){for(var n=[],r=[],a=0;t.length>a;a++){var o=t[a];n.push(o[0]),r.push(o[1])}return e(n,r)}function w(t){var n=t.slice(0);return t.length&&n.push(t[0]),n}function B(t,n,r,a){var o=1-a;return o*o*t+2*a*o*n+a*a*r}function D(t,n,r){var a=t+r-2*n;if(o(a,0))return[.5];var e=(t-n)/a;return e>1||0>e?[]:[e]}function F(t,o,e,u,i,h,c){if(0===c)return(a(t,o,e,u)+a(e,u,i,h)+a(t,o,i,h))/2;var f=function(t,n,r,a,o,e,u){var i=B(t,r,o,u),h=B(n,a,e,u),c=M(t,n,r,a,u),f=M(r,a,o,e,u);return[[t,n,c.x,c.y,i,h],[i,h,f.x,f.y,o,e]]}(t,o,e,u,i,h,.5),l=f[0],s=f[1];return l.push(c-1),s.push(c-1),F.apply(void 0,r([],n(l),!1))+F.apply(void 0,r([],n(s),!1))}Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)}),v=new y(2),y!=Float32Array&&(v[0]=0,v[1]=0),t.arcBox=function(t,n,r,a,o,e,u){for(var i=function(t,n,r){return Math.atan(-n/t*Math.tan(r))}(r,a,o),f=1/0,l=-1/0,s=[e,u],p=2*-Math.PI;2*Math.PI>=p;p+=Math.PI){var v=i+p;u>e?v>e&&u>v&&s.push(v):v>u&&e>v&&s.push(v)}for(p=0;s.length>p;p++){var y=h(t,0,r,a,o,s[p]);f>y&&(f=y),y>l&&(l=y)}var M=function(t,n,r){return Math.atan(n/(t*Math.tan(r)))}(r,a,o),g=1/0,x=-1/0,d=[e,u];for(p=2*-Math.PI;2*Math.PI>=p;p+=Math.PI){var P=M+p;u>e?P>e&&u>P&&d.push(P):P>u&&e>P&&d.push(P)}for(p=0;d.length>p;p++){var b=c(0,n,r,a,o,d[p]);g>b&&(g=b),b>x&&(x=b)}return{x:f,y:g,width:l-f,height:x-g}},t.arcNearestPoint=function(t,r,a,o,e,u,h,c,s){var p=n(l(c-t,s-r,-e),2),v=function(t,n,r,a,o,e){var u=r,h=a;if(0===u||0===h)return{x:t,y:n};for(var c=o-t,f=e-n,l=Math.abs(c),s=Math.abs(f),p=u*u,v=h*h,y=Math.PI/4,M=0,g=0,x=0;4>x;x++){M=u*Math.cos(y),g=h*Math.sin(y);var d=(p-v)*Math.pow(Math.cos(y),3)/u,P=(v-p)*Math.pow(Math.sin(y),3)/h,b=M-d,m=g-P,A=l-d,I=s-P,q=Math.hypot(m,b),L=Math.hypot(I,A);y=Math.min(Math.PI/2,Math.max(0,y+=q*Math.asin((b*I-m*A)/(q*L))/Math.sqrt(p+v-M*M-g*g)))}return{x:t+i(M,c),y:n+i(g,f)}}(0,0,a,o,p[0],p[1]),y=function(t,n,r,a){return(Math.atan2(a*t,r*n)+2*Math.PI)%(2*Math.PI)}(a,o,v.x,v.y);u>y?v=f(a,o,u):y>h&&(v=f(a,o,h));var M=l(v.x,v.y,e);return{x:M[0]+t,y:M[1]+r}},t.arcTangentAngle=function(t,n,r,a,o,e,i,h){var c=(i-e)*h+e,f=function(t,n,r,a,o,e,u,i){return-1*r*Math.cos(o)*Math.sin(i)-a*Math.sin(o)*Math.cos(i)}(0,0,r,a,o,0,0,c),l=function(t,n,r,a,o,e,u,i){return-1*r*Math.sin(o)*Math.sin(i)+a*Math.cos(o)*Math.cos(i)}(0,0,r,a,o,0,0,c);return u(Math.atan2(l,f))},t.cubicBox=function(t,n,r,a,o,u,i,h){for(var c=[t,i],f=[n,h],l=P(t,r,o,i),s=P(n,a,u,h),p=0;l.length>p;p++)c.push(x(t,r,o,i,l[p]));for(p=0;s.length>p;p++)f.push(x(n,a,u,h,s[p]));return e(c,f)},t.cubicLength=function(t,n,r,a,o,e,u,i){return b(t,n,r,a,o,e,u,i,3)},t.cubicNearestPoint=function(t,n,r,a,o,e,u,i,h,c,f){return p([t,r,o,u],[n,a,e,i],h,c,x,f)},t.cubicPointAt=function(t,n,r,a,o,e,u,i,h){return{x:x(t,r,o,u,h),y:x(n,a,e,i,h)}},t.cubicPointDistance=function(t,n,r,o,e,u,i,h,c,f,l){var s=this.nearestPoint(t,n,r,o,e,u,i,h,c,f,l);return a(s.x,s.y,c,f)},t.cubicTangentAngle=function(t,n,r,a,o,e,i,h,c){var f=d(t,r,o,i,c),l=d(n,a,e,h,c);return u(Math.atan2(l,f))},t.distance=a,t.lineBox=function(t,n,r,a){return e([t,r],[n,a])},t.lineLength=function(t,n,r,o){return a(t,n,r,o)},t.linePointAt=M,t.linePointDistance=g,t.linePointToLine=function(t,n,r,a,o,e){var u=[r-t,a-n];if(function(t,n){return t[0]===n[0]&&t[1]===n[1]}(u,[0,0]))return Math.sqrt((o-t)*(o-t)+(e-n)*(e-n));var i=[-u[1],u[0]];return function(t,n){var r=n[0],a=n[1],o=r*r+a*a;o>0&&(o=1/Math.sqrt(o)),t[0]=n[0]*o,t[1]=n[1]*o}(i,i),Math.abs(function(t,n){return t[0]*n[0]+t[1]*n[1]}([o-t,e-n],i))},t.lineTangentAngle=function(t,n,r,a){return Math.atan2(a-n,r-t)},t.polygonBox=function(t){return T(t)},t.polygonLength=function(t){return A(w(t))},t.polygonPointAt=function(t,n){return I(w(t),n)},t.polygonPointDistance=function(t,n,r){return L(w(t),n,r)},t.polygonTangentAngle=function(t,n){return q(w(t),n)},t.polylineBox=T,t.polylineLength=function(t){return A(t)},t.polylinePointAt=function(t,n){return I(t,n)},t.polylinePointDistance=function(t,n,r){return L(t,n,r)},t.polylineTangentAngle=function(t,n){return q(t,n)},t.quadBox=function(t,n,r,a,o,u){var i=D(t,r,o)[0],h=D(n,a,u)[0],c=[t,o],f=[n,u];return void 0!==i&&c.push(B(t,r,o,i)),void 0!==h&&f.push(B(n,a,u,h)),e(c,f)},t.quadLength=function(t,n,r,a,o,e){return F(t,n,r,a,o,e,3)},t.quadNearestPoint=function(t,n,r,a,o,e,u,i){return p([t,r,o],[n,a,e],u,i,B)},t.quadPointDistance=function(t,n,r,o,e,u,i,h){var c=this.nearestPoint(t,n,r,o,e,u,i,h);return a(c.x,c.y,i,h)}}));
//# sourceMappingURL=index.umd.min.js.map
import type { BBox, Point } from './types';
declare const _default: {
/**
* 计算线段的包围盒
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {object} 包围盒对象
*/
box(x1: number, y1: number, x2: number, y2: number): BBox;
/**
* 线段的长度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
length(x1: number, y1: number, x2: number, y2: number): number;
/**
* 根据比例获取点
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} t 指定比例
* @return {object} 包含 x, y 的点
*/
pointAt(x1: number, y1: number, x2: number, y2: number, t: number): Point;
/**
* 点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointDistance(x1: number, y1: number, x2: number, y2: number, x: number, y: number): number;
/**
* 点到直线的距离,而不是点到线段的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @param {number} x 测试点 x
* @param {number} y 测试点 y
* @return {number} 距离
*/
pointToLine(x1: number, y1: number, x2: number, y2: number, x: number, y: number): number;
/**
* 线段的角度
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 导数
*/
tangentAngle(x1: number, y1: number, x2: number, y2: number): number;
};
export default _default;
//# sourceMappingURL=line.d.ts.map
export declare function box(x1: number, y1: number, x2: number, y2: number): BBox;
export declare function length(x1: number, y1: number, x2: number, y2: number): number;
export declare function pointAt(x1: number, y1: number, x2: number, y2: number, t: number): Point;
export declare function pointDistance(x1: number, y1: number, x2: number, y2: number, x: number, y: number): number;
export declare function pointToLine(x1: number, y1: number, x2: number, y2: number, x: number, y: number): number;
export declare function tangentAngle(x1: number, y1: number, x2: number, y2: number): number;
import type { PointTuple } from './types';
declare const _default: {
/**
* 计算多边形的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box(points: PointTuple[]): import("./types").BBox;
/**
* 计算多边形的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多边形边的长度
*/
length(points: PointTuple[]): number;
/**
* 根据比例获取多边形的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt(points: PointTuple[], t: number): import("./types").Point;
/**
* 指定点到多边形的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多边形的距离
*/
pointDistance(points: PointTuple[], x: number, y: number): number;
/**
* 根据比例获取多边形的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多边形的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle(points: PointTuple[], t: number): number;
};
export default _default;
//# sourceMappingURL=polygon.d.ts.map
export declare function box(points: PointTuple[]): import("./types").BBox;
export declare function length(points: PointTuple[]): number;
export declare function pointAt(points: PointTuple[], t: number): import("./types").Point;
export declare function pointDistance(points: PointTuple[], x: number, y: number): number;
export declare function tangentAngle(points: PointTuple[], t: number): number;

@@ -1,39 +0,6 @@

import type { PointTuple, BBox } from './types';
declare const _default: {
/**
* 计算多折线的包围盒
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 包围盒
*/
box(points: PointTuple[]): BBox;
/**
* 计算多折线的长度
* @param {array} points 点的集合 [x,y] 的形式
* @return {object} 多条边的长度
*/
length(points: PointTuple[]): number;
/**
* 根据比例获取多折线的点
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的点
*/
pointAt(points: PointTuple[], t: number): import("./types").Point;
/**
* 指定点到多折线的距离
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} x 指定点的 x
* @param {number} y 指定点的 y
* @return {number} 点到多折线的距离
*/
pointDistance(points: PointTuple[], x: number, y: number): number;
/**
* 根据比例获取多折线的切线角度
* @param {array} points 点的集合 [x,y] 的形式
* @param {number} t 在多折线的长度上的比例
* @return {object} 根据比例值计算出来的角度
*/
tangentAngle(points: PointTuple[], t: number): number;
};
export default _default;
//# sourceMappingURL=polyline.d.ts.map
import type { BBox, PointTuple } from './types';
export declare function box(points: PointTuple[]): BBox;
export declare function length(points: PointTuple[]): number;
export declare function pointAt(points: PointTuple[], t: number): import("./types").Point;
export declare function pointDistance(points: PointTuple[], x: number, y: number): number;
export declare function tangentAngle(points: PointTuple[], t: number): number;
import type { Point } from './types';
declare function quadraticAt(p0: number, p1: number, p2: number, t: number): number;
declare const _default: {
box(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): import("./types").BBox;
length(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): number;
nearestPoint(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x0: number, y0: number): Point;
pointDistance(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x0: number, y0: number): number;
interpolationAt: typeof quadraticAt;
pointAt(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): Point;
divide(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): number[][];
tangentAngle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): number;
};
export default _default;
//# sourceMappingURL=quadratic.d.ts.map
export declare function box(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): import("./types").BBox;
export declare function length(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): number;
export declare function nearestPoint(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x0: number, y0: number): Point;
export declare function pointDistance(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x0: number, y0: number): number;
export declare function pointAt(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): Point;
export declare function divide(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): number[][];
export declare function tangentAngle(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): number;

@@ -17,2 +17,1 @@ import type { Point, PointTuple } from './types';

export declare function distanceAtSegment(points: PointTuple[], x: number, y: number): number;
//# sourceMappingURL=segments.d.ts.map

@@ -29,2 +29,1 @@ /**

};
//# sourceMappingURL=types.d.ts.map
import type { BBox } from './types';
/**
* 两点之间的距离
* @param {number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 结束点 x
* @param {number} y2 结束点 y
* @return {number} 距离
*/
export declare function distance(x1: number, y1: number, x2: number, y2: number): number;

@@ -20,2 +12,1 @@ export declare function isNumberEqual(v1: number, v2: number): boolean;

export declare function piMod(angle: number): number;
//# sourceMappingURL=util.d.ts.map
{
"name": "@antv/g-math",
"version": "1.7.49",
"version": "1.8.0-alpha.1",
"description": "Geometry util",

@@ -19,2 +19,7 @@ "keywords": [

"author": "https://github.com/orgs/antvis/people",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/index.esm.js",
"default": "./dist/index.js"
},
"main": "dist/index.js",

@@ -30,16 +35,15 @@ "unpkg": "dist/index.umd.min.js",

],
"scripts": {
"sync": "tnpm sync"
},
"dependencies": {
"gl-matrix": "^3.1.0",
"tslib": "^2.3.1"
"tslib": "^2.5.3"
},
"devDependencies": {
"@types/jest": "^25.0.0"
},
"publishConfig": {
"access": "public"
},
"gitHead": "53932c66ed9f2cbc28993e1e359c8df27703fc52"
}
"scripts": {
"build": "npm run clean && rollup -c",
"clean": "rimraf dist",
"sync": "tnpm sync",
"watch": "rollup -c -w"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc