import { SPoint } from "@persagy-web/draw/lib"; export class generate { /** * 计算角平分线上的距离这两条直线l的点 * * @param p1 第一个点 * @param p2 第二个点 也是2条线的交点 * @param p3 第三个点 * @param l 距离2条线的距离 */ static getBisector(p1: SPoint, p2: SPoint, p3: SPoint, l: number) { const dy1 = p1.y - p2.y; const dx1 = p1.x - p2.x; const dy2 = p3.y - p2.y; const dx2 = p3.x - p2.x; // 线1的斜率 const k1 = dy1 / dx1; // 线2的斜率 const k2 = dy2 / dx2; // 线1与x轴的夹角 const temp1 = Math.atan(k1) const a1 = k1 >= 0 ? temp1 : temp1 + Math.PI; // 线2与x轴的夹角 const temp2 = Math.atan(k2) const a2 = k2 >= 0 ? temp2 : temp2 + Math.PI; // 角平分线斜率 const k = Math.tan((a1 + a2) / 2); // 角平分线b const b = p2.y - k * p2.x; // 距离两条线l的点 到交点p2的距离 const Lb2 = l / Math.sin(Math.abs(a1 - a2) / 2); // 将距离公式与直线方程连立,并且将直线方程代入,得到一元二次方程 Ax^2 + Bx + C = 0;然后根据得根公式得到2个解 const A = k * k + 1; const B = 2 * k * b - 2 * p2.x - 2 * k * p2.y; const C = b * b - Lb2 * Lb2 + p2.x * p2.x + p2.y * p2.y - 2 * b * p2.y; // 求解 const X1 = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A); const X2 = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); const Y1 = k * X1 + b; const Y2 = k * X2 + b; return [Number(X1.toFixed(2)), Number(Y1.toFixed(2)), Number(X2.toFixed(2)), Number(Y2.toFixed(2))] } /** * 计算一条线的垂线上距离线l的2个点 * * @param p1 点1 * @param p2 点2 * @param l 距离这条线的距离 */ static getVertical(p1: SPoint, p2: SPoint, l: number) { const dy1 = p1.y - p2.y; const dx1 = p1.x - p2.x; // 线1的斜率 const k1 = dy1 / dx1; // 垂线的斜率 const k = -1 / k1; // 垂线的b const b = p1.y - k * p1.x; // 将距离公式与直线方程连立,并且将直线方程代入,得到一元二次方程 Ax^2 + Bx + C = 0;然后根据得根公式得到2个解 const A = k * k + 1; const B = 2 * k * b - 2 * p1.x - 2 * k * p1.y; const C = b * b - l * l + p1.x * p1.x + p1.y * p1.y - 2 * b * p1.y; // 求解 const X1 = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A); const X2 = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A); const Y1 = k * X1 + b; const Y2 = k * X2 + b; return [Number(X1.toFixed(2)), Number(Y1.toFixed(2)), Number(X2.toFixed(2)), Number(Y2.toFixed(2))] } /** * 计算线段交点 * * @param line1 线段1 * @param line2 线段2 * @return SPoint 交点 null 平行但不重合 'repeat' 重合 */ static lineIntersection( p1: SPoint, p2: SPoint, p3: SPoint, p4: SPoint ): SPoint | null | string { let k1 = (p2.y - p1.y) / (p2.x - p1.x); let b1 = p2.y - k1 * p2.x; let k2 = (p4.y - p3.y) / (p4.x - p3.x); let b2 = p3.y - k2 * p3.x; if (k1 == k2) { if (b1 == b2) { return "repeat"; } return null; } let intersectionX = (b2 - b1) / (k1 - k2); let intersectionY = k1 * intersectionX + b1; // 取线段上的最大最小值可以上下换 let minX = Math.min(p1.x, p2.x); let maxX = Math.max(p3.x, p4.x); if (intersectionX >= minX && intersectionX <= maxX) { return new SPoint(intersectionX, intersectionY); } return null; } /** * 去除中间多于的点 */ }