lost-sia 2.0.1-alpha11 → 2.0.1-alpha13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Annotation/ui/atoms/AnnoBar.js +1 -1
- package/dist/Annotation/ui/atoms/Edge.js +1 -1
- package/dist/Annotation/ui/atoms/Node.js +1 -1
- package/dist/Annotation/ui/tools/BBox.js +1 -1
- package/dist/Annotation/ui/tools/Line.js +1 -1
- package/dist/Annotation/ui/tools/Polygon.js +1 -1
- package/dist/Canvas/Canvas.d.ts +2 -1
- package/dist/Canvas/Canvas.js +1 -1
- package/dist/Sia.js +1 -1
- package/dist/Toolbar/Toolbar.js +1 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.js +1 -1
- package/dist/models/KeyAction.d.ts +2 -1
- package/dist/models/KeyAction.js +1 -1
- package/dist/stories/Canvas/Canvas.stories.d.ts +2 -1
- package/dist/utils/KeyMapper.js +1 -1
- package/dist/utils/mouse.js +1 -1
- package/dist/utils/siaIcons.js +5 -5
- package/dist/utils/transform.js +1 -1
- package/dist/utils/windowViewport.d.ts +22 -0
- package/dist/utils/windowViewport.js +1 -1
- package/package.json +9 -8
- package/src/Annotation/ui/atoms/AnnoBar.tsx +46 -46
- package/src/Annotation/ui/atoms/Edge.tsx +23 -23
- package/src/Annotation/ui/atoms/Node.tsx +51 -51
- package/src/Annotation/ui/tools/BBox.tsx +129 -145
- package/src/Annotation/ui/tools/Line.tsx +81 -87
- package/src/Annotation/ui/tools/Polygon.tsx +92 -95
- package/src/Canvas/Canvas.tsx +369 -397
- package/src/InfoBoxes/AnnoStats.jsx +1 -1
- package/src/InfoBoxes/InfoBoxArea.jsx +32 -34
- package/src/{Sia2.tsx → Sia.tsx} +156 -175
- package/src/Toolbar/Toolbar.tsx +4 -4
- package/src/index.ts +6 -17
- package/src/models/KeyAction.ts +1 -0
- package/src/stories/AnnotationTools.stories.tsx +21 -21
- package/src/stories/Canvas/Canvas.stories.tsx +31 -26
- package/src/stories/Canvas/CanvasOffset.tsx +23 -25
- package/src/stories/MinimalSia.stories.tsx +22 -22
- package/src/stories/SIA2/DemoWrapper.tsx +20 -24
- package/src/stories/SIA2/Sia2.stories.tsx +24 -24
- package/src/utils/KeyMapper.ts +3 -0
- package/src/utils/siaIcons.jsx +5 -7
- package/src/utils/windowViewport.ts +34 -0
- package/dist/AnnoExampleViewer.js +0 -1
- package/dist/AnnoLabelInput.js +0 -1
- package/dist/AnnoToolBar.js +0 -19
- package/dist/Annotation/AnnoBar.js +0 -1
- package/dist/Annotation/Annotation.js +0 -1
- package/dist/Annotation/BBox.js +0 -1
- package/dist/Annotation/Edge.js +0 -1
- package/dist/Annotation/InfSelectionArea.js +0 -1
- package/dist/Annotation/Line.js +0 -1
- package/dist/Annotation/Node.js +0 -1
- package/dist/Annotation/Point.js +0 -1
- package/dist/Annotation/Polygon.js +0 -1
- package/dist/Canvas.js +0 -1
- package/dist/ImgBar.js +0 -1
- package/dist/InfoBoxes/AnnoDetails.js +0 -1
- package/dist/InfoBoxes/AnnoStats.js +0 -1
- package/dist/InfoBoxes/InfoBox.js +0 -1
- package/dist/InfoBoxes/InfoBoxArea.js +0 -1
- package/dist/InfoBoxes/LabelInfo.js +0 -1
- package/dist/LabelInput.js +0 -1
- package/dist/Prompt.js +0 -1
- package/dist/SIAFilterButton.js +0 -1
- package/dist/SIASettingButton.js +0 -1
- package/dist/Sia2.js +0 -1
- package/dist/SiaPopup.js +0 -1
- package/dist/ToolBar.js +0 -1
- package/dist/ToolbarItem.js +0 -1
- package/dist/_virtual/_commonjsHelpers.js +0 -1
- package/dist/_virtual/lodash.js +0 -1
- package/dist/assets/Annotation/Annotation-Cd5Ua5TG.css +0 -1
- package/dist/assets/Toolbar-Cp1xyYeH.css +0 -1
- package/dist/filterTools.js +0 -1
- package/dist/siaDummyData.js +0 -7
- package/dist/stories/Canvas/CanvasOffset.js +0 -1
- package/dist/stories/FilterDropdown.stories.js +0 -1
- package/dist/stories/SIA/SIA.stories.d.ts +0 -36
- package/dist/stories/SIA2/DemoWrapper.js +0 -1
- package/dist/stories/Toolbar/ImageTools/ImageLabel.stories.d.ts +0 -13
- package/dist/stories/siaDummyData.js +0 -1
- package/dist/stories/siaDummyData2.js +0 -7
- package/dist/types/annoStatus.js +0 -1
- package/dist/types/canvasActions.js +0 -1
- package/dist/types/cursorstyles.js +0 -1
- package/dist/types/modes.js +0 -1
- package/dist/types/notificationType.js +0 -1
- package/dist/types/toolbarEvents.js +0 -1
- package/dist/types/tools.js +0 -1
- package/dist/utils/annoConversion.js +0 -1
- package/dist/utils/annoConversion2.d.ts +0 -27
- package/dist/utils/annoConversion2.js +0 -1
- package/dist/utils/colorlut.js +0 -1
- package/dist/utils/constraints.js +0 -1
- package/dist/utils/hist.js +0 -1
- package/dist/utils/keyActions.js +0 -1
- package/dist/utils/mouse2.js +0 -1
- package/dist/utils/transform2.js +0 -1
- package/src/AnnoLabelInput.jsx +0 -109
- package/src/AnnoToolBar.jsx +0 -153
- package/src/Annotation/AnnoBar.jsx +0 -154
- package/src/Annotation/Annotation.jsx +0 -395
- package/src/Annotation/Annotation.scss +0 -47
- package/src/Annotation/BBox.jsx +0 -299
- package/src/Annotation/Edge.jsx +0 -92
- package/src/Annotation/InfSelectionArea.jsx +0 -72
- package/src/Annotation/Line.jsx +0 -68
- package/src/Annotation/Node.jsx +0 -282
- package/src/Annotation/Point.jsx +0 -200
- package/src/Annotation/Polygon.jsx +0 -404
- package/src/Canvas.jsx +0 -2194
- package/src/ImgBar.jsx +0 -131
- package/src/LabelInput.jsx +0 -238
- package/src/Prompt.jsx +0 -45
- package/src/SIAFilterButton.jsx +0 -186
- package/src/Sia.jsx +0 -478
- package/src/SiaPopup.jsx +0 -15
- package/src/ToolBar.jsx +0 -463
- package/src/Toolbar/ToolbarItem.jsx +0 -30
- package/src/Toolbar.css +0 -13
- package/src/ToolbarItem.jsx +0 -31
- package/src/filterTools.js +0 -5
- package/src/stories/SIA/SIA.stories.tsx +0 -64
- package/src/stories/Toolbar/ImageTools/ImageLabel.stories.tsx +0 -31
- package/src/stories/lost.js +0 -54
- package/src/stories/store.js +0 -18
- package/src/test.js +0 -7
- package/src/types/annoStatus.js +0 -4
- package/src/types/canvasActions.js +0 -58
- package/src/types/cursorstyles.js +0 -3
- package/src/types/modes.js +0 -9
- package/src/types/notificationType.js +0 -11
- package/src/types/toolbarEvents.js +0 -35
- package/src/types/tools.js +0 -17
- package/src/utils/annoConversion.js +0 -145
- package/src/utils/annoConversion2.ts +0 -145
- package/src/utils/colorlut.js +0 -68
- package/src/utils/constraints.js +0 -81
- package/src/utils/mouse.js +0 -14
- package/src/utils/transform.js +0 -336
- package/src/utils/windowViewport.js +0 -34
- /package/dist/{Sia2.d.ts → Sia.d.ts} +0 -0
- /package/dist/utils/{mouse2.d.ts → mouse.d.ts} +0 -0
- /package/dist/utils/{transform2.d.ts → transform.d.ts} +0 -0
- /package/src/utils/{mouse2.ts → mouse.ts} +0 -0
- /package/src/utils/{transform2.ts → transform.ts} +0 -0
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { CSSProperties, MouseEvent, useEffect, useRef, useState } from
|
|
1
|
+
import { CSSProperties, MouseEvent, useEffect, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
// rename type to avoid naming conflict
|
|
4
|
-
import { AnnotationSettings, Point } from
|
|
5
|
-
import Node from
|
|
6
|
-
import AnnotationMode from
|
|
7
|
-
import Edge from
|
|
8
|
-
import
|
|
4
|
+
import { AnnotationSettings, Point } from '../../../types'
|
|
5
|
+
import Node from '../atoms/Node'
|
|
6
|
+
import AnnotationMode from '../../../models/AnnotationMode'
|
|
7
|
+
import Edge from '../atoms/Edge'
|
|
8
|
+
import mouse from '../../../utils/mouse'
|
|
9
9
|
|
|
10
10
|
type LineProps = {
|
|
11
|
-
annotationSettings: AnnotationSettings
|
|
12
|
-
coordinates: Point[]
|
|
13
|
-
isSelected: boolean
|
|
14
|
-
annotationMode: AnnotationMode
|
|
15
|
-
setAnnotationMode: (annotationMode: AnnotationMode) => void
|
|
16
|
-
pageToStageOffset: Point
|
|
17
|
-
svgScale: number
|
|
18
|
-
svgTranslation: Point
|
|
19
|
-
style: CSSProperties
|
|
20
|
-
onAddNode: (coordinates: Point[]) => void
|
|
21
|
-
onDeleteNode: (coordinates: Point[]) => void
|
|
22
|
-
onFinishAnnoCreate: () => void
|
|
23
|
-
onIsDraggingStateChanged: (newDraggingState: boolean) => void
|
|
24
|
-
onMoving: (coordinates: Point[]) => void
|
|
25
|
-
onMoved: () => void
|
|
26
|
-
}
|
|
11
|
+
annotationSettings: AnnotationSettings
|
|
12
|
+
coordinates: Point[]
|
|
13
|
+
isSelected: boolean
|
|
14
|
+
annotationMode: AnnotationMode
|
|
15
|
+
setAnnotationMode: (annotationMode: AnnotationMode) => void
|
|
16
|
+
pageToStageOffset: Point
|
|
17
|
+
svgScale: number
|
|
18
|
+
svgTranslation: Point
|
|
19
|
+
style: CSSProperties
|
|
20
|
+
onAddNode: (coordinates: Point[]) => void
|
|
21
|
+
onDeleteNode: (coordinates: Point[]) => void
|
|
22
|
+
onFinishAnnoCreate: () => void
|
|
23
|
+
onIsDraggingStateChanged: (newDraggingState: boolean) => void
|
|
24
|
+
onMoving: (coordinates: Point[]) => void // during moving - update coordinates in parent
|
|
25
|
+
onMoved: () => void // moving finished - send annotation changed event
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
const Line = ({
|
|
29
29
|
annotationSettings,
|
|
@@ -41,43 +41,38 @@ const Line = ({
|
|
|
41
41
|
onMoved,
|
|
42
42
|
onIsDraggingStateChanged,
|
|
43
43
|
}: LineProps) => {
|
|
44
|
-
const [isAnnoDragging, setIsAnnoDragging] = useState<boolean>(false)
|
|
44
|
+
const [isAnnoDragging, setIsAnnoDragging] = useState<boolean>(false)
|
|
45
45
|
|
|
46
46
|
// onMove and onMouseUp events are fired in the same frame
|
|
47
47
|
// use a ref to access the updated value without waiting until the next frame
|
|
48
|
-
const [didAnnoActuallyMove, setDidAnnoActuallyMove] =
|
|
49
|
-
|
|
50
|
-
const didAnnoActuallyMoveRef = useRef<boolean>(didAnnoActuallyMove);
|
|
48
|
+
const [didAnnoActuallyMove, setDidAnnoActuallyMove] = useState<boolean>(false)
|
|
49
|
+
const didAnnoActuallyMoveRef = useRef<boolean>(didAnnoActuallyMove)
|
|
51
50
|
|
|
52
51
|
useEffect(() => {
|
|
53
|
-
didAnnoActuallyMoveRef.current = didAnnoActuallyMove
|
|
54
|
-
}, [didAnnoActuallyMove])
|
|
52
|
+
didAnnoActuallyMoveRef.current = didAnnoActuallyMove
|
|
53
|
+
}, [didAnnoActuallyMove])
|
|
55
54
|
|
|
56
55
|
const onMouseDown = (e: MouseEvent) => {
|
|
57
|
-
if (annotationSettings.canEdit === false) return
|
|
56
|
+
if (annotationSettings.canEdit === false) return
|
|
58
57
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
annotationMode !== AnnotationMode.CREATE &&
|
|
62
|
-
e.button === 0
|
|
63
|
-
)
|
|
64
|
-
setIsAnnoDragging(true);
|
|
58
|
+
if (isSelected && annotationMode !== AnnotationMode.CREATE && e.button === 0)
|
|
59
|
+
setIsAnnoDragging(true)
|
|
65
60
|
|
|
66
61
|
if (e.button === 2 && annotationMode == AnnotationMode.CREATE) {
|
|
67
62
|
const antiScaledMousePositionInStageCoordinates =
|
|
68
|
-
|
|
63
|
+
mouse.getAntiScaledMouseStagePosition(
|
|
69
64
|
e,
|
|
70
65
|
pageToStageOffset,
|
|
71
66
|
svgScale,
|
|
72
67
|
svgTranslation,
|
|
73
|
-
)
|
|
68
|
+
)
|
|
74
69
|
|
|
75
|
-
const newCoordinates = [...coordinates]
|
|
76
|
-
newCoordinates.push(antiScaledMousePositionInStageCoordinates)
|
|
70
|
+
const newCoordinates = [...coordinates]
|
|
71
|
+
newCoordinates.push(antiScaledMousePositionInStageCoordinates)
|
|
77
72
|
|
|
78
|
-
onAddNode(newCoordinates)
|
|
73
|
+
onAddNode(newCoordinates)
|
|
79
74
|
}
|
|
80
|
-
}
|
|
75
|
+
}
|
|
81
76
|
|
|
82
77
|
const onMouseMove = (e: MouseEvent) => {
|
|
83
78
|
if (isAnnoDragging) {
|
|
@@ -87,66 +82,66 @@ const Line = ({
|
|
|
87
82
|
// counter the canvas scaling (it will be automatically applied when rendering the annotation coordinates)
|
|
88
83
|
x: (coordinate.x += e.movementX / svgScale),
|
|
89
84
|
y: (coordinate.y += e.movementY / svgScale),
|
|
90
|
-
}
|
|
91
|
-
})
|
|
85
|
+
}
|
|
86
|
+
})
|
|
92
87
|
|
|
93
88
|
// only escalate event when mouse actually moved
|
|
94
89
|
if (e.movementX !== 0 || e.movementY !== 0) {
|
|
95
|
-
setDidAnnoActuallyMove(true)
|
|
96
|
-
onMoving(movedCoordinates)
|
|
90
|
+
setDidAnnoActuallyMove(true)
|
|
91
|
+
onMoving(movedCoordinates)
|
|
97
92
|
}
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
if (annotationMode === AnnotationMode.CREATE) {
|
|
101
|
-
const mousePointInStage =
|
|
96
|
+
const mousePointInStage = mouse.getAntiScaledMouseStagePosition(
|
|
102
97
|
e,
|
|
103
98
|
pageToStageOffset,
|
|
104
99
|
svgScale,
|
|
105
100
|
svgTranslation,
|
|
106
|
-
)
|
|
101
|
+
)
|
|
107
102
|
|
|
108
|
-
let newCoords: Point[] = [...coordinates]
|
|
103
|
+
let newCoords: Point[] = [...coordinates]
|
|
109
104
|
|
|
110
105
|
// last coordinate = mouse position - update it
|
|
111
|
-
if (coordinates.length > 1) newCoords = coordinates.slice(0, -1)
|
|
106
|
+
if (coordinates.length > 1) newCoords = coordinates.slice(0, -1)
|
|
112
107
|
|
|
113
|
-
newCoords.push(mousePointInStage)
|
|
108
|
+
newCoords.push(mousePointInStage)
|
|
114
109
|
|
|
115
|
-
onMoving(newCoords)
|
|
110
|
+
onMoving(newCoords)
|
|
116
111
|
}
|
|
117
|
-
}
|
|
112
|
+
}
|
|
118
113
|
|
|
119
114
|
useEffect(() => {
|
|
120
|
-
onIsDraggingStateChanged(isAnnoDragging)
|
|
121
|
-
if (!isAnnoDragging) return
|
|
115
|
+
onIsDraggingStateChanged(isAnnoDragging)
|
|
116
|
+
if (!isAnnoDragging) return
|
|
122
117
|
|
|
123
118
|
const handleMouseUp = () => {
|
|
124
|
-
setIsAnnoDragging(false)
|
|
119
|
+
setIsAnnoDragging(false)
|
|
125
120
|
|
|
126
|
-
if (didAnnoActuallyMoveRef.current) onMoved()
|
|
127
|
-
setDidAnnoActuallyMove(false)
|
|
128
|
-
}
|
|
121
|
+
if (didAnnoActuallyMoveRef.current) onMoved()
|
|
122
|
+
setDidAnnoActuallyMove(false)
|
|
123
|
+
}
|
|
129
124
|
|
|
130
|
-
window.addEventListener(
|
|
125
|
+
window.addEventListener('mouseup', handleMouseUp)
|
|
131
126
|
|
|
132
127
|
return () => {
|
|
133
|
-
window.removeEventListener(
|
|
134
|
-
}
|
|
135
|
-
}, [isAnnoDragging])
|
|
128
|
+
window.removeEventListener('mouseup', handleMouseUp)
|
|
129
|
+
}
|
|
130
|
+
}, [isAnnoDragging])
|
|
136
131
|
|
|
137
132
|
const renderInfiniteSelectionArea = () => {
|
|
138
133
|
return (
|
|
139
134
|
<circle
|
|
140
135
|
cx={coordinates[0].x}
|
|
141
136
|
cy={coordinates[0].y}
|
|
142
|
-
r={
|
|
137
|
+
r={'100%'}
|
|
143
138
|
style={{ opacity: 0 }}
|
|
144
139
|
onMouseDown={onMouseDown}
|
|
145
140
|
onMouseMove={onMouseMove}
|
|
146
141
|
onContextMenu={(e) => e.preventDefault()}
|
|
147
142
|
/>
|
|
148
|
-
)
|
|
149
|
-
}
|
|
143
|
+
)
|
|
144
|
+
}
|
|
150
145
|
|
|
151
146
|
const renderNodes = () => {
|
|
152
147
|
const svgNodes = coordinates.map((coordinate: Point, index: number) => (
|
|
@@ -160,27 +155,27 @@ const Line = ({
|
|
|
160
155
|
svgTranslation={svgTranslation}
|
|
161
156
|
style={style}
|
|
162
157
|
onDeleteNode={() => {
|
|
163
|
-
const newCoordinates = [...coordinates]
|
|
164
|
-
newCoordinates.splice(index, 1)
|
|
165
|
-
onDeleteNode(newCoordinates)
|
|
158
|
+
const newCoordinates = [...coordinates]
|
|
159
|
+
newCoordinates.splice(index, 1)
|
|
160
|
+
onDeleteNode(newCoordinates)
|
|
166
161
|
}}
|
|
167
162
|
onMoving={(index, newPoint) => {
|
|
168
|
-
const newCoordinates = [...coordinates]
|
|
169
|
-
newCoordinates[index] = newPoint
|
|
170
|
-
onMoving(newCoordinates)
|
|
163
|
+
const newCoordinates = [...coordinates]
|
|
164
|
+
newCoordinates[index] = newPoint
|
|
165
|
+
onMoving(newCoordinates)
|
|
171
166
|
}}
|
|
172
167
|
onMoved={() => onMoved()}
|
|
173
168
|
onIsDraggingStateChanged={onIsDraggingStateChanged}
|
|
174
169
|
/>
|
|
175
|
-
))
|
|
170
|
+
))
|
|
176
171
|
|
|
177
|
-
return svgNodes
|
|
178
|
-
}
|
|
172
|
+
return svgNodes
|
|
173
|
+
}
|
|
179
174
|
|
|
180
175
|
const renderEdges = () => {
|
|
181
176
|
const svgEdges = coordinates.map((coordinate: Point, index: number) => {
|
|
182
177
|
// last coordinate has no end - dont draw it
|
|
183
|
-
if (index + 1 >= coordinates.length) return
|
|
178
|
+
if (index + 1 >= coordinates.length) return
|
|
184
179
|
|
|
185
180
|
return (
|
|
186
181
|
<Edge
|
|
@@ -192,12 +187,12 @@ const Line = ({
|
|
|
192
187
|
svgTranslation={svgTranslation}
|
|
193
188
|
style={style}
|
|
194
189
|
onAddNode={(coordinate: Point) => {
|
|
195
|
-
const newCoordinates = [...coordinates]
|
|
190
|
+
const newCoordinates = [...coordinates]
|
|
196
191
|
|
|
197
192
|
// add element at index while keeping the others
|
|
198
|
-
newCoordinates.splice(index + 1, 0, coordinate)
|
|
193
|
+
newCoordinates.splice(index + 1, 0, coordinate)
|
|
199
194
|
|
|
200
|
-
onAddNode(newCoordinates)
|
|
195
|
+
onAddNode(newCoordinates)
|
|
201
196
|
}}
|
|
202
197
|
onDoubleClick={() =>
|
|
203
198
|
annotationMode === AnnotationMode.CREATE && onFinishAnnoCreate()
|
|
@@ -205,14 +200,13 @@ const Line = ({
|
|
|
205
200
|
onMouseDown={onMouseDown}
|
|
206
201
|
onMouseMove={onMouseMove}
|
|
207
202
|
/>
|
|
208
|
-
)
|
|
209
|
-
})
|
|
203
|
+
)
|
|
204
|
+
})
|
|
210
205
|
|
|
211
|
-
return svgEdges
|
|
212
|
-
}
|
|
206
|
+
return svgEdges
|
|
207
|
+
}
|
|
213
208
|
|
|
214
|
-
const canRenderNodes: boolean =
|
|
215
|
-
isSelected && annotationMode !== AnnotationMode.CREATE;
|
|
209
|
+
const canRenderNodes: boolean = isSelected && annotationMode !== AnnotationMode.CREATE
|
|
216
210
|
|
|
217
211
|
// nodes need to be drawn after the edges to make them fully clickable
|
|
218
212
|
return (
|
|
@@ -222,7 +216,7 @@ const Line = ({
|
|
|
222
216
|
{renderEdges()}
|
|
223
217
|
{canRenderNodes && renderNodes()}
|
|
224
218
|
</g>
|
|
225
|
-
)
|
|
226
|
-
}
|
|
219
|
+
)
|
|
220
|
+
}
|
|
227
221
|
|
|
228
|
-
export default Line
|
|
222
|
+
export default Line
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { CSSProperties, MouseEvent, useEffect, useRef, useState } from
|
|
1
|
+
import { CSSProperties, MouseEvent, useEffect, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
// rename type to avoid naming conflict
|
|
4
|
-
import { Point, SIANotification } from
|
|
5
|
-
import Node from
|
|
6
|
-
import PolygonArea from
|
|
7
|
-
import AnnotationMode from
|
|
8
|
-
import Edge from
|
|
9
|
-
import
|
|
10
|
-
import { NotificationType } from
|
|
11
|
-
import { AnnotationSettings } from
|
|
4
|
+
import { Point, SIANotification } from '../../../types'
|
|
5
|
+
import Node from '../atoms/Node'
|
|
6
|
+
import PolygonArea from '../atoms/PolygonArea'
|
|
7
|
+
import AnnotationMode from '../../../models/AnnotationMode'
|
|
8
|
+
import Edge from '../atoms/Edge'
|
|
9
|
+
import mouse from '../../../utils/mouse'
|
|
10
|
+
import { NotificationType } from '../../../models'
|
|
11
|
+
import { AnnotationSettings } from '../../../types'
|
|
12
12
|
|
|
13
13
|
type PolygonProps = {
|
|
14
|
-
annotationSettings: AnnotationSettings
|
|
15
|
-
coordinates: Point[]
|
|
16
|
-
isSelected: boolean
|
|
17
|
-
isDisabled?: boolean
|
|
18
|
-
annotationMode: AnnotationMode
|
|
19
|
-
setAnnotationMode: (annotationMode: AnnotationMode) => void
|
|
20
|
-
pageToStageOffset: Point
|
|
21
|
-
svgScale: number
|
|
22
|
-
svgTranslation: Point
|
|
23
|
-
style: CSSProperties
|
|
24
|
-
onAddNode: (coordinates: Point[]) => void
|
|
25
|
-
onDeleteNode: (coordinates: Point[]) => void
|
|
26
|
-
onFinishAnnoCreate: () => void
|
|
27
|
-
onIsDraggingStateChanged: (newDraggingState: boolean) => void
|
|
28
|
-
onMoving: (coordinates: Point[]) => void
|
|
29
|
-
onMoved: () => void
|
|
30
|
-
onNotification?: (notification: SIANotification) => void
|
|
31
|
-
}
|
|
14
|
+
annotationSettings: AnnotationSettings
|
|
15
|
+
coordinates: Point[]
|
|
16
|
+
isSelected: boolean
|
|
17
|
+
isDisabled?: boolean
|
|
18
|
+
annotationMode: AnnotationMode
|
|
19
|
+
setAnnotationMode: (annotationMode: AnnotationMode) => void
|
|
20
|
+
pageToStageOffset: Point
|
|
21
|
+
svgScale: number
|
|
22
|
+
svgTranslation: Point
|
|
23
|
+
style: CSSProperties
|
|
24
|
+
onAddNode: (coordinates: Point[]) => void
|
|
25
|
+
onDeleteNode: (coordinates: Point[]) => void
|
|
26
|
+
onFinishAnnoCreate: () => void
|
|
27
|
+
onIsDraggingStateChanged: (newDraggingState: boolean) => void
|
|
28
|
+
onMoving: (coordinates: Point[]) => void // during moving - update coordinates in parent
|
|
29
|
+
onMoved: () => void // moving finished - send annotation changed event
|
|
30
|
+
onNotification?: (notification: SIANotification) => void
|
|
31
|
+
}
|
|
32
32
|
|
|
33
33
|
const Polygon = ({
|
|
34
34
|
annotationSettings,
|
|
@@ -48,31 +48,30 @@ const Polygon = ({
|
|
|
48
48
|
onMoved,
|
|
49
49
|
onNotification = (_) => {},
|
|
50
50
|
}: PolygonProps) => {
|
|
51
|
-
const [isAnnoDragging, setIsAnnoDragging] = useState<boolean>(false)
|
|
51
|
+
const [isAnnoDragging, setIsAnnoDragging] = useState<boolean>(false)
|
|
52
52
|
|
|
53
53
|
// onMove and onMouseUp events are fired in the same frame
|
|
54
54
|
// use a ref to access the updated value without waiting until the next frame
|
|
55
|
-
const [didAnnoActuallyMove, setDidAnnoActuallyMove] =
|
|
56
|
-
|
|
57
|
-
const didAnnoActuallyMoveRef = useRef<boolean>(didAnnoActuallyMove);
|
|
55
|
+
const [didAnnoActuallyMove, setDidAnnoActuallyMove] = useState<boolean>(false)
|
|
56
|
+
const didAnnoActuallyMoveRef = useRef<boolean>(didAnnoActuallyMove)
|
|
58
57
|
|
|
59
58
|
const handleFinishAnnoCreate = () => {
|
|
60
59
|
if (coordinates.length < 3)
|
|
61
60
|
return onNotification({
|
|
62
|
-
message:
|
|
63
|
-
title:
|
|
61
|
+
message: 'Polygons must have at least 3 nodes',
|
|
62
|
+
title: 'Polygon Error',
|
|
64
63
|
type: NotificationType.ERROR,
|
|
65
|
-
})
|
|
64
|
+
})
|
|
66
65
|
|
|
67
|
-
onFinishAnnoCreate()
|
|
68
|
-
}
|
|
66
|
+
onFinishAnnoCreate()
|
|
67
|
+
}
|
|
69
68
|
|
|
70
69
|
useEffect(() => {
|
|
71
|
-
didAnnoActuallyMoveRef.current = didAnnoActuallyMove
|
|
72
|
-
}, [didAnnoActuallyMove])
|
|
70
|
+
didAnnoActuallyMoveRef.current = didAnnoActuallyMove
|
|
71
|
+
}, [didAnnoActuallyMove])
|
|
73
72
|
|
|
74
73
|
const onMouseDown = (e: MouseEvent) => {
|
|
75
|
-
if (annotationSettings.canEdit === false) return
|
|
74
|
+
if (annotationSettings.canEdit === false) return
|
|
76
75
|
|
|
77
76
|
if (
|
|
78
77
|
isSelected &&
|
|
@@ -80,26 +79,26 @@ const Polygon = ({
|
|
|
80
79
|
annotationMode !== AnnotationMode.ADD &&
|
|
81
80
|
e.button === 0
|
|
82
81
|
)
|
|
83
|
-
setIsAnnoDragging(true)
|
|
82
|
+
setIsAnnoDragging(true)
|
|
84
83
|
|
|
85
84
|
if (
|
|
86
85
|
e.button === 2 &&
|
|
87
86
|
[AnnotationMode.CREATE, AnnotationMode.ADD].includes(annotationMode)
|
|
88
87
|
) {
|
|
89
88
|
const antiScaledMousePositionInStageCoordinates =
|
|
90
|
-
|
|
89
|
+
mouse.getAntiScaledMouseStagePosition(
|
|
91
90
|
e,
|
|
92
91
|
pageToStageOffset,
|
|
93
92
|
svgScale,
|
|
94
93
|
svgTranslation,
|
|
95
|
-
)
|
|
94
|
+
)
|
|
96
95
|
|
|
97
|
-
const newCoordinates = [...coordinates]
|
|
98
|
-
newCoordinates.push(antiScaledMousePositionInStageCoordinates)
|
|
96
|
+
const newCoordinates = [...coordinates]
|
|
97
|
+
newCoordinates.push(antiScaledMousePositionInStageCoordinates)
|
|
99
98
|
|
|
100
|
-
onAddNode(newCoordinates)
|
|
99
|
+
onAddNode(newCoordinates)
|
|
101
100
|
}
|
|
102
|
-
}
|
|
101
|
+
}
|
|
103
102
|
|
|
104
103
|
const onMouseMove = (e: MouseEvent) => {
|
|
105
104
|
if (isAnnoDragging) {
|
|
@@ -109,52 +108,52 @@ const Polygon = ({
|
|
|
109
108
|
// counter the canvas scaling (it will be automatically applied when rendering the annotation coordinates)
|
|
110
109
|
x: (coordinate.x += e.movementX / svgScale),
|
|
111
110
|
y: (coordinate.y += e.movementY / svgScale),
|
|
112
|
-
}
|
|
113
|
-
})
|
|
111
|
+
}
|
|
112
|
+
})
|
|
114
113
|
|
|
115
114
|
// only escalate event when mouse actually moved
|
|
116
115
|
if (e.movementX !== 0 || e.movementY !== 0) {
|
|
117
|
-
setDidAnnoActuallyMove(true)
|
|
118
|
-
onMoving(movedCoordinates)
|
|
116
|
+
setDidAnnoActuallyMove(true)
|
|
117
|
+
onMoving(movedCoordinates)
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
if (annotationMode === AnnotationMode.CREATE) {
|
|
123
|
-
const mousePointInStage =
|
|
122
|
+
const mousePointInStage = mouse.getAntiScaledMouseStagePosition(
|
|
124
123
|
e,
|
|
125
124
|
pageToStageOffset,
|
|
126
125
|
svgScale,
|
|
127
126
|
svgTranslation,
|
|
128
|
-
)
|
|
127
|
+
)
|
|
129
128
|
|
|
130
|
-
let newCoords: Point[] = [...coordinates]
|
|
129
|
+
let newCoords: Point[] = [...coordinates]
|
|
131
130
|
|
|
132
131
|
// last coordinate = mouse position - update it
|
|
133
|
-
if (coordinates.length > 1) newCoords = coordinates.slice(0, -1)
|
|
132
|
+
if (coordinates.length > 1) newCoords = coordinates.slice(0, -1)
|
|
134
133
|
|
|
135
|
-
newCoords.push(mousePointInStage)
|
|
134
|
+
newCoords.push(mousePointInStage)
|
|
136
135
|
|
|
137
|
-
onMoving(newCoords)
|
|
136
|
+
onMoving(newCoords)
|
|
138
137
|
}
|
|
139
|
-
}
|
|
138
|
+
}
|
|
140
139
|
|
|
141
140
|
useEffect(() => {
|
|
142
|
-
onIsDraggingStateChanged(isAnnoDragging)
|
|
143
|
-
if (!isAnnoDragging) return
|
|
141
|
+
onIsDraggingStateChanged(isAnnoDragging)
|
|
142
|
+
if (!isAnnoDragging) return
|
|
144
143
|
|
|
145
144
|
const handleMouseUp = () => {
|
|
146
|
-
setIsAnnoDragging(false)
|
|
145
|
+
setIsAnnoDragging(false)
|
|
147
146
|
|
|
148
|
-
if (didAnnoActuallyMoveRef.current) onMoved()
|
|
149
|
-
setDidAnnoActuallyMove(false)
|
|
150
|
-
}
|
|
147
|
+
if (didAnnoActuallyMoveRef.current) onMoved()
|
|
148
|
+
setDidAnnoActuallyMove(false)
|
|
149
|
+
}
|
|
151
150
|
|
|
152
|
-
window.addEventListener(
|
|
151
|
+
window.addEventListener('mouseup', handleMouseUp)
|
|
153
152
|
|
|
154
153
|
return () => {
|
|
155
|
-
window.removeEventListener(
|
|
156
|
-
}
|
|
157
|
-
}, [isAnnoDragging])
|
|
154
|
+
window.removeEventListener('mouseup', handleMouseUp)
|
|
155
|
+
}
|
|
156
|
+
}, [isAnnoDragging])
|
|
158
157
|
|
|
159
158
|
const renderNodes = () => {
|
|
160
159
|
const svgNodes = coordinates.map((coordinate: Point, index: number) => (
|
|
@@ -171,34 +170,32 @@ const Polygon = ({
|
|
|
171
170
|
// 4 is the lowest node count where we can delete one
|
|
172
171
|
if (coordinates.length < 4)
|
|
173
172
|
return onNotification({
|
|
174
|
-
message:
|
|
175
|
-
title:
|
|
173
|
+
message: 'Polygons must have at least 3 nodes',
|
|
174
|
+
title: 'Polygon Error',
|
|
176
175
|
type: NotificationType.ERROR,
|
|
177
|
-
})
|
|
176
|
+
})
|
|
178
177
|
|
|
179
|
-
const newCoordinates = [...coordinates]
|
|
180
|
-
newCoordinates.splice(index, 1)
|
|
181
|
-
onDeleteNode(newCoordinates)
|
|
178
|
+
const newCoordinates = [...coordinates]
|
|
179
|
+
newCoordinates.splice(index, 1)
|
|
180
|
+
onDeleteNode(newCoordinates)
|
|
182
181
|
}}
|
|
183
182
|
onMoving={(index, newPoint) => {
|
|
184
|
-
const newCoordinates = [...coordinates]
|
|
185
|
-
newCoordinates[index] = newPoint
|
|
186
|
-
onMoving(newCoordinates)
|
|
183
|
+
const newCoordinates = [...coordinates]
|
|
184
|
+
newCoordinates[index] = newPoint
|
|
185
|
+
onMoving(newCoordinates)
|
|
187
186
|
}}
|
|
188
187
|
onMoved={() => onMoved()}
|
|
189
188
|
onIsDraggingStateChanged={onIsDraggingStateChanged}
|
|
190
189
|
/>
|
|
191
|
-
))
|
|
190
|
+
))
|
|
192
191
|
|
|
193
|
-
return svgNodes
|
|
194
|
-
}
|
|
192
|
+
return svgNodes
|
|
193
|
+
}
|
|
195
194
|
|
|
196
195
|
const renderEdges = () => {
|
|
197
196
|
const svgEdges = coordinates.map((coordinate: Point, index: number) => {
|
|
198
197
|
const endCoordinates: Point =
|
|
199
|
-
index + 1 < coordinates.length
|
|
200
|
-
? coordinates[index + 1]
|
|
201
|
-
: coordinates[0];
|
|
198
|
+
index + 1 < coordinates.length ? coordinates[index + 1] : coordinates[0]
|
|
202
199
|
|
|
203
200
|
return (
|
|
204
201
|
<Edge
|
|
@@ -211,10 +208,10 @@ const Polygon = ({
|
|
|
211
208
|
svgTranslation={svgTranslation}
|
|
212
209
|
style={style}
|
|
213
210
|
onAddNode={(coordinate: Point) => {
|
|
214
|
-
const newCoordinates = [...coordinates]
|
|
215
|
-
newCoordinates.splice(index + 1, 0, coordinate)
|
|
211
|
+
const newCoordinates = [...coordinates]
|
|
212
|
+
newCoordinates.splice(index + 1, 0, coordinate)
|
|
216
213
|
|
|
217
|
-
onAddNode(newCoordinates)
|
|
214
|
+
onAddNode(newCoordinates)
|
|
218
215
|
}}
|
|
219
216
|
onDoubleClick={() =>
|
|
220
217
|
annotationMode === AnnotationMode.CREATE && handleFinishAnnoCreate()
|
|
@@ -222,24 +219,24 @@ const Polygon = ({
|
|
|
222
219
|
onMouseDown={onMouseDown}
|
|
223
220
|
onMouseMove={onMouseMove}
|
|
224
221
|
/>
|
|
225
|
-
)
|
|
226
|
-
})
|
|
227
|
-
return svgEdges
|
|
228
|
-
}
|
|
222
|
+
)
|
|
223
|
+
})
|
|
224
|
+
return svgEdges
|
|
225
|
+
}
|
|
229
226
|
|
|
230
227
|
const renderInfiniteSelectionArea = () => {
|
|
231
228
|
return (
|
|
232
229
|
<circle
|
|
233
230
|
cx={coordinates[0].x}
|
|
234
231
|
cy={coordinates[0].y}
|
|
235
|
-
r={
|
|
232
|
+
r={'100%'}
|
|
236
233
|
style={{ opacity: 0 }}
|
|
237
234
|
onMouseDown={onMouseDown}
|
|
238
235
|
onMouseMove={onMouseMove}
|
|
239
236
|
onContextMenu={(e) => e.preventDefault()}
|
|
240
237
|
/>
|
|
241
|
-
)
|
|
242
|
-
}
|
|
238
|
+
)
|
|
239
|
+
}
|
|
243
240
|
|
|
244
241
|
// nodes need to be drawn after the polyline to make them clickable
|
|
245
242
|
return (
|
|
@@ -265,7 +262,7 @@ const Polygon = ({
|
|
|
265
262
|
{isSelected && annotationSettings.canEdit && renderEdges()}
|
|
266
263
|
{isSelected && annotationMode !== AnnotationMode.CREATE && renderNodes()}
|
|
267
264
|
</g>
|
|
268
|
-
)
|
|
269
|
-
}
|
|
265
|
+
)
|
|
266
|
+
}
|
|
270
267
|
|
|
271
|
-
export default Polygon
|
|
268
|
+
export default Polygon
|