coordTransform.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // 定义雷达坐标系中的矩形接口
  2. export interface RadarRect {
  3. x_cm_start: number
  4. x_cm_stop: number
  5. y_cm_start: number
  6. y_cm_stop: number
  7. }
  8. // 定义画布坐标系中的矩形接口
  9. export interface CanvasRect {
  10. left: number
  11. top: number
  12. width: number
  13. height: number
  14. }
  15. // 定义雷达在画布中的位置接口
  16. export interface RadarPosition {
  17. x_radar: number
  18. y_radar: number
  19. }
  20. // 定义家具在雷达坐标系中的接口
  21. export interface RadarFurniture {
  22. x: number
  23. y: number
  24. width: number
  25. height: number
  26. }
  27. /**
  28. * 检测区域、子区域 矩形转换 雷达坐标系 --> 画布坐标系
  29. * @param src_rect - 雷达坐标系矩形
  30. * @param p_radar - 画布中雷达的位置
  31. * @returns CSS 可用矩形
  32. */
  33. export function convert_region_r2c(src_rect: RadarRect, p_radar: RadarPosition): CanvasRect {
  34. const x_radar = p_radar.x_radar
  35. const y_radar = p_radar.y_radar
  36. const left = x_radar + src_rect.x_cm_start
  37. const top = y_radar - src_rect.y_cm_stop
  38. const width = src_rect.x_cm_stop - src_rect.x_cm_start
  39. const height = src_rect.y_cm_stop - src_rect.y_cm_start
  40. return { left, top, width, height }
  41. }
  42. /**
  43. * 检测区域、子区域 矩形转换 画布坐标系 --> 雷达坐标系
  44. * @param dst_rect - 画布矩形
  45. * @param p_radar - 雷达在画布坐标系中的位置
  46. * @returns 雷达坐标矩形
  47. */
  48. export function convert_region_c2r(dst_rect: CanvasRect, p_radar: RadarPosition): RadarRect {
  49. const x_radar = p_radar.x_radar
  50. const y_radar = p_radar.y_radar
  51. const x_cm_start = dst_rect.left - x_radar
  52. const x_cm_stop = x_cm_start + dst_rect.width
  53. const y_cm_stop = y_radar - dst_rect.top
  54. const y_cm_start = y_cm_stop - dst_rect.height
  55. return {
  56. x_cm_start,
  57. x_cm_stop,
  58. y_cm_start,
  59. y_cm_stop,
  60. }
  61. }
  62. /**
  63. * 家具 矩形转换 雷达坐标系 --> 画布坐标系
  64. * @param furniture - 雷达坐标家具对象
  65. * @param p_radar - 雷达在画布上的坐标
  66. * @returns CSS 可用家具矩形
  67. */
  68. export function convert_furniture_r2c(
  69. furniture: RadarFurniture,
  70. p_radar: RadarPosition
  71. ): CanvasRect {
  72. const x_radar = p_radar.x_radar
  73. const y_radar = p_radar.y_radar
  74. const left = x_radar + furniture.x
  75. const top = y_radar - furniture.y
  76. const width = furniture.width
  77. const height = furniture.height
  78. return {
  79. left,
  80. top,
  81. width,
  82. height,
  83. }
  84. }
  85. /**
  86. * 家具 矩形转换 画布坐标系 --> 雷达坐标系
  87. * @param furniture_item - 画布矩形(CSS)
  88. * @param p_radar - 雷达在画布上的坐标
  89. * @returns 雷达坐标家具矩形
  90. */
  91. export function convert_furniture_c2r(
  92. furniture_item: CanvasRect,
  93. p_radar: RadarPosition
  94. ): RadarFurniture {
  95. const x_radar = p_radar.x_radar
  96. const y_radar = p_radar.y_radar
  97. const x = furniture_item.left - x_radar
  98. const y = y_radar - furniture_item.top
  99. const width = furniture_item.width
  100. const height = furniture_item.height
  101. return {
  102. x,
  103. y,
  104. width,
  105. height,
  106. }
  107. }
  108. /* ===================== 旋转方法 =================================== */
  109. interface Rect {
  110. left: number
  111. top: number
  112. width: number
  113. height: number
  114. }
  115. interface Point {
  116. x: number
  117. y: number
  118. }
  119. /**
  120. * 顺时针旋转矩形
  121. * @param src_rect - 输入矩形 { left, top, width, height }
  122. * @param pRadar - 雷达中心坐标 { x, y }
  123. * @param angle - 顺时针旋转角度 0, 90, 180, 270
  124. * @returns 旋转后的矩形 { left, top, width, height }
  125. */
  126. export function rotateRect_cw(src_rect: Rect, pRadar: Point, angle: number): Rect {
  127. if (![0, 90, 180, 270].includes(angle)) angle = 0
  128. const { left, top, width, height } = src_rect
  129. const cx = left + width / 2
  130. const cy = top + height / 2
  131. const dx = cx - pRadar.x
  132. const dy = cy - pRadar.y
  133. let new_dx: number = 0
  134. let new_dy: number = 0
  135. switch (angle) {
  136. case 0:
  137. new_dx = dx
  138. new_dy = dy
  139. break
  140. case 90:
  141. new_dx = -dy
  142. new_dy = dx
  143. break
  144. case 180:
  145. new_dx = -dx
  146. new_dy = -dy
  147. break
  148. case 270:
  149. new_dx = dy
  150. new_dy = -dx
  151. break
  152. }
  153. const new_cx = pRadar.x + new_dx
  154. const new_cy = pRadar.y + new_dy
  155. let new_width = width
  156. let new_height = height
  157. if (angle === 90 || angle === 270) {
  158. new_width = height
  159. new_height = width
  160. }
  161. return {
  162. left: new_cx - new_width / 2,
  163. top: new_cy - new_height / 2,
  164. width: new_width,
  165. height: new_height,
  166. }
  167. }
  168. /**
  169. * 逆时针旋转矩形(家具/检测区域)
  170. * @param src_rect - 输入矩形 { left, top, width, height }
  171. * @param pRadar - 雷达中心坐标 { x, y }
  172. * @param angle - 逆时针旋转角度 0, 90, 180, 270
  173. * @returns 旋转后的矩形 { left, top, width, height }
  174. */
  175. export function rotateRect_ccw(src_rect: Rect, pRadar: Point, angle: number): Rect {
  176. if (![0, 90, 180, 270].includes(angle)) angle = 0
  177. const { left, top, width, height } = src_rect
  178. const cx = left + width / 2
  179. const cy = top + height / 2
  180. const dx = cx - pRadar.x
  181. const dy = cy - pRadar.y
  182. let new_dx: number = 0
  183. let new_dy: number = 0
  184. switch (angle) {
  185. case 0:
  186. new_dx = dx
  187. new_dy = dy
  188. break
  189. case 90:
  190. new_dx = dy
  191. new_dy = -dx
  192. break
  193. case 180:
  194. new_dx = -dx
  195. new_dy = -dy
  196. break
  197. case 270:
  198. new_dx = -dy
  199. new_dy = dx
  200. break
  201. }
  202. const new_cx = pRadar.x + new_dx
  203. const new_cy = pRadar.y + new_dy
  204. let new_width = width
  205. let new_height = height
  206. if (angle === 90 || angle === 270) {
  207. new_width = height
  208. new_height = width
  209. }
  210. return {
  211. left: new_cx - new_width / 2,
  212. top: new_cy - new_height / 2,
  213. width: new_width,
  214. height: new_height,
  215. }
  216. }
  217. interface Point {
  218. x: number
  219. y: number
  220. }
  221. /**
  222. * 将雷达坐标系中的点转换到画布坐标系(旋转 + 平移)
  223. * @param src_point - 雷达坐标系中的点
  224. * @param pRadar - 雷达在画布坐标系中的坐标
  225. * @param angle - 雷达顺时针旋转角度(度)
  226. * @returns 画布坐标系中的点
  227. */
  228. export function convert_point_r2c(src_point: Point, pRadar: Point, angle: number): Point {
  229. const rad = (angle * Math.PI) / 180 // 角度转弧度(顺时针为正)
  230. const cosA = Math.cos(rad)
  231. const sinA = Math.sin(rad)
  232. // 顺时针旋转
  233. const xRot = src_point.x * cosA + src_point.y * sinA
  234. const yRot = -src_point.x * sinA + src_point.y * cosA
  235. // 平移到画布坐标系
  236. return {
  237. x: pRadar.x + xRot,
  238. y: pRadar.y - yRot,
  239. }
  240. }