|
|
@@ -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
|
|