generate.ts 4.9 KB

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