@woosh/meep-engine 2.43.21 → 2.43.23

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 (50) hide show
  1. package/core/collection/HashMap.d.ts +2 -2
  2. package/core/collection/HashMap.js +22 -2
  3. package/core/geom/3d/morton/mortonEncode_magicbits.js +18 -0
  4. package/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +2 -2
  5. package/core/geom/3d/topology/struct/TopoEdge.js +4 -0
  6. package/core/geom/3d/topology/struct/TopoMesh.js +25 -0
  7. package/core/geom/3d/topology/struct/TopoTriangle.js +4 -0
  8. package/core/geom/3d/topology/struct/TopoVertex.js +8 -0
  9. package/core/geom/3d/topology/struct/binary/BinaryElementPool.js +288 -0
  10. package/core/geom/3d/topology/struct/binary/BinaryElementPool.spec.js +36 -0
  11. package/core/geom/3d/topology/struct/binary/BinaryTopology.js +617 -0
  12. package/core/geom/3d/topology/struct/binary/BinaryTopology.spec.js +16 -0
  13. package/core/geom/3d/topology/struct/binary/io/OrderedEdge.js +66 -0
  14. package/core/geom/3d/topology/struct/binary/io/bt_index_geometry_to_topology.js +188 -0
  15. package/core/geom/3d/topology/struct/binary/io/bt_index_geometry_to_topology.spec.js +84 -0
  16. package/core/geom/3d/topology/struct/binary/io/bt_mesh_calc_edges.js +51 -0
  17. package/core/geom/3d/topology/struct/binary/io/create_edge.js +106 -0
  18. package/core/geom/3d/topology/struct/binary/io/get_or_create_edge_map.js +26 -0
  19. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_has_vertex.js +16 -0
  20. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_has_vertex.spec.js +15 -0
  21. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_other_vertex.js +21 -0
  22. package/core/geom/3d/topology/struct/binary/query/bt_mesh_edge_other_vertex.spec.js +16 -0
  23. package/core/geom/3d/topology/struct/prototypeBinaryTopology.js +55 -0
  24. package/core/path/PATH_SEPARATOR.js +1 -0
  25. package/core/path/computeFileExtension.js +24 -0
  26. package/core/path/computeFileExtension.spec.js +13 -0
  27. package/core/path/computePathBase.js +21 -0
  28. package/core/path/computePathBase.spec.js +13 -0
  29. package/core/path/computePathDirectory.js +25 -0
  30. package/editor/view/library/MeshLibraryView.js +1 -1
  31. package/engine/asset/guessAssetType.js +1 -1
  32. package/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
  33. package/engine/asset/loaders/texture/TextureAssetLoader.js +1 -1
  34. package/engine/ecs/storage/BinaryBufferSerializer.js +7 -0
  35. package/engine/graphics/material/composeCompile.js +3 -5
  36. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +90 -65
  37. package/engine/graphics/sh3/README.md +2 -0
  38. package/engine/graphics/sh3/path_tracer/PathTracer.js +2 -15
  39. package/engine/graphics/sh3/path_tracer/getBiasedNormalSample.js +1 -1
  40. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +14 -9
  41. package/engine/graphics/texture/cubemap/load_environment_map.js +1 -1
  42. package/engine/graphics/util/makeMeshPreviewScene.js +38 -26
  43. package/engine/network/RemoteController.js +98 -0
  44. package/engine/network/remoteEditor.js +33 -0
  45. package/engine/save/storage/IndexedDBStorage.js +1 -0
  46. package/package.json +1 -1
  47. package/view/elements/MeshPreview.js +5 -1
  48. package/core/FilePath.js +0 -73
  49. package/core/FilePath.spec.js +0 -25
  50. package/core/geom/3d/topology/struct/BinaryTopology.js +0 -112
