@operato/scene-indoor-map 7.3.9 → 7.3.19

Sign up to get free protection for your applications and to get access to all the features.
package/src/floor.ts DELETED
@@ -1,385 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- import { Component, ComponentNature, Container } from '@hatiolab/things-scene'
5
-
6
- import IndoorMap from './indoor-map'
7
-
8
- const NATURE: ComponentNature = {
9
- mutable: false,
10
- resizable: true,
11
- rotatable: true,
12
- properties: [
13
- {
14
- type: 'action',
15
- label: 'remove',
16
- name: 'remove',
17
- property: {
18
- icon: 'remove_circle',
19
- action: function (floor: Floor) {
20
- let indoor = floor.parent as IndoorMap
21
- indoor.removeComponent(floor)
22
- indoor.setState('activeIndex', 0)
23
- }
24
- }
25
- }
26
- ]
27
- }
28
-
29
- export default class Floor extends Container {
30
- private _clickPoint?: Component
31
-
32
- get hasTextProperty() {
33
- return false
34
- }
35
-
36
- get showMoveHandle() {
37
- return false
38
- }
39
-
40
- /*
41
- * PATH 리스트를 직접 수정할 수 있는 지를 결정한다.
42
- *
43
- * 일반적으로 PATH는 바운드 생성을 위해서 논리적으로 생성되므로, 직접 수정하지 않는다.(return false)
44
- * 그러나, 각 꼭지점들이 개별로 움직이는 다각형류는 path 라는 모델데이타를 가지므로, 직접수정이 가능할 수 있다.(return true)
45
- *
46
- * Immutable 컴포넌트의 형상을 바꾸는 방법은 바운드를 이용한 리사이즈나, 특별한 컨트롤을 통해서 가능하다.
47
- */
48
- get mutable() {
49
- return false
50
- }
51
-
52
- /*
53
- * BOUND를 통해서 리사이즈를 할 수 있는 지를 결정한다.
54
- *
55
- * 일반적으로 면적을 갖는 컴포넌트는 대체로 가능하다.(return true)
56
- * 그러나, LINE 등 면적을 가지지않는 컴포넌트는 가능하지 않도록 정의한다.(return false)
57
- */
58
- get resizable() {
59
- return false
60
- }
61
-
62
- /*
63
- * 회전을 할 수 있는 지를 결정한다.
64
- *
65
- * 일반적으로 모든 컴포넌트는 가능하다.(return true)
66
- */
67
- get rotatable() {
68
- return false
69
- }
70
-
71
- get nature() {
72
- return NATURE
73
- }
74
-
75
- // drawLocationMarkers(locations) {
76
- // for (let uuid in locations) {
77
- // let locInfo = locations[uuid]
78
- // let props = locInfo.props || {}
79
-
80
- // props.width = props.width || 10
81
- // props.height = props.height || 10
82
-
83
- // let currentTime = new Date().getTime()
84
- // // let diffTime = 500
85
- // let diffTime = currentTime - locInfo.lastUpdateTime
86
-
87
- // if (diffTime < locInfo.updateInterval) {
88
- // let movingObject = this.findById(uuid)
89
- // if (movingObject) {
90
- // // props.yaw = 0;
91
- // // props.roll = 0;
92
-
93
- // movingObject.set(props)
94
- // for (let key in props) {
95
- // movingObject[key] = props[key]
96
- // }
97
- // } else {
98
- // // TODO: marker의 초기값 관련 로직 정리 필요.
99
-
100
- // let config = Object.assign(
101
- // {
102
- // type: locInfo.type || 'rect',
103
- // // type: locInfo.type || "camera",
104
- // id: uuid,
105
- // fillStyle: 'red',
106
- // left: props.center.x - props.width * 0.5,
107
- // top: props.center.y - props.height * 0.5,
108
- // cx: props.center.x,
109
- // cy: props.center.y
110
- // },
111
- // props
112
- // )
113
-
114
- // let marker = Model.compile(config)
115
-
116
- // this.addComponent(marker)
117
-
118
- // // movingObject = this.findById(uuid)
119
- // // if(movingObject) {
120
- // // movingObject.set(props);
121
- // // }
122
- // }
123
- // } else {
124
- // let movingObject = this.findById(uuid)
125
- // this.removeComponent(movingObject)
126
- // }
127
-
128
- // this.invalidate()
129
- // }
130
- // }
131
-
132
- // simulate(point) {
133
- // // for(let i in this.components) {
134
- // // if(this.components[i].model.type != 'beacon')
135
- // // continue;
136
- // //
137
- // // let beacon = this.components[i]
138
- // // let distance = Math.sqrt(Math.pow(beacon.center.x - point.x, 2) + Math.pow(beacon.center.y - point.y, 2)) * 0.01
139
- // // let rssi = -10 * Math.log10(distance) + (beacon.txPower || -71)
140
- // //
141
- // // let randRssi = gaussian(rssi, Math.pow(4.894686948810031, 2))
142
- // //
143
- // // rssi = randRssi.ppf(Math.random())
144
- // //
145
- // // console.log(rssi);
146
- // // }
147
-
148
- // let beacons: {
149
- // distance: number;
150
- // gaussian: number;
151
- // txPower: number;
152
- // }[] = []
153
-
154
- // for (let i in this.components) {
155
- // if (this.components[i].model.type != 'beacon') continue
156
-
157
- // let beacon = this.components[i]
158
-
159
- // beacon.distance = Math.sqrt(
160
- // Math.pow(beacon.center.x - point.x, 2) +
161
- // Math.pow(beacon.center.y - point.y, 2)
162
- // )
163
- // beacon.gaussian = gaussian(
164
- // beacon.model.txPower || -71,
165
- // Math.pow(3.209, 2)
166
- // )
167
- // beacon.txPower = beacon.gaussian.ppf(Math.random())
168
-
169
- // beacons.push(beacon)
170
- // }
171
-
172
- // beacons = beacons.slice(0)
173
-
174
- // this.calculatePosition(beacons, point)
175
- // }
176
-
177
- // calculatePosition(nodeArr, position) {
178
- // let beacons = nodeArr
179
-
180
- // beacons.sort(function(a, b) {
181
- // let rssiA = -10 * Math.log10(a.distance) + a.txPower
182
- // let rssiB = -10 * Math.log10(b.distance) + b.txPower
183
-
184
- // return Math.abs(rssiA) - Math.abs(rssiB)
185
- // })
186
-
187
- // let beaconCombs = this.k_combinations(beacons.slice(0, 4), 3)
188
- // let positions = []
189
-
190
- // for (let i in beaconCombs) {
191
- // let beaconComb = beaconCombs[i]
192
- // let beaconA = beaconComb[0]
193
- // let beaconB = beaconComb[1]
194
- // let beaconC = beaconComb[2]
195
-
196
- // let xa = beaconA.center.x
197
- // let ya = beaconA.center.y
198
- // let xb = beaconB.center.x
199
- // let yb = beaconB.center.y
200
- // let xc = beaconC.center.x
201
- // let yc = beaconC.center.y
202
- // let ra = beaconA.distance
203
- // let rb = beaconB.distance
204
- // let rc = beaconC.distance
205
-
206
- // // let ra = Math.sqrt(Math.pow(beaconA.center.x - position.x, 2) + Math.pow(beaconA.center.y - position.y, 2)) * 0.01
207
- // // let rb = Math.sqrt(Math.pow(beaconB.center.x - position.x, 2) + Math.pow(beaconB.center.y - position.y, 2)) * 0.01
208
- // // let rc = Math.sqrt(Math.pow(beaconC.center.x - position.x, 2) + Math.pow(beaconC.center.y - position.y, 2)) * 0.01
209
-
210
- // let rssiA = -10 * Math.log10(beaconA.distance * 0.01) + beaconA.txPower
211
- // let rssiB = -10 * Math.log10(beaconB.distance * 0.01) + beaconB.txPower
212
- // let rssiC = -10 * Math.log10(beaconC.distance * 0.01) + beaconC.txPower
213
-
214
- // ra = this.calculateDistance(beaconA.txPower, rssiA) * 100
215
- // rb = this.calculateDistance(beaconB.txPower, rssiB) * 100
216
- // rc = this.calculateDistance(beaconC.txPower, rssiC) * 100
217
-
218
- // let xaSq = xa * xa,
219
- // xbSq = xb * xb,
220
- // xcSq = xc * xc,
221
- // yaSq = ya * ya,
222
- // ybSq = yb * yb,
223
- // ycSq = yc * yc,
224
- // raSq = ra * ra,
225
- // rbSq = rb * rb,
226
- // rcSq = rc * rc
227
- // let numerator1 =
228
- // (xb - xa) * (xcSq + ycSq - rcSq) +
229
- // (xa - xc) * (xbSq + ybSq - rbSq) +
230
- // (xc - xb) * (xaSq + yaSq - raSq)
231
- // let denominator1 = 2 * (yc * (xb - xa) + yb * (xa - xc) + ya * (xc - xb))
232
- // let y = numerator1 / denominator1
233
- // let numerator2 =
234
- // rbSq - raSq + xaSq - xbSq + yaSq - ybSq - 2 * (ya - yb) * y
235
- // let denominator2 = 2 * (xa - xb)
236
- // let x = numerator2 / denominator2
237
-
238
- // if (Number.isFinite(x) && Number.isFinite(y)) {
239
- // positions.push({
240
- // x: x,
241
- // y: y
242
- // })
243
- // }
244
- // }
245
-
246
- // let avgPosition = this.averageOfPositions(positions)
247
-
248
- // if (this._simPosition) this.removeComponent(this._simPosition)
249
-
250
- // this._simPosition = Model.compile({
251
- // type: 'ellipse',
252
- // cx: avgPosition.x,
253
- // cy: avgPosition.y,
254
- // rx: 10,
255
- // ry: 10,
256
- // fillStyle: 'navy'
257
- // })
258
-
259
- // this.addComponent(this._simPosition)
260
- // }
261
-
262
- // calculateDistance(txPower, rssi) {
263
- // if (rssi == 0) {
264
- // return -1.0 // if we cannot determine distance, return -1.
265
- // }
266
-
267
- // let ratio = (rssi * 1.0) / txPower
268
- // if (ratio < 1.0) {
269
- // return Math.pow(ratio, 10)
270
- // } else {
271
- // let accuracy = 0.89976 * Math.pow(ratio, 7.7095) + 0.111
272
- // return accuracy
273
- // }
274
- // }
275
-
276
- // calculateAngle(p1, p2, p3) {
277
- // let l1 = Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2),
278
- // l2 = Math.pow(p2.x - p3.x, 2) + Math.pow(p2.y - p3.y, 2),
279
- // l3 = Math.pow(p3.x - p1.x, 2) + Math.pow(p3.y - p1.y, 2)
280
-
281
- // return Math.acos((l1 + l2 - l3) / Math.sqrt(4 * l1 * l2))
282
- // }
283
-
284
- // averageOfPositions(p) {
285
- // let sumOfX = 0
286
- // let sumOfY = 0
287
-
288
- // for (let i in p) {
289
- // let point = p[i]
290
- // sumOfX += point.x
291
- // sumOfY += point.y
292
- // }
293
-
294
- // return {
295
- // x: sumOfX / p.length,
296
- // y: sumOfY / p.length
297
- // }
298
- // }
299
-
300
- // k_combinations(set, k) {
301
- // var i, j, combs, head, tailcombs
302
-
303
- // // There is no way to take e.g. sets of 5 elements from
304
- // // a set of 4.
305
- // if (k > set.length || k <= 0) {
306
- // return []
307
- // }
308
-
309
- // // K-sized set has only one K-sized subset.
310
- // if (k == set.length) {
311
- // return [set]
312
- // }
313
-
314
- // // There is N 1-sized subsets in a N-sized set.
315
- // if (k == 1) {
316
- // combs = []
317
- // for (i = 0; i < set.length; i++) {
318
- // combs.push([set[i]])
319
- // }
320
- // return combs
321
- // }
322
-
323
- // // Assert {1 < k < set.length}
324
-
325
- // // Algorithm description:
326
- // // To get k-combinations of a set, we want to join each element
327
- // // with all (k-1)-combinations of the other elements. The set of
328
- // // these k-sized sets would be the desired result. However, as we
329
- // // represent sets with lists, we need to take duplicates into
330
- // // account. To avoid producing duplicates and also unnecessary
331
- // // computing, we use the following approach: each element i
332
- // // divides the list into three: the preceding elements, the
333
- // // current element i, and the subsequent elements. For the first
334
- // // element, the list of preceding elements is empty. For element i,
335
- // // we compute the (k-1)-computations of the subsequent elements,
336
- // // join each with the element i, and store the joined to the set of
337
- // // computed k-combinations. We do not need to take the preceding
338
- // // elements into account, because they have already been the i:th
339
- // // element so they are already computed and stored. When the length
340
- // // of the subsequent list drops below (k-1), we cannot find any
341
- // // (k-1)-combs, hence the upper limit for the iteration:
342
- // combs = []
343
- // for (i = 0; i < set.length - k + 1; i++) {
344
- // // head is a list that includes only our current element.
345
- // head = set.slice(i, i + 1)
346
- // // We take smaller combinations from the subsequent elements
347
- // tailcombs = this.k_combinations(set.slice(i + 1), k - 1)
348
- // // For each (k-1)-combination we join it with the current
349
- // // and store it to the set of k-combinations.
350
- // for (j = 0; j < tailcombs.length; j++) {
351
- // combs.push(head.concat(tailcombs[j]))
352
- // }
353
- // }
354
- // return combs
355
- // }
356
-
357
- // onclick(e) {
358
- // return
359
-
360
- // let point = this.transcoordC2S(e.offsetX, e.offsetY)
361
-
362
- // if (this._clickPoint) {
363
- // this.removeComponent(this._clickPoint)
364
- // }
365
-
366
- // this._clickPoint = Model.compile({
367
- // type: 'ellipse',
368
- // cx: point.x,
369
- // cy: point.y,
370
- // rx: 10,
371
- // ry: 10,
372
- // fillStyle: 'red'
373
- // })
374
-
375
- // this.addComponent(this._clickPoint)
376
- // this.simulate(point)
377
- // // let self = this
378
- // // setTimeout(function() {
379
- // // self.simulate(point)
380
- // // }, 500)
381
- // this.invalidate()
382
- // }
383
- }
384
-
385
- Component.register('floor', Floor)
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- export { default as Floor } from './floor'
5
- export { default as IndoorMap } from './indoor-map'
6
- export { default as Rack } from './rack'
7
- // export { default as Beacon } from './beacon'
8
- // export { default as Camera } from './camera'
9
- // export { default as Quaternion } from './quaternion'
package/src/indoor-map.ts DELETED
@@ -1,213 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- import { CardLayout, Component, ComponentNature, Container, Model, POINT, State } from '@hatiolab/things-scene'
5
-
6
- const LABEL_WIDTH = 25
7
- const LABEL_HEIGHT = 25
8
-
9
- function rgba(r: number, g: number, b: number, a: number) {
10
- return `rgba(${r}, ${g}, ${b}, ${a})`
11
- }
12
-
13
- const NATURE: ComponentNature = {
14
- mutable: false,
15
- resizable: true,
16
- rotatable: true,
17
- properties: [
18
- {
19
- type: 'action',
20
- label: 'add-floor',
21
- name: 'addFloor',
22
- property: {
23
- icon: 'add_circle',
24
- action: (indoorMap: IndoorMap) => {
25
- indoorMap.addFloor()
26
- }
27
- }
28
- },
29
- {
30
- type: 'number',
31
- label: 'active index',
32
- name: 'activeIndex'
33
- }
34
- ],
35
- 'value-property': 'activeIndex',
36
- help: 'scene/component/indoor-map'
37
- }
38
-
39
- export default class IndoorMap extends Container {
40
- private _focused: boolean = false
41
- private __down_point?: POINT
42
-
43
- get nature() {
44
- return NATURE
45
- }
46
-
47
- get layout() {
48
- return CardLayout
49
- }
50
-
51
- get layoutConfig() {
52
- return (
53
- this.getState('layoutConfig') || {
54
- activeIndex: this.activeIndex
55
- }
56
- )
57
- }
58
-
59
- set layoutConfig(config) {
60
- this.setState('layoutConfig', config)
61
- }
62
-
63
- get activeIndex() {
64
- return this.getState('activeIndex')
65
- }
66
-
67
- set activeIndex(activeIndex: number) {
68
- this.setState('activeIndex', Number(activeIndex))
69
- }
70
-
71
- ready() {
72
- super.ready()
73
-
74
- if (this.components.length == 0) {
75
- this.addFloor()
76
- }
77
-
78
- this.layoutConfig = {
79
- ...this.layoutConfig,
80
- activeIndex: this.activeIndex
81
- }
82
- }
83
-
84
- postrender(context: CanvasRenderingContext2D) {
85
- if (!this.app.isViewMode && this._focused) {
86
- var { left, top, width, fillStyle } = this.state
87
-
88
- // floor 선택 탭 그리기
89
- for (let i = 0; i < this.components.length; i++) {
90
- context.beginPath()
91
-
92
- context.rect(left - LABEL_WIDTH, top + i * LABEL_HEIGHT, LABEL_WIDTH, LABEL_HEIGHT)
93
-
94
- let color = 255 - ((20 * (i + 1)) % 255)
95
- context.fillStyle = rgba(color, color, color, 1)
96
- context.fill()
97
-
98
- context.closePath()
99
- }
100
-
101
- context.beginPath()
102
-
103
- context.moveTo(left, top)
104
- context.lineTo(left - LABEL_WIDTH, top)
105
- context.lineTo(left - LABEL_WIDTH, top + this.components.length * LABEL_HEIGHT)
106
- context.lineTo(left, top + this.components.length * LABEL_HEIGHT)
107
-
108
- context.strokeStyle = '#ccc'
109
- context.stroke()
110
-
111
- context.closePath()
112
- }
113
-
114
- super.postrender(context)
115
- }
116
-
117
- contains(x: number, y: number) {
118
- var contains = super.contains(x, y)
119
-
120
- if (this.app.isViewMode) return contains
121
-
122
- var { left, top, width } = this.bounds
123
- var h = LABEL_HEIGHT
124
-
125
- contains =
126
- contains ||
127
- // card selector 영역에 포함되는지
128
- (x < Math.max(left - LABEL_WIDTH, left) &&
129
- x > Math.min(left - LABEL_WIDTH, left) &&
130
- y < Math.max(top + h * this.size(), top) &&
131
- y > Math.min(top + h * this.size(), top))
132
-
133
- if (contains) this._focused = true
134
- else this._focused = false
135
-
136
- this.invalidate()
137
- return contains
138
- }
139
-
140
- onchange(after: State) {
141
- if ('activeIndex' in after) {
142
- this.layoutConfig = {
143
- ...this.layoutConfig,
144
- activeIndex: after.activeIndex
145
- }
146
- }
147
- }
148
-
149
- onmouseup(e: MouseEvent) {
150
- var down_point = this.__down_point
151
- delete this.__down_point
152
-
153
- if (!down_point || down_point.x != e.offsetX || down_point.y != e.offsetY) {
154
- return
155
- }
156
-
157
- var point = this.transcoordC2S(e.offsetX, e.offsetY)
158
-
159
- var { left, top } = this.state
160
-
161
- var x = point.x - left
162
- var y = point.y - top
163
-
164
- if (x > 0) return
165
-
166
- y /= LABEL_HEIGHT
167
- y = Math.floor(y)
168
-
169
- if (!this.layoutConfig) {
170
- this.layoutConfig = {}
171
- }
172
-
173
- if (y >= this.components.length) {
174
- return
175
- }
176
-
177
- // /* 생성 버튼이 클릭되면, 새로운 floor를 추가한다. */
178
- // if(y == this.components.length) {
179
- // this.add(Model.compile({
180
- // type: 'floor',
181
- // width: 100,
182
- // height: 100
183
- // }))
184
- // }
185
- this.setState('activeIndex', y)
186
- }
187
-
188
- onmousedown(e: MouseEvent) {
189
- this.__down_point = {
190
- x: e.offsetX,
191
- y: e.offsetY
192
- }
193
- }
194
-
195
- addFloor() {
196
- const color = 255 - ((20 * (this.components.length + 1)) % 255)
197
- const hex = color.toString(16)
198
-
199
- const floor = Model.compile({
200
- type: 'floor',
201
- fillStyle: `#${hex}${hex}${hex}`,
202
- top: 0,
203
- left: 0,
204
- width: 100,
205
- height: 100
206
- })
207
-
208
- this.addComponent(floor)
209
- this.setState('activeIndex', this.components.length - 1)
210
- }
211
- }
212
-
213
- Component.register('indoor-map', IndoorMap)