@woosh/meep-engine 2.134.5 → 2.135.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/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/editor/tools/v2/TransformControlsGizmo.js +1 -1
- package/editor/view/node-graph/NodeGraphEditorView.js +2 -2
- package/package.json +1 -1
- package/src/core/assert.d.ts +0 -2
- package/src/core/assert.d.ts.map +1 -1
- package/src/core/assert.js +0 -6
- package/src/core/color/Color.d.ts +0 -5
- package/src/core/color/Color.d.ts.map +1 -1
- package/src/core/color/Color.js +1 -7
- package/src/core/geom/2d/hash-grid/SpatialHashGrid.js +386 -386
- package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +1 -1
- package/src/core/geom/2d/quad-tree-binary/QuadTree.js +714 -714
- package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +160 -160
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +96 -96
- package/src/core/geom/packing/max-rect/MaxRectanglesPacker.js +1 -1
- package/src/core/geom/packing/max-rect/findBestContainer.js +4 -4
- package/src/core/geom/packing/max-rect/packOneBox.js +2 -2
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +1 -1
- package/src/core/graph/layout/box/BoxLayouter.js +7 -7
- package/src/core/graph/layout/box/position_box_next_to_box.js +6 -6
- package/src/core/math/computeWholeDivisorLow.js +33 -33
- package/src/core/math/linalg/eigen/eigen_values_find_spectral_gap.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts +10 -0
- package/src/core/math/linalg/eigen/matrix_eigenvalues_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_eigenvalues_in_place.js +8 -7
- package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.js +11 -5
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +15 -0
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_qr_in_place.js +8 -2
- package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.d.ts +0 -3
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -0
- package/src/core/{graph → math/linalg}/eigen/matrix_top_eigenvector_power_iteration.js +0 -3
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts +19 -0
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.d.ts.map +1 -0
- package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +161 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts +15 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.d.ts.map +1 -0
- package/src/core/math/linalg/polynomial_real_roots_in_interval.js +200 -0
- package/src/core/math/solveCubic.d.ts +15 -0
- package/src/core/math/solveCubic.d.ts.map +1 -0
- package/src/core/math/solveCubic.js +82 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.d.ts +23 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_bounds_t.js +109 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts +25 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.js +44 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts +16 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +120 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +11 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +451 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts +12 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +339 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts +15 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +21 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.d.ts +24 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.d.ts.map +1 -0
- package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -0
- package/src/core/math/spline/v3_computeCatmullRomSplineUniformDistance.js +1 -1
- package/src/core/model/node-graph/visual/NodeGraphVisualData.js +1 -1
- package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
- package/src/core/process/delay.js +16 -16
- package/src/engine/animation/async/TimeSeries.js +300 -300
- package/src/engine/animation/curve/AnimationCurve.d.ts +0 -4
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +1 -6
- package/src/engine/animation/curve/draw/position_canvas_to_curve.js +2 -2
- package/src/engine/animation/curve/draw/position_curve_to_canvas.js +2 -2
- package/src/engine/ecs/fow/shader/FogOfWarRenderer.js +145 -145
- package/src/engine/ecs/gui/position/ViewportPositionSystem.js +2 -2
- package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
- package/src/engine/ecs/transform/Transform.d.ts +0 -10
- package/src/engine/ecs/transform/Transform.d.ts.map +1 -1
- package/src/engine/ecs/transform/Transform.js +0 -12
- package/src/engine/graphics/composit/CompositLayer.js +254 -254
- package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +1 -1
- package/src/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +2 -2
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +3 -3
- package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +201 -201
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
- package/src/engine/graphics/render/buffer/slot/parameter/ProgramValueSlotParameterSet.js +2 -2
- package/src/engine/graphics/render/forward_plus/LightManager.js +1226 -1226
- package/src/engine/graphics/render/forward_plus/model/PointLight.js +1 -1
- package/src/engine/graphics/sh3/lpv/lpv_obtain_storage_cached_volume.js +1 -1
- package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +2 -2
- package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.js +1 -1
- package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
- package/src/engine/graphics/texture/sampler/serialization/TextureBinaryBufferSerializer.js +2 -2
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts +2 -6
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts.map +1 -1
- package/src/engine/intelligence/behavior/ecs/BehaviorComponent.js +0 -10
- package/src/engine/intelligence/mcts/MonteCarlo.js +275 -275
- package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
- package/src/generation/grid/GridData.js +220 -220
- package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +385 -385
- package/src/view/elements/image/SvgImageView.js +1 -1
- package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
- package/src/view/minimap/gl/MinimapFogOfWar.js +3 -3
- package/src/view/util/DomSizeObserver.js +1 -1
- package/src/core/binary/clz32.d.ts +0 -6
- package/src/core/binary/clz32.d.ts.map +0 -1
- package/src/core/binary/clz32.js +0 -5
- package/src/core/binary/type/dataTypeFromTypedArray.d.ts +0 -8
- package/src/core/binary/type/dataTypeFromTypedArray.d.ts.map +0 -1
- package/src/core/binary/type/dataTypeFromTypedArray.js +0 -11
- package/src/core/collection/array/computeHashIntegerArray.d.ts +0 -1
- package/src/core/collection/array/computeHashIntegerArray.d.ts.map +0 -1
- package/src/core/collection/array/computeHashIntegerArray.js +0 -7
- package/src/core/collection/array/typed/typedArrayToDataType.d.ts +0 -6
- package/src/core/collection/array/typed/typedArrayToDataType.d.ts.map +0 -1
- package/src/core/collection/array/typed/typedArrayToDataType.js +0 -6
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts +0 -6
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.d.ts.map +0 -1
- package/src/core/geom/3d/mat4/MATRIX_4_IDENTITY.js +0 -7
- package/src/core/graph/eigen/eigen_values_find_spectral_gap.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts +0 -8
- package/src/core/graph/eigen/matrix_eigenvalues_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_householder_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_qr_in_place.d.ts +0 -9
- package/src/core/graph/eigen/matrix_qr_in_place.d.ts.map +0 -1
- package/src/core/graph/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +0 -1
- package/src/core/math/spline/cubicCurve.d.ts +0 -6
- package/src/core/math/spline/cubicCurve.d.ts.map +0 -1
- package/src/core/math/spline/cubicCurve.js +0 -6
- package/src/core/math/spline/spline_bezier2.d.ts +0 -6
- package/src/core/math/spline/spline_bezier2.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier2.js +0 -6
- package/src/core/math/spline/spline_bezier3.d.ts +0 -6
- package/src/core/math/spline/spline_bezier3.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier3.js +0 -6
- package/src/core/math/spline/spline_bezier3_bounds.d.ts +0 -6
- package/src/core/math/spline/spline_bezier3_bounds.d.ts.map +0 -1
- package/src/core/math/spline/spline_bezier3_bounds.js +0 -6
- package/src/core/math/spline/spline_hermite3.d.ts +0 -6
- package/src/core/math/spline/spline_hermite3.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3.js +0 -6
- package/src/core/math/spline/spline_hermite3_bounds.d.ts +0 -6
- package/src/core/math/spline/spline_hermite3_bounds.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3_bounds.js +0 -6
- package/src/core/math/spline/spline_hermite3_to_bezier.d.ts +0 -2
- package/src/core/math/spline/spline_hermite3_to_bezier.d.ts.map +0 -1
- package/src/core/math/spline/spline_hermite3_to_bezier.js +0 -6
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts +0 -37
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.d.ts.map +0 -1
- package/src/engine/intelligence/behavior/decorator/RepeatUntilFailureBehavior.js +0 -70
- /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.d.ts +0 -0
- /package/src/core/{graph → math/linalg}/eigen/eigen_values_find_spectral_gap.js +0 -0
- /package/src/core/{graph → math/linalg}/eigen/matrix_householder_in_place.d.ts +0 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { polynomial_real_roots_in_interval } from "../linalg/polynomial_real_roots_in_interval.js";
|
|
2
|
+
import { solve_linear_system_GEPP_2x2 } from "../linalg/solve_linear_system_GEPP_2x2.js";
|
|
3
|
+
import { spline3_hermite_to_monomial } from "./spline3_hermite_to_monomial.js";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
ND specialization (dim ≥ 3). Closest approach is the global minimum of
|
|
7
|
+
|
|
8
|
+
Φ(s, t) = Σ_d (A_d(s) − B_d(t))²
|
|
9
|
+
|
|
10
|
+
over the closed unit square [0, 1]². It can occur at:
|
|
11
|
+
1. an interior critical point where ∇Φ = 0
|
|
12
|
+
2. a boundary edge minimum (one parameter pinned at 0 or 1)
|
|
13
|
+
3. a corner
|
|
14
|
+
|
|
15
|
+
Interior critical points are roots of the bivariate gradient system
|
|
16
|
+
|
|
17
|
+
F(s, t) = ½ ∂Φ/∂s = Σ_d (A_d(s) − B_d(t)) A_d′(s) (bidegree (5, 3))
|
|
18
|
+
G(s, t) = ½ ∂Φ/∂t = −Σ_d (A_d(s) − B_d(t)) B_d′(t) (bidegree (3, 5))
|
|
19
|
+
|
|
20
|
+
The fully analytical route eliminates t through the 8×8 Sylvester resultant
|
|
21
|
+
of F and G, yielding a univariate of degree ≤ 34 in s. Implementing that
|
|
22
|
+
with exact polynomial-coefficient arithmetic is genuinely large code, well
|
|
23
|
+
beyond the scope of this change. As a first cut, this implementation finds
|
|
24
|
+
interior critical points by 2D Newton from a starting grid — quadratically
|
|
25
|
+
convergent once close, but reliant on the grid being fine enough to cover
|
|
26
|
+
the basins of attraction of all real critical points. It is enough for the
|
|
27
|
+
routine geometric configurations the rest of this proposal targets and
|
|
28
|
+
leaves a clear seam for the resultant route to land later without changing
|
|
29
|
+
the public API.
|
|
30
|
+
|
|
31
|
+
Boundary edges and corners are handled exactly: each edge reduces to a
|
|
32
|
+
quintic-derivative root-finding (degree 5) of the kind already used in the
|
|
33
|
+
2D path, and corners are direct evaluations.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const MAX_DIM = 16;
|
|
37
|
+
|
|
38
|
+
// Per-dim monomial coefficient buffers, one each for A and B. Length 4*MAX_DIM.
|
|
39
|
+
const _a_mono = new Float64Array(4 * MAX_DIM);
|
|
40
|
+
const _b_mono = new Float64Array(4 * MAX_DIM);
|
|
41
|
+
|
|
42
|
+
const _newton_FG = new Float64Array(2);
|
|
43
|
+
const _newton_J = new Float64Array(4);
|
|
44
|
+
const _newton_J_scratch = new Float64Array(4);
|
|
45
|
+
const _newton_RHS = new Float64Array(2);
|
|
46
|
+
|
|
47
|
+
const _candidate_st = new Float64Array(2);
|
|
48
|
+
const _edge_fixed_point = new Float64Array(MAX_DIM);
|
|
49
|
+
|
|
50
|
+
const NEWTON_MAX_ITER = 32;
|
|
51
|
+
const NEWTON_GRADIENT_TOLERANCE = 1e-13;
|
|
52
|
+
const NEWTON_STEP_TOLERANCE = 1e-15;
|
|
53
|
+
|
|
54
|
+
const GRID_SIDE = 9; // 9x9 = 81 starting points
|
|
55
|
+
|
|
56
|
+
const EDGE_QUINTIC_LEN = 6;
|
|
57
|
+
const _edge_quintic = new Float64Array(EDGE_QUINTIC_LEN);
|
|
58
|
+
const _edge_roots = new Float64Array(5);
|
|
59
|
+
|
|
60
|
+
const CRITICAL_POINT_DEDUPE_TOLERANCE = 1e-7;
|
|
61
|
+
const _seen_s = new Float64Array(GRID_SIDE * GRID_SIDE + 8);
|
|
62
|
+
const _seen_t = new Float64Array(GRID_SIDE * GRID_SIDE + 8);
|
|
63
|
+
|
|
64
|
+
// ── monomial helpers (per-dim cubic) ───────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
function poly3_eval(coeffs4, base, x) {
|
|
67
|
+
return coeffs4[base] + x * (coeffs4[base + 1] + x * (coeffs4[base + 2] + x * coeffs4[base + 3]));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function poly3_deriv(coeffs4, base, x) {
|
|
71
|
+
return coeffs4[base + 1] + x * (2 * coeffs4[base + 2] + x * 3 * coeffs4[base + 3]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function poly3_second_deriv(coeffs4, base, x) {
|
|
75
|
+
return 2 * coeffs4[base + 2] + 6 * coeffs4[base + 3] * x;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── core: F, G, and Jacobian at (s, t) ─────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
function eval_FG(dim, s, t, out) {
|
|
81
|
+
let F = 0, G = 0;
|
|
82
|
+
for (let d = 0; d < dim; d++) {
|
|
83
|
+
const base = 4 * d;
|
|
84
|
+
const A = poly3_eval(_a_mono, base, s);
|
|
85
|
+
const Ap = poly3_deriv(_a_mono, base, s);
|
|
86
|
+
const B = poly3_eval(_b_mono, base, t);
|
|
87
|
+
const Bp = poly3_deriv(_b_mono, base, t);
|
|
88
|
+
const diff = A - B;
|
|
89
|
+
F += diff * Ap;
|
|
90
|
+
G -= diff * Bp;
|
|
91
|
+
}
|
|
92
|
+
out[0] = F;
|
|
93
|
+
out[1] = G;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function eval_jacobian(dim, s, t, out_J) {
|
|
97
|
+
let Jss = 0, Jst = 0, Jts = 0, Jtt = 0;
|
|
98
|
+
for (let d = 0; d < dim; d++) {
|
|
99
|
+
const base = 4 * d;
|
|
100
|
+
const A = poly3_eval(_a_mono, base, s);
|
|
101
|
+
const Ap = poly3_deriv(_a_mono, base, s);
|
|
102
|
+
const App = poly3_second_deriv(_a_mono, base, s);
|
|
103
|
+
const B = poly3_eval(_b_mono, base, t);
|
|
104
|
+
const Bp = poly3_deriv(_b_mono, base, t);
|
|
105
|
+
const Bpp = poly3_second_deriv(_b_mono, base, t);
|
|
106
|
+
const diff = A - B;
|
|
107
|
+
|
|
108
|
+
Jss += Ap * Ap + diff * App;
|
|
109
|
+
Jst += -Bp * Ap;
|
|
110
|
+
Jts += -Ap * Bp;
|
|
111
|
+
Jtt += Bp * Bp - diff * Bpp;
|
|
112
|
+
}
|
|
113
|
+
// Row-major 2x2: [Jss, Jst; Jts, Jtt]
|
|
114
|
+
out_J[0] = Jss;
|
|
115
|
+
out_J[1] = Jst;
|
|
116
|
+
out_J[2] = Jts;
|
|
117
|
+
out_J[3] = Jtt;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function eval_phi(dim, s, t) {
|
|
121
|
+
let acc = 0;
|
|
122
|
+
for (let d = 0; d < dim; d++) {
|
|
123
|
+
const base = 4 * d;
|
|
124
|
+
const A = poly3_eval(_a_mono, base, s);
|
|
125
|
+
const B = poly3_eval(_b_mono, base, t);
|
|
126
|
+
const diff = A - B;
|
|
127
|
+
acc += diff * diff;
|
|
128
|
+
}
|
|
129
|
+
return acc;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 2D Newton on (F, G) from a starting (s, t). Writes the converged (s, t) into
|
|
134
|
+
* `out` and returns true iff it converged inside [0, 1]² with small gradient.
|
|
135
|
+
*/
|
|
136
|
+
function newton_2d(dim, s_init, t_init, out) {
|
|
137
|
+
let s = s_init;
|
|
138
|
+
let t = t_init;
|
|
139
|
+
|
|
140
|
+
for (let iter = 0; iter < NEWTON_MAX_ITER; iter++) {
|
|
141
|
+
eval_FG(dim, s, t, _newton_FG);
|
|
142
|
+
const F = _newton_FG[0];
|
|
143
|
+
const G = _newton_FG[1];
|
|
144
|
+
|
|
145
|
+
if (Math.abs(F) < NEWTON_GRADIENT_TOLERANCE && Math.abs(G) < NEWTON_GRADIENT_TOLERANCE) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
eval_jacobian(dim, s, t, _newton_J);
|
|
150
|
+
|
|
151
|
+
_newton_RHS[0] = F;
|
|
152
|
+
_newton_RHS[1] = G;
|
|
153
|
+
|
|
154
|
+
// solve_linear_system_GEPP_2x2 mutates the input matrix; use a scratch copy.
|
|
155
|
+
for (let k = 0; k < 4; k++) _newton_J_scratch[k] = _newton_J[k];
|
|
156
|
+
if (!solve_linear_system_GEPP_2x2(_newton_J_scratch, _newton_RHS, _newton_RHS)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const ds = _newton_RHS[0];
|
|
161
|
+
const dt = _newton_RHS[1];
|
|
162
|
+
|
|
163
|
+
s -= ds;
|
|
164
|
+
t -= dt;
|
|
165
|
+
|
|
166
|
+
if (Math.abs(ds) < NEWTON_STEP_TOLERANCE && Math.abs(dt) < NEWTON_STEP_TOLERANCE) {
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (s < -1e-9 || s > 1 + 1e-9) return false;
|
|
172
|
+
if (t < -1e-9 || t > 1 + 1e-9) return false;
|
|
173
|
+
|
|
174
|
+
eval_FG(dim, s, t, _newton_FG);
|
|
175
|
+
if (Math.abs(_newton_FG[0]) > 1e-6 || Math.abs(_newton_FG[1]) > 1e-6) return false;
|
|
176
|
+
|
|
177
|
+
out[0] = s < 0 ? 0 : (s > 1 ? 1 : s);
|
|
178
|
+
out[1] = t < 0 ? 0 : (t > 1 ? 1 : t);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ── boundary edge: nearest point on (varying-axis) curve to a fixed N-D point ──
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Minimise ‖(curve_mono...)(t) − point[]‖² over t ∈ [0, 1], where the curve
|
|
186
|
+
* is `dim`-dimensional with monomial coefficients packed as
|
|
187
|
+
* `[α0_0, α1_0, α2_0, α3_0, α0_1, α1_1, ..., α3_{dim-1}]`.
|
|
188
|
+
*
|
|
189
|
+
* The squared distance is a degree-6 polynomial in t; its derivative is a
|
|
190
|
+
* quintic. We hand the quintic to the polynomial root finder, then test the
|
|
191
|
+
* roots plus the endpoints t = 0 and t = 1.
|
|
192
|
+
*
|
|
193
|
+
* Writes `[t_min, dist²]` into `out` (length ≥ 2).
|
|
194
|
+
*/
|
|
195
|
+
function nearest_t_to_fixed_point(curve_mono, dim, point, point_offset, out) {
|
|
196
|
+
for (let i = 0; i < EDGE_QUINTIC_LEN; i++) _edge_quintic[i] = 0;
|
|
197
|
+
|
|
198
|
+
for (let d = 0; d < dim; d++) {
|
|
199
|
+
const base = 4 * d;
|
|
200
|
+
const dx0 = curve_mono[base] - point[point_offset + d];
|
|
201
|
+
const dx1 = curve_mono[base + 1];
|
|
202
|
+
const dx2 = curve_mono[base + 2];
|
|
203
|
+
const dx3 = curve_mono[base + 3];
|
|
204
|
+
// derivative coefficients
|
|
205
|
+
const e0 = dx1, e1 = 2 * dx2, e2 = 3 * dx3;
|
|
206
|
+
|
|
207
|
+
// (dx0 + dx1 t + dx2 t² + dx3 t³) · (e0 + e1 t + e2 t²) accumulated
|
|
208
|
+
_edge_quintic[0] += dx0 * e0;
|
|
209
|
+
_edge_quintic[1] += dx0 * e1 + dx1 * e0;
|
|
210
|
+
_edge_quintic[2] += dx0 * e2 + dx1 * e1 + dx2 * e0;
|
|
211
|
+
_edge_quintic[3] += dx1 * e2 + dx2 * e1 + dx3 * e0;
|
|
212
|
+
_edge_quintic[4] += dx2 * e2 + dx3 * e1;
|
|
213
|
+
_edge_quintic[5] += dx3 * e2;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const root_count = polynomial_real_roots_in_interval(
|
|
217
|
+
_edge_quintic, 5, 0, 1, _edge_roots, 0
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
let best_t = 0;
|
|
221
|
+
let best_d2 = Number.POSITIVE_INFINITY;
|
|
222
|
+
|
|
223
|
+
for (let i = -2; i < root_count; i++) {
|
|
224
|
+
const t = i === -2 ? 0 : (i === -1 ? 1 : _edge_roots[i]);
|
|
225
|
+
let d2 = 0;
|
|
226
|
+
for (let d = 0; d < dim; d++) {
|
|
227
|
+
const base = 4 * d;
|
|
228
|
+
const v = curve_mono[base] + t * (curve_mono[base + 1] + t * (curve_mono[base + 2] + t * curve_mono[base + 3]));
|
|
229
|
+
const dv = v - point[point_offset + d];
|
|
230
|
+
d2 += dv * dv;
|
|
231
|
+
}
|
|
232
|
+
if (d2 < best_d2) {
|
|
233
|
+
best_d2 = d2;
|
|
234
|
+
best_t = t;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
out[0] = best_t;
|
|
239
|
+
out[1] = best_d2;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ── public ────────────────────────────────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* ND specialization (dim ≥ 3). See module preamble for algorithmic notes.
|
|
246
|
+
*
|
|
247
|
+
* @param {Float64Array|number[]} a length 4*dim
|
|
248
|
+
* @param {Float64Array|number[]} b length 4*dim
|
|
249
|
+
* @param {number} dim ≥ 3 (also correct for dim ≥ 2 but slower than the 2D path)
|
|
250
|
+
* @param {Float64Array|number[]} result writes [s, t]
|
|
251
|
+
* @param {number} result_offset
|
|
252
|
+
* @returns {number} squared distance at closest approach
|
|
253
|
+
*/
|
|
254
|
+
export function spline3_hermite_intersection_spline3_hermite_nd(
|
|
255
|
+
a, b, dim,
|
|
256
|
+
result, result_offset
|
|
257
|
+
) {
|
|
258
|
+
if (dim > MAX_DIM) {
|
|
259
|
+
throw new Error(`dim=${dim} exceeds MAX_DIM=${MAX_DIM}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Pack monomial coefficients per-axis into the module buffers.
|
|
263
|
+
for (let d = 0; d < dim; d++) {
|
|
264
|
+
const off = 4 * d;
|
|
265
|
+
spline3_hermite_to_monomial(_a_mono, off, 1, a[off], a[off + 1], a[off + 2], a[off + 3]);
|
|
266
|
+
spline3_hermite_to_monomial(_b_mono, off, 1, b[off], b[off + 1], b[off + 2], b[off + 3]);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
let best_s = 0;
|
|
270
|
+
let best_t = 0;
|
|
271
|
+
let best_d2 = Number.POSITIVE_INFINITY;
|
|
272
|
+
let seen_count = 0;
|
|
273
|
+
|
|
274
|
+
const try_candidate = (s, t) => {
|
|
275
|
+
// Dedupe near-identical critical points discovered from different grid starts.
|
|
276
|
+
for (let i = 0; i < seen_count; i++) {
|
|
277
|
+
if (Math.abs(_seen_s[i] - s) < CRITICAL_POINT_DEDUPE_TOLERANCE
|
|
278
|
+
&& Math.abs(_seen_t[i] - t) < CRITICAL_POINT_DEDUPE_TOLERANCE) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
_seen_s[seen_count] = s;
|
|
283
|
+
_seen_t[seen_count] = t;
|
|
284
|
+
seen_count++;
|
|
285
|
+
|
|
286
|
+
const d2 = eval_phi(dim, s, t);
|
|
287
|
+
if (d2 < best_d2) {
|
|
288
|
+
best_d2 = d2;
|
|
289
|
+
best_s = s;
|
|
290
|
+
best_t = t;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// Interior critical points via Newton from a grid.
|
|
295
|
+
const step = 1 / (GRID_SIDE - 1);
|
|
296
|
+
for (let i = 0; i < GRID_SIDE; i++) {
|
|
297
|
+
const s_init = i * step;
|
|
298
|
+
for (let j = 0; j < GRID_SIDE; j++) {
|
|
299
|
+
const t_init = j * step;
|
|
300
|
+
if (newton_2d(dim, s_init, t_init, _candidate_st)) {
|
|
301
|
+
try_candidate(_candidate_st[0], _candidate_st[1]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Boundary edges. Each edge problem reduces to "nearest point on the
|
|
307
|
+
// *other* curve to a fixed point on the boundary curve".
|
|
308
|
+
const tmp_pt = _edge_fixed_point;
|
|
309
|
+
|
|
310
|
+
// Edge s = 0: fixed point is A(0); minimise over t on B.
|
|
311
|
+
for (let d = 0; d < dim; d++) tmp_pt[d] = _a_mono[4 * d]; // α0
|
|
312
|
+
nearest_t_to_fixed_point(_b_mono, dim, tmp_pt, 0, _candidate_st);
|
|
313
|
+
try_candidate(0, _candidate_st[0]);
|
|
314
|
+
|
|
315
|
+
// Edge s = 1: A(1) = α0 + α1 + α2 + α3.
|
|
316
|
+
for (let d = 0; d < dim; d++) {
|
|
317
|
+
const base = 4 * d;
|
|
318
|
+
tmp_pt[d] = _a_mono[base] + _a_mono[base + 1] + _a_mono[base + 2] + _a_mono[base + 3];
|
|
319
|
+
}
|
|
320
|
+
nearest_t_to_fixed_point(_b_mono, dim, tmp_pt, 0, _candidate_st);
|
|
321
|
+
try_candidate(1, _candidate_st[0]);
|
|
322
|
+
|
|
323
|
+
// Edge t = 0: fixed point is B(0); minimise over s on A.
|
|
324
|
+
for (let d = 0; d < dim; d++) tmp_pt[d] = _b_mono[4 * d];
|
|
325
|
+
nearest_t_to_fixed_point(_a_mono, dim, tmp_pt, 0, _candidate_st);
|
|
326
|
+
try_candidate(_candidate_st[0], 0);
|
|
327
|
+
|
|
328
|
+
// Edge t = 1.
|
|
329
|
+
for (let d = 0; d < dim; d++) {
|
|
330
|
+
const base = 4 * d;
|
|
331
|
+
tmp_pt[d] = _b_mono[base] + _b_mono[base + 1] + _b_mono[base + 2] + _b_mono[base + 3];
|
|
332
|
+
}
|
|
333
|
+
nearest_t_to_fixed_point(_a_mono, dim, tmp_pt, 0, _candidate_st);
|
|
334
|
+
try_candidate(_candidate_st[0], 1);
|
|
335
|
+
|
|
336
|
+
result[result_offset] = best_s;
|
|
337
|
+
result[result_offset + 1] = best_t;
|
|
338
|
+
return best_d2;
|
|
339
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boolean intersection test for two cubic Hermite curves.
|
|
3
|
+
*
|
|
4
|
+
* Returns `true` if a true intersection exists OR if the closest approach is
|
|
5
|
+
* within `tolerance` (Euclidean distance). Tolerance = 0 reduces to exact
|
|
6
|
+
* intersection.
|
|
7
|
+
*
|
|
8
|
+
* @param {Float64Array|number[]} a length 4*dim, layout described in {@link spline3_hermite_intersection_spline3_hermite}
|
|
9
|
+
* @param {Float64Array|number[]} b same layout
|
|
10
|
+
* @param {number} dim ≥ 1
|
|
11
|
+
* @param {number} tolerance ≥ 0
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
export function spline3_hermite_intersects_spline3_hermite(a: Float64Array | number[], b: Float64Array | number[], dim: number, tolerance: number): boolean;
|
|
15
|
+
//# sourceMappingURL=spline3_hermite_intersects_spline3_hermite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spline3_hermite_intersects_spline3_hermite.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,8DANW,YAAY,GAAC,MAAM,EAAE,KACrB,YAAY,GAAC,MAAM,EAAE,OACrB,MAAM,aACN,MAAM,GACJ,OAAO,CAKnB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spline3_hermite_intersection_spline3_hermite } from "./spline3_hermite_intersection_spline3_hermite.js";
|
|
2
|
+
|
|
3
|
+
const _scratch_st = new Float64Array(2);
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Boolean intersection test for two cubic Hermite curves.
|
|
7
|
+
*
|
|
8
|
+
* Returns `true` if a true intersection exists OR if the closest approach is
|
|
9
|
+
* within `tolerance` (Euclidean distance). Tolerance = 0 reduces to exact
|
|
10
|
+
* intersection.
|
|
11
|
+
*
|
|
12
|
+
* @param {Float64Array|number[]} a length 4*dim, layout described in {@link spline3_hermite_intersection_spline3_hermite}
|
|
13
|
+
* @param {Float64Array|number[]} b same layout
|
|
14
|
+
* @param {number} dim ≥ 1
|
|
15
|
+
* @param {number} tolerance ≥ 0
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export function spline3_hermite_intersects_spline3_hermite(a, b, dim, tolerance) {
|
|
19
|
+
const d2 = spline3_hermite_intersection_spline3_hermite(a, b, dim, _scratch_st, 0);
|
|
20
|
+
return d2 <= tolerance * tolerance;
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-dimensional cubic Hermite to monomial-basis conversion.
|
|
3
|
+
*
|
|
4
|
+
* Given a Hermite segment defined by `(p0, p1, m0, m1)` whose value at parameter
|
|
5
|
+
* `t ∈ [0, 1]` is computed by {@link spline3_hermite}, this writes the monomial
|
|
6
|
+
* coefficients `α₀, α₁, α₂, α₃` into the result array such that
|
|
7
|
+
*
|
|
8
|
+
* spline3_hermite(t, p0, p1, m0, m1) === α₀ + α₁·t + α₂·t² + α₃·t³
|
|
9
|
+
*
|
|
10
|
+
* for all t.
|
|
11
|
+
*
|
|
12
|
+
* @param {number[]|Float32Array|Float64Array} result
|
|
13
|
+
* @param {number} result_offset
|
|
14
|
+
* @param {number} result_stride step between successive coefficient slots; useful when interleaving multiple dimensions in one array
|
|
15
|
+
* @param {number} p0
|
|
16
|
+
* @param {number} p1
|
|
17
|
+
* @param {number} m0
|
|
18
|
+
* @param {number} m1
|
|
19
|
+
*
|
|
20
|
+
* @author Alex Goldring
|
|
21
|
+
* @copyright Company Named Limited (c) 2025
|
|
22
|
+
*/
|
|
23
|
+
export function spline3_hermite_to_monomial(result: number[] | Float32Array | Float64Array, result_offset: number, result_stride: number, p0: number, p1: number, m0: number, m1: number): void;
|
|
24
|
+
//# sourceMappingURL=spline3_hermite_to_monomial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spline3_hermite_to_monomial.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/spline/spline3_hermite_to_monomial.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,oDAXW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,iBACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAiBhB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One-dimensional cubic Hermite to monomial-basis conversion.
|
|
5
|
+
*
|
|
6
|
+
* Given a Hermite segment defined by `(p0, p1, m0, m1)` whose value at parameter
|
|
7
|
+
* `t ∈ [0, 1]` is computed by {@link spline3_hermite}, this writes the monomial
|
|
8
|
+
* coefficients `α₀, α₁, α₂, α₃` into the result array such that
|
|
9
|
+
*
|
|
10
|
+
* spline3_hermite(t, p0, p1, m0, m1) === α₀ + α₁·t + α₂·t² + α₃·t³
|
|
11
|
+
*
|
|
12
|
+
* for all t.
|
|
13
|
+
*
|
|
14
|
+
* @param {number[]|Float32Array|Float64Array} result
|
|
15
|
+
* @param {number} result_offset
|
|
16
|
+
* @param {number} result_stride step between successive coefficient slots; useful when interleaving multiple dimensions in one array
|
|
17
|
+
* @param {number} p0
|
|
18
|
+
* @param {number} p1
|
|
19
|
+
* @param {number} m0
|
|
20
|
+
* @param {number} m1
|
|
21
|
+
*
|
|
22
|
+
* @author Alex Goldring
|
|
23
|
+
* @copyright Company Named Limited (c) 2025
|
|
24
|
+
*/
|
|
25
|
+
export function spline3_hermite_to_monomial(
|
|
26
|
+
result,
|
|
27
|
+
result_offset,
|
|
28
|
+
result_stride,
|
|
29
|
+
p0, p1, m0, m1
|
|
30
|
+
) {
|
|
31
|
+
assert.greaterThan(result_stride, 0, 'result_stride must be greater than 0');
|
|
32
|
+
|
|
33
|
+
result[result_offset] = p0;
|
|
34
|
+
result[result_offset + result_stride] = m0;
|
|
35
|
+
result[result_offset + 2 * result_stride] = -3 * p0 + 3 * p1 - 2 * m0 - m1;
|
|
36
|
+
result[result_offset + 3 * result_stride] = 2 * p0 - 2 * p1 + m0 + m1;
|
|
37
|
+
}
|
|
@@ -165,7 +165,7 @@ export class NodeGraphVisualData {
|
|
|
165
165
|
const node = nodes[i];
|
|
166
166
|
|
|
167
167
|
node.dimensions.position.set(bounds.x0 + PADDING, bounds.y0 + PADDING);
|
|
168
|
-
node.dimensions.size.set(bounds.
|
|
168
|
+
node.dimensions.size.set(bounds.width - PADDING * 2, bounds.height - PADDING * 2);
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
|