Browse Source

improves hit testing for draw shapes

main
Steve Ruiz 4 years ago
parent
commit
c51c6631e1
1 changed files with 32 additions and 25 deletions
  1. 32
    25
      lib/shape-utils/draw.tsx

+ 32
- 25
lib/shape-utils/draw.tsx View File

@@ -3,16 +3,19 @@ import * as vec from 'utils/vec'
3 3
 import { DashStyle, DrawShape, ShapeStyles, ShapeType } from 'types'
4 4
 import { registerShapeUtils } from './index'
5 5
 import { intersectPolylineBounds } from 'utils/intersections'
6
-import { boundsContainPolygon } from 'utils/bounds'
6
+import { boundsContain, boundsContainPolygon } from 'utils/bounds'
7 7
 import getStroke from 'perfect-freehand'
8 8
 import {
9 9
   getBoundsCenter,
10 10
   getBoundsFromPoints,
11
+  getRotatedCorners,
11 12
   getSvgPathFromStroke,
13
+  rotateBounds,
12 14
   translateBounds,
13 15
 } from 'utils/utils'
14 16
 import { defaultStyle, getShapeStyle } from 'lib/shape-styles'
15 17
 
18
+const rotatedCache = new WeakMap<DrawShape, number[][]>([])
16 19
 const pathCache = new WeakMap<DrawShape['points'], string>([])
17 20
 
18 21
 const draw = registerShapeUtils<DrawShape>({
@@ -69,20 +72,16 @@ const draw = registerShapeUtils<DrawShape>({
69 72
   },
70 73
 
71 74
   getRotatedBounds(shape) {
72
-    const bounds =
73
-      this.boundsCache.get(shape) || getBoundsFromPoints(shape.points)
74
-
75
-    const center = getBoundsCenter(bounds)
76
-
77
-    const rotatedPts = shape.points.map((pt) =>
78
-      vec.rotWith(pt, center, shape.rotation)
79
-    )
80
-    const rotatedBounds = translateBounds(
81
-      getBoundsFromPoints(rotatedPts),
75
+    const rBounds = translateBounds(
76
+      getBoundsFromPoints(shape.points, shape.rotation),
82 77
       shape.point
83 78
     )
84 79
 
85
-    return rotatedBounds
80
+    const bounds = this.getBounds(shape)
81
+
82
+    const delta = vec.sub(getBoundsCenter(bounds), getBoundsCenter(rBounds))
83
+
84
+    return translateBounds(rBounds, delta)
86 85
   },
87 86
 
88 87
   getCenter(shape) {
@@ -100,22 +99,30 @@ const draw = registerShapeUtils<DrawShape>({
100 99
   },
101 100
 
102 101
   hitTestBounds(this, shape, brushBounds) {
103
-    const b = this.getBounds(shape)
104
-    const center = [b.minX + b.width / 2, b.minY + b.height / 2]
102
+    // Test axis-aligned shape
103
+    if (shape.rotation === 0) {
104
+      return (
105
+        boundsContain(brushBounds, this.getBounds(shape)) ||
106
+        intersectPolylineBounds(shape.points, brushBounds).length > 0
107
+      )
108
+    }
109
+
110
+    // Test rotated shape
111
+    const rBounds = this.getRotatedBounds(shape)
105 112
 
106
-    const rotatedCorners = [
107
-      [b.minX, b.minY],
108
-      [b.maxX, b.minY],
109
-      [b.maxX, b.maxY],
110
-      [b.minX, b.maxY],
111
-    ].map((point) => vec.rotWith(point, center, shape.rotation))
113
+    if (!rotatedCache.has(shape)) {
114
+      const c = getBoundsCenter(rBounds)
115
+      rotatedCache.set(
116
+        shape,
117
+        shape.points.map((pt) =>
118
+          vec.rotWith(vec.add(pt, shape.point), c, shape.rotation)
119
+        )
120
+      )
121
+    }
112 122
 
113 123
     return (
114
-      boundsContainPolygon(brushBounds, rotatedCorners) ||
115
-      intersectPolylineBounds(
116
-        shape.points.map((point) => vec.add(point, shape.point)),
117
-        brushBounds
118
-      ).length > 0
124
+      boundsContain(brushBounds, rBounds) ||
125
+      intersectPolylineBounds(rotatedCache.get(shape), brushBounds).length > 0
119 126
     )
120 127
   },
121 128
 

Loading…
Cancel
Save