Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

shape-utils.ts 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. import {
  2. boundsCollide,
  3. boundsContain,
  4. pointInBounds,
  5. } from "state/sessions/brush-session"
  6. import { Bounds, ShapeType, Shapes } from "types"
  7. import { intersectCircleBounds } from "./intersections"
  8. import * as vec from "./vec"
  9. type BaseShapeUtils<K extends ShapeType> = {
  10. getBounds(shape: Shapes[K]): Bounds
  11. hitTest(shape: Shapes[K], test: number[]): boolean
  12. rotate(shape: Shapes[K]): Shapes[K]
  13. translate(shape: Shapes[K]): Shapes[K]
  14. scale(shape: Shapes[K], scale: number): Shapes[K]
  15. stretch(shape: Shapes[K], scaleX: number, scaleY: number): Shapes[K]
  16. }
  17. /* ----------------------- Dot ---------------------- */
  18. const DotUtils: BaseShapeUtils<ShapeType.Dot> = {
  19. getBounds(shape) {
  20. const {
  21. point: [cx, cy],
  22. } = shape
  23. return {
  24. minX: cx,
  25. maxX: cx + 4,
  26. minY: cy,
  27. maxY: cy + 4,
  28. width: 4,
  29. height: 4,
  30. }
  31. },
  32. hitTest(shape, test) {
  33. return vec.dist(shape.point, test) < 4
  34. },
  35. rotate(shape) {
  36. return shape
  37. },
  38. translate(shape) {
  39. return shape
  40. },
  41. scale(shape, scale: number) {
  42. return shape
  43. },
  44. stretch(shape, scaleX: number, scaleY: number) {
  45. return shape
  46. },
  47. }
  48. /* --------------------- Circle --------------------- */
  49. const CircleUtils: BaseShapeUtils<ShapeType.Circle> = {
  50. getBounds(shape) {
  51. const {
  52. point: [cx, cy],
  53. radius,
  54. } = shape
  55. return {
  56. minX: cx,
  57. maxX: cx + radius * 2,
  58. minY: cy,
  59. maxY: cy + radius * 2,
  60. width: radius * 2,
  61. height: radius * 2,
  62. }
  63. },
  64. hitTest(shape, test) {
  65. return (
  66. vec.dist(vec.addScalar(shape.point, shape.radius), test) < shape.radius
  67. )
  68. },
  69. rotate(shape) {
  70. return shape
  71. },
  72. translate(shape) {
  73. return shape
  74. },
  75. scale(shape, scale: number) {
  76. return shape
  77. },
  78. stretch(shape, scaleX: number, scaleY: number) {
  79. return shape
  80. },
  81. }
  82. /* --------------------- Ellipse -------------------- */
  83. const EllipseUtils: BaseShapeUtils<ShapeType.Ellipse> = {
  84. getBounds(shape) {
  85. return {
  86. minX: 0,
  87. minY: 0,
  88. maxX: 0,
  89. maxY: 0,
  90. width: 0,
  91. height: 0,
  92. }
  93. },
  94. hitTest(shape) {
  95. return true
  96. },
  97. rotate(shape) {
  98. return shape
  99. },
  100. translate(shape) {
  101. return shape
  102. },
  103. scale(shape, scale: number) {
  104. return shape
  105. },
  106. stretch(shape, scaleX: number, scaleY: number) {
  107. return shape
  108. },
  109. }
  110. /* ---------------------- Line ---------------------- */
  111. const LineUtils: BaseShapeUtils<ShapeType.Line> = {
  112. getBounds(shape) {
  113. return {
  114. minX: 0,
  115. minY: 0,
  116. maxX: 0,
  117. maxY: 0,
  118. width: 0,
  119. height: 0,
  120. }
  121. },
  122. hitTest(shape) {
  123. return true
  124. },
  125. rotate(shape) {
  126. return shape
  127. },
  128. translate(shape) {
  129. return shape
  130. },
  131. scale(shape, scale: number) {
  132. return shape
  133. },
  134. stretch(shape, scaleX: number, scaleY: number) {
  135. return shape
  136. },
  137. }
  138. /* ----------------------- Ray ---------------------- */
  139. const RayUtils: BaseShapeUtils<ShapeType.Ray> = {
  140. getBounds(shape) {
  141. return {
  142. minX: Infinity,
  143. minY: Infinity,
  144. maxX: Infinity,
  145. maxY: Infinity,
  146. width: Infinity,
  147. height: Infinity,
  148. }
  149. },
  150. hitTest(shape) {
  151. return true
  152. },
  153. rotate(shape) {
  154. return shape
  155. },
  156. translate(shape) {
  157. return shape
  158. },
  159. scale(shape, scale: number) {
  160. return shape
  161. },
  162. stretch(shape, scaleX: number, scaleY: number) {
  163. return shape
  164. },
  165. }
  166. /* ------------------ Line Segment ------------------ */
  167. const PolylineUtils: BaseShapeUtils<ShapeType.Polyline> = {
  168. getBounds(shape) {
  169. let minX = 0
  170. let minY = 0
  171. let maxX = 0
  172. let maxY = 0
  173. for (let [x, y] of shape.points) {
  174. minX = Math.min(x, minX)
  175. minY = Math.min(y, minY)
  176. maxX = Math.max(x, maxX)
  177. maxY = Math.max(y, maxY)
  178. }
  179. return {
  180. minX: minX + shape.point[0],
  181. minY: minY + shape.point[1],
  182. maxX: maxX + shape.point[0],
  183. maxY: maxY + shape.point[1],
  184. width: maxX - minX,
  185. height: maxY - minY,
  186. }
  187. },
  188. hitTest(shape) {
  189. return true
  190. },
  191. rotate(shape) {
  192. return shape
  193. },
  194. translate(shape) {
  195. return shape
  196. },
  197. scale(shape, scale: number) {
  198. return shape
  199. },
  200. stretch(shape, scaleX: number, scaleY: number) {
  201. return shape
  202. },
  203. }
  204. /* -------------------- Rectangle ------------------- */
  205. const RectangleUtils: BaseShapeUtils<ShapeType.Rectangle> = {
  206. getBounds(shape) {
  207. const {
  208. point: [x, y],
  209. size: [width, height],
  210. } = shape
  211. return {
  212. minX: x,
  213. maxX: x + width,
  214. minY: y,
  215. maxY: y + height,
  216. width,
  217. height,
  218. }
  219. },
  220. hitTest(shape) {
  221. return true
  222. },
  223. rotate(shape) {
  224. return shape
  225. },
  226. translate(shape) {
  227. return shape
  228. },
  229. scale(shape, scale: number) {
  230. return shape
  231. },
  232. stretch(shape, scaleX: number, scaleY: number) {
  233. return shape
  234. },
  235. }
  236. const shapeUtils: { [K in ShapeType]: BaseShapeUtils<K> } = {
  237. [ShapeType.Dot]: DotUtils,
  238. [ShapeType.Circle]: CircleUtils,
  239. [ShapeType.Ellipse]: EllipseUtils,
  240. [ShapeType.Line]: LineUtils,
  241. [ShapeType.Ray]: RayUtils,
  242. [ShapeType.Polyline]: PolylineUtils,
  243. [ShapeType.Rectangle]: RectangleUtils,
  244. }
  245. export default shapeUtils