core.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import math
  2. # 巷道间距
  3. # 计算旋转角度
  4. def calculate_route(point_1, point_2):
  5. a, b = point_1
  6. c, d = point_2
  7. return math.atan((d - b) / (c - a))
  8. # 计算旋转坐标
  9. def calculate_route_coordinate(point, route):
  10. x = point[0]
  11. y = point[1]
  12. x1 = x * math.cos(route) + y * math.sin(route)
  13. y1 = -x * math.sin(route) + y * math.cos(route)
  14. return (x1, y1)
  15. def find_point_on_line(A, B, fraction):
  16. """
  17. 计算线段AB上距离A点fraction长度处的点C的坐标。
  18. 参数:
  19. A -- 点A的坐标,形式为(x1, y1)
  20. B -- 点B的坐标,形式为(x2, y2)
  21. fraction -- 线段AB上距离A点的比例(0到1之间)
  22. 返回:
  23. 点C的坐标,形式为(x, y)
  24. """
  25. x1, y1 = A
  26. x2, y2 = B
  27. # 使用线性插值计算C点的坐标
  28. x = x1 + (x2 - x1) * fraction
  29. y = y1 + (y2 - y1) * fraction
  30. return (x, y)
  31. def scale_point(x, y, k):
  32. """
  33. 缩放二维点坐标。
  34. 参数:
  35. x, y: 原点的x和y坐标。
  36. k: 缩放因子。
  37. 返回:
  38. 新的x'和y'坐标。
  39. """
  40. x_prime = k * x
  41. y_prime = k * y
  42. return x_prime, y_prime
  43. # 计算 a点到b点之间1/x处(距离a点)的c点坐标
  44. def calculate_point_c(point_a, point_b, x):
  45. x_a, y_a = point_a
  46. x_b, y_b = point_b
  47. # 计算方向向量
  48. dx = x_b - x_a
  49. dy = y_b - y_a
  50. # 计算方向向量的模长
  51. distance_ab = math.sqrt(dx ** 2 + dy ** 2)
  52. # 计算单位方向向量
  53. unit_vector_x = dx / distance_ab
  54. unit_vector_y = dy / distance_ab
  55. # 计算点C的坐标
  56. x_c = x_a + (1 / x) * unit_vector_x
  57. y_c = y_a + (1 / x) * unit_vector_y
  58. return x_c, y_c
  59. # 找线段之间某点的坐标
  60. def rotate_point_around_another(point_a, point_b, a):
  61. x_a, y_a = point_a
  62. x_b, y_b = point_b
  63. """
  64. 旋转点A(x_a, y_a)围绕点B(x_b, y_b) a 弧度后的新坐标。
  65. """
  66. # 将A点的坐标转换到以B点为原点的坐标系中
  67. dx = x_a - x_b
  68. dy = y_a - y_b
  69. # 旋转坐标
  70. x_prime = dx * math.cos(a) - dy * math.sin(a)
  71. y_prime = dx * math.sin(a) + dy * math.cos(a)
  72. # 将旋转后的坐标转换回原来的坐标系
  73. x_rotated = x_prime + x_b
  74. y_rotated = y_prime + y_b
  75. return x_rotated, y_rotated
  76. def calculate_angle_with_x_axis(point1, point2):
  77. x1, y1 = point1
  78. x2, y2 = point2
  79. """
  80. 计算线段(x1, y1)到(x2, y2)与x轴的夹角(以弧度为单位)。
  81. 结果角度是从x轴正方向逆时针旋转到线段方向所经过的角度。
  82. """
  83. # 首先计算线段的斜率
  84. if x1 == x2: # 避免除以零
  85. if y2 > y1:
  86. return math.pi / 2 # 垂直于x轴且向上
  87. elif y2 < y1:
  88. return -math.pi / 2 # 垂直于x轴且向下
  89. else:
  90. return 0 # 与x轴重合
  91. else:
  92. slope = (y2 - y1) / (x2 - x1)
  93. # 使用atan2计算角度,它返回从x轴正方向到点(y, x)的向量与x轴之间的夹角
  94. # 注意:atan2的参数顺序是(y的差, x的差),即(y2-y1, x2-x1)
  95. angle_radians = math.atan2(y2 - y1, x2 - x1)
  96. return angle_radians
  97. def get_color_by_layer(layer_id):
  98. return {
  99. '1': 53,
  100. '2': 83,
  101. '3': 133,
  102. '4': 173
  103. }.get(layer_id)
  104. def min_distance_between_segments(seg1, seg2):
  105. """
  106. 计算两条线段之间的最小距离(基于端点之间的最小距离)
  107. seg1, seg2: 线段的端点坐标,例如 [(x1, y1), (x2, y2)]
  108. """
  109. # 提取端点
  110. p1, p2 = seg1
  111. p3, p4 = seg2
  112. # 计算所有端点之间的距离
  113. dist1 = distance(p1, p3)
  114. dist2 = distance(p1, p4)
  115. dist3 = distance(p2, p3)
  116. dist4 = distance(p2, p4)
  117. # 返回最小距离
  118. return min(dist1, dist2, dist3, dist4)
  119. def distance(p1, p2):
  120. """计算两点之间的距离"""
  121. return math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2)
  122. def symmetric_point(A, B):
  123. """
  124. 计算点A相对于点B的对称点C的坐标
  125. 参数:
  126. A -- 点A的坐标,形式为(x_a, y_a)
  127. B -- 点B的坐标,形式为(x_b, y_b)
  128. 返回:
  129. 点C的坐标,形式为(x_c, y_c)
  130. """
  131. x_a, y_a = A
  132. x_b, y_b = B
  133. x_c = 2 * x_b - x_a
  134. y_c = 2 * y_b - y_a
  135. return x_c, y_c
  136. def parallel_line(start, end, distance):
  137. """
  138. 计算与给定线段平行且距离为distance的线段(只返回上方的一条)。
  139. 参数:
  140. start -- 原始线段的起点坐标,形式为(x, y)
  141. end -- 原始线段的终点坐标,形式为(x, y)
  142. distance -- 平行线段与原始线段的距离
  143. 返回:
  144. tuple -- 平行线段的起点和终点坐标,形式为((new_start_x, new_start_y), (new_end_x, new_end_y))
  145. """
  146. # 计算原始线段的斜率
  147. if start[0] == end[0]: # 斜率不存在(垂直线)
  148. # 对于垂直线,我们只需在x坐标上保持不变,y坐标增减distance
  149. new_start = (start[0], start[1] + distance)
  150. new_end = (end[0], end[1] + distance)
  151. else:
  152. # 计算斜率
  153. slope = (end[1] - start[1]) / (end[0] - start[0])
  154. # 计算法线的斜率(负倒数)
  155. normal_slope = -1 / slope
  156. # 计算法线方向上从起点到距离distance的点的偏移量
  157. # 注意:这里我们使用勾股定理的简化形式,因为距离是垂直于线段的
  158. # 实际上,我们只需要y方向的偏移量,因为x方向的偏移量由斜率决定
  159. dx = distance / math.sqrt(1 + slope ** 2)
  160. dy = slope * dx
  161. # 计算新线段的起点和终点
  162. # 注意:这里我们假设距离是正值,只计算上方的平行线
  163. # 如果需要下方的平行线,可以将dy的符号取反
  164. new_start = (start[0] - dy / slope, start[1] + dx)
  165. new_end = (end[0] - dy / slope, end[1] + dx)
  166. # 注意:上面的计算方式在斜率为负时可能不正确,因为它没有考虑线段的方向
  167. # 一种更健壮的方法是分别计算与start和end距离为distance的点,然后取这两个点作为新线段的端点
  168. # 但为了简单起见,这里我们假设斜率不是负数或垂直线的情况已经处理
  169. # 注意:上面的计算方式在斜率为负或接近0时可能不准确,下面是一个更准确的版本
  170. # 它直接计算与start和end等距的点
  171. # 考虑到斜率可能接近无穷(即几乎垂直),我们使用向量叉积的概念来避免除以0
  172. vector = (end[0] - start[0], end[1] - start[1])
  173. norm = (-vector[1], vector[0]) # 法线向量
  174. norm_length = math.sqrt(norm[0] ** 2 + norm[1] ** 2)
  175. unit_norm = (norm[0] / norm_length, norm[1] / norm_length) # 单位法线向量
  176. offset_point_start = (start[0] + unit_norm[0] * distance, start[1] + unit_norm[1] * distance)
  177. offset_point_end = (end[0] + unit_norm[0] * distance, end[1] + unit_norm[1] * distance)
  178. return (offset_point_start, offset_point_end)
  179. def shrink_line(start, end, scale_factor):
  180. """
  181. 将线段缩小指定的倍数。
  182. 参数:
  183. start -- 原始线段的起点坐标,形式为(x, y)
  184. end -- 原始线段的终点坐标,形式为(x, y)
  185. scale_factor -- 缩小倍数,例如0.5表示缩小到原来的一半
  186. 返回:
  187. tuple -- 缩小后的线段的起点和终点坐标,形式为((new_start_x, new_start_y), (new_end_x, new_end_y))
  188. """
  189. # 计算原始线段的长度和方向向量
  190. length = ((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2) ** 0.5
  191. direction = ((end[0] - start[0]) / length, (end[1] - start[1]) / length)
  192. # 计算缩小后的线段的长度
  193. new_length = length * scale_factor
  194. # 计算缩小后的线段的起点和终点
  195. new_start = start
  196. new_end = (start[0] + direction[0] * new_length, start[1] + direction[1] * new_length)
  197. return (new_start, new_end)