Переглянути джерело

adds polyline, intersections for polyline

main
Steve Ruiz 4 роки тому
джерело
коміт
f5d555863c

+ 3
- 0
components/canvas/shape.tsx Переглянути файл

@@ -3,6 +3,7 @@ import { useSelector } from "state"
3 3
 import { ShapeType } from "types"
4 4
 import Circle from "./shapes/circle"
5 5
 import Dot from "./shapes/dot"
6
+import Polyline from "./shapes/polyline"
6 7
 import Rectangle from "./shapes/rectangle"
7 8
 
8 9
 /*
@@ -24,6 +25,8 @@ function Shape({ id }: { id: string }) {
24 25
       return <Circle {...shape} />
25 26
     case ShapeType.Rectangle:
26 27
       return <Rectangle {...shape} />
28
+    case ShapeType.Polyline:
29
+      return <Polyline {...shape} />
27 30
     default:
28 31
       return null
29 32
   }

+ 8
- 17
components/canvas/shapes/circle.tsx Переглянути файл

@@ -1,10 +1,8 @@
1
-import state, { useSelector } from "state"
1
+import { useSelector } from "state"
2 2
 import { CircleShape } from "types"
3
-import ShapeGroup from "./shape-group"
4
-import { getPointerEventInfo } from "utils/utils"
3
+import ShapeGroup from "./shape-g"
5 4
 
6
-interface BaseCircleProps {
7
-  point: number[]
5
+interface BaseCircleProps extends Pick<CircleShape, "radius"> {
8 6
   radius: number
9 7
   fill?: string
10 8
   stroke?: string
@@ -12,7 +10,6 @@ interface BaseCircleProps {
12 10
 }
13 11
 
14 12
 function BaseCircle({
15
-  point,
16 13
   radius,
17 14
   fill = "#ccc",
18 15
   stroke = "none",
@@ -20,8 +17,8 @@ function BaseCircle({
20 17
 }: BaseCircleProps) {
21 18
   return (
22 19
     <circle
23
-      cx={point[0] + strokeWidth}
24
-      cy={point[1] + strokeWidth}
20
+      cx={strokeWidth}
21
+      cy={strokeWidth}
25 22
       r={radius - strokeWidth}
26 23
       fill={fill}
27 24
       stroke={stroke}
@@ -33,16 +30,10 @@ function BaseCircle({
33 30
 export default function Circle({ id, point, radius }: CircleShape) {
34 31
   const isSelected = useSelector((state) => state.values.selectedIds.has(id))
35 32
   return (
36
-    <ShapeGroup id={id}>
37
-      <BaseCircle point={point} radius={radius} />
33
+    <ShapeGroup id={id} point={point}>
34
+      <BaseCircle radius={radius} />
38 35
       {isSelected && (
39
-        <BaseCircle
40
-          point={point}
41
-          radius={radius}
42
-          fill="none"
43
-          stroke="blue"
44
-          strokeWidth={1}
45
-        />
36
+        <BaseCircle radius={radius} fill="none" stroke="blue" strokeWidth={1} />
46 37
       )}
47 38
     </ShapeGroup>
48 39
   )

+ 10
- 14
components/canvas/shapes/dot.tsx Переглянути файл

@@ -1,50 +1,46 @@
1 1
 import { useSelector } from "state"
2 2
 import { DotShape } from "types"
3
-import ShapeGroup from "./shape-group"
3
+import ShapeGroup from "./shape-g"
4 4
 
5 5
 interface BaseCircleProps {
6
-  point: number[]
7 6
   fill?: string
8 7
   stroke?: string
9 8
   strokeWidth?: number
10 9
 }
11 10
 
12 11
 function BaseDot({
13
-  point,
14 12
   fill = "#ccc",
15 13
   stroke = "none",
16 14
   strokeWidth = 0,
17 15
 }: BaseCircleProps) {
18 16
   return (
19
-    <g>
17
+    <>
20 18
       <circle
21
-        cx={point[0] + strokeWidth}
22
-        cy={point[1] + strokeWidth}
19
+        cx={strokeWidth}
20
+        cy={strokeWidth}
23 21
         r={8}
24 22
         fill="transparent"
25 23
         stroke="none"
26 24
         strokeWidth="0"
27 25
       />
28 26
       <circle
29
-        cx={point[0] + strokeWidth}
30
-        cy={point[1] + strokeWidth}
27
+        cx={strokeWidth}
28
+        cy={strokeWidth}
31 29
         r={Math.max(1, 4 - strokeWidth)}
32 30
         fill={fill}
33 31
         stroke={stroke}
34 32
         strokeWidth={strokeWidth}
35 33
       />
36
-    </g>
34
+    </>
37 35
   )
38 36
 }
39 37
 
40 38
 export default function Dot({ id, point }: DotShape) {
41 39
   const isSelected = useSelector((state) => state.values.selectedIds.has(id))
42 40
   return (
43
-    <ShapeGroup id={id}>
44
-      <BaseDot point={point} />
45
-      {isSelected && (
46
-        <BaseDot point={point} fill="none" stroke="blue" strokeWidth={1} />
47
-      )}
41
+    <ShapeGroup id={id} point={point}>
42
+      <BaseDot />
43
+      {isSelected && <BaseDot fill="none" stroke="blue" strokeWidth={1} />}
48 44
     </ShapeGroup>
49 45
   )
50 46
 }

+ 35
- 0
components/canvas/shapes/polyline.tsx Переглянути файл

@@ -0,0 +1,35 @@
1
+import { useSelector } from "state"
2
+import { PolylineShape } from "types"
3
+import ShapeGroup from "./shape-g"
4
+
5
+interface BasePolylineProps extends Pick<PolylineShape, "points"> {
6
+  fill?: string
7
+  stroke?: string
8
+  strokeWidth?: number
9
+}
10
+
11
+function BasePolyline({
12
+  points,
13
+  fill = "none",
14
+  stroke = "#ccc",
15
+  strokeWidth = 2,
16
+}: BasePolylineProps) {
17
+  return (
18
+    <polyline
19
+      points={points.toString()}
20
+      fill={fill}
21
+      stroke={stroke}
22
+      strokeWidth={strokeWidth}
23
+    />
24
+  )
25
+}
26
+
27
+export default function Polyline({ id, point, points }: PolylineShape) {
28
+  const isSelected = useSelector((state) => state.values.selectedIds.has(id))
29
+  return (
30
+    <ShapeGroup id={id} point={point}>
31
+      <BasePolyline points={points} />
32
+      {isSelected && <BasePolyline points={points} fill="none" stroke="blue" />}
33
+    </ShapeGroup>
34
+  )
35
+}

+ 7
- 15
components/canvas/shapes/rectangle.tsx Переглянути файл

@@ -1,9 +1,8 @@
1 1
 import { useSelector } from "state"
2 2
 import { RectangleShape } from "types"
3
-import ShapeGroup from "./shape-group"
3
+import ShapeGroup from "./shape-g"
4 4
 
5
-interface BaseRectangleProps {
6
-  point: number[]
5
+interface BaseRectangleProps extends Pick<RectangleShape, "size"> {
7 6
   size: number[]
8 7
   fill?: string
9 8
   stroke?: string
@@ -11,7 +10,6 @@ interface BaseRectangleProps {
11 10
 }
12 11
 
13 12
 function BaseRectangle({
14
-  point,
15 13
   size,
16 14
   fill = "#ccc",
17 15
   stroke = "none",
@@ -19,8 +17,8 @@ function BaseRectangle({
19 17
 }: BaseRectangleProps) {
20 18
   return (
21 19
     <rect
22
-      x={point[0] + strokeWidth}
23
-      y={point[1] + strokeWidth}
20
+      x={strokeWidth}
21
+      y={strokeWidth}
24 22
       width={size[0] - strokeWidth * 2}
25 23
       height={size[1] - strokeWidth * 2}
26 24
       fill={fill}
@@ -33,16 +31,10 @@ function BaseRectangle({
33 31
 export default function Rectangle({ id, point, size }: RectangleShape) {
34 32
   const isSelected = useSelector((state) => state.values.selectedIds.has(id))
35 33
   return (
36
-    <ShapeGroup id={id}>
37
-      <BaseRectangle point={point} size={size} />
34
+    <ShapeGroup id={id} point={point}>
35
+      <BaseRectangle size={size} />
38 36
       {isSelected && (
39
-        <BaseRectangle
40
-          point={point}
41
-          size={size}
42
-          fill="none"
43
-          stroke="blue"
44
-          strokeWidth={1}
45
-        />
37
+        <BaseRectangle size={size} fill="none" stroke="blue" strokeWidth={1} />
46 38
       )}
47 39
     </ShapeGroup>
48 40
   )

components/canvas/shapes/shape-group.tsx → components/canvas/shapes/shape-g.tsx Переглянути файл

@@ -1,17 +1,19 @@
1 1
 import React from "react"
2 2
 import state from "state"
3
-import { Shape } from "types"
4 3
 import { getPointerEventInfo } from "utils/utils"
5 4
 
6 5
 export default function ShapeGroup({
7 6
   id,
8 7
   children,
8
+  point,
9 9
 }: {
10 10
   id: string
11 11
   children: React.ReactNode
12
+  point: number[]
12 13
 }) {
13 14
   return (
14 15
     <g
16
+      transform={`translate(${point})`}
15 17
       onPointerDown={(e) =>
16 18
         state.send("POINTED_SHAPE", { id, ...getPointerEventInfo(e) })
17 19
       }

+ 7
- 3
state/data.ts Переглянути файл

@@ -30,12 +30,16 @@ export const defaultDocument: Data["document"] = {
30 30
         },
31 31
         shape2: {
32 32
           id: "shape2",
33
-          type: ShapeType.Circle,
33
+          type: ShapeType.Polyline,
34 34
           name: "Shape 2",
35 35
           parentId: "page0",
36 36
           childIndex: 2,
37
-          point: [200, 800],
38
-          radius: 25,
37
+          point: [200, 600],
38
+          points: [
39
+            [0, 0],
40
+            [75, 200],
41
+            [100, 50],
42
+          ],
39 43
           rotation: 0,
40 44
         },
41 45
         shape3: {

+ 37
- 33
state/sessions/brush-session.ts Переглянути файл

@@ -1,14 +1,17 @@
1 1
 import { current } from "immer"
2 2
 import { Bounds, Data, Shape, ShapeType } from "types"
3 3
 import BaseSession from "./base-session"
4
-import shapeUtils from "utils/shapes"
4
+import shapeUtils from "utils/shape-utils"
5 5
 import { getBoundsFromPoints } from "utils/utils"
6 6
 import * as vec from "utils/vec"
7
-import { intersectCircleBounds } from "utils/intersections"
7
+import {
8
+  intersectCircleBounds,
9
+  intersectPolylineBounds,
10
+} from "utils/intersections"
8 11
 
9 12
 interface BrushSnapshot {
10 13
   selectedIds: string[]
11
-  shapes: { shape: Shape; bounds: Bounds }[]
14
+  shapes: { shape: Shape; test: (bounds: Bounds) => boolean }[]
12 15
 }
13 16
 
14 17
 export default class BrushSession extends BaseSession {
@@ -31,32 +34,7 @@ export default class BrushSession extends BaseSession {
31 34
     data.selectedIds = [
32 35
       ...snapshot.selectedIds,
33 36
       ...snapshot.shapes
34
-        .filter(({ shape, bounds }) => {
35
-          switch (shape.type) {
36
-            case ShapeType.Circle: {
37
-              return (
38
-                boundsContained(bounds, brushBounds) ||
39
-                intersectCircleBounds(shape.point, shape.radius, brushBounds)
40
-                  .length
41
-              )
42
-            }
43
-            case ShapeType.Dot: {
44
-              return (
45
-                boundsContained(bounds, brushBounds) ||
46
-                intersectCircleBounds(shape.point, 4, brushBounds).length
47
-              )
48
-            }
49
-            case ShapeType.Rectangle: {
50
-              return (
51
-                boundsContained(bounds, brushBounds) ||
52
-                boundsCollide(bounds, brushBounds)
53
-              )
54
-            }
55
-            default: {
56
-              return boundsContained(bounds, brushBounds)
57
-            }
58
-          }
59
-        })
37
+        .filter(({ test }) => test(brushBounds))
60 38
         .map(({ shape }) => shape.id),
61 39
     ]
62 40
 
@@ -72,7 +50,7 @@ export default class BrushSession extends BaseSession {
72 50
     data.brush = undefined
73 51
   }
74 52
 
75
-  static getSnapshot(data: Data) {
53
+  static getSnapshot(data: Data): BrushSnapshot {
76 54
     const {
77 55
       selectedIds,
78 56
       document: { pages },
@@ -88,21 +66,47 @@ export default class BrushSession extends BaseSession {
88 66
         .map((shape) => {
89 67
           switch (shape.type) {
90 68
             case ShapeType.Dot: {
69
+              const bounds = shapeUtils[shape.type].getBounds(shape)
70
+
91 71
               return {
92 72
                 shape,
93
-                bounds: shapeUtils[shape.type].getBounds(shape),
73
+                test: (brushBounds: Bounds) =>
74
+                  boundsContained(bounds, brushBounds) ||
75
+                  intersectCircleBounds(shape.point, 4, brushBounds).length > 0,
94 76
               }
95 77
             }
96 78
             case ShapeType.Circle: {
79
+              const bounds = shapeUtils[shape.type].getBounds(shape)
80
+
97 81
               return {
98 82
                 shape,
99
-                bounds: shapeUtils[shape.type].getBounds(shape),
83
+                test: (brushBounds: Bounds) =>
84
+                  boundsContained(bounds, brushBounds) ||
85
+                  intersectCircleBounds(shape.point, shape.radius, brushBounds)
86
+                    .length > 0,
100 87
               }
101 88
             }
102 89
             case ShapeType.Rectangle: {
90
+              const bounds = shapeUtils[shape.type].getBounds(shape)
91
+
92
+              return {
93
+                shape,
94
+                test: (brushBounds: Bounds) =>
95
+                  boundsContained(bounds, brushBounds) ||
96
+                  boundsCollide(bounds, brushBounds),
97
+              }
98
+            }
99
+            case ShapeType.Polyline: {
100
+              const bounds = shapeUtils[shape.type].getBounds(shape)
101
+              const points = shape.points.map((point) =>
102
+                vec.add(point, shape.point)
103
+              )
104
+
103 105
               return {
104 106
                 shape,
105
-                bounds: shapeUtils[shape.type].getBounds(shape),
107
+                test: (brushBounds: Bounds) =>
108
+                  boundsContained(bounds, brushBounds) ||
109
+                  intersectPolylineBounds(points, brushBounds).length > 0,
106 110
               }
107 111
             }
108 112
             default: {

+ 7
- 13
types.ts Переглянути файл

@@ -26,7 +26,7 @@ export enum ShapeType {
26 26
   Ellipse = "ellipse",
27 27
   Line = "line",
28 28
   Ray = "ray",
29
-  LineSegment = "lineSegment",
29
+  Polyline = "Polyline",
30 30
   Rectangle = "rectangle",
31 31
   // Glob = "glob",
32 32
   // Spline = "spline",
@@ -40,48 +40,42 @@ export interface BaseShape {
40 40
   parentId: string
41 41
   childIndex: number
42 42
   name: string
43
+  point: number[]
43 44
   rotation: 0
44 45
 }
45 46
 
46 47
 export interface DotShape extends BaseShape {
47 48
   type: ShapeType.Dot
48
-  point: number[]
49 49
 }
50 50
 
51 51
 export interface CircleShape extends BaseShape {
52 52
   type: ShapeType.Circle
53
-  point: number[]
54 53
   radius: number
55 54
 }
56 55
 
57 56
 export interface EllipseShape extends BaseShape {
58 57
   type: ShapeType.Ellipse
59
-  point: number[]
60 58
   radiusX: number
61 59
   radiusY: number
62 60
 }
63 61
 
64 62
 export interface LineShape extends BaseShape {
65 63
   type: ShapeType.Line
66
-  point: number[]
67 64
   vector: number[]
68 65
 }
69 66
 
70 67
 export interface RayShape extends BaseShape {
71 68
   type: ShapeType.Ray
72
-  point: number[]
73 69
   vector: number[]
74 70
 }
75 71
 
76
-export interface LineSegmentShape extends BaseShape {
77
-  type: ShapeType.LineSegment
78
-  start: number[]
79
-  end: number[]
72
+export interface PolylineShape extends BaseShape {
73
+  type: ShapeType.Polyline
74
+  points: number[][]
80 75
 }
81 76
 
82 77
 export interface RectangleShape extends BaseShape {
83 78
   type: ShapeType.Rectangle
84
-  point: number[]
85 79
   size: number[]
86 80
 }
87 81
 
@@ -91,7 +85,7 @@ export type Shape =
91 85
   | EllipseShape
92 86
   | LineShape
93 87
   | RayShape
94
-  | LineSegmentShape
88
+  | PolylineShape
95 89
   | RectangleShape
96 90
 
97 91
 export interface Bounds {
@@ -109,6 +103,6 @@ export interface Shapes extends Record<ShapeType, Shape> {
109 103
   [ShapeType.Ellipse]: EllipseShape
110 104
   [ShapeType.Line]: LineShape
111 105
   [ShapeType.Ray]: RayShape
112
-  [ShapeType.LineSegment]: LineSegmentShape
106
+  [ShapeType.Polyline]: PolylineShape
113 107
   [ShapeType.Rectangle]: RectangleShape
114 108
 }

+ 116
- 11
utils/intersections.ts Переглянути файл

@@ -7,7 +7,47 @@ interface Intersection {
7 7
   points: number[][]
8 8
 }
9 9
 
10
-export function intersectCircleLine(
10
+function getIntersection(
11
+  points: number[][],
12
+  message = points.length ? "Intersection" : "No intersection"
13
+) {
14
+  return { didIntersect: points.length > 0, message, points }
15
+}
16
+
17
+export function intersectLineSegments(
18
+  a1: number[],
19
+  a2: number[],
20
+  b1: number[],
21
+  b2: number[]
22
+) {
23
+  const AB = vec.sub(a1, b1)
24
+  const BV = vec.sub(b2, b1)
25
+  const AV = vec.sub(a2, a1)
26
+
27
+  const ua_t = BV[0] * AB[1] - BV[1] * AB[0]
28
+  const ub_t = AV[0] * AB[1] - AV[1] * AB[0]
29
+  const u_b = BV[1] * AV[0] - BV[0] * AV[1]
30
+
31
+  if (ua_t === 0 || ub_t === 0) {
32
+    return getIntersection([], "Coincident")
33
+  }
34
+
35
+  if (u_b === 0) {
36
+    return getIntersection([], "Parallel")
37
+  }
38
+
39
+  if (u_b != 0) {
40
+    const ua = ua_t / u_b
41
+    const ub = ub_t / u_b
42
+    if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
43
+      return getIntersection([vec.add(a1, vec.mul(AV, ua))])
44
+    }
45
+  }
46
+
47
+  return getIntersection([])
48
+}
49
+
50
+export function intersectCircleLineSegment(
11 51
   c: number[],
12 52
   r: number,
13 53
   a1: number[],
@@ -66,19 +106,60 @@ export function intersectCircleRectangle(
66 106
 
67 107
   const intersections: Intersection[] = []
68 108
 
69
-  const topIntersection = intersectCircleLine(c, r, tl, tr)
109
+  const topIntersection = intersectCircleLineSegment(c, r, tl, tr)
110
+  const rightIntersection = intersectCircleLineSegment(c, r, tr, br)
111
+  const bottomIntersection = intersectCircleLineSegment(c, r, bl, br)
112
+  const leftIntersection = intersectCircleLineSegment(c, r, tl, bl)
113
+
114
+  if (topIntersection.didIntersect) {
115
+    intersections.push({ ...topIntersection, message: "top" })
116
+  }
117
+
118
+  if (rightIntersection.didIntersect) {
119
+    intersections.push({ ...rightIntersection, message: "right" })
120
+  }
121
+
122
+  if (bottomIntersection.didIntersect) {
123
+    intersections.push({ ...bottomIntersection, message: "bottom" })
124
+  }
125
+
126
+  if (leftIntersection.didIntersect) {
127
+    intersections.push({ ...leftIntersection, message: "left" })
128
+  }
129
+
130
+  return intersections
131
+}
132
+
133
+export function intersectRectangleLineSegment(
134
+  point: number[],
135
+  size: number[],
136
+  a1: number[],
137
+  a2: number[]
138
+) {
139
+  const tl = point
140
+  const tr = vec.add(point, [size[0], 0])
141
+  const br = vec.add(point, size)
142
+  const bl = vec.add(point, [0, size[1]])
143
+
144
+  const intersections: Intersection[] = []
145
+
146
+  const topIntersection = intersectLineSegments(a1, a2, tl, tr)
147
+  const rightIntersection = intersectLineSegments(a1, a2, tr, br)
148
+  const bottomIntersection = intersectLineSegments(a1, a2, bl, br)
149
+  const leftIntersection = intersectLineSegments(a1, a2, tl, bl)
150
+
70 151
   if (topIntersection.didIntersect) {
71 152
     intersections.push({ ...topIntersection, message: "top" })
72 153
   }
73
-  const rightIntersection = intersectCircleLine(c, r, tr, br)
154
+
74 155
   if (rightIntersection.didIntersect) {
75 156
     intersections.push({ ...rightIntersection, message: "right" })
76 157
   }
77
-  const bottomIntersection = intersectCircleLine(c, r, bl, br)
158
+
78 159
   if (bottomIntersection.didIntersect) {
79 160
     intersections.push({ ...bottomIntersection, message: "bottom" })
80 161
   }
81
-  const leftIntersection = intersectCircleLine(c, r, tl, bl)
162
+
82 163
   if (leftIntersection.didIntersect) {
83 164
     intersections.push({ ...leftIntersection, message: "left" })
84 165
   }
@@ -86,18 +167,42 @@ export function intersectCircleRectangle(
86 167
   return intersections
87 168
 }
88 169
 
170
+/* -------------------------------------------------- */
171
+/*                  Shape vs. Bounds                  */
172
+/* -------------------------------------------------- */
173
+
89 174
 export function intersectCircleBounds(
90 175
   c: number[],
91 176
   r: number,
92 177
   bounds: Bounds
93 178
 ): Intersection[] {
94 179
   const { minX, minY, width, height } = bounds
95
-  const intersections = intersectCircleRectangle(
96
-    c,
97
-    r,
98
-    [minX, minY],
99
-    [width, height]
100
-  )
180
+  return intersectCircleRectangle(c, r, [minX, minY], [width, height])
181
+}
182
+
183
+export function intersectLineSegmentBounds(
184
+  a1: number[],
185
+  a2: number[],
186
+  bounds: Bounds
187
+) {
188
+  const { minX, minY, width, height } = bounds
189
+  return intersectRectangleLineSegment([minX, minY], [width, height], a1, a2)
190
+}
191
+
192
+export function intersectPolylineBounds(points: number[][], bounds: Bounds) {
193
+  const { minX, minY, width, height } = bounds
194
+  const intersections: Intersection[] = []
195
+
196
+  for (let i = 1; i < points.length; i++) {
197
+    intersections.push(
198
+      ...intersectRectangleLineSegment(
199
+        [minX, minY],
200
+        [width, height],
201
+        points[i - 1],
202
+        points[i]
203
+      )
204
+    )
205
+  }
101 206
 
102 207
   return intersections
103 208
 }

