mrpas 1.2.1 → 2.1.0

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/index-es6.js DELETED
@@ -1,469 +0,0 @@
1
- /**
2
- * Check whether point (x,y) is transparent (i.e. is not an obstacle)
3
- * @callback isTransparent
4
- * @param {number} x
5
- * @param {number} y
6
- * @returns {boolean}
7
- */
8
- /**
9
- * Check whether point (x,y) has previously been marked as visible
10
- * @callback isVisible
11
- * @param {number} x
12
- * @param {number} y
13
- * @returns {boolean}
14
- */
15
- /**
16
- * Mark point (x,y) as visible
17
- * @callback setVisible
18
- * @param {number} x
19
- * @param {number} y
20
- */
21
- /**
22
- * A data object passed into the octant methods
23
- * @typedef {object} fovData
24
- * @property {number} minX
25
- * @property {number} minY
26
- * @property {number} maxX
27
- * @property {number} maxY
28
- * @property {number} originX
29
- * @property {number} originY
30
- * @property {number} radius
31
- * @property {isVisible} isVisible
32
- * @property {setVisible} setVisible
33
- */
34
-
35
- class Mrpas {
36
- /**
37
- * @param {number} mapWidth
38
- * @param {number} mapHeight
39
- * @param {isTransparent} isTransparent
40
- */
41
- constructor(mapWidth, mapHeight, isTransparent) {
42
- /**
43
- * @type {number}
44
- * @private
45
- */
46
- this._mapWidth = mapWidth;
47
-
48
- /**
49
- * @type {number}
50
- * @private
51
- */
52
- this._mapHeight = mapHeight;
53
-
54
- /**
55
- * @type {isTransparent}
56
- * @private
57
- */
58
- this._isTransparent = isTransparent;
59
- }
60
-
61
- /**
62
- * Compute the FOV in an octant adjacent to the Y axis
63
- * @param {number} deltaX
64
- * @param {number} deltaY
65
- * @param {fovData} data
66
- * @private
67
- */
68
- _computeOctantY(deltaX, deltaY, data) {
69
- /**
70
- * @type {Array.<number>}
71
- */
72
- const startAngle = [];
73
-
74
- /**
75
- * @type {Array.<number>}
76
- */
77
- const endAngle = [];
78
-
79
- /**
80
- * @type {number}
81
- */
82
- let iteration = 1;
83
-
84
- /**
85
- * @type {boolean}
86
- */
87
- let done = false;
88
-
89
- /**
90
- * @type {number}
91
- */
92
- let totalObstacles = 0;
93
-
94
- /**
95
- * @type {number}
96
- */
97
- let obstaclesInLastLine = 0;
98
-
99
- /**
100
- * @type {number}
101
- */
102
- let minAngle = 0;
103
-
104
- /**
105
- * @type {number}
106
- */
107
- let x;
108
-
109
- /**
110
- * @type {number}
111
- */
112
- let y;
113
-
114
- /**
115
- * @type {number}
116
- */
117
- let slopesPerCell;
118
-
119
- /**
120
- * @type {number}
121
- */
122
- let halfSlopes;
123
-
124
- /**
125
- * @type {number}
126
- */
127
- let processedCell;
128
-
129
- /**
130
- * @type {number}
131
- */
132
- let min;
133
-
134
- /**
135
- * @type {number}
136
- */
137
- let max;
138
-
139
- /**
140
- * @type {boolean}
141
- */
142
- let visible;
143
-
144
- /**
145
- * @type {boolean}
146
- */
147
- let extended;
148
-
149
- /**
150
- * @type {number}
151
- */
152
- let centreSlope;
153
-
154
- /**
155
- * @type {number}
156
- */
157
- let startSlope;
158
-
159
- /**
160
- * @type {number}
161
- */
162
- let endSlope;
163
-
164
- y = data.originY + deltaY;
165
- if (y < data.minY || y > data.maxY) {
166
- done = true;
167
- }
168
- while (!done) {
169
- slopesPerCell = 1.0 / iteration;
170
- halfSlopes = slopesPerCell * 0.5;
171
- processedCell = parseInt((minAngle + halfSlopes) / slopesPerCell);
172
- min = Math.max(data.minX, data.originX - iteration);
173
- max = Math.min(data.maxX, data.originX + iteration);
174
- done = true;
175
- for (x = data.originX + (processedCell * deltaX); x >= min && x <= max; x += deltaX) {
176
- visible = true;
177
- extended = false;
178
- centreSlope = processedCell * slopesPerCell;
179
- startSlope = centreSlope - halfSlopes;
180
- endSlope = centreSlope + halfSlopes;
181
- if (obstaclesInLastLine > 0) {
182
- if (
183
- !(
184
- data.isVisible(x, y - deltaY) &&
185
- this._isTransparent(x, y - deltaY)
186
- ) &&
187
- !(
188
- data.isVisible(x - deltaX, y - deltaY) &&
189
- this._isTransparent(x - deltaX, y - deltaY)
190
- )
191
- ) {
192
- visible = false;
193
- } else {
194
- for (let idx = 0; idx < obstaclesInLastLine && visible; ++idx) {
195
- if (startSlope <= endAngle[idx] && endSlope >= startAngle[idx]) {
196
- if (this._isTransparent(x, y)) {
197
- if (centreSlope > startAngle[idx] && centreSlope < endAngle[idx]) {
198
- visible = false;
199
- }
200
- } else {
201
- if (startSlope >= startAngle[idx] && endSlope <= endAngle[idx]) {
202
- visible = false;
203
- } else {
204
- startAngle[idx] = Math.min(startAngle[idx], startSlope);
205
- endAngle[idx] = Math.max(endAngle[idx], endSlope);
206
- extended = true;
207
- }
208
- }
209
- }
210
- }
211
- }
212
- }
213
- if (visible) {
214
- done = false;
215
- data.setVisible(x, y);
216
- if (!this._isTransparent(x, y)) {
217
- if (minAngle >= startSlope) {
218
- minAngle = endSlope;
219
- if (processedCell == iteration) {
220
- done = true;
221
- }
222
- } else if (!extended) {
223
- startAngle[totalObstacles] = startSlope;
224
- endAngle[totalObstacles++] = endSlope;
225
- }
226
- }
227
- }
228
- processedCell++;
229
- }
230
- if (iteration == data.radius) {
231
- done = true;
232
- }
233
- iteration++;
234
- obstaclesInLastLine = totalObstacles;
235
- y += deltaY;
236
- if (y < data.minY || y > data.maxY) {
237
- done = true;
238
- }
239
- }
240
- }
241
-
242
- /**
243
- * Compute the FOV in an octant adjacent to the X axis
244
- * @param {number} deltaX
245
- * @param {number} deltaY
246
- * @param {fovData} data
247
- * @private
248
- */
249
- _computeOctantX(deltaX, deltaY, data) {
250
- /**
251
- * @type {Array.<number>}
252
- */
253
- const startAngle = [];
254
-
255
- /**
256
- * @type {Array.<number>}
257
- */
258
- const endAngle = [];
259
-
260
- /**
261
- * @type {number}
262
- */
263
- let iteration = 1;
264
-
265
- /**
266
- * @type {boolean}
267
- */
268
- let done = false;
269
-
270
- /**
271
- * @type {number}
272
- */
273
- let totalObstacles = 0;
274
-
275
- /**
276
- * @type {number}
277
- */
278
- let obstaclesInLastLine = 0;
279
-
280
- /**
281
- * @type {number}
282
- */
283
- let minAngle = 0;
284
-
285
- /**
286
- * @type {number}
287
- */
288
- let x;
289
-
290
- /**
291
- * @type {number}
292
- */
293
- let y;
294
-
295
- /**
296
- * @type {number}
297
- */
298
- let slopesPerCell;
299
-
300
- /**
301
- * @type {number}
302
- */
303
- let halfSlopes;
304
-
305
- /**
306
- * @type {number}
307
- */
308
- let processedCell;
309
-
310
- /**
311
- * @type {number}
312
- */
313
- let min;
314
-
315
- /**
316
- * @type {number}
317
- */
318
- let max;
319
-
320
- /**
321
- * @type {boolean}
322
- */
323
- let visible;
324
-
325
- /**
326
- * @type {boolean}
327
- */
328
- let extended;
329
-
330
- /**
331
- * @type {number}
332
- */
333
- let centreSlope;
334
-
335
- /**
336
- * @type {number}
337
- */
338
- let startSlope;
339
-
340
- /**
341
- * @type {number}
342
- */
343
- let endSlope;
344
-
345
- x = data.originX + deltaX;
346
- if (x < data.minX || x > data.maxX) {
347
- done = true;
348
- }
349
- while (!done) {
350
- slopesPerCell = 1.0 / iteration;
351
- halfSlopes = slopesPerCell * 0.5;
352
- processedCell = parseInt((minAngle + halfSlopes) / slopesPerCell);
353
- min = Math.max(data.minY, data.originY - iteration);
354
- max = Math.min(data.maxY, data.originY + iteration);
355
- done = true;
356
- for (y = data.originY + (processedCell * deltaY); y >= min && y <= max; y += deltaY) {
357
- visible = true;
358
- extended = false;
359
- centreSlope = processedCell * slopesPerCell;
360
- startSlope = centreSlope - halfSlopes;
361
- endSlope = centreSlope + halfSlopes;
362
- if (obstaclesInLastLine > 0) {
363
- if (
364
- !(
365
- data.isVisible(x - deltaX, y) &&
366
- this._isTransparent(x - deltaX, y)
367
- ) &&
368
- !(
369
- data.isVisible(x - deltaX, y - deltaY) &&
370
- this._isTransparent(x - deltaX, y - deltaY)
371
- )
372
- ) {
373
- visible = false;
374
- } else {
375
- for (let idx = 0; idx < obstaclesInLastLine && visible; ++idx) {
376
- if (startSlope <= endAngle[idx] && endSlope >= startAngle[idx]) {
377
- if (this._isTransparent(x, y)) {
378
- if (centreSlope > startAngle[idx] && centreSlope < endAngle[idx]) {
379
- visible = false;
380
- }
381
- } else {
382
- if (startSlope >= startAngle[idx] && endSlope <= endAngle[idx]) {
383
- visible = false;
384
- } else {
385
- startAngle[idx] = Math.min(startAngle[idx], startSlope);
386
- endAngle[idx] = Math.max(endAngle[idx], endSlope);
387
- extended = true;
388
- }
389
- }
390
- }
391
- }
392
- }
393
- }
394
- if (visible) {
395
- done = false;
396
- data.setVisible(x, y);
397
- if (!this._isTransparent(x, y)) {
398
- if (minAngle >= startSlope) {
399
- minAngle = endSlope;
400
- if (processedCell == iteration) {
401
- done = true;
402
- }
403
- } else if (!extended) {
404
- startAngle[totalObstacles] = startSlope;
405
- endAngle[totalObstacles++] = endSlope;
406
- }
407
- }
408
- }
409
- processedCell++;
410
- }
411
- if (iteration == data.radius) {
412
- done = true;
413
- }
414
- iteration++;
415
- obstaclesInLastLine = totalObstacles;
416
- x += deltaX;
417
- if (x < data.minX || x > data.maxX) {
418
- done = true;
419
- }
420
- }
421
- }
422
-
423
- /**
424
- * Change the dimensions of the map
425
- * @param {number} mapWidth
426
- * @param {number} mapHeight
427
- */
428
- setMapDimensions(mapWidth, mapHeight) {
429
- this._mapWidth = mapWidth;
430
- this._mapHeight = mapHeight;
431
- }
432
-
433
- /**
434
- * @param {number} originX
435
- * @param {number} originY
436
- * @param {number} radius
437
- * @param {isVisible} isVisible
438
- * @param {setVisible} setVisible
439
- */
440
- compute(originX, originY, radius, isVisible, setVisible) {
441
- setVisible(originX, originY);
442
-
443
- /**
444
- * @type {fovData}
445
- */
446
- const data = {
447
- minX: Math.max(0, originX - radius),
448
- minY: Math.max(0, originY - radius),
449
- maxX: Math.min(this._mapWidth - 1, originX + radius),
450
- maxY: Math.min(this._mapHeight - 1, originY + radius),
451
- originX: originX,
452
- originY: originY,
453
- radius: radius,
454
- isVisible: isVisible,
455
- setVisible: setVisible
456
- };
457
-
458
- this._computeOctantY(1, 1, data);
459
- this._computeOctantX(1, 1, data);
460
- this._computeOctantY(1, -1, data);
461
- this._computeOctantX(1, -1, data);
462
- this._computeOctantY(-1, 1, data);
463
- this._computeOctantX(-1, 1, data);
464
- this._computeOctantY(-1, -1, data);
465
- this._computeOctantX(-1, -1, data);
466
- }
467
- }
468
-
469
- module.exports.Mrpas = Mrpas;