@woosh/meep-engine 2.42.7 → 2.43.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/core/binary/BitSet.js +4 -4
- package/core/binary/ctz32.js +40 -0
- package/core/collection/ObservedMap.js +61 -57
- package/core/collection/heap/FastBinaryHeap.js +7 -1
- package/core/collection/heap/Uint32Heap.js +19 -0
- package/core/collection/map/AsyncLoadingCache.js +3 -1
- package/core/geom/2d/compute_polygon_area_2d.js +32 -0
- package/core/geom/2d/compute_polygon_area_2d.spec.js +10 -0
- package/core/geom/2d/compute_triangle_area_2d.js +15 -0
- package/core/geom/2d/compute_triangle_area_2d.spec.js +9 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.js +64 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.spec.js +33 -0
- package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +82 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +135 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +282 -0
- package/core/geom/2d/convex-hull/orientation3.js +444 -0
- package/core/geom/2d/convex-hull/orientation3_array.js +22 -0
- package/core/geom/2d/convex-hull/orientation3_v2.js +12 -0
- package/core/geom/2d/intersect_ray_2d.js +56 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +0 -81
- package/core/geom/2d/quad-tree/qt_match_data_by_circle.js +70 -0
- package/core/geom/3d/matrix/m4_multiply_alphatensor.js +131 -0
- package/core/geom/3d/plane/orient3d_fast.js +2 -6
- package/core/geom/3d/tetrahedra/README.md +7 -0
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +3 -1
- package/core/geom/3d/tetrahedra/delaunay/Cavity.js +48 -0
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.js → delaunay/compute_delaunay_tetrahedral_mesh.js} +15 -7
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.spec.js → delaunay/compute_delaunay_tetrahedral_mesh.spec.js} +0 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +73 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +48 -0
- package/core/geom/3d/tetrahedra/hxt/a.js +524 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.js +140 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
- package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +35 -20
- package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +98 -0
- package/core/geom/3d/tetrahedra/tetrahedra_collection.js +60 -131
- package/core/geom/packing/{MaxRectangles.js → max-rect/MaxRectangles.js} +28 -124
- package/core/geom/packing/max-rect/removeRedundantBoxes.js +69 -0
- package/core/geom/packing/max-rect/removeRedundantBoxesArray.js +40 -0
- package/core/geom/v3_distance_above_plane.js +1 -1
- package/core/graph/layout/BoxLayouter.js +2 -88
- package/core/graph/layout/CircleLayout.js +2 -1
- package/core/graph/layout/box/forceIntoBox.js +45 -0
- package/core/graph/layout/box/pullBoxTowardsPoint.js +20 -0
- package/core/graph/layout/box/resolveAABB2Overlap.js +22 -0
- package/core/math/bessel_3.js +11 -0
- package/core/math/bessel_i0.js +26 -0
- package/core/process/executor/ConcurrentExecutor.spec.js +2 -1
- package/core/process/task/util/actionTask.js +19 -0
- package/core/process/task/util/countTask.js +62 -0
- package/core/process/task/util/delayTask.js +45 -0
- package/core/process/task/util/emptyTask.js +19 -0
- package/core/process/task/util/failingTask.js +17 -0
- package/core/process/task/util/futureTask.js +48 -0
- package/core/process/task/util/promiseTask.js +42 -0
- package/core/process/task/util/randomCountTask.js +64 -0
- package/core/process/task/util/wrapTaskIgnoreFailure.js +47 -0
- package/engine/Engine.js +8 -8
- package/engine/EngineBootstrapper.js +1 -1
- package/engine/asset/AssetManager.js +197 -53
- package/engine/asset/AssetRequest.js +32 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +62 -50
- package/engine/asset/loaders/image/png/PNG.js +15 -1
- package/engine/asset/loaders/image/png/PNGReader.js +3 -2
- package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -1
- package/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
- package/engine/ecs/storage/JSONDeSerializer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -1
- package/engine/graphics/camera/makeScreenScissorFrustum.js +1 -1
- package/engine/graphics/camera/testClippingPlaneComputation.js +4 -45
- package/engine/graphics/ecs/camera/FrustumProjector.js +6 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +5 -0
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +23 -4
- package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +11 -0
- package/engine/graphics/geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js +1 -2
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +5 -2
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +18 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +15 -0
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +66 -79
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +134 -0
- package/engine/graphics/impostors/octahedral/util/build_cutout_from_atlas_by_alpha.js +128 -0
- package/engine/graphics/impostors/octahedral/util/build_geometry_from_cutout_shape.js +32 -0
- package/engine/graphics/impostors/octahedral/util/load_mesh_for_bake.js +31 -0
- package/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.js +107 -0
- package/engine/graphics/material/manager/ManagedMaterial.js +4 -0
- package/engine/graphics/material/manager/MaterialManager.js +1 -0
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +7 -3
- package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +2 -2
- package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +0 -19
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +83 -27
- package/engine/graphics/shadows/ShadowMapRenderer.js +11 -4
- package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +2 -1
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +208 -38
- package/engine/graphics/texture/atlas/TextureAtlas.js +31 -24
- package/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +1 -1
- package/engine/graphics/texture/sampler/filter/box.js +16 -0
- package/engine/graphics/texture/sampler/filter/cubic2.js +32 -0
- package/engine/graphics/texture/sampler/filter/gaussian.js +16 -0
- package/engine/graphics/texture/sampler/filter/kaiser_1.js +19 -0
- package/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +19 -0
- package/engine/graphics/texture/sampler/filter/mitchell.js +55 -0
- package/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +109 -0
- package/engine/graphics/texture/sampler/filter/triangle.js +19 -0
- package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +187 -86
- package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +77 -25
- package/engine/graphics/texture/sampler/search/make_edge_condition_channel_threshold.js +34 -0
- package/engine/graphics/texture/sampler/search/sampler2d_find_pixels.js +24 -0
- package/engine/graphics/texture/sprite/prototypeSpriteCutoutGeometry.js +212 -0
- package/engine/knowledge/database/StaticKnowledgeDataTable.js +1 -1
- package/engine/navigation/grid/AStar.js +1 -1
- package/engine/plugin/EnginePluginManager.js +28 -27
- package/engine/plugin/PluginReferenceContext.js +9 -0
- package/engine/scene/Scene.js +1 -1
- package/engine/scene/SerializedScene.js +1 -1
- package/engine/scene/transitionToScene.js +3 -1
- package/generation/example/main.js +1 -1
- package/generation/grid/generation/GridTaskApplyActionToCells.js +1 -1
- package/generation/grid/generation/GridTaskDensityMarkerDistribution.js +1 -1
- package/generation/grid/generation/GridTaskExecuteRuleTimes.js +1 -1
- package/generation/grid/generation/NoopGridTaskGenerator.js +1 -1
- package/generation/grid/generation/discrete/GridTaskCellularAutomata.js +2 -1
- package/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
- package/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +3 -2
- package/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +1 -1
- package/generation/grid/generation/grid/GridTaskAddNodesFixed.js +1 -1
- package/generation/grid/generation/road/GridTaskGenerateRoads.js +3 -2
- package/generation/grid/generation/util/buildDistanceMapToObjective.js +1 -1
- package/generation/markers/GridActionRuleSet.js +2 -1
- package/generation/placement/GridCellActionTransformNearbyMarkers.js +2 -4
- package/generation/theme/ThemeEngine.js +4 -1
- package/package.json +1 -1
- package/view/asset/AssetLoaderStatusView.js +5 -5
- package/view/minimap/gl/MinimapTerrainGL.js +1 -2
- package/view/renderModel.js +1 -1
- package/view/tooltip/TooltipView.js +5 -5
- package/core/process/task/TaskUtils.js +0 -352
|
@@ -1,122 +1,13 @@
|
|
|
1
|
-
import BinaryHeap from "
|
|
2
|
-
import { assert } from "
|
|
3
|
-
import { max2 } from "
|
|
4
|
-
import { min2 } from "
|
|
5
|
-
import { QuadTreeDatum } from "
|
|
6
|
-
import { QuadTreeNode } from "
|
|
7
|
-
import AABB2 from "
|
|
8
|
-
import Vector2 from "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* Remove all rectangles that are fully contained within others
|
|
12
|
-
* @param {AABB2[]} boxes
|
|
13
|
-
*/
|
|
14
|
-
function removeRedundantBoxesArray(boxes) {
|
|
15
|
-
let i, j;
|
|
16
|
-
let numBoxes = boxes.length;
|
|
17
|
-
|
|
18
|
-
loop_a: for (i = 0; i < numBoxes; i++) {
|
|
19
|
-
const a = boxes[i];
|
|
20
|
-
|
|
21
|
-
const ax0 = a.x0;
|
|
22
|
-
const ay0 = a.y0;
|
|
23
|
-
const ax1 = a.x1;
|
|
24
|
-
const ay1 = a.y1;
|
|
25
|
-
|
|
26
|
-
for (j = i + 1; j < numBoxes; j++) {
|
|
27
|
-
const b = boxes[j];
|
|
28
|
-
|
|
29
|
-
const bx0 = b.x0;
|
|
30
|
-
const by0 = b.y0;
|
|
31
|
-
const bx1 = b.x1;
|
|
32
|
-
const by1 = b.y1;
|
|
33
|
-
|
|
34
|
-
//question is now whether it is containment
|
|
35
|
-
if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
|
|
36
|
-
//b contains a
|
|
37
|
-
boxes.splice(i, 1);
|
|
38
|
-
i--;
|
|
39
|
-
numBoxes--;
|
|
40
|
-
continue loop_a;
|
|
41
|
-
} else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
|
|
42
|
-
//a contains b
|
|
43
|
-
boxes.splice(j, 1);
|
|
44
|
-
j--;
|
|
45
|
-
numBoxes--;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Remove all rectangles that are fully contained within others
|
|
54
|
-
* @param {QuadTreeNode} boxes
|
|
55
|
-
*/
|
|
56
|
-
function removeRedundantBoxes(boxes) {
|
|
57
|
-
const removals = [];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let datum;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
*
|
|
64
|
-
* @param {QuadTreeDatum} intersection
|
|
65
|
-
*/
|
|
66
|
-
function visitDatumIntersection(intersection) {
|
|
67
|
-
if (datum === intersection) {
|
|
68
|
-
//skip self
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const ax0 = intersection.x0;
|
|
73
|
-
const ay0 = intersection.y0;
|
|
74
|
-
const ax1 = intersection.x1;
|
|
75
|
-
const ay1 = intersection.y1;
|
|
76
|
-
|
|
77
|
-
const bx0 = datum.x0;
|
|
78
|
-
const by0 = datum.y0;
|
|
79
|
-
const bx1 = datum.x1;
|
|
80
|
-
const by1 = datum.y1;
|
|
81
|
-
|
|
82
|
-
//question is now whether it is containment
|
|
83
|
-
if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
|
|
84
|
-
//b contains a
|
|
85
|
-
removals.push(intersection);
|
|
86
|
-
} else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
|
|
87
|
-
//a contains b
|
|
88
|
-
removals.push(datum);
|
|
89
|
-
|
|
90
|
-
//scheduled removal of the datum, prevent further traversal
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
*
|
|
97
|
-
* @param {QuadTreeNode} node
|
|
98
|
-
*/
|
|
99
|
-
function visitTreeNode(node) {
|
|
100
|
-
const data = node.data;
|
|
101
|
-
const dataCount = data.length;
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < dataCount; i++) {
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
* @type {QuadTreeDatum}
|
|
107
|
-
*/
|
|
108
|
-
datum = data[i];
|
|
109
|
-
|
|
110
|
-
node.traverseRectangleIntersections(datum.x0, datum.y0, datum.x1, datum.y1, visitDatumIntersection);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
boxes.traversePreOrder(visitTreeNode);
|
|
115
|
-
|
|
116
|
-
for (const removal of removals) {
|
|
117
|
-
removal.disconnect();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
1
|
+
import BinaryHeap from "../../../collection/heap/FastBinaryHeap.js";
|
|
2
|
+
import { assert } from "../../../assert.js";
|
|
3
|
+
import { max2 } from "../../../math/max2.js";
|
|
4
|
+
import { min2 } from "../../../math/min2.js";
|
|
5
|
+
import { QuadTreeDatum } from "../../2d/quad-tree/QuadTreeDatum.js";
|
|
6
|
+
import { QuadTreeNode } from "../../2d/quad-tree/QuadTreeNode.js";
|
|
7
|
+
import AABB2 from "../../AABB2.js";
|
|
8
|
+
import Vector2 from "../../Vector2.js";
|
|
9
|
+
import { removeRedundantBoxesArray } from "./removeRedundantBoxesArray.js";
|
|
10
|
+
import { removeRedundantBoxes } from "./removeRedundantBoxes.js";
|
|
120
11
|
|
|
121
12
|
|
|
122
13
|
/**
|
|
@@ -301,7 +192,7 @@ function packOneBox(box, free) {
|
|
|
301
192
|
container.disconnect();
|
|
302
193
|
|
|
303
194
|
//place box at bottom left of the container
|
|
304
|
-
const y0 = container.
|
|
195
|
+
const y0 = container.y0;
|
|
305
196
|
const x0 = container.x0;
|
|
306
197
|
|
|
307
198
|
box.set(x0, y0, x0 + w, y0 + h);
|
|
@@ -310,8 +201,8 @@ function packOneBox(box, free) {
|
|
|
310
201
|
cutArea(box, free);
|
|
311
202
|
|
|
312
203
|
//split remaining space
|
|
313
|
-
if (
|
|
314
|
-
const splitA = new QuadTreeDatum(container.x0,
|
|
204
|
+
if (box.y1 !== container.y1) {
|
|
205
|
+
const splitA = new QuadTreeDatum(container.x0, box.y1, container.x1, container.y1);
|
|
315
206
|
|
|
316
207
|
free.insertDatum(splitA);
|
|
317
208
|
}
|
|
@@ -321,7 +212,6 @@ function packOneBox(box, free) {
|
|
|
321
212
|
free.insertDatum(splitB);
|
|
322
213
|
}
|
|
323
214
|
|
|
324
|
-
removeRedundantBoxes(free);
|
|
325
215
|
|
|
326
216
|
return true;
|
|
327
217
|
}
|
|
@@ -405,6 +295,7 @@ export class MaxRectanglesPacker {
|
|
|
405
295
|
|
|
406
296
|
if (success) {
|
|
407
297
|
this.boxes.push(box);
|
|
298
|
+
removeRedundantBoxes(this.free);
|
|
408
299
|
}
|
|
409
300
|
|
|
410
301
|
// assert.ok(this.validate());
|
|
@@ -412,6 +303,16 @@ export class MaxRectanglesPacker {
|
|
|
412
303
|
return success;
|
|
413
304
|
}
|
|
414
305
|
|
|
306
|
+
/**
|
|
307
|
+
*
|
|
308
|
+
* @param {number} w
|
|
309
|
+
* @param {number} h
|
|
310
|
+
* @return {boolean}
|
|
311
|
+
*/
|
|
312
|
+
canAdd(w, h) {
|
|
313
|
+
return findBestContainer(w, h, this.free, costByRemainingArea) !== null;
|
|
314
|
+
}
|
|
315
|
+
|
|
415
316
|
/**
|
|
416
317
|
* Method is transactional, if one box fails to be packed, all fail and packer is reverted to original state
|
|
417
318
|
* @param {AABB2[]} boxes
|
|
@@ -444,7 +345,7 @@ export class MaxRectanglesPacker {
|
|
|
444
345
|
const boxIndex = heap.pop();
|
|
445
346
|
const box = boxes[boxIndex];
|
|
446
347
|
|
|
447
|
-
if (!this.
|
|
348
|
+
if (!packOneBox(box, this.free)) {
|
|
448
349
|
//remove whatever has been packed
|
|
449
350
|
const removeFailCount = this.removeMany(packed);
|
|
450
351
|
|
|
@@ -452,11 +353,14 @@ export class MaxRectanglesPacker {
|
|
|
452
353
|
|
|
453
354
|
return false;
|
|
454
355
|
} else {
|
|
356
|
+
this.boxes.push(box);
|
|
455
357
|
//box packed successfully
|
|
456
358
|
packed.push(box);
|
|
457
359
|
}
|
|
458
360
|
}
|
|
459
361
|
|
|
362
|
+
removeRedundantBoxes(this.free);
|
|
363
|
+
|
|
460
364
|
return true;
|
|
461
365
|
}
|
|
462
366
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove all rectangles that are fully contained within others
|
|
3
|
+
* @param {QuadTreeNode} boxes
|
|
4
|
+
*/
|
|
5
|
+
export function removeRedundantBoxes(boxes) {
|
|
6
|
+
const removals = [];
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
let datum;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {QuadTreeDatum} intersection
|
|
14
|
+
*/
|
|
15
|
+
function visitDatumIntersection(intersection) {
|
|
16
|
+
if (datum === intersection) {
|
|
17
|
+
//skip self
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ax0 = intersection.x0;
|
|
22
|
+
const ay0 = intersection.y0;
|
|
23
|
+
const ax1 = intersection.x1;
|
|
24
|
+
const ay1 = intersection.y1;
|
|
25
|
+
|
|
26
|
+
const bx0 = datum.x0;
|
|
27
|
+
const by0 = datum.y0;
|
|
28
|
+
const bx1 = datum.x1;
|
|
29
|
+
const by1 = datum.y1;
|
|
30
|
+
|
|
31
|
+
//question is now whether it is containment
|
|
32
|
+
if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
|
|
33
|
+
//b contains a
|
|
34
|
+
removals.push(intersection);
|
|
35
|
+
} else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
|
|
36
|
+
//a contains b
|
|
37
|
+
removals.push(datum);
|
|
38
|
+
|
|
39
|
+
//scheduled removal of the datum, prevent further traversal
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {QuadTreeNode} node
|
|
47
|
+
*/
|
|
48
|
+
function visitTreeNode(node) {
|
|
49
|
+
const data = node.data;
|
|
50
|
+
const dataCount = data.length;
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < dataCount; i++) {
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @type {QuadTreeDatum}
|
|
56
|
+
*/
|
|
57
|
+
datum = data[i];
|
|
58
|
+
|
|
59
|
+
node.traverseRectangleIntersections(datum.x0, datum.y0, datum.x1, datum.y1, visitDatumIntersection);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
boxes.traversePreOrder(visitTreeNode);
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < removals.length; i++) {
|
|
66
|
+
const removal = removals[i];
|
|
67
|
+
removal.disconnect();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove all rectangles that are fully contained within others
|
|
3
|
+
* @param {AABB2[]} boxes
|
|
4
|
+
*/
|
|
5
|
+
export function removeRedundantBoxesArray(boxes) {
|
|
6
|
+
let i, j;
|
|
7
|
+
let numBoxes = boxes.length;
|
|
8
|
+
|
|
9
|
+
loop_a: for (i = 0; i < numBoxes; i++) {
|
|
10
|
+
const a = boxes[i];
|
|
11
|
+
|
|
12
|
+
const ax0 = a.x0;
|
|
13
|
+
const ay0 = a.y0;
|
|
14
|
+
const ax1 = a.x1;
|
|
15
|
+
const ay1 = a.y1;
|
|
16
|
+
|
|
17
|
+
for (j = i + 1; j < numBoxes; j++) {
|
|
18
|
+
const b = boxes[j];
|
|
19
|
+
|
|
20
|
+
const bx0 = b.x0;
|
|
21
|
+
const by0 = b.y0;
|
|
22
|
+
const bx1 = b.x1;
|
|
23
|
+
const by1 = b.y1;
|
|
24
|
+
|
|
25
|
+
//question is now whether it is containment
|
|
26
|
+
if (ax0 >= bx0 && ax1 <= bx1 && ay0 >= by0 && ay1 <= by1) {
|
|
27
|
+
//b contains a
|
|
28
|
+
boxes.splice(i, 1);
|
|
29
|
+
i--;
|
|
30
|
+
numBoxes--;
|
|
31
|
+
continue loop_a;
|
|
32
|
+
} else if (bx0 >= ax0 && bx1 <= ax1 && by0 >= ay0 && by1 <= ay1) {
|
|
33
|
+
//a contains b
|
|
34
|
+
boxes.splice(j, 1);
|
|
35
|
+
j--;
|
|
36
|
+
numBoxes--;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -15,6 +15,6 @@ export function v3_distance_above_plane(
|
|
|
15
15
|
x, y, z,
|
|
16
16
|
normalX, normalY, normalZ, planeConstant
|
|
17
17
|
) {
|
|
18
|
-
// this is
|
|
18
|
+
// this is the same as v4_dot(v4(x,y,z,1.0), v4(plane.normal, plane.constant));
|
|
19
19
|
return v3_dot(normalX, normalY, normalZ, x, y, z) + planeConstant;
|
|
20
20
|
}
|
|
@@ -6,31 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import AABB2 from "../../geom/AABB2.js";
|
|
8
8
|
import Vector2 from "../../geom/Vector2.js";
|
|
9
|
-
import { resolveBoxOverlapUsingForce } from "./box/resolveBoxOverlapUsingForce.js";
|
|
10
9
|
import { computeDisconnectedSubGraphs } from "./computeDisconnectedSubGraphs.js";
|
|
11
10
|
import { Connection } from "./Connection.js";
|
|
11
|
+
import { resolveAABB2Overlap } from "./box/resolveAABB2Overlap.js";
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param {AABB2[]} boxes
|
|
17
|
-
* @param {number} maxSteps
|
|
18
|
-
*/
|
|
19
|
-
export function resolveAABB2Overlap(boxes, maxSteps) {
|
|
20
|
-
const forces = [];
|
|
21
|
-
|
|
22
|
-
const n = boxes.length;
|
|
23
|
-
for (let i = 0; i < n; i++) {
|
|
24
|
-
forces.push(new Vector2(0, 0));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
let overlapMoves = -1;
|
|
28
|
-
while (maxSteps > 0 && overlapMoves !== 0) {
|
|
29
|
-
maxSteps--;
|
|
30
|
-
overlapMoves = resolveBoxOverlapUsingForce(forces, boxes);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
14
|
/**
|
|
35
15
|
*
|
|
36
16
|
* @param {Connection} edge
|
|
@@ -201,27 +181,6 @@ function applyPull(edges, strength) {
|
|
|
201
181
|
}
|
|
202
182
|
}
|
|
203
183
|
|
|
204
|
-
/**
|
|
205
|
-
*
|
|
206
|
-
* @param {AABB2} box
|
|
207
|
-
* @param {number} targetX target point X coordinate
|
|
208
|
-
* @param {number} targetY target point Y coordinate
|
|
209
|
-
* @param {number} strength
|
|
210
|
-
*/
|
|
211
|
-
export function pullBoxTowardsPoint(box, targetX, targetY, strength) {
|
|
212
|
-
const midX = box.midX();
|
|
213
|
-
const midY = box.midY();
|
|
214
|
-
|
|
215
|
-
const deltaX = targetX - midX;
|
|
216
|
-
const deltaY = targetY - midY;
|
|
217
|
-
|
|
218
|
-
//multiply by strength
|
|
219
|
-
const displacementX = deltaX * strength;
|
|
220
|
-
const displacementY = deltaY * strength;
|
|
221
|
-
|
|
222
|
-
box.move(displacementX, displacementY);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
184
|
/**
|
|
226
185
|
*
|
|
227
186
|
* @param {Array.<AABB2>} boxes
|
|
@@ -502,50 +461,6 @@ function doLayerLayout(boxes) {
|
|
|
502
461
|
}
|
|
503
462
|
}
|
|
504
463
|
|
|
505
|
-
/**
|
|
506
|
-
* Note: assumes that boxes to be contained are strictly smaller than the container in both dimensions
|
|
507
|
-
* @param {AABB2} container
|
|
508
|
-
* @param {Array.<AABB2>} boxes
|
|
509
|
-
*/
|
|
510
|
-
function forceIntoBox(container, boxes) {
|
|
511
|
-
for (let i = 0, l = boxes.length; i < l; i++) {
|
|
512
|
-
const box = boxes[i];
|
|
513
|
-
|
|
514
|
-
if (box.locked === true) {
|
|
515
|
-
continue;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
let dX = 0;
|
|
519
|
-
let dY = 0;
|
|
520
|
-
|
|
521
|
-
const bx0 = box.x0;
|
|
522
|
-
const bx1 = box.x1;
|
|
523
|
-
|
|
524
|
-
const by0 = box.y0;
|
|
525
|
-
const by1 = box.y1;
|
|
526
|
-
|
|
527
|
-
const cx0 = container.x0;
|
|
528
|
-
const cx1 = container.x1;
|
|
529
|
-
|
|
530
|
-
const cy0 = container.y0;
|
|
531
|
-
const cy1 = container.y1;
|
|
532
|
-
|
|
533
|
-
if (bx0 < cx0) {
|
|
534
|
-
dX = cx0 - bx0;
|
|
535
|
-
} else if (bx1 > cx1) {
|
|
536
|
-
dX = cx1 - bx1;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
if (by0 < cy0) {
|
|
540
|
-
dY = cy0 - by0;
|
|
541
|
-
} else if (by1 > cy1) {
|
|
542
|
-
dY = cy1 - by1;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
box.move(dX, dY);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
464
|
/**
|
|
550
465
|
*
|
|
551
466
|
* @param {AABB2[]} boxes
|
|
@@ -665,6 +580,5 @@ function forceLayout(input, graph, center = null) {
|
|
|
665
580
|
|
|
666
581
|
export {
|
|
667
582
|
forceLayout,
|
|
668
|
-
alignOnOrigin
|
|
669
|
-
forceIntoBox
|
|
583
|
+
alignOnOrigin
|
|
670
584
|
};
|
|
@@ -10,9 +10,10 @@ import { line2SegmentsIntersect } from "../../geom/LineSegment2.js";
|
|
|
10
10
|
import Vector2, { v2_distance } from "../../geom/Vector2.js";
|
|
11
11
|
import { max2 } from "../../math/max2.js";
|
|
12
12
|
import { min2 } from "../../math/min2.js";
|
|
13
|
-
import { applyCentralGravityAABB2
|
|
13
|
+
import { applyCentralGravityAABB2 } from "./BoxLayouter.js";
|
|
14
14
|
import { computeDisconnectedSubGraphs } from "./computeDisconnectedSubGraphs.js";
|
|
15
15
|
import { Connection } from "./Connection.js";
|
|
16
|
+
import { resolveAABB2Overlap } from "./box/resolveAABB2Overlap.js";
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Note: assumes that boxes to be contained are strictly smaller than the container in both dimensions
|
|
3
|
+
* @param {AABB2} container
|
|
4
|
+
* @param {Array.<AABB2>} boxes
|
|
5
|
+
*/
|
|
6
|
+
function forceIntoBox(container, boxes) {
|
|
7
|
+
for (let i = 0, l = boxes.length; i < l; i++) {
|
|
8
|
+
const box = boxes[i];
|
|
9
|
+
|
|
10
|
+
if (box.locked === true) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let dX = 0;
|
|
15
|
+
let dY = 0;
|
|
16
|
+
|
|
17
|
+
const bx0 = box.x0;
|
|
18
|
+
const bx1 = box.x1;
|
|
19
|
+
|
|
20
|
+
const by0 = box.y0;
|
|
21
|
+
const by1 = box.y1;
|
|
22
|
+
|
|
23
|
+
const cx0 = container.x0;
|
|
24
|
+
const cx1 = container.x1;
|
|
25
|
+
|
|
26
|
+
const cy0 = container.y0;
|
|
27
|
+
const cy1 = container.y1;
|
|
28
|
+
|
|
29
|
+
if (bx0 < cx0) {
|
|
30
|
+
dX = cx0 - bx0;
|
|
31
|
+
} else if (bx1 > cx1) {
|
|
32
|
+
dX = cx1 - bx1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (by0 < cy0) {
|
|
36
|
+
dY = cy0 - by0;
|
|
37
|
+
} else if (by1 > cy1) {
|
|
38
|
+
dY = cy1 - by1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
box.move(dX, dY);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { forceIntoBox };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {AABB2} box
|
|
4
|
+
* @param {number} targetX target point X coordinate
|
|
5
|
+
* @param {number} targetY target point Y coordinate
|
|
6
|
+
* @param {number} strength
|
|
7
|
+
*/
|
|
8
|
+
export function pullBoxTowardsPoint(box, targetX, targetY, strength) {
|
|
9
|
+
const midX = box.midX();
|
|
10
|
+
const midY = box.midY();
|
|
11
|
+
|
|
12
|
+
const deltaX = targetX - midX;
|
|
13
|
+
const deltaY = targetY - midY;
|
|
14
|
+
|
|
15
|
+
//multiply by strength
|
|
16
|
+
const displacementX = deltaX * strength;
|
|
17
|
+
const displacementY = deltaY * strength;
|
|
18
|
+
|
|
19
|
+
box.move(displacementX, displacementY);
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Vector2 from "../../../geom/Vector2.js";
|
|
2
|
+
import { resolveBoxOverlapUsingForce } from "./resolveBoxOverlapUsingForce.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {AABB2[]} boxes
|
|
7
|
+
* @param {number} maxSteps
|
|
8
|
+
*/
|
|
9
|
+
export function resolveAABB2Overlap(boxes, maxSteps) {
|
|
10
|
+
const forces = [];
|
|
11
|
+
|
|
12
|
+
const n = boxes.length;
|
|
13
|
+
for (let i = 0; i < n; i++) {
|
|
14
|
+
forces.push(new Vector2(0, 0));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let overlapMoves = -1;
|
|
18
|
+
while (maxSteps > 0 && overlapMoves !== 0) {
|
|
19
|
+
maxSteps--;
|
|
20
|
+
overlapMoves = resolveBoxOverlapUsingForce(forces, boxes);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kaiser Bessel Function of third kind
|
|
3
|
+
* @see https://www.shadertoy.com/view/wlf3RH
|
|
4
|
+
* @returns {number}
|
|
5
|
+
* @param {number} x
|
|
6
|
+
*/
|
|
7
|
+
export function bessel_3(x) {
|
|
8
|
+
const y = 0.5 * x;
|
|
9
|
+
const y2 = (y * y);
|
|
10
|
+
return (y2 * y * (1.0 / 6.0 + y2 * (1.0 / 24.0 + y2 * (1.0 / 240.0 + y2 * (1.0 / 4320.0 + y2 / 120960.0)))));
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Modified bessel function of the first kind
|
|
5
|
+
* @see https://mathworld.wolfram.com/ModifiedBesselFunctionoftheFirstKind.html
|
|
6
|
+
* @see https://computergraphics.stackexchange.com/questions/6393/kaiser-windowed-sinc-filter-for-mip-mapping
|
|
7
|
+
* @see https://github.com/terifan/ImageResampler/blob/dbc212ce6aaa769bf3c9623cb6ead58ffd51d76c/src/org/terifan/image_resampler/FilterFactory.java
|
|
8
|
+
* @param {number} x
|
|
9
|
+
* @returns {number}
|
|
10
|
+
*/
|
|
11
|
+
export function bessel_i0(x) {
|
|
12
|
+
assert.notNaN(x, 'x');
|
|
13
|
+
|
|
14
|
+
let sum = 1.0;
|
|
15
|
+
|
|
16
|
+
const y = x * x * 0.25;
|
|
17
|
+
|
|
18
|
+
let t = y;
|
|
19
|
+
|
|
20
|
+
for (let i = 2; t > 1e-7; i++) {
|
|
21
|
+
sum += t;
|
|
22
|
+
t *= y / (i * i);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return sum;
|
|
26
|
+
}
|
|
@@ -3,8 +3,9 @@ import Task from "../task/Task.js"
|
|
|
3
3
|
import TaskGroup from "../task/TaskGroup.js";
|
|
4
4
|
import { TaskSignal } from "../task/TaskSignal.js";
|
|
5
5
|
import TaskState from "../task/TaskState.js";
|
|
6
|
-
import { emptyTask, failingTask } from "../task/TaskUtils.js";
|
|
7
6
|
import ConcurrentExecutor from "./ConcurrentExecutor.js";
|
|
7
|
+
import { emptyTask } from "../task/util/emptyTask.js";
|
|
8
|
+
import { failingTask } from "../task/util/failingTask.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Task from "../Task.js";
|
|
2
|
+
import { TaskSignal } from "../TaskSignal.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {function} action
|
|
7
|
+
* @param {string} name
|
|
8
|
+
* @return {Task}
|
|
9
|
+
*/
|
|
10
|
+
export function actionTask(action, name = "unnamed") {
|
|
11
|
+
return new Task({
|
|
12
|
+
name,
|
|
13
|
+
cycleFunction() {
|
|
14
|
+
action();
|
|
15
|
+
|
|
16
|
+
return TaskSignal.EndSuccess;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { TaskSignal } from "../TaskSignal.js";
|
|
2
|
+
import Task from "../Task.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {number|function(*):number} initial
|
|
7
|
+
* @param {number|function(*):number} limit
|
|
8
|
+
* @param {function(index:int)} callback
|
|
9
|
+
* @returns {Task}
|
|
10
|
+
*/
|
|
11
|
+
export function countTask(initial, limit, callback) {
|
|
12
|
+
let initialValue = 0;
|
|
13
|
+
let limitValue = 0;
|
|
14
|
+
|
|
15
|
+
let i = initialValue;
|
|
16
|
+
|
|
17
|
+
function cycle() {
|
|
18
|
+
if (i >= limitValue) {
|
|
19
|
+
return TaskSignal.EndSuccess;
|
|
20
|
+
}
|
|
21
|
+
callback(i);
|
|
22
|
+
i++;
|
|
23
|
+
|
|
24
|
+
return TaskSignal.Continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const initialType = typeof initial;
|
|
28
|
+
const limitType = typeof limit;
|
|
29
|
+
|
|
30
|
+
const name = "count (from " + ((initialType === 'number') ? initial : 'variable') + " to " + ((limitType === 'number') ? limit : 'variable') + ")";
|
|
31
|
+
|
|
32
|
+
return new Task({
|
|
33
|
+
name: name,
|
|
34
|
+
initializer() {
|
|
35
|
+
|
|
36
|
+
if (initialType === "number") {
|
|
37
|
+
initialValue = initial;
|
|
38
|
+
} else if (initialType === "function") {
|
|
39
|
+
initialValue = initial();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (limitType === "number") {
|
|
43
|
+
limitValue = limit;
|
|
44
|
+
} else if (limitType === "function") {
|
|
45
|
+
limitValue = limit();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
i = initialValue;
|
|
49
|
+
|
|
50
|
+
},
|
|
51
|
+
cycleFunction: cycle,
|
|
52
|
+
computeProgress: function () {
|
|
53
|
+
const span = limitValue - initialValue;
|
|
54
|
+
|
|
55
|
+
if (span === 0) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (i - initialValue) / span;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|