lost-sia 1.3.0 → 2.0.0-alpha1

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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/package.json +60 -47
  4. package/src/AnnoExampleViewer.jsx +57 -0
  5. package/src/AnnoLabelInput.jsx +99 -0
  6. package/src/AnnoToolBar.jsx +132 -0
  7. package/src/Annotation/AnnoBar.jsx +148 -0
  8. package/src/Annotation/Annotation.jsx +358 -0
  9. package/src/Annotation/Annotation.scss +47 -0
  10. package/src/Annotation/BBox.jsx +291 -0
  11. package/src/Annotation/Edge.jsx +82 -0
  12. package/src/Annotation/InfSelectionArea.jsx +71 -0
  13. package/src/Annotation/Line.jsx +60 -0
  14. package/src/Annotation/Node.jsx +278 -0
  15. package/src/Annotation/Point.jsx +196 -0
  16. package/src/Annotation/Polygon.jsx +361 -0
  17. package/src/Canvas.jsx +1843 -0
  18. package/src/ImgBar.jsx +123 -0
  19. package/src/InfoBoxes/AnnoDetails.jsx +166 -0
  20. package/src/InfoBoxes/AnnoStats.jsx +104 -0
  21. package/src/InfoBoxes/InfoBox.jsx +78 -0
  22. package/src/InfoBoxes/InfoBoxArea.jsx +155 -0
  23. package/src/InfoBoxes/LabelInfo.jsx +95 -0
  24. package/src/LabelInput.jsx +224 -0
  25. package/src/Prompt.jsx +46 -0
  26. package/src/SIA.scss +10 -0
  27. package/src/SIAFilterButton.jsx +178 -0
  28. package/src/SIASettingButton.jsx +122 -0
  29. package/src/Sia.jsx +491 -0
  30. package/src/SiaPopup.jsx +10 -0
  31. package/src/ToolBar.jsx +399 -0
  32. package/src/Toolbar.css +13 -0
  33. package/src/ToolbarItem.jsx +25 -0
  34. package/src/filterTools.js +3 -0
  35. package/src/index.js +16 -0
  36. package/src/siaDummyData.js +265 -0
  37. package/src/style.scss +3 -0
  38. package/src/test.js +7 -0
  39. package/src/types/annoStatus.js +4 -0
  40. package/src/types/canvasActions.js +57 -0
  41. package/src/types/cursorstyles.js +3 -0
  42. package/src/types/modes.js +8 -0
  43. package/src/types/notificationType.js +4 -0
  44. package/src/types/toolbarEvents.js +33 -0
  45. package/src/types/tools.js +11 -0
  46. package/src/utils/annoConversion.js +115 -0
  47. package/src/utils/colorlut.js +67 -0
  48. package/src/utils/constraints.js +75 -0
  49. package/src/utils/hist.js +67 -0
  50. package/src/utils/keyActions.js +107 -0
  51. package/src/utils/mouse.js +14 -0
  52. package/src/utils/siaIcons.jsx +95 -0
  53. package/src/utils/transform.js +318 -0
  54. package/src/utils/uiConfig.js +57 -0
  55. package/src/utils/windowViewport.js +35 -0
  56. package/CHANGELOG.md +0 -169
  57. package/dist/index.css +0 -24823
  58. package/dist/index.es.js +0 -10482
  59. package/dist/index.es.js.map +0 -1
  60. package/dist/index.js +0 -10497
  61. package/dist/index.js.map +0 -1
