import { distance, getBBoxByArray } from './util'; import * as vec2 from 'gl-matrix/vec2'; import { BBox, Point } from './types'; export 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 { 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(x1: number, y1: number, x2: number, y2: number) { 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(x1: number, y1: number, x2: number, y2: number, t: number): Point { return { x: (1 - t) * x1 + t * x2, y: (1 - t) * y1 + t * y2, }; }, /** * 点到线段的距离 * @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 { // 投影距离 x1, y1 的向量,假设 p, p1, p2 三个点,投影点为 a // p1a = p1p.p1p2/|p1p2| * (p1p 的单位向量) const cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1); if (cross < 0) { return distance(x1, y1, x, y); } const 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(x1: number, y1: number, x2: number, y2: number, x: number, y: number) { const d = [x2 - x1, y2 - y1]; // 如果端点相等,则判定点到点的距离 if (vec2.exactEquals(d, [0, 0])) { return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)); } const u = [-d[1], d[0]]; vec2.normalize(u, u); const 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(x1: number, y1: number, x2: number, y2: number) { return Math.atan2(y2 - y1, x2 - x1); }, };