generate.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { SPoint } from "@persagy-web/draw/lib";
  2. export class generate {
  3. /**
  4. * 计算角平分线上的距离这两条直线l的点
  5. *
  6. * @param p1 第一个点
  7. * @param p2 第二个点 也是2条线的交点
  8. * @param p3 第三个点
  9. * @param l 距离2条线的距离
  10. */
  11. static getBisector(p1: SPoint, p2: SPoint, p3: SPoint, l: number) {
  12. const dy1 = p1.y - p2.y;
  13. const dx1 = p1.x - p2.x;
  14. const dy2 = p3.y - p2.y;
  15. const dx2 = p3.x - p2.x;
  16. // 线1的斜率
  17. const k1 = dy1 / dx1;
  18. // 线2的斜率
  19. const k2 = dy2 / dx2;
  20. // 线1与x轴的夹角
  21. const temp1 = Math.atan(k1)
  22. const a1 = k1 >= 0 ? temp1 : temp1 + Math.PI;
  23. // 线2与x轴的夹角
  24. const temp2 = Math.atan(k2)
  25. const a2 = k2 >= 0 ? temp2 : temp2 + Math.PI;
  26. // 角平分线斜率
  27. const k = Math.tan((a1 + a2) / 2);
  28. // 角平分线b
  29. const b = p2.y - k * p2.x;
  30. // 距离两条线l的点 到交点p2的距离
  31. const Lb2 = l / Math.sin(Math.abs(a1 - a2) / 2);
  32. // 将距离公式与直线方程连立,并且将直线方程代入,得到一元二次方程 Ax^2 + Bx + C = 0;然后根据得根公式得到2个解
  33. const A = k * k + 1;
  34. const B = 2 * k * b - 2 * p2.x - 2 * k * p2.y;
  35. const C = b * b - Lb2 * Lb2 + p2.x * p2.x + p2.y * p2.y - 2 * b * p2.y;
  36. // 求解
  37. const X1 = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A);
  38. const X2 = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
  39. const Y1 = k * X1 + b;
  40. const Y2 = k * X2 + b;
  41. return [Number(X1.toFixed(2)), Number(Y1.toFixed(2)), Number(X2.toFixed(2)), Number(Y2.toFixed(2))]
  42. }
  43. /**
  44. * 计算一条线的垂线上距离线l的2个点
  45. *
  46. * @param p1 点1
  47. * @param p2 点2
  48. * @param l 距离这条线的距离
  49. */
  50. static getVertical(p1: SPoint, p2: SPoint, l: number) {
  51. const dy1 = p1.y - p2.y;
  52. const dx1 = p1.x - p2.x;
  53. // 线1的斜率
  54. const k1 = dy1 / dx1;
  55. // 垂线的斜率
  56. const k = -1 / k1;
  57. // 垂线的b
  58. const b = p1.y - k * p1.x;
  59. // 将距离公式与直线方程连立,并且将直线方程代入,得到一元二次方程 Ax^2 + Bx + C = 0;然后根据得根公式得到2个解
  60. const A = k * k + 1;
  61. const B = 2 * k * b - 2 * p1.x - 2 * k * p1.y;
  62. const C = b * b - l * l + p1.x * p1.x + p1.y * p1.y - 2 * b * p1.y;
  63. // 求解
  64. const X1 = (-B + Math.sqrt(B * B - 4 * A * C)) / (2 * A);
  65. const X2 = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
  66. const Y1 = k * X1 + b;
  67. const Y2 = k * X2 + b;
  68. return [Number(X1.toFixed(2)), Number(Y1.toFixed(2)), Number(X2.toFixed(2)), Number(Y2.toFixed(2))]
  69. }
  70. /**
  71. * 计算线段交点
  72. *
  73. * @param line1 线段1
  74. * @param line2 线段2
  75. * @return SPoint 交点 null 平行但不重合 'repeat' 重合
  76. */
  77. static lineIntersection(
  78. p1: SPoint, p2: SPoint, p3: SPoint, p4: SPoint
  79. ): SPoint | null | string {
  80. let k1 = (p2.y - p1.y) / (p2.x - p1.x);
  81. let b1 = p2.y - k1 * p2.x;
  82. let k2 = (p4.y - p3.y) / (p4.x - p3.x);
  83. let b2 = p3.y - k2 * p3.x;
  84. if (k1 == k2) {
  85. if (b1 == b2) {
  86. return "repeat";
  87. }
  88. return null;
  89. }
  90. let intersectionX = (b2 - b1) / (k1 - k2);
  91. let intersectionY = k1 * intersectionX + b1;
  92. // 取线段上的最大最小值可以上下换
  93. let minX = Math.min(p1.x, p2.x);
  94. let maxX = Math.max(p3.x, p4.x);
  95. if (intersectionX >= minX && intersectionX <= maxX) {
  96. return new SPoint(intersectionX, intersectionY);
  97. }
  98. return null;
  99. }
  100. /**
  101. * 去除中间多于的点
  102. */
  103. }