@operato/scene-indoor-map 7.3.9 → 7.3.19

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/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)