@@ -0,0 +1,617 @@
1
+ import { BinaryElementPool } from "./BinaryElementPool.js";
2
+ import { array_copy } from "../../../../../collection/array/copyArray.js";
3
+ import { assert } from "../../../../../assert.js";
4
+
5
+ /**
6
+ * Byte size of FLOAT_32
7
+ * @readonly
8
+ * @type {number}
9
+ */
10
+ const FLOAT_32_SIZE = 4;
11
+
12
+ /**
13
+ * Byte size of UINT_32
14
+ * @readonly
15
+ * @type {number}
16
+ */
17
+ const UINT_32_SIZE = 4;
18
+
19
+ /**
20
+ * @readonly
21
+ * @type {number}
22
+ */
23
+ export const NULL_POINTER = 0xFFFFFFFF;
24
+
25
+ /**
26
+ * Heavily influenced by blender's internal mesh structure
27
+ * @see https://github.com/blender/blender/blob/master/source/blender/bmesh/bmesh_class.h
28
+ */
29
+ export class BinaryTopology {
30
+ /**
31
+ * structure:
32
+ * coordinate: float32[3] // vertex coordinates
33
+ * normal: float32[3] // vertex normal
34
+ * edge_pointer: uint32 // Pointer to (any) edge using this vertex (for disk cycles)
35
+ *
36
+ * @type {BinaryElementPool}
37
+ * @private
38
+ */
39
+ __vertex_pool = new BinaryElementPool(3 * FLOAT_32_SIZE + 3 * FLOAT_32_SIZE + UINT_32_SIZE);
40
+ /**
41
+ * structure:
42
+ * v1: uint32 // Vertices (unordered)
43
+ * v2: uint32 // Vertices (unordered)
44
+ * l: uint32 // The list of loops around the edge points at a Loop
45
+ * v1_disk_link: uint32[2] // Disk Cycle Pointers edge around vertex v1 and d2 does the same for v2.
46
+ * v2_disk_link: uint32[2] // see above
47
+ * @type {BinaryElementPool}
48
+ * @private
49
+ */
50
+ __edge_pool = new BinaryElementPool(UINT_32_SIZE * 7);
51
+ /**
52
+ * Loop represents a corner of the face
53
+ * structure:
54
+ * v: uint32 // The vertex this loop points to. This vertex must be unique within the cycle
55
+ * e: uint32 // The edge this loop uses.
56
+ * f: uint32 // The face this loop is part of.
57
+ * radial_next: uint32 // Other loops connected to this edge.
58
+ * radial_prev: uint32
59
+ * next: uint32 // Other loops that are part of this face.
60
+ * prev: uint32
61
+ * @type {BinaryElementPool}
62
+ * @private
63
+ */
64
+ __loop_pool = new BinaryElementPool(UINT_32_SIZE * 7);
65
+ /**
66
+ * structure:
67
+ * l_first: uint32 // first loop pointer
68
+ * no: float32[3] // Face normal
69
+ * @type {BinaryElementPool}
70
+ * @private
71
+ */
72
+ __face_pool = new BinaryElementPool(UINT_32_SIZE + FLOAT_32_SIZE * 3);
73
+
74
+
75
+ /**
76
+ * Total (approximate) size of this structure in memory, in bytes
77
+ * @return {number}
78
+ */
79
+ get byteSize() {
80
+ return this.__loop_pool.byteSize
81
+ + this.__vertex_pool.byteSize
82
+ + this.__edge_pool.byteSize
83
+ + this.__face_pool.byteSize
84
+ ;
85
+ }
86
+
87
+ trim() {
88
+ this.__loop_pool.trim();
89
+ this.__vertex_pool.trim();
90
+ this.__edge_pool.trim();
91
+ this.__face_pool.trim();
92
+ }
93
+
94
+ get vertices() {
95
+ return this.__vertex_pool;
96
+ }
97
+
98
+ /**
99
+ * Edges are shared among faces, edges point to 2 unordered vertices
100
+ * @return {BinaryElementPool}
101
+ */
102
+ get edges() {
103
+ return this.__edge_pool;
104
+ }
105
+
106
+ /**
107
+ * Loops are corners of faces, a single vertex can be associated with many loops, one per connected face
108
+ * @return {BinaryElementPool}
109
+ */
110
+ get loops() {
111
+ return this.__loop_pool;
112
+ }
113
+
114
+ get faces() {
115
+ return this.__face_pool;
116
+ }
117
+
118
+
119
+ /**
120
+ * Clear the topology, removed all data
121
+ */
122
+ clear() {
123
+ this.__vertex_pool.clear();
124
+ this.__edge_pool.clear();
125
+ this.__loop_pool.clear();
126
+ this.__face_pool.clear();
127
+ }
128
+
129
+ /**
130
+ *
131
+ * @param {number[]|ArrayLike<number>|Float32Array} result
132
+ * @param {number} result_offset
133
+ * @param {number} id vertex ID
134
+ */
135
+ vertex_read_coordinate(result, result_offset, id) {
136
+ const pool = this.__vertex_pool;
137
+
138
+ const v_address = pool.element_address(id);
139
+ const v_offset = v_address >> 2; // get 4-byte boundary
140
+ array_copy(pool.data_float32, v_offset, result, result_offset, 3);
141
+ }
142
+
143
+ /**
144
+ *
145
+ * @param {number} id
146
+ * @param {number[]} value
147
+ * @param {number} value_offset
148
+ */
149
+ vertex_write_coordinate(id, value, value_offset) {
150
+ const pool = this.__vertex_pool;
151
+
152
+ const v_address = pool.element_address(id);
153
+ const v_offset = v_address >> 2; // get 4-byte boundary
154
+ array_copy(value, value_offset, pool.data_float32, v_offset, 3);
155
+ }
156
+
157
+ /**
158
+ *
159
+ * @param {number[]|ArrayLike<number>|Float32Array} result
160
+ * @param {number} result_offset
161
+ * @param {number} id vertex ID
162
+ */
163
+ vertex_read_normal(result, result_offset, id) {
164
+ const pool = this.__vertex_pool;
165
+
166
+ const v_address = pool.element_address(id) + 3 * FLOAT_32_SIZE;
167
+ const v_offset = v_address >> 2; // get 4-byte boundary
168
+ array_copy(pool.data_float32, v_offset, result, result_offset, 3);
169
+ }
170
+
171
+ /**
172
+ *
173
+ * @param {number} id
174
+ * @param {number[]} value
175
+ * @param {number} value_offset
176
+ */
177
+ vertex_write_normal(id, value, value_offset) {
178
+ const pool = this.__vertex_pool;
179
+
180
+ const v_address = pool.element_address(id) + 3 * FLOAT_32_SIZE;
181
+ const v_offset = v_address >> 2; // get 4-byte boundary
182
+ array_copy(value, value_offset, pool.data_float32, v_offset, 3);
183
+ }
184
+
185
+ /**
186
+ * @param {number} id
187
+ * @returns {number}
188
+ */
189
+ vertex_read_edge(id) {
190
+ const pool = this.__vertex_pool;
191
+
192
+ const address = pool.element_address(id);
193
+ return pool.data_view.getUint32(address + 6 * UINT_32_SIZE);
194
+
195
+ }
196
+
197
+ /**
198
+ *
199
+ * @param {number} edge_id
200
+ * @param {number} id
201
+ */
202
+ vertex_write_edge(id, edge_id) {
203
+ const pool = this.__vertex_pool;
204
+
205
+ const address = pool.element_address(id);
206
+ pool.data_view.setUint32(address + 6 * UINT_32_SIZE, edge_id);
207
+ }
208
+
209
+ /**
210
+ * @param {number} id edge ID
211
+ * @returns {number}
212
+ */
213
+ edge_read_vertex1(id) {
214
+ const pool = this.__edge_pool;
215
+
216
+ const address = pool.element_address(id);
217
+ return pool.data_view.getUint32(address);
218
+
219
+ }
220
+
221
+ /**
222
+ *
223
+ * @param {number} value
224
+ * @param {number} id edge ID
225
+ */
226
+ edge_write_vertex1(id, value) {
227
+ const pool = this.__edge_pool;
228
+
229
+ const address = pool.element_address(id);
230
+ pool.data_view.setUint32(address, value);
231
+ }
232
+
233
+ /**
234
+ * @param {number} id edge ID
235
+ * @returns {number}
236
+ */
237
+ edge_read_vertex2(id) {
238
+ const pool = this.__edge_pool;
239
+
240
+ const address = pool.element_address(id);
241
+ return pool.data_view.getUint32(address + UINT_32_SIZE);
242
+
243
+ }
244
+
245
+ /**
246
+ *
247
+ * @param {number} value
248
+ * @param {number} id edge ID
249
+ */
250
+ edge_write_vertex2(id, value) {
251
+ const pool = this.__edge_pool;
252
+
253
+ const address = pool.element_address(id);
254
+ pool.data_view.setUint32(address + UINT_32_SIZE, value);
255
+ }
256
+
257
+
258
+ /**
259
+ * @param {number} id edge ID
260
+ * @returns {number}
261
+ */
262
+ edge_read_loop(id) {
263
+ assert.isNonNegativeInteger(id, 'id');
264
+ const pool = this.__edge_pool;
265
+
266
+ assert.equal(pool.is_allocated(id), true, 'element is not allocated');
267
+
268
+ const address = pool.element_address(id);
269
+ return pool.data_view.getUint32(address + 2 * UINT_32_SIZE);
270
+
271
+ }
272
+
273
+ /**
274
+ *
275
+ * @param {number} value
276
+ * @param {number} id edge ID
277
+ */
278
+ edge_write_loop(id, value) {
279
+ const pool = this.__edge_pool;
280
+
281
+ const address = pool.element_address(id);
282
+ pool.data_view.setUint32(address + 2 * UINT_32_SIZE, value);
283
+ }
284
+
285
+ /**
286
+ * @param {number} id edge ID
287
+ * @returns {number}
288
+ */
289
+ edge_read_v1_disk_next(id) {
290
+ assert.isNonNegativeInteger(id, 'id');
291
+ const pool = this.__edge_pool;
292
+
293
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
294
+
295
+ const address = pool.element_address(id);
296
+ return pool.data_view.getUint32(address + 3 * UINT_32_SIZE);
297
+
298
+ }
299
+
300
+ /**
301
+ *
302
+ * @param {number} value
303
+ * @param {number} id edge ID
304
+ */
305
+ edge_write_v1_disk_next(id, value) {
306
+ const pool = this.__edge_pool;
307
+
308
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
309
+
310
+ const address = pool.element_address(id);
311
+ pool.data_view.setUint32(address + 3 * UINT_32_SIZE, value);
312
+ }
313
+
314
+ /**
315
+ * @param {number} id edge ID
316
+ * @returns {number}
317
+ */
318
+ edge_read_v1_disk_prev(id) {
319
+ assert.isNonNegativeInteger(id, 'id');
320
+ const pool = this.__edge_pool;
321
+
322
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
323
+
324
+ const address = pool.element_address(id);
325
+ return pool.data_view.getUint32(address + 4 * UINT_32_SIZE);
326
+
327
+ }
328
+
329
+ /**
330
+ *
331
+ * @param {number} value
332
+ * @param {number} id edge ID
333
+ */
334
+ edge_write_v1_disk_prev(id, value) {
335
+ const pool = this.__edge_pool;
336
+
337
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
338
+
339
+ const address = pool.element_address(id);
340
+ pool.data_view.setUint32(address + 4 * UINT_32_SIZE, value);
341
+ }
342
+
343
+ /**
344
+ * @param {number} id edge ID
345
+ * @returns {number}
346
+ */
347
+ edge_read_v2_disk_next(id) {
348
+ assert.isNonNegativeInteger(id, 'id');
349
+ const pool = this.__edge_pool;
350
+
351
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
352
+
353
+ const address = pool.element_address(id);
354
+ return pool.data_view.getUint32(address + 5 * UINT_32_SIZE);
355
+
356
+ }
357
+
358
+ /**
359
+ *
360
+ * @param {number} value
361
+ * @param {number} id edge ID
362
+ */
363
+ edge_write_v2_disk_next(id, value) {
364
+ const pool = this.__edge_pool;
365
+
366
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
367
+
368
+ const address = pool.element_address(id);
369
+ pool.data_view.setUint32(address + 5 * UINT_32_SIZE, value);
370
+ }
371
+
372
+ /**
373
+ * @param {number} id edge ID
374
+ * @returns {number}
375
+ */
376
+ edge_read_v2_disk_prev(id) {
377
+ assert.isNonNegativeInteger(id, 'id');
378
+ const pool = this.__edge_pool;
379
+
380
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
381
+
382
+ const address = pool.element_address(id);
383
+ return pool.data_view.getUint32(address + 6 * UINT_32_SIZE);
384
+
385
+ }
386
+
387
+ /**
388
+ *
389
+ * @param {number} value
390
+ * @param {number} id edge ID
391
+ */
392
+ edge_write_v2_disk_prev(id, value) {
393
+ const pool = this.__edge_pool;
394
+
395
+ // assert.equal(pool.is_allocated(id), true, 'element is not allocated');
396
+
397
+ const address = pool.element_address(id);
398
+ pool.data_view.setUint32(address + 6 * UINT_32_SIZE, value);
399
+ }
400
+
401
+ loop_create() {
402
+ const id = this.__loop_pool.allocate();
403
+
404
+ this.loop_initialize(id);
405
+
406
+ return id;
407
+ }
408
+
409
+ /**
410
+ * Put loop into valid initial state, set all pointers to NULL
411
+ * @param {number} id
412
+ */
413
+ loop_initialize(id) {
414
+ this.loop_write_radial_next(id, id);
415
+ this.loop_write_radial_prev(id, id);
416
+ this.loop_write_next(id, id);
417
+ this.loop_write_prev(id, id);
418
+ }
419
+
420
+ /**
421
+ * @param {number} id loop ID
422
+ * @returns {number}
423
+ */
424
+ loop_read_vertex(id) {
425
+ const pool = this.__loop_pool;
426
+
427
+ const address = pool.element_address(id);
428
+ return pool.data_view.getUint32(address);
429
+
430
+ }
431
+
432
+ /**
433
+ *
434
+ * @param {number} value
435
+ * @param {number} id loop ID
436
+ */
437
+ loop_write_vertex(id, value) {
438
+ const pool = this.__loop_pool;
439
+
440
+ const address = pool.element_address(id);
441
+ pool.data_view.setUint32(address, value);
442
+ }
443
+
444
+ /**
445
+ *
446
+ * @param {number} id loop ID
447
+ * @returns {number}
448
+ */
449
+ loop_read_edge(id) {
450
+ const pool = this.__loop_pool;
451
+
452
+ const address = pool.element_address(id);
453
+ return pool.data_view.getUint32(address + UINT_32_SIZE);
454
+ }
455
+
456
+ /**
457
+ *
458
+ * @param {number} value
459
+ * @param {number} id loop ID
460
+ */
461
+ loop_write_edge(id, value) {
462
+ const pool = this.__loop_pool;
463
+
464
+ const address = pool.element_address(id);
465
+ pool.data_view.setUint32(address + UINT_32_SIZE, value);
466
+ }
467
+
468
+ /**
469
+ *
470
+ * @param {number} id loop ID
471
+ * @returns {number}
472
+ */
473
+ loop_read_face(id) {
474
+ const pool = this.__loop_pool;
475
+
476
+ const address = pool.element_address(id);
477
+ return pool.data_view.getUint32(address + 2 * UINT_32_SIZE);
478
+ }
479
+
480
+ /**
481
+ *
482
+ * @param {number} value
483
+ * @param {number} id loop ID
484
+ */
485
+ loop_write_face(id, value) {
486
+ assert.isNonNegativeInteger(id, 'id');
487
+
488
+ const pool = this.__loop_pool;
489
+
490
+ const address = pool.element_address(id);
491
+ pool.data_view.setUint32(address + 2 * UINT_32_SIZE, value);
492
+ }
493
+
494
+ /**
495
+ *
496
+ * @param {number} id loop ID
497
+ * @returns {number}
498
+ */
499
+ loop_read_radial_next(id) {
500
+ assert.isNonNegativeInteger(id, 'id');
501
+ const pool = this.__loop_pool;
502
+
503
+ const address = pool.element_address(id);
504
+ return pool.data_view.getUint32(address + 3 * UINT_32_SIZE);
505
+ }
506
+
507
+ /**
508
+ *
509
+ * @param {number} value
510
+ * @param {number} id loop ID
511
+ */
512
+ loop_write_radial_next(id, value) {
513
+ assert.isNonNegativeInteger(id, 'id');
514
+ const pool = this.__loop_pool;
515
+
516
+ const address = pool.element_address(id);
517
+ pool.data_view.setUint32(address + 3 * UINT_32_SIZE, value);
518
+ }
519
+
520
+ /**
521
+ *
522
+ * @param {number} id loop ID
523
+ * @returns {number}
524
+ */
525
+ loop_read_radial_prev(id) {
526
+ assert.isNonNegativeInteger(id, 'id');
527
+ const pool = this.__loop_pool;
528
+
529
+ const address = pool.element_address(id);
530
+ return pool.data_view.getUint32(address + 4 * UINT_32_SIZE);
531
+ }
532
+
533
+ /**
534
+ *
535
+ * @param {number} value
536
+ * @param {number} id loop ID
537
+ */
538
+ loop_write_radial_prev(id, value) {
539
+ assert.isNonNegativeInteger(id, 'id');
540
+ const pool = this.__loop_pool;
541
+
542
+ const address = pool.element_address(id);
543
+ pool.data_view.setUint32(address + 4 * UINT_32_SIZE, value);
544
+ }
545
+
546
+ /**
547
+ *
548
+ * @param {number} id loop ID
549
+ * @returns {number}
550
+ */
551
+ loop_read_next(id) {
552
+ const pool = this.__loop_pool;
553
+
554
+ const address = pool.element_address(id);
555
+ return pool.data_view.getUint32(address + 5 * UINT_32_SIZE);
556
+ }
557
+
558
+ /**
559
+ *
560
+ * @param {number} value
561
+ * @param {number} id loop ID
562
+ */
563
+ loop_write_next(id, value) {
564
+ const pool = this.__loop_pool;
565
+
566
+ const address = pool.element_address(id);
567
+ pool.data_view.setUint32(address + 5 * UINT_32_SIZE, value);
568
+ }
569
+
570
+ /**
571
+ *
572
+ * @param {number} id loop ID
573
+ * @returns {number}
574
+ */
575
+ loop_read_prev(id) {
576
+ const pool = this.__loop_pool;
577
+
578
+ const address = pool.element_address(id);
579
+ return pool.data_view.getUint32(address + 6 * UINT_32_SIZE);
580
+ }
581
+
582
+ /**
583
+ *
584
+ * @param {number} value
585
+ * @param {number} id loop ID
586
+ */
587
+ loop_write_prev(id, value) {
588
+ const pool = this.__loop_pool;
589
+
590
+ const address = pool.element_address(id);
591
+ pool.data_view.setUint32(address + 6 * UINT_32_SIZE, value);
592
+ }
593
+
594
+ /**
595
+ *
596
+ * @param {number} id face ID
597
+ * @returns {number}
598
+ */
599
+ face_read_loop(id) {
600
+ const pool = this.__face_pool;
601
+
602
+ const address = pool.element_address(id);
603
+ return pool.data_view.getUint32(address);
604
+ }
605
+
606
+ /**
607
+ *
608
+ * @param {number} value
609
+ * @param {number} id face ID
610
+ */
611
+ face_write_loop(id, value) {
612
+ const pool = this.__face_pool;
613
+
614
+ const address = pool.element_address(id);
615
+ pool.data_view.setUint32(address, value);
616
+ }
617
+ }
@@ -0,0 +1,16 @@
1
+ import { BinaryTopology } from "./BinaryTopology.js";
2
+
3
+ test('create and set vertex', () => {
4
+
5
+ const topo = new BinaryTopology();
6
+
7
+ const v = topo.vertices.allocate();
8
+
9
+ topo.vertex_write_coordinate(v, [1, 2, 0], 0);
10
+
11
+ const coordinate = [];
12
+
13
+ topo.vertex_read_coordinate(coordinate, 0, v);
14
+
15
+ expect(coordinate).toEqual([1, 2, 0]);
16
+ });
@@ -0,0 +1,66 @@
1
+ import { split_by_2 } from "../../../../morton/mortonEncode_magicbits.js";
2
+
3
+ export class OrderedEdge {
4
+ /**
5
+ *
6
+ * @param {number} v1
7
+ * @param {number} v2
8
+ */
9
+ constructor(v1, v2) {
10
+ if (v1 < v2) {
11
+ this.v_low = v1;
12
+ this.v_high = v2;
13
+ } else {
14
+ this.v_low = v2;
15
+ this.v_high = v1;
16
+ }
17
+ }
18
+
19
+ /**
20
+ *
21
+ * @param {number} v1
22
+ * @param {number} v2
23
+ */
24
+ set(v1, v2) {
25
+ if (v1 < v2) {
26
+ this.v_low = v1;
27
+ this.v_high = v2;
28
+ } else {
29
+ this.v_low = v2;
30
+ this.v_high = v1;
31
+ }
32
+ }
33
+
34
+ /**
35
+ *
36
+ * @param {OrderedEdge} other
37
+ */
38
+ copy(other) {
39
+ this.v_low = other.v_low;
40
+ this.v_high = other.v_high;
41
+ }
42
+
43
+ clone() {
44
+ return new OrderedEdge(this.v_low, this.v_high);
45
+ }
46
+
47
+ /**
48
+ *
49
+ * @return {number}
50
+ */
51
+ hash() {
52
+ // resulting hashes are close by
53
+ return split_by_2(this.v_low) | (split_by_2(this.v_high) << 1);
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param {OrderedEdge} other
59
+ * @returns {boolean}
60
+ */
61
+ equals(other) {
62
+ return this.v_low === other.v_low
63
+ && this.v_high === other.v_high
64
+ ;
65
+ }
66
+ }