@woosh/meep-engine 2.43.1 → 2.43.3
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/core/bvh2/aabb3/aabb3_array_combine.js +2 -2
- package/core/collection/RingBuffer.js +4 -2
- package/core/collection/RingBuffer.spec.js +59 -0
- package/core/collection/array/ArrayIteratorRandom.js +1 -1
- package/core/collection/{ArrayUtils.spec.js → array/arrayPickBestElement.spec.js} +1 -1
- package/core/collection/array/arrayPickBestElements.js +51 -0
- package/core/collection/array/arrayPickMinElement.js +43 -0
- package/core/collection/array/arrayQuickSort.js +1 -1
- package/core/collection/array/arraySetSortingDiff.js +1 -1
- package/core/collection/array/arraySwapElements.js +12 -0
- package/core/collection/array/groupArrayBy.js +42 -0
- package/core/collection/array/isArrayEqual.js +50 -0
- package/core/collection/array/randomMultipleFromArray.js +34 -0
- package/core/collection/array/randomizeArrayElementOrder.js +23 -0
- package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +1 -1
- package/core/geom/3d/aabb/aabb3_build_frustum.js +1 -1
- package/core/geom/3d/aabb/compute_aabb_from_points.js +1 -1
- package/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +3 -1
- package/core/geom/3d/morton/v3_morton_encode_transformed.spec.js +20 -0
- package/core/geom/3d/plane/orient3d_fast.js +8 -10
- package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +0 -23
- package/core/geom/3d/plane/plane_three_compute_convex3_plane_intersection.js +24 -0
- package/core/geom/3d/shape/UnionShape3D.js +1 -1
- package/core/geom/3d/tetrahedra/README.md +10 -1
- package/core/geom/3d/tetrahedra/{tetrahedra_collection.js → TetrahedralMesh.js} +236 -152
- package/core/geom/3d/tetrahedra/TetrahedralMesh.spec.js +156 -0
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +2 -2
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.spec.js +4 -4
- package/core/geom/3d/tetrahedra/delaunay/Cavity.js +45 -7
- package/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +44 -9
- package/core/geom/3d/tetrahedra/delaunay/debug_validate_mesh.js +19 -0
- package/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +155 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity2.js +224 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.js +77 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.spec.js +30 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_insert_point.js +98 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +13 -6
- package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +9 -9
- package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +1 -1
- package/core/geom/3d/tetrahedra/tetrahedron_compute_signed_volume.js +83 -0
- package/core/geom/3d/tetrahedra/tetrahedron_compute_signed_volume.spec.js +24 -0
- package/core/geom/3d/tetrahedra/tetrahedron_contains_point.spec.js +66 -0
- package/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.js +119 -0
- package/core/geom/Bezier.js +0 -27
- package/core/geom/Plane.js +0 -4
- package/core/geom/packing/miniball/Subspan.js +2 -2
- package/core/geom/v3_lerp.js +6 -1
- package/core/math/isqrt.js +28 -0
- package/core/math/isqrt.spec.js +9 -0
- package/core/math/max.spec.js +25 -0
- package/core/math/min2.spec.js +25 -0
- package/core/model/node-graph/node/NodeInstance.js +3 -3
- package/core/primitives/strings/prefixTree/PrefixTreeLeaf.js +1 -1
- package/core/process/task/util/randomCountTask.js +1 -1
- package/editor/ecs/component/editors/primitive/ArrayEditor.js +1 -1
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +6 -0
- package/editor/view/ecs/components/common/AutoCanvasView.js +13 -25
- package/engine/asset/AssetManager.d.ts +5 -1
- package/engine/asset/AssetManager.js +50 -15
- package/engine/asset/AssetManager.spec.js +17 -11
- package/engine/asset/AssetRequest.js +57 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +22 -0
- package/engine/asset/loaders/AssetLoader.js +1 -1
- package/engine/ecs/System.js +1 -1
- package/engine/ecs/dynamic_actions/DynamicActorSystem.js +1 -1
- package/engine/graphics/FrameRunner.js +5 -9
- package/engine/graphics/ecs/animation/animator/AnimationClipDefinition.js +1 -1
- package/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +1 -1
- package/engine/graphics/ecs/camera/Camera.js +1 -10
- package/engine/graphics/ecs/camera/CameraSystem.js +8 -8
- package/engine/graphics/ecs/camera/ProjectionType.js +9 -0
- package/engine/graphics/ecs/camera/build_three_camera_object.js +3 -3
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +59 -4
- package/engine/graphics/geometry/VertexDataSpec.js +1 -1
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +3 -3
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +1 -1
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +3 -1
- package/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.spec.js +4 -0
- package/engine/graphics/render/forward_plus/computeFrustumCorners.js +4 -2
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/engine/graphics/render/layers/RenderLayerUtils.js +2 -2
- package/engine/graphics/shaders/DenoiseShader.js +1 -1
- package/engine/graphics/texture/atlas/AtlasPatch.js +11 -3
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +2 -2
- package/engine/graphics/texture/atlas/TextureAtlas.js +7 -1
- package/engine/graphics/texture/atlas/TextureAtlas.spec.js +22 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +0 -64
- package/engine/graphics/texture/sampler/Sampler2D.spec.js +2 -1
- package/engine/graphics/texture/sampler/sampler2d_combine.js +67 -0
- package/engine/intelligence/behavior/ecs/BehaviorSystem.spec.js +0 -3
- package/engine/network/PriorityFetch.js +192 -0
- package/engine/simulation/DormandPrince.js +1 -1
- package/engine/ui/DraggableAspect.js +0 -1
- package/generation/grid/generation/road/GridTaskGenerateRoads.js +1 -1
- package/package.json +1 -1
- package/view/elements/CanvasView.js +7 -1
- package/view/elements/image/HTMLElementCacheKey.js +1 -1
- package/view/util/DomSizeObserver.js +3 -5
- package/core/collection/ArrayUtils.js +0 -263
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +0 -73
- package/core/geom/3d/tetrahedra/hxt/a.js +0 -524
- package/core/geom/3d/tetrahedra/hxt/hxt.js +0 -140
- package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import FastBinaryHeap from "../../core/collection/heap/FastBinaryHeap.js";
|
|
2
|
+
import { noop } from "../../core/function/Functions.js";
|
|
3
|
+
import { assert } from "../../core/assert.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @readonly
|
|
7
|
+
* @type {{high: number, auto: number, low: number}}
|
|
8
|
+
*/
|
|
9
|
+
const priority_value_map = {
|
|
10
|
+
"high": 10,
|
|
11
|
+
"low": -1,
|
|
12
|
+
"auto": 0
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {string|undefined} p
|
|
18
|
+
* @return {number}
|
|
19
|
+
*/
|
|
20
|
+
function extract_priority_from_resource(p) {
|
|
21
|
+
|
|
22
|
+
let v = 0;
|
|
23
|
+
|
|
24
|
+
if (typeof p === "string") {
|
|
25
|
+
v = priority_value_map[p];
|
|
26
|
+
|
|
27
|
+
if (v === undefined) {
|
|
28
|
+
console.warn(`Unsupported request priority value '${p}', defaulting to 'auto'`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
v = priority_value_map['auto'];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return v;
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class FetchRequest {
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param {Request|string} resource
|
|
42
|
+
* @param {{}} options
|
|
43
|
+
*/
|
|
44
|
+
constructor(resource, options) {
|
|
45
|
+
let priority = 0;
|
|
46
|
+
|
|
47
|
+
this.__resource = resource;
|
|
48
|
+
this.__options = options;
|
|
49
|
+
|
|
50
|
+
if (typeof this.__resource === "object" && typeof this.__resource.priority !== "undefined") {
|
|
51
|
+
priority = extract_priority_from_resource(this.__resource.priority);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.__priority = priority;
|
|
55
|
+
|
|
56
|
+
this.fulfillment = {
|
|
57
|
+
resolve: null, reject: null
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
this.promise = new Promise((resolve, reject) => {
|
|
61
|
+
this.fulfillment.resolve = resolve;
|
|
62
|
+
this.fulfillment.reject = reject;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @param {FetchRequest} request
|
|
70
|
+
* @returns {number}
|
|
71
|
+
*/
|
|
72
|
+
function get_priority_score(request) {
|
|
73
|
+
return -request.__priority;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @readonly
|
|
78
|
+
* @type {number}
|
|
79
|
+
*/
|
|
80
|
+
const DEFAULT_CONCURRENCY = Infinity;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Wraps {@link fetch} api and adds concurrency management to it by queueing requests,
|
|
84
|
+
* as well as prioritization in that queue
|
|
85
|
+
*/
|
|
86
|
+
export class PriorityFetch {
|
|
87
|
+
constructor({
|
|
88
|
+
adapter = noop,
|
|
89
|
+
concurrency = DEFAULT_CONCURRENCY
|
|
90
|
+
}) {
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* @type {number}
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
this.__concurrency = concurrency;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
*
|
|
100
|
+
* @type {BinaryHeap<FetchRequest>}
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
this.__queue = new FastBinaryHeap(get_priority_score);
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @type {Set<FetchRequest>}
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
this.__pending_set = new Set();
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @type {null}
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
this.__adapter = adapter;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
*
|
|
122
|
+
* @param {function} v
|
|
123
|
+
*/
|
|
124
|
+
set adapter(v) {
|
|
125
|
+
this.__adapter = v;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
*
|
|
130
|
+
* @param {number} v
|
|
131
|
+
*/
|
|
132
|
+
set concurrency(v) {
|
|
133
|
+
assert.isNumber(v, 'v');
|
|
134
|
+
assert.notNaN(v, 'v');
|
|
135
|
+
assert.greaterThan(v, 0, 'concurrency must be greater than 0');
|
|
136
|
+
|
|
137
|
+
this.__concurrency = v;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @return {number}
|
|
143
|
+
*/
|
|
144
|
+
get concurrency() {
|
|
145
|
+
return this.__concurrency;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
*
|
|
150
|
+
* @param {FetchRequest} req
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
153
|
+
__dispatch(req) {
|
|
154
|
+
const promise = this.__adapter(req.__resource, req.__options);
|
|
155
|
+
|
|
156
|
+
promise.finally(() => {
|
|
157
|
+
this.__pending_set.delete(req);
|
|
158
|
+
|
|
159
|
+
this.__prod();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
promise
|
|
163
|
+
.then(
|
|
164
|
+
(v) => {
|
|
165
|
+
req.fulfillment.resolve(v);
|
|
166
|
+
},
|
|
167
|
+
(reason) => {
|
|
168
|
+
req.fulfillment.reject(reason);
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
__prod() {
|
|
174
|
+
if (this.__pending_set.size < this.__concurrency && !this.__queue.isEmpty()) {
|
|
175
|
+
const req = this.__queue.pop();
|
|
176
|
+
|
|
177
|
+
this.__dispatch(req);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fetch(resource, options) {
|
|
182
|
+
const req = new FetchRequest(resource, options);
|
|
183
|
+
|
|
184
|
+
if (this.__pending_set.size < this.__concurrency) {
|
|
185
|
+
this.__dispatch(req);
|
|
186
|
+
} else {
|
|
187
|
+
this.__queue.push(req);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return req.promise;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -166,7 +166,7 @@ function computeStepSize(fxy, x, y, suggestedStepSize, tolerance, maxIterations,
|
|
|
166
166
|
* @param {number} hmax max step size
|
|
167
167
|
* @param {number} hmin min step size
|
|
168
168
|
* @param {number} max_iteration maximum number of iterations
|
|
169
|
-
* @returns {
|
|
169
|
+
* @returns {Array.<number>}
|
|
170
170
|
*/
|
|
171
171
|
function odedopri(fxy, x0, y0, x1, tol, hmax, hmin, max_iteration) {
|
|
172
172
|
|
|
@@ -34,7 +34,6 @@ export class DraggableAspect {
|
|
|
34
34
|
const pointerGlobal = this.pointerGlobal = new PointerDevice(window);
|
|
35
35
|
|
|
36
36
|
const dragOriginalPosition = new Vector2();
|
|
37
|
-
const delta = new Vector2();
|
|
38
37
|
const pointer_position_last = new Vector2();
|
|
39
38
|
|
|
40
39
|
if (stopPropagation) {
|
|
@@ -11,7 +11,6 @@ import { buildPathFromDistanceMap } from "../util/buildPathFromDistanceMap.js";
|
|
|
11
11
|
import { GridCellActionPlaceTags } from "../../../placement/action/GridCellActionPlaceTags.js";
|
|
12
12
|
import { GridTags } from "../../../GridTags.js";
|
|
13
13
|
import { CellMatcher } from "../../../rules/CellMatcher.js";
|
|
14
|
-
import { groupArrayBy } from "../../../../core/collection/ArrayUtils.js";
|
|
15
14
|
import { collectIteratorValueToArray } from "../../../../core/collection/IteratorUtils.js";
|
|
16
15
|
import { QuadTreeNode } from "../../../../core/geom/2d/quad-tree/QuadTreeNode.js";
|
|
17
16
|
import AABB2 from "../../../../core/geom/AABB2.js";
|
|
@@ -24,6 +23,7 @@ import { RoadConnectionNetwork } from "./RoadConnectionNetwork.js";
|
|
|
24
23
|
import { MirGridLayers } from "../../../example/grid/MirGridLayers.js";
|
|
25
24
|
import { actionTask } from "../../../../core/process/task/util/actionTask.js";
|
|
26
25
|
import { countTask } from "../../../../core/process/task/util/countTask.js";
|
|
26
|
+
import { groupArrayBy } from "../../../../core/collection/array/groupArrayBy.js";
|
|
27
27
|
|
|
28
28
|
const NODE_TYPE_ROAD_CONNECTOR = 'Road Connector';
|
|
29
29
|
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.43.
|
|
8
|
+
"version": "2.43.3",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import View from "../View.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Wrapper around {@link HTMLCanvasElement}, exposes {@link CanvasRenderingContext2D}
|
|
5
|
+
*/
|
|
4
6
|
export class CanvasView extends View {
|
|
5
7
|
constructor() {
|
|
6
8
|
super();
|
|
@@ -8,6 +10,10 @@ export class CanvasView extends View {
|
|
|
8
10
|
const canvas = document.createElement('canvas');
|
|
9
11
|
this.el = canvas;
|
|
10
12
|
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @type {CanvasRenderingContext2D}
|
|
16
|
+
*/
|
|
11
17
|
this.context2d = canvas.getContext('2d');
|
|
12
18
|
|
|
13
19
|
this.size.onChanged.add(this.__handleSizeChange, this);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { isArrayEqual } from "../../../core/collection/ArrayUtils.js";
|
|
2
1
|
import { KeyValuePair } from "../../../core/collection/KeyValuePair.js";
|
|
3
2
|
import { computeStringHash } from "../../../core/primitives/strings/computeStringHash.js";
|
|
4
3
|
import { computeHashArray } from "../../../core/collection/array/computeHashArray.js";
|
|
5
4
|
import { computeHashIntegerArray } from "../../../core/collection/array/computeHashIntegerArray.js";
|
|
5
|
+
import { isArrayEqual } from "../../../core/collection/array/isArrayEqual.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
*
|
|
@@ -54,13 +54,11 @@ export class DomSizeObserver {
|
|
|
54
54
|
* @param {number} [depth=0] how deep should the observation go
|
|
55
55
|
*/
|
|
56
56
|
constructor({ depth = 0 } = {}) {
|
|
57
|
-
const rectangle = new Rectangle();
|
|
58
|
-
|
|
59
57
|
/**
|
|
60
58
|
*
|
|
61
59
|
* @type {Rectangle}
|
|
62
60
|
*/
|
|
63
|
-
this.dimensions =
|
|
61
|
+
this.dimensions = new Rectangle();
|
|
64
62
|
|
|
65
63
|
/**
|
|
66
64
|
*
|
|
@@ -169,7 +167,7 @@ export class DomSizeObserver {
|
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
/**
|
|
172
|
-
*
|
|
170
|
+
* Will attach to the view's element and automatically start/stop observing when the view is linked/unlinked
|
|
173
171
|
* @param {View} view
|
|
174
172
|
*/
|
|
175
173
|
watchView(view) {
|
|
@@ -184,7 +182,7 @@ export class DomSizeObserver {
|
|
|
184
182
|
}
|
|
185
183
|
|
|
186
184
|
/**
|
|
187
|
-
*
|
|
185
|
+
* Counterpart to {@link #watchView}
|
|
188
186
|
* @param {View} view
|
|
189
187
|
*/
|
|
190
188
|
unwatchView(view) {
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {Array} first
|
|
4
|
-
* @param {Array} second
|
|
5
|
-
* @returns {boolean}
|
|
6
|
-
*/
|
|
7
|
-
import { assert } from "../assert.js";
|
|
8
|
-
import { returnZero } from "../function/Functions.js";
|
|
9
|
-
import { min2 } from "../math/min2.js";
|
|
10
|
-
import { HashMap } from "./HashMap.js";
|
|
11
|
-
import { randomIntegerBetween } from "../math/random/randomIntegerBetween.js";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @template T
|
|
16
|
-
* @param {function} random
|
|
17
|
-
* @param {T[]} array
|
|
18
|
-
*/
|
|
19
|
-
export function randomizeArrayElementOrder(random, array) {
|
|
20
|
-
const n = array.length;
|
|
21
|
-
|
|
22
|
-
const lastValidIndex = n - 1;
|
|
23
|
-
|
|
24
|
-
for (let i = 0; i < n; i++) {
|
|
25
|
-
const t = randomIntegerBetween(random, 0, lastValidIndex);
|
|
26
|
-
|
|
27
|
-
if (t === i) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
arraySwapElements(array, i, t);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Pick multiple random items from an array
|
|
37
|
-
*
|
|
38
|
-
* @template T
|
|
39
|
-
* @param {function} random
|
|
40
|
-
* @param {T[]} source
|
|
41
|
-
* @param {T[]} target
|
|
42
|
-
* @param {number} count how many items to pick
|
|
43
|
-
* @returns {T}
|
|
44
|
-
*/
|
|
45
|
-
export function randomMultipleFromArray(random, source, target, count) {
|
|
46
|
-
|
|
47
|
-
const order = [];
|
|
48
|
-
|
|
49
|
-
const source_length = source.length;
|
|
50
|
-
for (let i = 0; i < source_length; i++) {
|
|
51
|
-
order[i] = i;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
randomizeArrayElementOrder(random, order);
|
|
55
|
-
|
|
56
|
-
const target_length = min2(source_length, count);
|
|
57
|
-
|
|
58
|
-
for (let i = 0; i < target_length; i++) {
|
|
59
|
-
const index = order[i];
|
|
60
|
-
const element = source[index];
|
|
61
|
-
target.push(element);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return target_length;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @template T,R
|
|
69
|
-
* @param {T[]} first
|
|
70
|
-
* @param {R[]} second
|
|
71
|
-
* @return {boolean}
|
|
72
|
-
*/
|
|
73
|
-
export function isArrayEqual(first, second) {
|
|
74
|
-
|
|
75
|
-
const il = first.length;
|
|
76
|
-
|
|
77
|
-
if (il !== second.length) return false;
|
|
78
|
-
|
|
79
|
-
let i = 0;
|
|
80
|
-
|
|
81
|
-
for (; i < il; i++) {
|
|
82
|
-
|
|
83
|
-
const a = first[i];
|
|
84
|
-
const b = second[i];
|
|
85
|
-
|
|
86
|
-
if (a === b) {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (a === undefined) {
|
|
92
|
-
//a is undefined, and B is something else
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (a === null) {
|
|
97
|
-
//a is null and B is something else
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
//try "equals" method
|
|
102
|
-
if (typeof a.equals === "function") {
|
|
103
|
-
|
|
104
|
-
if (!a.equals(b)) {
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
} else {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return true;
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @template T
|
|
120
|
-
* @param {T[]} array
|
|
121
|
-
* @param {function(T):number} scoreFunction
|
|
122
|
-
* @returns {T[]}
|
|
123
|
-
*/
|
|
124
|
-
export function arrayPickBestElements(array, scoreFunction) {
|
|
125
|
-
assert.notEqual(array, undefined, 'array is undefined');
|
|
126
|
-
assert.isArray(array, 'array');
|
|
127
|
-
|
|
128
|
-
assert.typeOf(scoreFunction, 'function', 'scoreFunction');
|
|
129
|
-
|
|
130
|
-
let bestScore;
|
|
131
|
-
|
|
132
|
-
const size = array.length;
|
|
133
|
-
|
|
134
|
-
if (size === 0) {
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const first = array[0];
|
|
139
|
-
|
|
140
|
-
bestScore = scoreFunction(first);
|
|
141
|
-
|
|
142
|
-
assert.isNumber(bestScore, 'bestScore');
|
|
143
|
-
|
|
144
|
-
const result = [first];
|
|
145
|
-
|
|
146
|
-
for (let i = 1; i < size; i++) {
|
|
147
|
-
const el = array[i];
|
|
148
|
-
|
|
149
|
-
// compute score
|
|
150
|
-
const score = scoreFunction(el);
|
|
151
|
-
|
|
152
|
-
assert.isNumber(score, 'score');
|
|
153
|
-
|
|
154
|
-
if (score > bestScore) {
|
|
155
|
-
bestScore = score;
|
|
156
|
-
|
|
157
|
-
result.splice(0, result.length);
|
|
158
|
-
|
|
159
|
-
result.push(el);
|
|
160
|
-
} else if (score === bestScore) {
|
|
161
|
-
result.push(el);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return result;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @template T
|
|
170
|
-
* @param {T[]} array
|
|
171
|
-
* @param {function(T):number} scoreFunction
|
|
172
|
-
* @returns {T}
|
|
173
|
-
*/
|
|
174
|
-
export function arrayPickMinElement(array, scoreFunction) {
|
|
175
|
-
assert.notEqual(array, undefined, 'array is undefined');
|
|
176
|
-
assert.typeOf(scoreFunction, 'function', 'scoreFunction');
|
|
177
|
-
|
|
178
|
-
let bestElement;
|
|
179
|
-
let bestScore;
|
|
180
|
-
|
|
181
|
-
const size = array.length;
|
|
182
|
-
|
|
183
|
-
if (size === 0) {
|
|
184
|
-
return undefined;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
bestElement = array[0];
|
|
188
|
-
|
|
189
|
-
bestScore = scoreFunction(bestElement);
|
|
190
|
-
|
|
191
|
-
assert.typeOf(bestScore, 'number', 'bestScore');
|
|
192
|
-
|
|
193
|
-
for (let i = 1; i < size; i++) {
|
|
194
|
-
const el = array[i];
|
|
195
|
-
|
|
196
|
-
// compute score
|
|
197
|
-
const score = scoreFunction(el);
|
|
198
|
-
|
|
199
|
-
assert.typeOf(score, 'number', 'score');
|
|
200
|
-
|
|
201
|
-
if (score < bestScore) {
|
|
202
|
-
bestScore = score;
|
|
203
|
-
bestElement = el;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return bestElement;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @template T,K
|
|
212
|
-
* @param {T[]} array
|
|
213
|
-
* @param {function(T):K} groupingFunction
|
|
214
|
-
* @param keyHashFunction
|
|
215
|
-
* @returns {Map<K,T[]>}
|
|
216
|
-
*/
|
|
217
|
-
export function groupArrayBy(array, groupingFunction, keyHashFunction = returnZero) {
|
|
218
|
-
const result = new HashMap({
|
|
219
|
-
keyHashFunction,
|
|
220
|
-
keyEqualityFunction(a, b) {
|
|
221
|
-
if (a === b) {
|
|
222
|
-
return true;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (typeof a === "object" && a !== null && typeof a.equals === "function") {
|
|
226
|
-
return a.equals(b);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
for (let i = 0; i < array.length; i++) {
|
|
234
|
-
const element = array[i];
|
|
235
|
-
|
|
236
|
-
const groupKey = groupingFunction(element);
|
|
237
|
-
|
|
238
|
-
const group = result.get(groupKey);
|
|
239
|
-
|
|
240
|
-
if (group === undefined) {
|
|
241
|
-
result.set(groupKey, [element]);
|
|
242
|
-
} else {
|
|
243
|
-
group.push(element);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
return result;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* @template T
|
|
253
|
-
* @param {T[]} array
|
|
254
|
-
* @param {number} index0
|
|
255
|
-
* @param {number} index1
|
|
256
|
-
*/
|
|
257
|
-
export function arraySwapElements(array, index0, index1) {
|
|
258
|
-
const t = array[index0];
|
|
259
|
-
|
|
260
|
-
array[index0] = array[index1];
|
|
261
|
-
array[index1] = t;
|
|
262
|
-
}
|
|
263
|
-
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { assert } from "../../../../assert.js";
|
|
2
|
-
import { point_in_tetrahedron_circumsphere } from "../point_in_tetrahedron_circumsphere.js";
|
|
3
|
-
import { INVALID_NEIGHBOUR } from "../tetrahedra_collection.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {TetrahedralMesh} mesh
|
|
8
|
-
* @param {Cavity} cavity
|
|
9
|
-
* @param {number[]|Float32Array} points
|
|
10
|
-
* @param {number} containing_tetra tetrahedron that contains point
|
|
11
|
-
* @param {number} point_index point that forms the cavity
|
|
12
|
-
*/
|
|
13
|
-
export function tetrahedral_mesh_compute_cavity(mesh, cavity, points, containing_tetra, point_index) {
|
|
14
|
-
assert.isNonNegativeInteger(containing_tetra, 'containing_tetra');
|
|
15
|
-
|
|
16
|
-
cavity.reset();
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
* @type {number[]}
|
|
21
|
-
*/
|
|
22
|
-
const open_set = [
|
|
23
|
-
containing_tetra
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* @type {number[]}
|
|
29
|
-
*/
|
|
30
|
-
const closed_set = [];
|
|
31
|
-
|
|
32
|
-
// 2. find the Delaunay "cavity", a set of tetrahedrons who's circumsphere overlarlaps the point
|
|
33
|
-
// perform breadth-first expansion on the containing tetra to identify the cavity
|
|
34
|
-
while (open_set.length > 0) {
|
|
35
|
-
|
|
36
|
-
const tetra = open_set.pop();
|
|
37
|
-
cavity.push(tetra);
|
|
38
|
-
closed_set.push(tetra);
|
|
39
|
-
|
|
40
|
-
// get neighbours
|
|
41
|
-
for (let i = 0; i < 4; i++) {
|
|
42
|
-
|
|
43
|
-
const neighbour_encoded = mesh.getNeighbour(tetra, i);
|
|
44
|
-
const neighbour_tetra_index = neighbour_encoded >>> 2;
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
(neighbour_encoded === INVALID_NEIGHBOUR) // no neighbour
|
|
48
|
-
|| closed_set.includes(neighbour_tetra_index) // already visited
|
|
49
|
-
|| open_set.includes(neighbour_tetra_index) // already in open set
|
|
50
|
-
) {
|
|
51
|
-
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const a = mesh.getCornerIndex(neighbour_tetra_index, 0);
|
|
56
|
-
const b = mesh.getCornerIndex(neighbour_tetra_index, 1);
|
|
57
|
-
const c = mesh.getCornerIndex(neighbour_tetra_index, 2);
|
|
58
|
-
const d = mesh.getCornerIndex(neighbour_tetra_index, 3);
|
|
59
|
-
|
|
60
|
-
// check neighbour
|
|
61
|
-
const is_in_sphere = point_in_tetrahedron_circumsphere(points, a, b, c, d, containing_tetra);
|
|
62
|
-
|
|
63
|
-
if (is_in_sphere) {
|
|
64
|
-
open_set.push(neighbour_tetra_index);
|
|
65
|
-
} else {
|
|
66
|
-
// move directly to closed set
|
|
67
|
-
closed_set.push(neighbour_tetra_index);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|