@woosh/meep-engine 2.42.8 → 2.43.1
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.d.ts +2 -0
- 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/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/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
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { array_copy } from "../../../collection/array/copyArray.js";
|
|
2
|
+
import { Uint32Heap } from "../../../collection/heap/Uint32Heap.js";
|
|
3
|
+
import { intersect_ray_2d } from "../intersect_ray_2d.js";
|
|
4
|
+
import { compute_triangle_area_2d } from "../compute_triangle_area_2d.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const v2_temp = new Float32Array(2);
|
|
8
|
+
|
|
9
|
+
class Edge {
|
|
10
|
+
/**
|
|
11
|
+
* Unique index of this edge
|
|
12
|
+
* @type {number}
|
|
13
|
+
*/
|
|
14
|
+
index;
|
|
15
|
+
/**
|
|
16
|
+
* Index into position buffer
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
v0;
|
|
20
|
+
/**
|
|
21
|
+
* Index into position buffer
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
24
|
+
v1;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @type {Edge}
|
|
28
|
+
*/
|
|
29
|
+
next;
|
|
30
|
+
/**
|
|
31
|
+
* @type {Edge}
|
|
32
|
+
*/
|
|
33
|
+
prev;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param {number[]|Float32Array|Float64Array} output
|
|
39
|
+
* @param {number} output_offset
|
|
40
|
+
* @param {Edge} edge
|
|
41
|
+
* @param {number[]} vertex_buffer
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
function compute_collapse_target(output, output_offset, edge, vertex_buffer) {
|
|
45
|
+
const a0 = edge.prev.v0;
|
|
46
|
+
const a1 = edge.prev.v1;
|
|
47
|
+
|
|
48
|
+
const b0 = edge.next.v0;
|
|
49
|
+
const b1 = edge.next.v1;
|
|
50
|
+
|
|
51
|
+
const a0x = vertex_buffer[a0 * 2];
|
|
52
|
+
const a0y = vertex_buffer[a0 * 2 + 1];
|
|
53
|
+
|
|
54
|
+
const a1x = vertex_buffer[a1 * 2];
|
|
55
|
+
const a1y = vertex_buffer[a1 * 2 + 1];
|
|
56
|
+
|
|
57
|
+
const b0x = vertex_buffer[b0 * 2];
|
|
58
|
+
const b0y = vertex_buffer[b0 * 2 + 1];
|
|
59
|
+
|
|
60
|
+
const b1x = vertex_buffer[b1 * 2];
|
|
61
|
+
const b1y = vertex_buffer[b1 * 2 + 1];
|
|
62
|
+
|
|
63
|
+
const a_dir_x = a1x - a0x;
|
|
64
|
+
const a_dir_y = a1y - a0y;
|
|
65
|
+
|
|
66
|
+
const b_dir_x = b1x - b0x;
|
|
67
|
+
const b_dir_y = b1y - b0y;
|
|
68
|
+
|
|
69
|
+
return intersect_ray_2d(
|
|
70
|
+
output, output_offset,
|
|
71
|
+
a0x, a0y, a_dir_x, a_dir_y,
|
|
72
|
+
b0x, b0y, b_dir_x, b_dir_y
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param {number} point_offset
|
|
79
|
+
* @param {number} point_count
|
|
80
|
+
* @returns {Edge[]}
|
|
81
|
+
*/
|
|
82
|
+
function build_edges(point_offset, point_count) {
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
* @type {Edge[]}
|
|
86
|
+
*/
|
|
87
|
+
const edges = [];
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < point_count; i++) {
|
|
90
|
+
const edge = new Edge();
|
|
91
|
+
|
|
92
|
+
edge.index = i;
|
|
93
|
+
|
|
94
|
+
edge.v0 = i + point_offset;
|
|
95
|
+
edge.v1 = (i + 1) % point_count + point_offset;
|
|
96
|
+
|
|
97
|
+
edges[i] = edge;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// connect edges
|
|
101
|
+
for (let i = 0; i < point_count; i++) {
|
|
102
|
+
const edge = edges[i];
|
|
103
|
+
|
|
104
|
+
edge.next = edges[(i + 1) % point_count];
|
|
105
|
+
edge.prev = edges[(point_count + i - 1) % point_count];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return edges;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
*
|
|
113
|
+
* @param {Edge} edge
|
|
114
|
+
* @param {number[]|Float32Array|Float64Array} vertex_buffer
|
|
115
|
+
* @param {number} new_vertex_index
|
|
116
|
+
*/
|
|
117
|
+
function collapse_edge(edge, vertex_buffer, new_vertex_index) {
|
|
118
|
+
// this edge will be removed, previous and next edges will receive a new vertex where they connected to this edge
|
|
119
|
+
// adjacent edges will become neighbours
|
|
120
|
+
|
|
121
|
+
const valid = compute_collapse_target(v2_temp, 0, edge, vertex_buffer);
|
|
122
|
+
|
|
123
|
+
if (!valid) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const next = edge.next;
|
|
128
|
+
const prev = edge.prev;
|
|
129
|
+
|
|
130
|
+
// connect edges together
|
|
131
|
+
next.prev = prev;
|
|
132
|
+
prev.next = next;
|
|
133
|
+
|
|
134
|
+
// inject new vertex
|
|
135
|
+
|
|
136
|
+
next.v0 = new_vertex_index;
|
|
137
|
+
prev.v1 = new_vertex_index;
|
|
138
|
+
|
|
139
|
+
//write out new vertex
|
|
140
|
+
array_copy(v2_temp, 0, vertex_buffer, new_vertex_index * 2, 2);
|
|
141
|
+
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @param {Edge} edge
|
|
148
|
+
* @param {number[]|Float64Array|Float32Array} vertex_buffer
|
|
149
|
+
*/
|
|
150
|
+
function compute_collapse_cost(edge, vertex_buffer) {
|
|
151
|
+
if (!compute_collapse_target(v2_temp, 0, edge, vertex_buffer)) {
|
|
152
|
+
return Infinity;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const v0x = vertex_buffer[edge.v0 * 2];
|
|
156
|
+
const v0y = vertex_buffer[edge.v0 * 2 + 1];
|
|
157
|
+
|
|
158
|
+
const v1x = vertex_buffer[edge.v1 * 2];
|
|
159
|
+
const v1y = vertex_buffer[edge.v1 * 2 + 1];
|
|
160
|
+
|
|
161
|
+
const area = compute_triangle_area_2d(
|
|
162
|
+
v0x, v0y, v2_temp[0], v2_temp[1], v1x, v1y
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
//
|
|
166
|
+
// if (area < 0 || Number.isNaN(area)) {
|
|
167
|
+
// debugger;
|
|
168
|
+
// }
|
|
169
|
+
|
|
170
|
+
return area;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Will throw an error after not being able to collapse an edge for this many cycles
|
|
175
|
+
* @readonly
|
|
176
|
+
* @type {number}
|
|
177
|
+
*/
|
|
178
|
+
const RETRY_MAX_COUNT = 1000;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Relaxes existing convex hull by removing edges until desired cardinality of the hull is reached
|
|
182
|
+
* The algorithm reaches the similar solution as the one proposed by humus, but arrives at a solution much faster as it doesn't need to consider every combination of edges
|
|
183
|
+
* The algorithm is greedy, and thus it can lead to suboptimal cuts, especially on lower number of output vertices
|
|
184
|
+
*
|
|
185
|
+
* @copyright Alex Goldring 2022
|
|
186
|
+
*
|
|
187
|
+
* @param {number[]|Float32Array} output result will be written here
|
|
188
|
+
* @param {number} output_offset offset into output array where to write the result
|
|
189
|
+
* @param {number} output_point_count number of points to comprise bounding polygon
|
|
190
|
+
* @param {number[]} input_points Points to be bounded, must be an ordered loop
|
|
191
|
+
* @param {number} input_point_count number of points in the input to consider
|
|
192
|
+
* @returns {number} actual number of points, this can be lower because input polygon has too few points
|
|
193
|
+
*/
|
|
194
|
+
export function fixed_convex_hull_relaxation(
|
|
195
|
+
output, output_offset, output_point_count,
|
|
196
|
+
input_points, input_point_count
|
|
197
|
+
) {
|
|
198
|
+
if (output_point_count >= input_point_count) {
|
|
199
|
+
// special case, input polygon is smaller or equal to in cardinality to what's desired
|
|
200
|
+
array_copy(input_points, 0, output, output_offset, input_point_count * 2);
|
|
201
|
+
return input_point_count;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Point buffer will be twice as large as the input to have enough space for collapsing all the edges and recording
|
|
207
|
+
* new unique vertices produced
|
|
208
|
+
* @type {Float64Array}
|
|
209
|
+
*/
|
|
210
|
+
const point_buffer = new Float32Array(input_point_count * 4);
|
|
211
|
+
|
|
212
|
+
array_copy(input_points, 0, point_buffer, 0, input_point_count * 2);
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Offset into point buffer
|
|
216
|
+
* @type {number}
|
|
217
|
+
*/
|
|
218
|
+
let point_buffer_cursor = input_point_count;
|
|
219
|
+
|
|
220
|
+
const edges = build_edges(0, input_point_count);
|
|
221
|
+
const live_edge_set = new Set(edges);
|
|
222
|
+
|
|
223
|
+
const edge_heap = new Uint32Heap(input_point_count);
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
// build costs for edges
|
|
227
|
+
for (let i = 0; i < input_point_count; i++) {
|
|
228
|
+
const cost = compute_collapse_cost(edges[i], point_buffer);
|
|
229
|
+
edge_heap.insert(i, cost);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let retry = 0;
|
|
233
|
+
|
|
234
|
+
while (live_edge_set.size > output_point_count) {
|
|
235
|
+
const victim = edge_heap.pop_min();
|
|
236
|
+
|
|
237
|
+
const edge = edges[victim];
|
|
238
|
+
|
|
239
|
+
if (!collapse_edge(edge, point_buffer, point_buffer_cursor)) {
|
|
240
|
+
// couldn't collapse, re-insert with very high score
|
|
241
|
+
edge_heap.insert(victim, Infinity);
|
|
242
|
+
|
|
243
|
+
if (retry >= RETRY_MAX_COUNT) {
|
|
244
|
+
console.warn('Failed to collapse an edge after maximum number of retries has been reached');
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
retry++;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
retry = 0;
|
|
252
|
+
|
|
253
|
+
point_buffer_cursor++;
|
|
254
|
+
|
|
255
|
+
live_edge_set.delete(edge);
|
|
256
|
+
|
|
257
|
+
// update costs for surviving neighbours
|
|
258
|
+
const next_index = edge.next.index;
|
|
259
|
+
const prev_index = edge.prev.index;
|
|
260
|
+
edge_heap.update_score(next_index, compute_collapse_cost(edges[next_index], point_buffer));
|
|
261
|
+
edge_heap.update_score(prev_index, compute_collapse_cost(edges[prev_index], point_buffer));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// pick first edge to start walking
|
|
265
|
+
const first_live_edge = live_edge_set.values().next().value;
|
|
266
|
+
let e = first_live_edge;
|
|
267
|
+
|
|
268
|
+
let output_cursor = output_offset;
|
|
269
|
+
|
|
270
|
+
do {
|
|
271
|
+
// walk the loop, recording first vertex of each edge we visit
|
|
272
|
+
|
|
273
|
+
array_copy(point_buffer, e.v0 * 2, output, output_cursor, 2);
|
|
274
|
+
e = e.next;
|
|
275
|
+
|
|
276
|
+
output_cursor += 2;
|
|
277
|
+
|
|
278
|
+
} while (e !== first_live_edge);
|
|
279
|
+
|
|
280
|
+
// number of output vertices is derived from how many we recorded
|
|
281
|
+
return (output_cursor - output_offset) / 2;
|
|
282
|
+
}
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
var EPSILON = 1.1102230246251565e-16
|
|
2
|
+
var ERRBOUND3 = (3.0 + 16.0 * EPSILON) * EPSILON
|
|
3
|
+
const sum = linearExpansionSum;
|
|
4
|
+
const prod = robustProduct;
|
|
5
|
+
const sub = robustSubtract;
|
|
6
|
+
|
|
7
|
+
function robustSubtract(e, f) {
|
|
8
|
+
var ne = e.length;
|
|
9
|
+
var nf = f.length;
|
|
10
|
+
|
|
11
|
+
var n = ne + nf
|
|
12
|
+
var g = new Array(n)
|
|
13
|
+
var count = 0
|
|
14
|
+
var eptr = 0
|
|
15
|
+
var fptr = 0
|
|
16
|
+
var abs = Math.abs
|
|
17
|
+
var ei = e[eptr]
|
|
18
|
+
var ea = abs(ei)
|
|
19
|
+
var fi = -f[fptr]
|
|
20
|
+
var fa = abs(fi)
|
|
21
|
+
var a, b
|
|
22
|
+
if (ea < fa) {
|
|
23
|
+
b = ei
|
|
24
|
+
eptr += 1
|
|
25
|
+
if (eptr < ne) {
|
|
26
|
+
ei = e[eptr]
|
|
27
|
+
ea = abs(ei)
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
b = fi
|
|
31
|
+
fptr += 1
|
|
32
|
+
if (fptr < nf) {
|
|
33
|
+
fi = -f[fptr]
|
|
34
|
+
fa = abs(fi)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if ((eptr < ne && ea < fa) || (fptr >= nf)) {
|
|
38
|
+
a = ei
|
|
39
|
+
eptr += 1
|
|
40
|
+
if (eptr < ne) {
|
|
41
|
+
ei = e[eptr]
|
|
42
|
+
ea = abs(ei)
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
a = fi
|
|
46
|
+
fptr += 1
|
|
47
|
+
if (fptr < nf) {
|
|
48
|
+
fi = -f[fptr]
|
|
49
|
+
fa = abs(fi)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
var x = a + b
|
|
53
|
+
var bv = x - a
|
|
54
|
+
var y = b - bv
|
|
55
|
+
var q0 = y
|
|
56
|
+
var q1 = x
|
|
57
|
+
var _x, _bv, _av, _br, _ar
|
|
58
|
+
while (eptr < ne && fptr < nf) {
|
|
59
|
+
if (ea < fa) {
|
|
60
|
+
a = ei
|
|
61
|
+
eptr += 1
|
|
62
|
+
if (eptr < ne) {
|
|
63
|
+
ei = e[eptr]
|
|
64
|
+
ea = abs(ei)
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
a = fi
|
|
68
|
+
fptr += 1
|
|
69
|
+
if (fptr < nf) {
|
|
70
|
+
fi = -f[fptr]
|
|
71
|
+
fa = abs(fi)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
b = q0
|
|
75
|
+
x = a + b
|
|
76
|
+
bv = x - a
|
|
77
|
+
y = b - bv
|
|
78
|
+
if (y) {
|
|
79
|
+
g[count++] = y
|
|
80
|
+
}
|
|
81
|
+
_x = q1 + x
|
|
82
|
+
_bv = _x - q1
|
|
83
|
+
_av = _x - _bv
|
|
84
|
+
_br = x - _bv
|
|
85
|
+
_ar = q1 - _av
|
|
86
|
+
q0 = _ar + _br
|
|
87
|
+
q1 = _x
|
|
88
|
+
}
|
|
89
|
+
while (eptr < ne) {
|
|
90
|
+
a = ei
|
|
91
|
+
b = q0
|
|
92
|
+
x = a + b
|
|
93
|
+
bv = x - a
|
|
94
|
+
y = b - bv
|
|
95
|
+
if (y) {
|
|
96
|
+
g[count++] = y
|
|
97
|
+
}
|
|
98
|
+
_x = q1 + x
|
|
99
|
+
_bv = _x - q1
|
|
100
|
+
_av = _x - _bv
|
|
101
|
+
_br = x - _bv
|
|
102
|
+
_ar = q1 - _av
|
|
103
|
+
q0 = _ar + _br
|
|
104
|
+
q1 = _x
|
|
105
|
+
eptr += 1
|
|
106
|
+
if (eptr < ne) {
|
|
107
|
+
ei = e[eptr]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
while (fptr < nf) {
|
|
111
|
+
a = fi
|
|
112
|
+
b = q0
|
|
113
|
+
x = a + b
|
|
114
|
+
bv = x - a
|
|
115
|
+
y = b - bv
|
|
116
|
+
if (y) {
|
|
117
|
+
g[count++] = y
|
|
118
|
+
}
|
|
119
|
+
_x = q1 + x
|
|
120
|
+
_bv = _x - q1
|
|
121
|
+
_av = _x - _bv
|
|
122
|
+
_br = x - _bv
|
|
123
|
+
_ar = q1 - _av
|
|
124
|
+
q0 = _ar + _br
|
|
125
|
+
q1 = _x
|
|
126
|
+
fptr += 1
|
|
127
|
+
if (fptr < nf) {
|
|
128
|
+
fi = -f[fptr]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (q0) {
|
|
132
|
+
g[count++] = q0
|
|
133
|
+
}
|
|
134
|
+
if (q1) {
|
|
135
|
+
g[count++] = q1
|
|
136
|
+
}
|
|
137
|
+
if (!count) {
|
|
138
|
+
g[count++] = 0.0
|
|
139
|
+
}
|
|
140
|
+
g.length = count
|
|
141
|
+
return g
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function robustProduct(a, b) {
|
|
145
|
+
let r = [0]
|
|
146
|
+
if (a.length < b.length) {
|
|
147
|
+
for (var i = 0; i < a.length; ++i) {
|
|
148
|
+
r = linearExpansionSum(r, scaleLinearExpansion(b, a[i]))
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
for (var i = 0; i < b.length; ++i) {
|
|
152
|
+
r = linearExpansionSum(r, scaleLinearExpansion(a, b[i]))
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return r
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
var SPLITTER = +(Math.pow(2, 27) + 1.0)
|
|
159
|
+
|
|
160
|
+
function twoProduct(a, b, result) {
|
|
161
|
+
var x = a * b
|
|
162
|
+
|
|
163
|
+
var c = SPLITTER * a
|
|
164
|
+
var abig = c - a
|
|
165
|
+
var ahi = c - abig
|
|
166
|
+
var alo = a - ahi
|
|
167
|
+
|
|
168
|
+
var d = SPLITTER * b
|
|
169
|
+
var bbig = d - b
|
|
170
|
+
var bhi = d - bbig
|
|
171
|
+
var blo = b - bhi
|
|
172
|
+
|
|
173
|
+
var err1 = x - (ahi * bhi)
|
|
174
|
+
var err2 = err1 - (alo * bhi)
|
|
175
|
+
var err3 = err2 - (ahi * blo)
|
|
176
|
+
|
|
177
|
+
var y = alo * blo - err3
|
|
178
|
+
|
|
179
|
+
if (result) {
|
|
180
|
+
result[0] = y
|
|
181
|
+
result[1] = x
|
|
182
|
+
return result
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return [y, x]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function twoSum(a, b, result) {
|
|
189
|
+
var x = a + b
|
|
190
|
+
var bv = x - a
|
|
191
|
+
var av = x - bv
|
|
192
|
+
var br = b - bv
|
|
193
|
+
var ar = a - av
|
|
194
|
+
if (result) {
|
|
195
|
+
result[0] = ar + br
|
|
196
|
+
result[1] = x
|
|
197
|
+
return result
|
|
198
|
+
}
|
|
199
|
+
return [ar + br, x]
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function scaleLinearExpansion(e, scale) {
|
|
203
|
+
var n = e.length
|
|
204
|
+
if (n === 1) {
|
|
205
|
+
var ts = twoProduct(e[0], scale)
|
|
206
|
+
if (ts[0]) {
|
|
207
|
+
return ts
|
|
208
|
+
}
|
|
209
|
+
return [ts[1]]
|
|
210
|
+
}
|
|
211
|
+
var g = new Array(2 * n)
|
|
212
|
+
var q = [0.1, 0.1]
|
|
213
|
+
var t = [0.1, 0.1]
|
|
214
|
+
var count = 0
|
|
215
|
+
twoProduct(e[0], scale, q)
|
|
216
|
+
if (q[0]) {
|
|
217
|
+
g[count++] = q[0]
|
|
218
|
+
}
|
|
219
|
+
for (var i = 1; i < n; ++i) {
|
|
220
|
+
twoProduct(e[i], scale, t)
|
|
221
|
+
var pq = q[1]
|
|
222
|
+
twoSum(pq, t[0], q)
|
|
223
|
+
if (q[0]) {
|
|
224
|
+
g[count++] = q[0]
|
|
225
|
+
}
|
|
226
|
+
var a = t[1]
|
|
227
|
+
var b = q[1]
|
|
228
|
+
var x = a + b
|
|
229
|
+
var bv = x - a
|
|
230
|
+
var y = b - bv
|
|
231
|
+
q[1] = x
|
|
232
|
+
if (y) {
|
|
233
|
+
g[count++] = y
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (q[1]) {
|
|
237
|
+
g[count++] = q[1]
|
|
238
|
+
}
|
|
239
|
+
if (count === 0) {
|
|
240
|
+
g[count++] = 0.0
|
|
241
|
+
}
|
|
242
|
+
g.length = count
|
|
243
|
+
return g
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Adapted from https://github.com/mikolalysenko/robust-sum/blob/master/robust-sum.js
|
|
248
|
+
* @param {number[]} e
|
|
249
|
+
* @param {number[]} f
|
|
250
|
+
* @returns {number[]}
|
|
251
|
+
*/
|
|
252
|
+
function linearExpansionSum(e, f) {
|
|
253
|
+
var ne = e.length;
|
|
254
|
+
var nf = f.length;
|
|
255
|
+
|
|
256
|
+
var n = ne + nf
|
|
257
|
+
var g = new Array(n)
|
|
258
|
+
var count = 0
|
|
259
|
+
var eptr = 0
|
|
260
|
+
var fptr = 0
|
|
261
|
+
var abs = Math.abs
|
|
262
|
+
var ei = e[eptr]
|
|
263
|
+
var ea = abs(ei)
|
|
264
|
+
var fi = f[fptr]
|
|
265
|
+
var fa = abs(fi)
|
|
266
|
+
var a, b
|
|
267
|
+
if (ea < fa) {
|
|
268
|
+
b = ei
|
|
269
|
+
eptr += 1
|
|
270
|
+
if (eptr < ne) {
|
|
271
|
+
ei = e[eptr]
|
|
272
|
+
ea = abs(ei)
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
b = fi
|
|
276
|
+
fptr += 1
|
|
277
|
+
if (fptr < nf) {
|
|
278
|
+
fi = f[fptr]
|
|
279
|
+
fa = abs(fi)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if ((eptr < ne && ea < fa) || (fptr >= nf)) {
|
|
283
|
+
a = ei
|
|
284
|
+
eptr += 1
|
|
285
|
+
if (eptr < ne) {
|
|
286
|
+
ei = e[eptr]
|
|
287
|
+
ea = abs(ei)
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
a = fi
|
|
291
|
+
fptr += 1
|
|
292
|
+
if (fptr < nf) {
|
|
293
|
+
fi = f[fptr]
|
|
294
|
+
fa = abs(fi)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
var x = a + b
|
|
298
|
+
var bv = x - a
|
|
299
|
+
var y = b - bv
|
|
300
|
+
var q0 = y
|
|
301
|
+
var q1 = x
|
|
302
|
+
var _x, _bv, _av, _br, _ar
|
|
303
|
+
while (eptr < ne && fptr < nf) {
|
|
304
|
+
if (ea < fa) {
|
|
305
|
+
a = ei
|
|
306
|
+
eptr += 1
|
|
307
|
+
if (eptr < ne) {
|
|
308
|
+
ei = e[eptr]
|
|
309
|
+
ea = abs(ei)
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
a = fi
|
|
313
|
+
fptr += 1
|
|
314
|
+
if (fptr < nf) {
|
|
315
|
+
fi = f[fptr]
|
|
316
|
+
fa = abs(fi)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
b = q0
|
|
320
|
+
x = a + b
|
|
321
|
+
bv = x - a
|
|
322
|
+
y = b - bv
|
|
323
|
+
if (y) {
|
|
324
|
+
g[count++] = y
|
|
325
|
+
}
|
|
326
|
+
_x = q1 + x
|
|
327
|
+
_bv = _x - q1
|
|
328
|
+
_av = _x - _bv
|
|
329
|
+
_br = x - _bv
|
|
330
|
+
_ar = q1 - _av
|
|
331
|
+
q0 = _ar + _br
|
|
332
|
+
q1 = _x
|
|
333
|
+
}
|
|
334
|
+
while (eptr < ne) {
|
|
335
|
+
a = ei
|
|
336
|
+
b = q0
|
|
337
|
+
x = a + b
|
|
338
|
+
bv = x - a
|
|
339
|
+
y = b - bv
|
|
340
|
+
if (y) {
|
|
341
|
+
g[count++] = y
|
|
342
|
+
}
|
|
343
|
+
_x = q1 + x
|
|
344
|
+
_bv = _x - q1
|
|
345
|
+
_av = _x - _bv
|
|
346
|
+
_br = x - _bv
|
|
347
|
+
_ar = q1 - _av
|
|
348
|
+
q0 = _ar + _br
|
|
349
|
+
q1 = _x
|
|
350
|
+
eptr += 1
|
|
351
|
+
if (eptr < ne) {
|
|
352
|
+
ei = e[eptr]
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
while (fptr < nf) {
|
|
356
|
+
a = fi
|
|
357
|
+
b = q0
|
|
358
|
+
x = a + b
|
|
359
|
+
bv = x - a
|
|
360
|
+
y = b - bv
|
|
361
|
+
if (y) {
|
|
362
|
+
g[count++] = y
|
|
363
|
+
}
|
|
364
|
+
_x = q1 + x
|
|
365
|
+
_bv = _x - q1
|
|
366
|
+
_av = _x - _bv
|
|
367
|
+
_br = x - _bv
|
|
368
|
+
_ar = q1 - _av
|
|
369
|
+
q0 = _ar + _br
|
|
370
|
+
q1 = _x
|
|
371
|
+
fptr += 1
|
|
372
|
+
if (fptr < nf) {
|
|
373
|
+
fi = f[fptr]
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (q0) {
|
|
377
|
+
g[count++] = q0
|
|
378
|
+
}
|
|
379
|
+
if (q1) {
|
|
380
|
+
g[count++] = q1
|
|
381
|
+
}
|
|
382
|
+
if (!count) {
|
|
383
|
+
g[count++] = 0.0
|
|
384
|
+
}
|
|
385
|
+
g.length = count
|
|
386
|
+
return g
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
*
|
|
391
|
+
* @param {number[]} m0
|
|
392
|
+
* @param {number[]} m1
|
|
393
|
+
* @param {number[]} m2
|
|
394
|
+
* @returns {number}
|
|
395
|
+
*/
|
|
396
|
+
function orientation3Exact(m0, m1, m2) {
|
|
397
|
+
const p = sum(sum(prod(m1[1], m2[0]), prod(-m2[1], m1[0])), sum(prod(m0[1], m1[0]), prod(-m1[1], m0[0])))
|
|
398
|
+
const n = sum(prod(m0[1], m2[0]), prod(-m2[1], m0[0]))
|
|
399
|
+
const d = sub(p, n)
|
|
400
|
+
return d[d.length - 1]
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
*
|
|
405
|
+
* @param {number} ax
|
|
406
|
+
* @param {number} ay
|
|
407
|
+
* @param {number} bx
|
|
408
|
+
* @param {number} by
|
|
409
|
+
* @param {number} cx
|
|
410
|
+
* @param {number} cy
|
|
411
|
+
* @returns {number}
|
|
412
|
+
*/
|
|
413
|
+
export function orientation3(ax, ay, bx, by, cx, cy) {
|
|
414
|
+
|
|
415
|
+
const l = (ay - cy) * (bx - cx);
|
|
416
|
+
const r = (ax - cx) * (by - cy);
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
const det = l - r;
|
|
420
|
+
let s;
|
|
421
|
+
|
|
422
|
+
if (l > 0) {
|
|
423
|
+
if (r <= 0) {
|
|
424
|
+
return det
|
|
425
|
+
} else {
|
|
426
|
+
s = l + r
|
|
427
|
+
}
|
|
428
|
+
} else if (l < 0) {
|
|
429
|
+
if (r >= 0) {
|
|
430
|
+
return det
|
|
431
|
+
} else {
|
|
432
|
+
s = -(l + r)
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
return det
|
|
436
|
+
}
|
|
437
|
+
var tol = ERRBOUND3 * s
|
|
438
|
+
|
|
439
|
+
if (det >= tol || det <= -tol) {
|
|
440
|
+
return det
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return orientation3Exact([ax, ay], [bx, by], [cx, cy]);
|
|
444
|
+
}
|