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.js DELETED
@@ -1,470 +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
- /**
36
- * @param {number} mapWidth
37
- * @param {number} mapHeight
38
- * @param {isTransparent} isTransparent
39
- * @constructor
40
- */
41
- var Mrpas = function(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
- Mrpas.prototype._computeOctantY = function(deltaX, deltaY, data) {
69
- /**
70
- * @type {Array.<number>}
71
- */
72
- var startAngle = [];
73
-
74
- /**
75
- * @type {Array.<number>}
76
- */
77
- var endAngle = [];
78
-
79
- /**
80
- * @type {number}
81
- */
82
- var iteration = 1;
83
-
84
- /**
85
- * @type {boolean}
86
- */
87
- var done = false;
88
-
89
- /**
90
- * @type {number}
91
- */
92
- var totalObstacles = 0;
93
-
94
- /**
95
- * @type {number}
96
- */
97
- var obstaclesInLastLine = 0;
98
-
99
- /**
100
- * @type {number}
101
- */
102
- var minAngle = 0;
103
-
104
- /**
105
- * @type {number}
106
- */
107
- var x;
108
-
109
- /**
110
- * @type {number}
111
- */
112
- var y;
113
-
114
- /**
115
- * @type {number}
116
- */
117
- var slopesPerCell;
118
-
119
- /**
120
- * @type {number}
121
- */
122
- var halfSlopes;
123
-
124
- /**
125
- * @type {number}
126
- */
127
- var processedCell;
128
-
129
- /**
130
- * @type {number}
131
- */
132
- var min;
133
-
134
- /**
135
- * @type {number}
136
- */
137
- var max;
138
-
139
- /**
140
- * @type {boolean}
141
- */
142
- var visible;
143
-
144
- /**
145
- * @type {boolean}
146
- */
147
- var extended;
148
-
149
- /**
150
- * @type {number}
151
- */
152
- var centreSlope;
153
-
154
- /**
155
- * @type {number}
156
- */
157
- var startSlope;
158
-
159
- /**
160
- * @type {number}
161
- */
162
- var 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 (var 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
- ++idx;
210
- }
211
- }
212
- }
213
- }
214
- if (visible) {
215
- done = false;
216
- data.setVisible(x, y);
217
- if (!this._isTransparent(x, y)) {
218
- if (minAngle >= startSlope) {
219
- minAngle = endSlope;
220
- if (processedCell == iteration) {
221
- done = true;
222
- }
223
- } else if (!extended) {
224
- startAngle[totalObstacles] = startSlope;
225
- endAngle[totalObstacles++] = endSlope;
226
- }
227
- }
228
- }
229
- processedCell++;
230
- }
231
- if (iteration == data.radius) {
232
- done = true;
233
- }
234
- iteration++;
235
- obstaclesInLastLine = totalObstacles;
236
- y += deltaY;
237
- if (y < data.minY || y > data.maxY) {
238
- done = true;
239
- }
240
- }
241
- };
242
-
243
- /**
244
- * Compute the FOV in an octant adjacent to the X axis
245
- * @param {number} deltaX
246
- * @param {number} deltaY
247
- * @param {fovData} data
248
- * @private
249
- */
250
- Mrpas.prototype._computeOctantX = function(deltaX, deltaY, data) {
251
- /**
252
- * @type {Array.<number>}
253
- */
254
- var startAngle = [];
255
-
256
- /**
257
- * @type {Array.<number>}
258
- */
259
- var endAngle = [];
260
-
261
- /**
262
- * @type {number}
263
- */
264
- var iteration = 1;
265
-
266
- /**
267
- * @type {boolean}
268
- */
269
- var done = false;
270
-
271
- /**
272
- * @type {number}
273
- */
274
- var totalObstacles = 0;
275
-
276
- /**
277
- * @type {number}
278
- */
279
- var obstaclesInLastLine = 0;
280
-
281
- /**
282
- * @type {number}
283
- */
284
- var minAngle = 0;
285
-
286
- /**
287
- * @type {number}
288
- */
289
- var x;
290
-
291
- /**
292
- * @type {number}
293
- */
294
- var y;
295
-
296
- /**
297
- * @type {number}
298
- */
299
- var slopesPerCell;
300
-
301
- /**
302
- * @type {number}
303
- */
304
- var halfSlopes;
305
-
306
- /**
307
- * @type {number}
308
- */
309
- var processedCell;
310
-
311
- /**
312
- * @type {number}
313
- */
314
- var min;
315
-
316
- /**
317
- * @type {number}
318
- */
319
- var max;
320
-
321
- /**
322
- * @type {boolean}
323
- */
324
- var visible;
325
-
326
- /**
327
- * @type {boolean}
328
- */
329
- var extended;
330
-
331
- /**
332
- * @type {number}
333
- */
334
- var centreSlope;
335
-
336
- /**
337
- * @type {number}
338
- */
339
- var startSlope;
340
-
341
- /**
342
- * @type {number}
343
- */
344
- var endSlope;
345
-
346
- x = data.originX + deltaX;
347
- if (x < data.minX || x > data.maxX) {
348
- done = true;
349
- }
350
- while (!done) {
351
- slopesPerCell = 1.0 / iteration;
352
- halfSlopes = slopesPerCell * 0.5;
353
- processedCell = parseInt((minAngle + halfSlopes) / slopesPerCell);
354
- min = Math.max(data.minY, data.originY - iteration);
355
- max = Math.min(data.maxY, data.originY + iteration);
356
- done = true;
357
- for (y = data.originY + (processedCell * deltaY); y >= min && y <= max; y+=deltaY) {
358
- visible = true;
359
- extended = false;
360
- centreSlope = processedCell * slopesPerCell;
361
- startSlope = centreSlope - halfSlopes;
362
- endSlope = centreSlope + halfSlopes;
363
- if (obstaclesInLastLine > 0) {
364
- if (
365
- !(
366
- data.isVisible(x - deltaX, y) &&
367
- this._isTransparent(x - deltaX, y)
368
- ) &&
369
- !(
370
- data.isVisible(x - deltaX, y - deltaY) &&
371
- this._isTransparent(x - deltaX, y - deltaY)
372
- )
373
- ) {
374
- visible = false;
375
- } else {
376
- for (var idx = 0; idx < obstaclesInLastLine && visible; ++idx) {
377
- if (startSlope <= endAngle[idx] && endSlope >= startAngle[idx]) {
378
- if (this._isTransparent(x, y)) {
379
- if (centreSlope > startAngle[idx] && centreSlope < endAngle[idx]) {
380
- visible = false;
381
- }
382
- } else {
383
- if (startSlope >= startAngle[idx] && endSlope <= endAngle[idx]) {
384
- visible = false;
385
- } else {
386
- startAngle[idx] = Math.min(startAngle[idx], startSlope);
387
- endAngle[idx] = Math.max(endAngle[idx], endSlope);
388
- extended = true;
389
- }
390
- }
391
- ++idx;
392
- }
393
- }
394
- }
395
- }
396
- if (visible) {
397
- done = false;
398
- data.setVisible(x, y);
399
- if (!this._isTransparent(x, y)) {
400
- if (minAngle >= startSlope) {
401
- minAngle = endSlope;
402
- if (processedCell == iteration) {
403
- done = true;
404
- }
405
- } else if (!extended) {
406
- startAngle[totalObstacles] = startSlope;
407
- endAngle[totalObstacles++] = endSlope;
408
- }
409
- }
410
- }
411
- processedCell++;
412
- }
413
- if (iteration == data.radius) {
414
- done = true;
415
- }
416
- iteration++;
417
- obstaclesInLastLine = totalObstacles;
418
- x += deltaX;
419
- if (x < data.minX || x > data.maxX) {
420
- done = true;
421
- }
422
- }
423
- };
424
-
425
- /**
426
- * Change the dimensions of the map
427
- * @param {number} mapWidth
428
- * @param {number} mapHeight
429
- */
430
- Mrpas.prototype.setMapDimensions = function(mapWidth, mapHeight) {
431
- this._mapWidth = mapWidth;
432
- this._mapHeight = mapHeight;
433
- };
434
-
435
- /**
436
- * @param {number} originX
437
- * @param {number} originY
438
- * @param {number} radius
439
- * @param {isVisible} isVisible
440
- * @param {setVisible} setVisible
441
- */
442
- Mrpas.prototype.compute = function(originX, originY, radius, isVisible, setVisible) {
443
- setVisible(originX, originY);
444
-
445
- /**
446
- * @type {fovData}
447
- */
448
- var data = {
449
- minX: Math.max(0, originX - radius),
450
- minY: Math.max(0, originY - radius),
451
- maxX: Math.min(this._mapWidth - 1, originX + radius),
452
- maxY: Math.min(this._mapHeight - 1, originY + radius),
453
- originX: originX,
454
- originY: originY,
455
- radius: radius,
456
- isVisible: isVisible,
457
- setVisible: setVisible
458
- };
459
-
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
- this._computeOctantY(-1, -1, data);
467
- this._computeOctantX(-1, -1, data);
468
- };
469
-
470
- module.exports = Mrpas;