utils/shapes.ts → utils/shape-utils.ts Переглянути файл

@@ -3,19 +3,7 @@ import {
3 3
   boundsContain,
4 4
   pointInBounds,
5 5
 } from "state/sessions/brush-session"
6
-import {
7
-  Shape,
8
-  Bounds,
9
-  ShapeType,
10
-  CircleShape,
11
-  DotShape,
12
-  RectangleShape,
13
-  Shapes,
14
-  EllipseShape,
15
-  LineShape,
16
-  RayShape,
17
-  LineSegmentShape,
18
-} from "types"
6
+import { Bounds, ShapeType, Shapes } from "types"
19 7
 import { intersectCircleBounds } from "./intersections"
20 8
 import * as vec from "./vec"
21 9
 
@@ -224,15 +212,27 @@ const RayUtils: BaseShapeUtils<ShapeType.Ray> = {
224 212
 
225 213
 /* ------------------ Line Segment ------------------ */
226 214
 
227
-const LineSegmentUtils: BaseShapeUtils<ShapeType.LineSegment> = {
215
+const PolylineUtils: BaseShapeUtils<ShapeType.Polyline> = {
228 216
   getBounds(shape) {
217
+    let minX = 0
218
+    let minY = 0
219
+    let maxX = 0
220
+    let maxY = 0
221
+
222
+    for (let [x, y] of shape.points) {
223
+      minX = Math.min(x, minX)
224
+      minY = Math.min(y, minY)
225
+      maxX = Math.max(x, maxX)
226
+      maxY = Math.max(y, maxY)
227
+    }
228
+
229 229
     return {
230
-      minX: 0,
231
-      minY: 0,
232
-      maxX: 0,
233
-      maxY: 0,
234
-      width: 0,
235
-      height: 0,
230
+      minX: minX + shape.point[0],
231
+      minY: minY + shape.point[1],
232
+      maxX: maxX + shape.point[0],
233
+      maxY: maxY + shape.point[1],
234
+      width: maxX - minX,
235
+      height: maxY - minY,
236 236
     }
237 237
   },
238 238
 
@@ -303,7 +303,7 @@ const shapeUtils: { [K in ShapeType]: BaseShapeUtils<K> } = {
303 303
   [ShapeType.Ellipse]: EllipseUtils,
304 304
   [ShapeType.Line]: LineUtils,
305 305
   [ShapeType.Ray]: RayUtils,
306
-  [ShapeType.LineSegment]: LineSegmentUtils,
306
+  [ShapeType.Polyline]: PolylineUtils,
307 307
   [ShapeType.Rectangle]: RectangleUtils,
308 308
 }
309 309
 

Завантаження…
Відмінити
Зберегти