@@ -0,0 +1,82 @@
1
+ import React, {Component} from 'react'
2
+ import './Annotation.scss'
3
+
4
+
5
+
6
+ class Edge extends Component{
7
+
8
+ constructor(props){
9
+ super(props)
10
+ this.state = {
11
+ haloCss: 'node-halo-off'
12
+ }
13
+ }
14
+
15
+ componentDidUpdate(){
16
+ }
17
+
18
+ onMouseOver(e){
19
+ if (this.props.isSelected){
20
+ this.setState({haloCss: 'node-halo-on'})
21
+ }
22
+ }
23
+
24
+ onMouseLeave(e){
25
+ if (this.props.isSelected){
26
+ this.setState({haloCss: 'node-halo-off'})
27
+ }
28
+ }
29
+
30
+ onMouseDown(e){
31
+ if (this.props.onMouseDown){
32
+ this.props.onMouseDown(e, this.props.idx)
33
+ }
34
+ }
35
+
36
+ onMouseUp(e){
37
+ e.stopPropagation()
38
+ }
39
+
40
+ render(){
41
+ let p1, p2
42
+ if (!this.props.closingEdge){
43
+ if (this.props.idx - 1 < 0 ){
44
+ return null
45
+ }
46
+ if (this.props.idx > this.props.anno.length - 1){
47
+ return null
48
+ }
49
+ p1 = this.props.anno[this.props.idx - 1 ]
50
+ p2 = this.props.anno[this.props.idx]
51
+ } else {
52
+ if (this.props.idx === 0 && this.props.anno.length === 1) return null
53
+ p1 = this.props.anno[this.props.anno.length-1]
54
+ p2 = this.props.anno[0]
55
+ }
56
+ return(<g
57
+ onMouseOver={(e) => {this.onMouseOver(e)}}
58
+ onMouseLeave={e => {this.onMouseLeave(e)}}
59
+
60
+ >
61
+ <line x1={p1.x} y1={p1.y}
62
+ x2={p2.x} y2={p2.y} stroke="black"
63
+ // style={this.props.style}
64
+ strokeWidth={this.props.style.strokeWidth*3}
65
+ className={this.state.haloCss}
66
+ onMouseOver={(e) => {this.onMouseOver(e)}}
67
+ onMouseDown={e => this.onMouseDown(e)}
68
+ onMouseUp={e => this.onMouseUp(e)}
69
+ />
70
+ <line x1={p1.x} y1={p1.y}
71
+ x2={p2.x} y2={p2.y} stroke="black"
72
+ style={this.props.style}
73
+ className={this.props.className}
74
+ onMouseDown={e => this.onMouseDown(e)}
75
+ onMouseUp={e => this.onMouseUp(e)}
76
+ />
77
+ </g>
78
+ )
79
+ }
80
+ }
81
+
82
+ export default Edge;
@@ -0,0 +1,71 @@
1
+ import React, {Component} from 'react'
2
+
3
+ class InfSelectionArea extends Component{
4
+
5
+ constructor(props){
6
+ super(props)
7
+ this.state = {
8
+ selAreaCss: 'sel-area-off',
9
+ }
10
+ }
11
+
12
+ componentDidMount(){
13
+ if (this.props.enable){
14
+ this.enableSelArea()
15
+ } else {
16
+ this.disableSelArea()
17
+ }
18
+ }
19
+
20
+ componentDidUpdate(){
21
+ if (this.props.enable){
22
+ this.enableSelArea()
23
+ } else {
24
+ this.disableSelArea()
25
+ }
26
+ }
27
+
28
+ onMouseMove(e){
29
+ if (this.props.onMouseMove){
30
+ this.props.onMouseMove(e)
31
+ }
32
+ }
33
+
34
+ onMouseUp(e){
35
+ if (this.props.onMouseUp){
36
+ this.props.onMouseUp(e)
37
+ }
38
+ }
39
+
40
+ enableSelArea(){
41
+ if (this.state.selAreaCss !== 'sel-area-on'){
42
+ this.setState({selAreaCss: 'sel-area-on'})
43
+ }
44
+ }
45
+
46
+ disableSelArea(){
47
+ if (this.state.selAreaCss !== 'sel-area-off'){
48
+ this.setState({selAreaCss: 'sel-area-off'})
49
+ }
50
+ }
51
+
52
+
53
+ /*************
54
+ * RENDERING *
55
+ **************/
56
+ render(){
57
+ return(
58
+ <circle
59
+ cx={this.props.svg.width/2}
60
+ cy={this.props.svg.height/2}
61
+ r={'100%'}
62
+ className={this.state.selAreaCss}
63
+ onMouseMove={e => {this.onMouseMove(e)}}
64
+ onMouseUp={e => {this.onMouseUp(e)}}
65
+ />
66
+ )
67
+
68
+ }
69
+ }
70
+
71
+ export default InfSelectionArea
@@ -0,0 +1,60 @@
1
+ import React from 'react'
2
+ import Polygon from './Polygon'
3
+ import Edge from './Edge'
4
+
5
+ import * as modes from '../types/modes'
6
+
7
+
8
+
9
+ class Line extends Polygon{
10
+
11
+ /*************
12
+ * RENDERING *
13
+ **************/
14
+
15
+ renderEdges(){
16
+ if (!this.props.isSelected) return null
17
+ switch (this.state.anno.mode){
18
+ case modes.VIEW:
19
+ case modes.ADD:
20
+ return this.state.anno.data.map((e, idx) => {
21
+ return <Edge anno={this.state.anno.data}
22
+ idx={idx} key={idx} style={this.props.style}
23
+ className={this.props.className}
24
+ isSelected={this.props.isSelected}
25
+ onMouseDown={(e, idx) => {this.onEdgeMouseDown(e, idx)}}
26
+ />
27
+ })
28
+ default:
29
+ return null
30
+ }
31
+ }
32
+
33
+ renderPolyline(){
34
+ return <polyline points={this.toPolygonStr(this.state.anno.data)}
35
+ fill='none' stroke="purple"
36
+ style={{...this.props.style, fill:'none'}}
37
+ className={this.props.className}
38
+ />
39
+ }
40
+ render(){
41
+ if (this.state.anno){
42
+ return (
43
+ <g
44
+ onMouseMove={e => this.onMouseMove(e)}
45
+ onMouseUp={e => this.onMouseUp(e)}
46
+ onMouseDown={e => this.onMouseDown(e)}
47
+ >
48
+ {this.renderPolyline()}
49
+ {this.renderEdges()}
50
+ {this.renderNodes()}
51
+ {this.renderInfSelectionArea()}
52
+ </g>
53
+ )
54
+ } else {
55
+ return <g></g>
56
+ }
57
+ }
58
+ }
59
+
60
+ export default Line;
@@ -0,0 +1,278 @@
1
+ import React, { Component } from 'react'
2
+ import './Annotation.scss'
3
+ import * as modes from '../types/modes'
4
+ import * as cursorstyles from '../types/cursorstyles'
5
+
6
+
7
+ class Node extends Component {
8
+
9
+ /*************
10
+ * LIFECYCLE *
11
+ **************/
12
+ constructor(props) {
13
+ super(props)
14
+ this.state = {
15
+ haloCss: 'node-halo-off',
16
+ selAreaCss: 'sel-area-off',
17
+ // anno: undefined,
18
+ nodeSelected: false,
19
+ style: {}
20
+ }
21
+ }
22
+
23
+ componentDidMount() {
24
+ this.setState({
25
+ // anno: this.props.anno,
26
+ style: {
27
+ ...this.props.style,
28
+ cursor: this.getCursorStyle(this.props.mode)
29
+ }
30
+ })
31
+ // switch (this.props.mode){
32
+ // case modes.CREATE:
33
+ // if (this.props.idx !== 0){
34
+ // this.turnSelAreaOn()
35
+ // }
36
+ // default:
37
+ // break
38
+ // }
39
+ }
40
+
41
+ componentDidUpdate(prevProps) {
42
+ switch (this.props.mode) {
43
+ case modes.CREATE:
44
+ if (this.props.idx !== 0 || this.props.isPoint) {
45
+ this.turnSelAreaOn()
46
+ }
47
+ break
48
+ case modes.EDIT:
49
+ this.turnSelAreaOn()
50
+ break
51
+ default:
52
+ break
53
+ }
54
+ //on mode change
55
+ if (prevProps.mode !== this.props.mode) {
56
+ this.setState({
57
+ style: {
58
+ ...this.state.style,
59
+ cursor: this.getCursorStyle(this.props.mode)
60
+ }
61
+ })
62
+ }
63
+ if (prevProps.style !== this.props.style) {
64
+ this.setState({
65
+ style:
66
+ {
67
+ ...this.state.style,
68
+ ...this.props.style,
69
+ cursor: this.getCursorStyle(this.props.mode)
70
+ }
71
+ })
72
+ }
73
+ }
74
+
75
+ /*************
76
+ * EVENTS *
77
+ **************/
78
+
79
+ onClick(e) {
80
+ this.turnHaloOn()
81
+ if (this.props.onClick) {
82
+ this.props.onClick(e, this.props.idx)
83
+ }
84
+ }
85
+
86
+ onMouseMove(e) {
87
+ if (this.props.onMouseMove) {
88
+ this.props.onMouseMove(e, this.props.idx)
89
+ }
90
+ // switch (this.props.mode){
91
+ // case modes.CREATE:
92
+ // let newAnno = [...this.state.anno]
93
+ // const mousePos = mouse.getMousePosition(e, this.props.svg)
94
+ // newAnno[this.props.idx].x = mousePos.x
95
+ // newAnno[this.props.idx].y = mousePos.y
96
+ // this.setState({
97
+ // anno: newAnno
98
+ // })
99
+ // if (this.props.onAnnoUpdate){
100
+ // this.props.onAnnoUpdate(e, this.props.idx, newAnno)
101
+ // }
102
+ // default:
103
+ // break
104
+ // }
105
+ }
106
+
107
+ onContextMenu(e) {
108
+ e.preventDefault()
109
+ }
110
+
111
+ onMouseUp(e) {
112
+ switch (this.props.mode) {
113
+ case modes.EDIT:
114
+ switch (e.button) {
115
+ case 0:
116
+ this.turnSelAreaOff()
117
+ break
118
+ default:
119
+ break
120
+ }
121
+ break
122
+ default:
123
+ break
124
+ }
125
+ if (this.props.onMouseUp) {
126
+ this.props.onMouseUp(e, this.props.idx)
127
+ }
128
+ }
129
+
130
+ onMouseDown(e) {
131
+ e.stopPropagation()
132
+ if (this.props.onMouseDown) {
133
+ this.props.onMouseDown(e, this.props.idx)
134
+ }
135
+ switch (this.props.mode) {
136
+ case modes.CREATE:
137
+ switch (e.button) {
138
+ case 0:
139
+ this.turnSelAreaOff()
140
+ break
141
+ case 2:
142
+ this.turnSelAreaOff()
143
+ break
144
+ default:
145
+ break
146
+ }
147
+ // case modes.EDIT:
148
+ // switch (e.button){
149
+ // case 0:
150
+ // this.turnSelAreaOn()
151
+ // break
152
+ // default:
153
+ // break
154
+ // }
155
+ break
156
+ default:
157
+ break
158
+ }
159
+ }
160
+
161
+ onMouseOver(e) {
162
+ if (this.props.isSelected) {
163
+ this.turnHaloOn()
164
+ }
165
+ }
166
+
167
+ onMouseLeave(e) {
168
+ if (this.props.isSelected) {
169
+ this.turnHaloOff()
170
+ }
171
+ }
172
+
173
+ onDoubleClick(e) {
174
+ if (this.props.onDoubleClick) {
175
+ this.props.onDoubleClick(e, this.props.idx)
176
+ }
177
+ }
178
+
179
+ handleMouseLeave(e) {
180
+ if (this.props.onMouseLeave) {
181
+ this.props.onMouseLeave(e, this.props.idx)
182
+ }
183
+ }
184
+
185
+
186
+ /*************
187
+ * LOGIC *
188
+ **************/
189
+ getCursorStyle(mode) {
190
+ switch (mode) {
191
+ case modes.CREATE:
192
+ return cursorstyles.CREATE_NODE
193
+ case modes.EDIT:
194
+ return cursorstyles.EDIT_NODE
195
+ case modes.VIEW:
196
+ return cursorstyles.NORMAL_NODE
197
+ default:
198
+ break
199
+ }
200
+ }
201
+
202
+ turnSelAreaOn() {
203
+ if (this.state.selAreaCss !== 'sel-area-on') {
204
+ this.setState({
205
+ selAreaCss: 'sel-area-on'
206
+ })
207
+ }
208
+ }
209
+
210
+ turnSelAreaOff() {
211
+ if (this.state.selAreaCss !== 'sel-area-off') {
212
+ this.setState({
213
+ selAreaCss: 'sel-area-off'
214
+ })
215
+ }
216
+ }
217
+
218
+ turnHaloOn() {
219
+ this.setState({
220
+ haloCss: 'node-halo-on'
221
+ })
222
+ }
223
+
224
+ turnHaloOff() {
225
+ this.setState({
226
+ haloCss: 'node-halo-off'
227
+ })
228
+ }
229
+
230
+ /*************
231
+ * RENDERING *
232
+ **************/
233
+ renderHalo() {
234
+ if (this.state.haloCss === 'node-halo-off') return null
235
+ const data = this.props.anno[this.props.idx]
236
+
237
+ return <circle cx={data.x} cy={data.y} r={this.props.style.r * 3}
238
+ className={this.state.haloCss}
239
+ onMouseLeave={e => this.onMouseLeave(e)}
240
+ />
241
+ }
242
+ renderNodes() {
243
+ const data = this.props.anno[this.props.idx]
244
+ if (data === undefined) { return }
245
+ return (
246
+ <g
247
+ onClick={(e) => this.onClick(e)}
248
+ onMouseMove={e => this.onMouseMove(e)}
249
+ onContextMenu={e => this.onContextMenu(e)}
250
+ onMouseUp={e => this.onMouseUp(e)}
251
+ onMouseDown={e => this.onMouseDown(e)}
252
+ onDoubleClick={e => this.onDoubleClick(e)}
253
+ onMouseLeave={e => this.handleMouseLeave(e)}
254
+ >
255
+ <circle cx={data.x} cy={data.y} r={'100%'}
256
+ className={this.state.selAreaCss}
257
+ />
258
+ {this.renderHalo()}
259
+ <circle cx={data.x}
260
+ cy={data.y}
261
+ r={3} fill="red"
262
+ style={this.state.style}
263
+ className={this.props.className}
264
+ onMouseOver={e => this.onMouseOver(e)}
265
+ />
266
+ </g>
267
+ )
268
+ }
269
+ render() {
270
+ return (
271
+ <g>
272
+ {this.renderNodes()}
273
+ </g>
274
+ )
275
+ }
276
+ }
277
+
278
+ export default Node;
@@ -0,0 +1,196 @@
1
+ import React, {Component} from 'react'
2
+ import InfSelectionArea from './InfSelectionArea'
3
+ import Node from './Node'
4
+ import * as modes from '../types/modes'
5
+ import * as transform from '../utils/transform'
6
+ import * as canvasActions from '../types/canvasActions'
7
+
8
+ class Point extends Component{
9
+
10
+ /*************
11
+ * LIFECYCLE *
12
+ **************/
13
+ constructor(props){
14
+ super(props)
15
+ this.state = {
16
+ anno: undefined,
17
+ }
18
+ }
19
+
20
+ componentDidMount(prevProps){
21
+ if (this.props.anno.mode === modes.CREATE){
22
+ const data = this.props.anno.data[0]
23
+ const newAnno = {
24
+ ...this.props.anno,
25
+ data: [
26
+ {x: data.x, y: data.y}
27
+ ],
28
+ selectedNode: 0
29
+ }
30
+ this.setState({
31
+ anno: newAnno
32
+ })
33
+ } else {
34
+ this.setState({anno: {...this.props.anno}})
35
+ }
36
+ }
37
+
38
+ componentDidUpdate(prevProps){
39
+ if (prevProps.anno !== this.props.anno){
40
+ this.setState({anno: {...this.props.anno}})
41
+ }
42
+ }
43
+
44
+ /**************
45
+ * ANNO EVENTS *
46
+ ***************/
47
+ onMouseMove(e){
48
+ switch (this.state.anno.mode){
49
+ case modes.MOVE:
50
+ this.move(
51
+ e.movementX/this.props.svg.scale,
52
+ e.movementY/this.props.svg.scale
53
+ )
54
+ break
55
+ default:
56
+ break
57
+ }
58
+ }
59
+
60
+ onMouseUp(e){
61
+ switch (this.state.anno.mode){
62
+ case modes.MOVE:
63
+ if (e.button === 0){
64
+ this.requestModeChange(this.state.anno, modes.VIEW)
65
+ this.performedAction(this.state.anno, canvasActions.ANNO_MOVED)
66
+ }
67
+ break
68
+ case modes.CREATE:
69
+ this.requestModeChange(this.state.anno, modes.VIEW)
70
+
71
+ this.performedAction(this.state.anno, canvasActions.ANNO_CREATED)
72
+ break
73
+ default:
74
+ break
75
+ }
76
+ }
77
+
78
+ onNodeMouseDown(e, idx){
79
+ switch (this.state.anno.mode){
80
+ case modes.VIEW:
81
+ if (e.button === 0){
82
+ if (this.props.isSelected){
83
+ this.requestModeChange(this.state.anno, modes.MOVE)
84
+ }
85
+ }
86
+ break
87
+ default:
88
+ break
89
+ }
90
+ }
91
+
92
+ /*************
93
+ * LOGIC *
94
+ **************/
95
+ getResult(){
96
+ return this.state.anno
97
+ }
98
+
99
+ performedAction(anno, pAction){
100
+ if (this.props.onAction){
101
+ this.props.onAction(anno, pAction)
102
+ }
103
+ }
104
+
105
+ requestModeChange(anno, mode){
106
+ this.props.onModeChangeRequest(anno, mode)
107
+ }
108
+
109
+ move(movementX, movementY){
110
+ this.setState({
111
+ anno : {
112
+ ...this.state.anno,
113
+ data: transform.move(this.state.anno.data, movementX, movementY)
114
+ }
115
+ })
116
+ }
117
+
118
+ renderInfSelectionArea(){
119
+ switch (this.state.anno.mode){
120
+ case modes.MOVE:
121
+ return <InfSelectionArea enable={true}
122
+ svg={this.props.svg}
123
+ />
124
+ default:
125
+ return null
126
+ }
127
+ }
128
+
129
+ renderNode(){
130
+ if (!this.props.isSelected) return null
131
+ switch(this.state.anno.mode){
132
+ case modes.EDIT_LABEL:
133
+ case modes.MOVE:
134
+ return null
135
+ case modes.EDIT:
136
+ case modes.CREATE:
137
+ return <Node anno={this.state.anno.data}
138
+ key={this.state.selectedNode}
139
+ idx={this.state.anno.selectedNode}
140
+ style={this.props.style}
141
+ className={this.props.className}
142
+ isSelected={this.props.isSelected}
143
+ mode={this.state.anno.mode}
144
+ svg={this.props.svg}
145
+ onMouseDown={(e, idx) => this.onNodeMouseDown(e,idx)}
146
+ isPoint={true}
147
+ />
148
+ default:
149
+ return this.state.anno.data.map((e, idx) => {
150
+ return <Node anno={this.state.anno.data} idx={idx}
151
+ key={idx} style={this.props.style}
152
+ className={this.props.className}
153
+ isSelected={this.props.isSelected}
154
+ mode={this.state.anno.mode}
155
+ svg={this.props.svg}
156
+ onMouseDown={(e, idx) => this.onNodeMouseDown(e,idx)}
157
+ isPoint={true}
158
+ />
159
+ })
160
+ }
161
+ }
162
+
163
+ renderPoint(){
164
+ return this.state.anno.data.map((e, idx) => {
165
+ return (
166
+ <circle key={idx}
167
+ cx={e.x}
168
+ cy={e.y}
169
+ r={10} fill="red"
170
+ style={this.props.style}
171
+ className={this.props.className}
172
+ />
173
+ )
174
+ })
175
+
176
+ }
177
+
178
+ render(){
179
+ if (this.state.anno){
180
+ return(
181
+ <g
182
+ onMouseMove={e => this.onMouseMove(e)}
183
+ onMouseUp={e => this.onMouseUp(e)}
184
+ >
185
+ {this.renderPoint()}
186
+ {this.renderNode()}
187
+ {this.renderInfSelectionArea()}
188
+ </g>
189
+ )
190
+ } else {
191
+ return null
192
+ }
193
+ }
194
+ }
195
+
196
+ export default Point;