samcan 0.0.2 → 0.1.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/{license → LICENSE} +3 -1
- package/README.md +3 -0
- package/dist/camera/index.cjs +370 -0
- package/dist/camera/index.d.cts +54 -0
- package/dist/camera/index.d.ts +54 -0
- package/dist/camera/index.js +70 -0
- package/dist/document/index.cjs +735 -0
- package/dist/document/index.d.cts +174 -0
- package/dist/document/index.d.ts +174 -0
- package/dist/document/index.js +161 -0
- package/dist/editor/index.cjs +5007 -0
- package/dist/editor/index.d.cts +374 -0
- package/dist/editor/index.d.ts +374 -0
- package/dist/editor/index.js +2401 -0
- package/dist/engine/index.cjs +3752 -0
- package/dist/engine/index.d.cts +183 -0
- package/dist/engine/index.d.ts +183 -0
- package/dist/engine/index.js +111 -0
- package/dist/index.cjs +8899 -0
- package/dist/index.d.cts +962 -0
- package/dist/index.d.ts +962 -46
- package/dist/index.js +1008 -49
- package/dist/math/index.cjs +2230 -0
- package/dist/math/index.d.cts +302 -0
- package/dist/math/index.d.ts +302 -0
- package/dist/math/index.js +1109 -0
- package/dist/renderer/index.cjs +1865 -0
- package/dist/renderer/index.d.cts +91 -0
- package/dist/renderer/index.d.ts +91 -0
- package/dist/renderer/index.js +89 -0
- package/dist/shared/chunk-35pkr0zs.js +110 -0
- package/dist/shared/chunk-7sr7q84y.js +80 -0
- package/dist/shared/chunk-87399bz7.js +89 -0
- package/dist/shared/chunk-8ynnz57m.js +129 -0
- package/dist/shared/chunk-d6gxvapt.js +500 -0
- package/dist/shared/chunk-hewznwbd.js +305 -0
- package/dist/shared/chunk-jdvrd5tv.js +623 -0
- package/dist/shared/chunk-rvag1j46.js +461 -0
- package/dist/shared/chunk-rzxyjwk8.js +397 -0
- package/dist/shared/chunk-s3qdcmcq.js +1392 -0
- package/dist/shared/chunk-v53jprrn.js +68 -0
- package/dist/shared/chunk-wa3772hp.js +117 -0
- package/dist/spatial/index.cjs +954 -0
- package/dist/spatial/index.d.cts +136 -0
- package/dist/spatial/index.d.ts +136 -0
- package/dist/spatial/index.js +301 -0
- package/dist/stroke/index.cjs +1010 -0
- package/dist/stroke/index.d.cts +143 -0
- package/dist/stroke/index.d.ts +143 -0
- package/dist/stroke/index.js +343 -0
- package/package.json +122 -58
- package/dist/bundle.js +0 -5888
- package/dist/core/animation/animationruntime.d.ts +0 -238
- package/dist/core/animation/animationruntime.d.ts.map +0 -1
- package/dist/core/animation/animationruntime.js +0 -530
- package/dist/core/animation/animationruntime.js.map +0 -1
- package/dist/core/animation/animationstate.d.ts +0 -85
- package/dist/core/animation/animationstate.d.ts.map +0 -1
- package/dist/core/animation/animationstate.js +0 -119
- package/dist/core/animation/animationstate.js.map +0 -1
- package/dist/core/animation/animationtrack.d.ts +0 -55
- package/dist/core/animation/animationtrack.d.ts.map +0 -1
- package/dist/core/animation/animationtrack.js +0 -185
- package/dist/core/animation/animationtrack.js.map +0 -1
- package/dist/core/animation/easing.d.ts +0 -80
- package/dist/core/animation/easing.d.ts.map +0 -1
- package/dist/core/animation/easing.js +0 -126
- package/dist/core/animation/easing.js.map +0 -1
- package/dist/core/animation/index.d.ts +0 -11
- package/dist/core/animation/index.d.ts.map +0 -1
- package/dist/core/animation/index.js +0 -10
- package/dist/core/animation/index.js.map +0 -1
- package/dist/core/animation/interpolator.d.ts +0 -82
- package/dist/core/animation/interpolator.d.ts.map +0 -1
- package/dist/core/animation/interpolator.js +0 -108
- package/dist/core/animation/interpolator.js.map +0 -1
- package/dist/core/animation/keyframe.d.ts +0 -52
- package/dist/core/animation/keyframe.d.ts.map +0 -1
- package/dist/core/animation/keyframe.js +0 -65
- package/dist/core/animation/keyframe.js.map +0 -1
- package/dist/core/animation/logger.d.ts +0 -8
- package/dist/core/animation/logger.d.ts.map +0 -1
- package/dist/core/animation/logger.js +0 -20
- package/dist/core/animation/logger.js.map +0 -1
- package/dist/core/animation/statemachine.d.ts +0 -178
- package/dist/core/animation/statemachine.d.ts.map +0 -1
- package/dist/core/animation/statemachine.js +0 -378
- package/dist/core/animation/statemachine.js.map +0 -1
- package/dist/core/animation/statetransition.d.ts +0 -142
- package/dist/core/animation/statetransition.d.ts.map +0 -1
- package/dist/core/animation/statetransition.js +0 -189
- package/dist/core/animation/statetransition.js.map +0 -1
- package/dist/core/animation/timeline.d.ts +0 -62
- package/dist/core/animation/timeline.d.ts.map +0 -1
- package/dist/core/animation/timeline.js +0 -102
- package/dist/core/animation/timeline.js.map +0 -1
- package/dist/core/api.d.ts +0 -245
- package/dist/core/api.d.ts.map +0 -1
- package/dist/core/api.js +0 -369
- package/dist/core/api.js.map +0 -1
- package/dist/core/asset/assetmanager.d.ts +0 -196
- package/dist/core/asset/assetmanager.d.ts.map +0 -1
- package/dist/core/asset/assetmanager.js +0 -502
- package/dist/core/asset/assetmanager.js.map +0 -1
- package/dist/core/asset/index.d.ts +0 -3
- package/dist/core/asset/index.d.ts.map +0 -1
- package/dist/core/asset/index.js +0 -3
- package/dist/core/asset/index.js.map +0 -1
- package/dist/core/asset/types.d.ts +0 -36
- package/dist/core/asset/types.d.ts.map +0 -1
- package/dist/core/asset/types.js +0 -1
- package/dist/core/asset/types.js.map +0 -1
- package/dist/core/command/basecommand.d.ts +0 -29
- package/dist/core/command/basecommand.d.ts.map +0 -1
- package/dist/core/command/basecommand.js +0 -36
- package/dist/core/command/basecommand.js.map +0 -1
- package/dist/core/command/command.d.ts +0 -55
- package/dist/core/command/command.d.ts.map +0 -1
- package/dist/core/command/command.js +0 -1
- package/dist/core/command/command.js.map +0 -1
- package/dist/core/command/commandhistory.d.ts +0 -76
- package/dist/core/command/commandhistory.d.ts.map +0 -1
- package/dist/core/command/commandhistory.js +0 -122
- package/dist/core/command/commandhistory.js.map +0 -1
- package/dist/core/command/editorcommands.d.ts +0 -108
- package/dist/core/command/editorcommands.d.ts.map +0 -1
- package/dist/core/command/editorcommands.js +0 -274
- package/dist/core/command/editorcommands.js.map +0 -1
- package/dist/core/command/index.d.ts +0 -5
- package/dist/core/command/index.d.ts.map +0 -1
- package/dist/core/command/index.js +0 -5
- package/dist/core/command/index.js.map +0 -1
- package/dist/core/editor/events/emitter.d.ts +0 -45
- package/dist/core/editor/events/emitter.d.ts.map +0 -1
- package/dist/core/editor/events/emitter.js +0 -88
- package/dist/core/editor/events/emitter.js.map +0 -1
- package/dist/core/error/animationerror.d.ts +0 -27
- package/dist/core/error/animationerror.d.ts.map +0 -1
- package/dist/core/error/animationerror.js +0 -41
- package/dist/core/error/animationerror.js.map +0 -1
- package/dist/core/error/asseterror.d.ts +0 -32
- package/dist/core/error/asseterror.d.ts.map +0 -1
- package/dist/core/error/asseterror.js +0 -48
- package/dist/core/error/asseterror.js.map +0 -1
- package/dist/core/error/index.d.ts +0 -7
- package/dist/core/error/index.d.ts.map +0 -1
- package/dist/core/error/index.js +0 -7
- package/dist/core/error/index.js.map +0 -1
- package/dist/core/error/pluginerror.d.ts +0 -22
- package/dist/core/error/pluginerror.d.ts.map +0 -1
- package/dist/core/error/pluginerror.js +0 -33
- package/dist/core/error/pluginerror.js.map +0 -1
- package/dist/core/error/renderererror.d.ts +0 -26
- package/dist/core/error/renderererror.d.ts.map +0 -1
- package/dist/core/error/renderererror.js +0 -40
- package/dist/core/error/renderererror.js.map +0 -1
- package/dist/core/error/samcanerror.d.ts +0 -72
- package/dist/core/error/samcanerror.d.ts.map +0 -1
- package/dist/core/error/samcanerror.js +0 -108
- package/dist/core/error/samcanerror.js.map +0 -1
- package/dist/core/error/serializationerror.d.ts +0 -31
- package/dist/core/error/serializationerror.d.ts.map +0 -1
- package/dist/core/error/serializationerror.js +0 -46
- package/dist/core/error/serializationerror.js.map +0 -1
- package/dist/core/index.d.ts +0 -12
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -12
- package/dist/core/index.js.map +0 -1
- package/dist/core/math/color.d.ts +0 -56
- package/dist/core/math/color.d.ts.map +0 -1
- package/dist/core/math/color.js +0 -125
- package/dist/core/math/color.js.map +0 -1
- package/dist/core/math/index.d.ts +0 -14
- package/dist/core/math/index.d.ts.map +0 -1
- package/dist/core/math/index.js +0 -14
- package/dist/core/math/index.js.map +0 -1
- package/dist/core/math/matrix.d.ts +0 -101
- package/dist/core/math/matrix.d.ts.map +0 -1
- package/dist/core/math/matrix.js +0 -177
- package/dist/core/math/matrix.js.map +0 -1
- package/dist/core/math/paint.d.ts +0 -104
- package/dist/core/math/paint.d.ts.map +0 -1
- package/dist/core/math/paint.js +0 -204
- package/dist/core/math/paint.js.map +0 -1
- package/dist/core/math/path/index.d.ts +0 -94
- package/dist/core/math/path/index.d.ts.map +0 -1
- package/dist/core/math/path/index.js +0 -180
- package/dist/core/math/path/index.js.map +0 -1
- package/dist/core/math/path/operations.d.ts +0 -38
- package/dist/core/math/path/operations.d.ts.map +0 -1
- package/dist/core/math/path/operations.js +0 -149
- package/dist/core/math/path/operations.js.map +0 -1
- package/dist/core/math/pool.d.ts +0 -54
- package/dist/core/math/pool.d.ts.map +0 -1
- package/dist/core/math/pool.js +0 -97
- package/dist/core/math/pool.js.map +0 -1
- package/dist/core/math/pools.d.ts +0 -29
- package/dist/core/math/pools.d.ts.map +0 -1
- package/dist/core/math/pools.js +0 -50
- package/dist/core/math/pools.js.map +0 -1
- package/dist/core/math/rectangle.d.ts +0 -68
- package/dist/core/math/rectangle.d.ts.map +0 -1
- package/dist/core/math/rectangle.js +0 -124
- package/dist/core/math/rectangle.js.map +0 -1
- package/dist/core/math/utils.d.ts +0 -68
- package/dist/core/math/utils.d.ts.map +0 -1
- package/dist/core/math/utils.js +0 -110
- package/dist/core/math/utils.js.map +0 -1
- package/dist/core/math/vector2.d.ts +0 -85
- package/dist/core/math/vector2.d.ts.map +0 -1
- package/dist/core/math/vector2.js +0 -134
- package/dist/core/math/vector2.js.map +0 -1
- package/dist/core/plugin/animationcontroller.d.ts +0 -43
- package/dist/core/plugin/animationcontroller.d.ts.map +0 -1
- package/dist/core/plugin/animationcontroller.js +0 -11
- package/dist/core/plugin/animationcontroller.js.map +0 -1
- package/dist/core/plugin/index.d.ts +0 -6
- package/dist/core/plugin/index.d.ts.map +0 -1
- package/dist/core/plugin/index.js +0 -4
- package/dist/core/plugin/index.js.map +0 -1
- package/dist/core/plugin/plugin.d.ts +0 -53
- package/dist/core/plugin/plugin.d.ts.map +0 -1
- package/dist/core/plugin/plugin.js +0 -29
- package/dist/core/plugin/plugin.js.map +0 -1
- package/dist/core/plugin/pluginregistry.d.ts +0 -71
- package/dist/core/plugin/pluginregistry.d.ts.map +0 -1
- package/dist/core/plugin/pluginregistry.js +0 -143
- package/dist/core/plugin/pluginregistry.js.map +0 -1
- package/dist/core/renderer/batchmanager.d.ts +0 -68
- package/dist/core/renderer/batchmanager.d.ts.map +0 -1
- package/dist/core/renderer/batchmanager.js +0 -82
- package/dist/core/renderer/batchmanager.js.map +0 -1
- package/dist/core/renderer/canvas2drenderer.d.ts +0 -139
- package/dist/core/renderer/canvas2drenderer.d.ts.map +0 -1
- package/dist/core/renderer/canvas2drenderer.js +0 -499
- package/dist/core/renderer/canvas2drenderer.js.map +0 -1
- package/dist/core/renderer/dirtyregionmanager.d.ts +0 -54
- package/dist/core/renderer/dirtyregionmanager.d.ts.map +0 -1
- package/dist/core/renderer/dirtyregionmanager.js +0 -129
- package/dist/core/renderer/dirtyregionmanager.js.map +0 -1
- package/dist/core/renderer/index.d.ts +0 -8
- package/dist/core/renderer/index.d.ts.map +0 -1
- package/dist/core/renderer/index.js +0 -6
- package/dist/core/renderer/index.js.map +0 -1
- package/dist/core/renderer/renderer.d.ts +0 -154
- package/dist/core/renderer/renderer.d.ts.map +0 -1
- package/dist/core/renderer/renderer.js +0 -1
- package/dist/core/renderer/renderer.js.map +0 -1
- package/dist/core/renderer/rendererfactory.d.ts +0 -66
- package/dist/core/renderer/rendererfactory.d.ts.map +0 -1
- package/dist/core/renderer/rendererfactory.js +0 -219
- package/dist/core/renderer/rendererfactory.js.map +0 -1
- package/dist/core/renderer/webglrenderer.d.ts +0 -185
- package/dist/core/renderer/webglrenderer.d.ts.map +0 -1
- package/dist/core/renderer/webglrenderer.js +0 -1007
- package/dist/core/renderer/webglrenderer.js.map +0 -1
- package/dist/core/scene/index.d.ts +0 -4
- package/dist/core/scene/index.d.ts.map +0 -1
- package/dist/core/scene/index.js +0 -4
- package/dist/core/scene/index.js.map +0 -1
- package/dist/core/scene/node.d.ts +0 -162
- package/dist/core/scene/node.d.ts.map +0 -1
- package/dist/core/scene/node.js +0 -402
- package/dist/core/scene/node.js.map +0 -1
- package/dist/core/scene/nodes/artboard.d.ts +0 -42
- package/dist/core/scene/nodes/artboard.d.ts.map +0 -1
- package/dist/core/scene/nodes/artboard.js +0 -64
- package/dist/core/scene/nodes/artboard.js.map +0 -1
- package/dist/core/scene/nodes/groupnode.d.ts +0 -10
- package/dist/core/scene/nodes/groupnode.d.ts.map +0 -1
- package/dist/core/scene/nodes/groupnode.js +0 -12
- package/dist/core/scene/nodes/groupnode.js.map +0 -1
- package/dist/core/scene/nodes/imagenode.d.ts +0 -38
- package/dist/core/scene/nodes/imagenode.d.ts.map +0 -1
- package/dist/core/scene/nodes/imagenode.js +0 -77
- package/dist/core/scene/nodes/imagenode.js.map +0 -1
- package/dist/core/scene/nodes/index.d.ts +0 -5
- package/dist/core/scene/nodes/index.d.ts.map +0 -1
- package/dist/core/scene/nodes/index.js +0 -5
- package/dist/core/scene/nodes/index.js.map +0 -1
- package/dist/core/scene/nodes/shapenode.d.ts +0 -76
- package/dist/core/scene/nodes/shapenode.d.ts.map +0 -1
- package/dist/core/scene/nodes/shapenode.js +0 -212
- package/dist/core/scene/nodes/shapenode.js.map +0 -1
- package/dist/core/scene/transform.d.ts +0 -27
- package/dist/core/scene/transform.d.ts.map +0 -1
- package/dist/core/scene/transform.js +0 -52
- package/dist/core/scene/transform.js.map +0 -1
- package/dist/core/serialization/index.d.ts +0 -3
- package/dist/core/serialization/index.d.ts.map +0 -1
- package/dist/core/serialization/index.js +0 -2
- package/dist/core/serialization/index.js.map +0 -1
- package/dist/core/serialization/serializer.d.ts +0 -323
- package/dist/core/serialization/serializer.d.ts.map +0 -1
- package/dist/core/serialization/serializer.js +0 -1173
- package/dist/core/serialization/serializer.js.map +0 -1
- package/dist/core/serialization/types.d.ts +0 -242
- package/dist/core/serialization/types.d.ts.map +0 -1
- package/dist/core/serialization/types.js +0 -1
- package/dist/core/serialization/types.js.map +0 -1
- package/dist/core/timing/clock.d.ts +0 -43
- package/dist/core/timing/clock.d.ts.map +0 -1
- package/dist/core/timing/clock.js +0 -78
- package/dist/core/timing/clock.js.map +0 -1
- package/dist/core/timing/index.d.ts +0 -3
- package/dist/core/timing/index.d.ts.map +0 -1
- package/dist/core/timing/index.js +0 -3
- package/dist/core/timing/index.js.map +0 -1
- package/dist/core/timing/scheduler.d.ts +0 -72
- package/dist/core/timing/scheduler.d.ts.map +0 -1
- package/dist/core/timing/scheduler.js +0 -163
- package/dist/core/timing/scheduler.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/wrapper/react/index.d.ts +0 -5
- package/dist/wrapper/react/index.d.ts.map +0 -1
- package/dist/wrapper/react/index.js +0 -3
- package/dist/wrapper/react/index.js.map +0 -1
- package/dist/wrapper/react/samcan-player.d.ts +0 -26
- package/dist/wrapper/react/samcan-player.d.ts.map +0 -1
- package/dist/wrapper/react/samcan-player.js +0 -19
- package/dist/wrapper/react/samcan-player.js.map +0 -1
- package/dist/wrapper/react/use-samcan-player.d.ts +0 -33
- package/dist/wrapper/react/use-samcan-player.d.ts.map +0 -1
- package/dist/wrapper/react/use-samcan-player.js +0 -65
- package/dist/wrapper/react/use-samcan-player.js.map +0 -1
- package/readme.md +0 -96
|
@@ -0,0 +1,1010 @@
|
|
|
1
|
+
var import_node_module = require("node:module");
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
+
var __toCommonJS = (from) => {
|
|
8
|
+
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
if (entry)
|
|
10
|
+
return entry;
|
|
11
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
+
get: () => from[key],
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
}));
|
|
17
|
+
__moduleCache.set(from, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// stroke/index.ts
|
|
31
|
+
var exports_stroke = {};
|
|
32
|
+
__export(exports_stroke, {
|
|
33
|
+
stroke_to_path_commands: () => stroke_to_path_commands,
|
|
34
|
+
stabilize_point: () => stabilize_point,
|
|
35
|
+
spline_evaluation_interval_medium: () => spline_evaluation_interval_medium,
|
|
36
|
+
spline_evaluation_interval_low: () => spline_evaluation_interval_low,
|
|
37
|
+
spline_evaluation_interval_high: () => spline_evaluation_interval_high,
|
|
38
|
+
simplify_stroke_points_auto: () => simplify_stroke_points_auto,
|
|
39
|
+
simplify_stroke_points: () => simplify_stroke_points,
|
|
40
|
+
select_lod_from_zoom: () => select_lod_from_zoom,
|
|
41
|
+
reset_stabilizer: () => reset_stabilizer,
|
|
42
|
+
render_stroke_with_pressure: () => render_stroke_with_pressure,
|
|
43
|
+
render_stroke: () => render_stroke,
|
|
44
|
+
render_live_stroke: () => render_live_stroke,
|
|
45
|
+
process_stroke: () => process_stroke,
|
|
46
|
+
lod_medium: () => lod_medium,
|
|
47
|
+
lod_low: () => lod_low,
|
|
48
|
+
lod_high: () => lod_high,
|
|
49
|
+
get_stabilized_history: () => get_stabilized_history,
|
|
50
|
+
get_spline_evaluation_interval: () => get_spline_evaluation_interval,
|
|
51
|
+
get_simplified_for_lod: () => get_simplified_for_lod,
|
|
52
|
+
get_pressure_from_live_stroke: () => get_pressure_from_live_stroke,
|
|
53
|
+
get_points_from_live_stroke: () => get_points_from_live_stroke,
|
|
54
|
+
generate_stroke_id: () => generate_stroke_id,
|
|
55
|
+
fit_spline_to_stroke: () => fit_spline_to_stroke,
|
|
56
|
+
finalize_live_stroke: () => finalize_live_stroke,
|
|
57
|
+
default_stroke_style: () => default_stroke_style,
|
|
58
|
+
default_stabilizer_history_size: () => default_stabilizer_history_size,
|
|
59
|
+
default_smoothing_factor: () => default_smoothing_factor,
|
|
60
|
+
default_simplify_epsilon: () => default_simplify_epsilon,
|
|
61
|
+
default_lod_simplify_factor: () => default_lod_simplify_factor,
|
|
62
|
+
create_stroke_style: () => create_stroke_style,
|
|
63
|
+
create_stabilizer: () => create_stabilizer,
|
|
64
|
+
create_live_stroke: () => create_live_stroke,
|
|
65
|
+
compute_stroke_bounds: () => compute_stroke_bounds,
|
|
66
|
+
clone_stroke_style: () => clone_stroke_style,
|
|
67
|
+
add_raw_point_live_stroke: () => add_raw_point_live_stroke,
|
|
68
|
+
add_point_live_stroke: () => add_point_live_stroke
|
|
69
|
+
});
|
|
70
|
+
module.exports = __toCommonJS(exports_stroke);
|
|
71
|
+
|
|
72
|
+
// stroke/stroke.ts
|
|
73
|
+
var default_stroke_style = {
|
|
74
|
+
color: [0, 0, 0, 1],
|
|
75
|
+
width: 3,
|
|
76
|
+
opacity: 1,
|
|
77
|
+
pressure_sensitivity: 0.5
|
|
78
|
+
};
|
|
79
|
+
function create_stroke_style(color, width, opacity = 1, pressure_sensitivity = 0.5) {
|
|
80
|
+
return {
|
|
81
|
+
color: [color[0], color[1], color[2], color[3]],
|
|
82
|
+
width,
|
|
83
|
+
opacity,
|
|
84
|
+
pressure_sensitivity
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function clone_stroke_style(s) {
|
|
88
|
+
return {
|
|
89
|
+
color: [s.color[0], s.color[1], s.color[2], s.color[3]],
|
|
90
|
+
width: s.width,
|
|
91
|
+
opacity: s.opacity,
|
|
92
|
+
pressure_sensitivity: s.pressure_sensitivity
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// stroke/stabilizer.ts
|
|
96
|
+
var default_smoothing_factor = 0.3;
|
|
97
|
+
var default_stabilizer_history_size = 5;
|
|
98
|
+
function create_stabilizer(smoothing_factor = default_smoothing_factor) {
|
|
99
|
+
return {
|
|
100
|
+
history: [],
|
|
101
|
+
smoothing_factor
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function stabilize_point(state, raw, out) {
|
|
105
|
+
if (state.history.length === 0) {
|
|
106
|
+
out[0] = raw[0];
|
|
107
|
+
out[1] = raw[1];
|
|
108
|
+
} else {
|
|
109
|
+
const last = state.history[state.history.length - 1];
|
|
110
|
+
out[0] = last[0] + state.smoothing_factor * (raw[0] - last[0]);
|
|
111
|
+
out[1] = last[1] + state.smoothing_factor * (raw[1] - last[1]);
|
|
112
|
+
}
|
|
113
|
+
state.history.push([out[0], out[1]]);
|
|
114
|
+
if (state.history.length > default_stabilizer_history_size) {
|
|
115
|
+
state.history.shift();
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
function reset_stabilizer(state) {
|
|
120
|
+
state.history = [];
|
|
121
|
+
}
|
|
122
|
+
function get_stabilized_history(state) {
|
|
123
|
+
return state.history;
|
|
124
|
+
}
|
|
125
|
+
// math/color.ts
|
|
126
|
+
function create_color(r = 0, g = 0, b = 0, a = 1) {
|
|
127
|
+
return [
|
|
128
|
+
Math.max(0, Math.min(1, r)),
|
|
129
|
+
Math.max(0, Math.min(1, g)),
|
|
130
|
+
Math.max(0, Math.min(1, b)),
|
|
131
|
+
Math.max(0, Math.min(1, a))
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
function clone_color(c) {
|
|
135
|
+
return [c[0], c[1], c[2], c[3]];
|
|
136
|
+
}
|
|
137
|
+
function set_color(r, g, b, a = 1, out) {
|
|
138
|
+
out[0] = Math.max(0, Math.min(1, r));
|
|
139
|
+
out[1] = Math.max(0, Math.min(1, g));
|
|
140
|
+
out[2] = Math.max(0, Math.min(1, b));
|
|
141
|
+
out[3] = Math.max(0, Math.min(1, a));
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
function copy_color(c, out) {
|
|
145
|
+
out[0] = c[0];
|
|
146
|
+
out[1] = c[1];
|
|
147
|
+
out[2] = c[2];
|
|
148
|
+
out[3] = c[3];
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
function from_rgb_color(r, g, b, a = 255) {
|
|
152
|
+
return create_color(r / 255, g / 255, b / 255, a / 255);
|
|
153
|
+
}
|
|
154
|
+
function from_hex_color(hex) {
|
|
155
|
+
const cleaned = hex.replace("#", "");
|
|
156
|
+
const r = parseInt(cleaned.substring(0, 2), 16) / 255;
|
|
157
|
+
const g = parseInt(cleaned.substring(2, 4), 16) / 255;
|
|
158
|
+
const b = parseInt(cleaned.substring(4, 6), 16) / 255;
|
|
159
|
+
const a = cleaned.length === 8 ? parseInt(cleaned.substring(6, 8), 16) / 255 : 1;
|
|
160
|
+
return create_color(r, g, b, a);
|
|
161
|
+
}
|
|
162
|
+
function to_rgba_string_color(c) {
|
|
163
|
+
return `rgba(${Math.round(c[0] * 255)}, ${Math.round(c[1] * 255)}, ${Math.round(c[2] * 255)}, ${c[3]})`;
|
|
164
|
+
}
|
|
165
|
+
function to_hex_string_color(c) {
|
|
166
|
+
const r = Math.round(c[0] * 255).toString(16).padStart(2, "0");
|
|
167
|
+
const g = Math.round(c[1] * 255).toString(16).padStart(2, "0");
|
|
168
|
+
const b = Math.round(c[2] * 255).toString(16).padStart(2, "0");
|
|
169
|
+
const a = Math.round(c[3] * 255).toString(16).padStart(2, "0");
|
|
170
|
+
return c[3] === 1 ? `#${r}${g}${b}` : `#${r}${g}${b}${a}`;
|
|
171
|
+
}
|
|
172
|
+
function lerp_color(c1, c2, t, out) {
|
|
173
|
+
out[0] = c1[0] + (c2[0] - c1[0]) * t;
|
|
174
|
+
out[1] = c1[1] + (c2[1] - c1[1]) * t;
|
|
175
|
+
out[2] = c1[2] + (c2[2] - c1[2]) * t;
|
|
176
|
+
out[3] = c1[3] + (c2[3] - c1[3]) * t;
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
function equals_color(c1, c2, epsilon = 0.0001) {
|
|
180
|
+
return Math.abs(c1[0] - c2[0]) < epsilon && Math.abs(c1[1] - c2[1]) < epsilon && Math.abs(c1[2] - c2[2]) < epsilon && Math.abs(c1[3] - c2[3]) < epsilon;
|
|
181
|
+
}
|
|
182
|
+
function white_color() {
|
|
183
|
+
return [1, 1, 1, 1];
|
|
184
|
+
}
|
|
185
|
+
function black_color() {
|
|
186
|
+
return [0, 0, 0, 1];
|
|
187
|
+
}
|
|
188
|
+
function transparent_color() {
|
|
189
|
+
return [0, 0, 0, 0];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// renderer/style.ts
|
|
193
|
+
var line_cap_butt = 0;
|
|
194
|
+
var line_cap_round = 1;
|
|
195
|
+
var line_cap_square = 2;
|
|
196
|
+
var line_join_miter = 0;
|
|
197
|
+
var line_join_round = 1;
|
|
198
|
+
var line_join_bevel = 2;
|
|
199
|
+
function create_draw_style() {
|
|
200
|
+
return {
|
|
201
|
+
fill: null,
|
|
202
|
+
stroke: null,
|
|
203
|
+
stroke_width: 1,
|
|
204
|
+
line_cap: line_cap_round,
|
|
205
|
+
line_join: line_join_round,
|
|
206
|
+
miter_limit: 10,
|
|
207
|
+
alpha: 1
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function clone_draw_style(s) {
|
|
211
|
+
return {
|
|
212
|
+
fill: s.fill,
|
|
213
|
+
stroke: s.stroke,
|
|
214
|
+
stroke_width: s.stroke_width,
|
|
215
|
+
line_cap: s.line_cap,
|
|
216
|
+
line_join: s.line_join,
|
|
217
|
+
miter_limit: s.miter_limit,
|
|
218
|
+
alpha: s.alpha
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function copy_draw_style(s, out) {
|
|
222
|
+
const mutable_out = out;
|
|
223
|
+
mutable_out.fill = s.fill;
|
|
224
|
+
mutable_out.stroke = s.stroke;
|
|
225
|
+
mutable_out.stroke_width = s.stroke_width;
|
|
226
|
+
mutable_out.line_cap = s.line_cap;
|
|
227
|
+
mutable_out.line_join = s.line_join;
|
|
228
|
+
mutable_out.miter_limit = s.miter_limit;
|
|
229
|
+
mutable_out.alpha = s.alpha;
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
function set_draw_style(fill, stroke, stroke_width, line_cap, line_join, miter_limit, alpha, out) {
|
|
233
|
+
const mutable_out = out;
|
|
234
|
+
mutable_out.fill = fill;
|
|
235
|
+
mutable_out.stroke = stroke;
|
|
236
|
+
mutable_out.stroke_width = stroke_width;
|
|
237
|
+
mutable_out.line_cap = line_cap;
|
|
238
|
+
mutable_out.line_join = line_join;
|
|
239
|
+
mutable_out.miter_limit = miter_limit;
|
|
240
|
+
mutable_out.alpha = alpha;
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
243
|
+
function with_fill_draw_style(s, fill, out) {
|
|
244
|
+
const mutable_out = out;
|
|
245
|
+
mutable_out.fill = fill;
|
|
246
|
+
mutable_out.stroke = s.stroke;
|
|
247
|
+
mutable_out.stroke_width = s.stroke_width;
|
|
248
|
+
mutable_out.line_cap = s.line_cap;
|
|
249
|
+
mutable_out.line_join = s.line_join;
|
|
250
|
+
mutable_out.miter_limit = s.miter_limit;
|
|
251
|
+
mutable_out.alpha = s.alpha;
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
function with_stroke_draw_style(s, stroke, stroke_width, out) {
|
|
255
|
+
const mutable_out = out;
|
|
256
|
+
mutable_out.fill = s.fill;
|
|
257
|
+
mutable_out.stroke = stroke;
|
|
258
|
+
mutable_out.stroke_width = stroke_width;
|
|
259
|
+
mutable_out.line_cap = s.line_cap;
|
|
260
|
+
mutable_out.line_join = s.line_join;
|
|
261
|
+
mutable_out.miter_limit = s.miter_limit;
|
|
262
|
+
mutable_out.alpha = s.alpha;
|
|
263
|
+
return out;
|
|
264
|
+
}
|
|
265
|
+
function with_alpha_draw_style(s, alpha, out) {
|
|
266
|
+
const mutable_out = out;
|
|
267
|
+
mutable_out.fill = s.fill;
|
|
268
|
+
mutable_out.stroke = s.stroke;
|
|
269
|
+
mutable_out.stroke_width = s.stroke_width;
|
|
270
|
+
mutable_out.line_cap = s.line_cap;
|
|
271
|
+
mutable_out.line_join = s.line_join;
|
|
272
|
+
mutable_out.miter_limit = s.miter_limit;
|
|
273
|
+
mutable_out.alpha = alpha;
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
function with_line_cap_draw_style(s, line_cap, out) {
|
|
277
|
+
const mutable_out = out;
|
|
278
|
+
mutable_out.fill = s.fill;
|
|
279
|
+
mutable_out.stroke = s.stroke;
|
|
280
|
+
mutable_out.stroke_width = s.stroke_width;
|
|
281
|
+
mutable_out.line_cap = line_cap;
|
|
282
|
+
mutable_out.line_join = s.line_join;
|
|
283
|
+
mutable_out.miter_limit = s.miter_limit;
|
|
284
|
+
mutable_out.alpha = s.alpha;
|
|
285
|
+
return out;
|
|
286
|
+
}
|
|
287
|
+
function with_line_join_draw_style(s, line_join, miter_limit, out) {
|
|
288
|
+
const mutable_out = out;
|
|
289
|
+
mutable_out.fill = s.fill;
|
|
290
|
+
mutable_out.stroke = s.stroke;
|
|
291
|
+
mutable_out.stroke_width = s.stroke_width;
|
|
292
|
+
mutable_out.line_cap = s.line_cap;
|
|
293
|
+
mutable_out.line_join = line_join;
|
|
294
|
+
mutable_out.miter_limit = miter_limit;
|
|
295
|
+
mutable_out.alpha = s.alpha;
|
|
296
|
+
return out;
|
|
297
|
+
}
|
|
298
|
+
function equals_draw_style(a, b) {
|
|
299
|
+
const fill_equal = a.fill === null && b.fill === null || a.fill !== null && b.fill !== null && equals_color(a.fill, b.fill);
|
|
300
|
+
const stroke_equal = a.stroke === null && b.stroke === null || a.stroke !== null && b.stroke !== null && equals_color(a.stroke, b.stroke);
|
|
301
|
+
return fill_equal && stroke_equal && a.stroke_width === b.stroke_width && a.line_cap === b.line_cap && a.line_join === b.line_join && a.miter_limit === b.miter_limit && a.alpha === b.alpha;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// stroke/live.ts
|
|
305
|
+
var live_stroke_counter = 0;
|
|
306
|
+
function generate_stroke_id() {
|
|
307
|
+
live_stroke_counter = live_stroke_counter + 1;
|
|
308
|
+
return `stroke_${Date.now()}_${live_stroke_counter}`;
|
|
309
|
+
}
|
|
310
|
+
function create_live_stroke(style, id) {
|
|
311
|
+
return {
|
|
312
|
+
id: id ?? generate_stroke_id(),
|
|
313
|
+
points: [],
|
|
314
|
+
style: clone_stroke_style(style),
|
|
315
|
+
stabilizer_state: create_stabilizer()
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function add_point_live_stroke(live, position, pressure = 0.5, timestamp = Date.now()) {
|
|
319
|
+
const next_stabilizer_state = {
|
|
320
|
+
...live.stabilizer_state,
|
|
321
|
+
history: live.stabilizer_state.history.map((p) => [p[0], p[1]])
|
|
322
|
+
};
|
|
323
|
+
const stabilized = [0, 0];
|
|
324
|
+
stabilize_point(next_stabilizer_state, position, stabilized);
|
|
325
|
+
return add_point_to_live_stroke_internal(live, stabilized, pressure, timestamp, next_stabilizer_state);
|
|
326
|
+
}
|
|
327
|
+
function add_raw_point_live_stroke(live, raw_position, pressure = 0.5, timestamp = Date.now()) {
|
|
328
|
+
return add_point_to_live_stroke_internal(live, raw_position, pressure, timestamp);
|
|
329
|
+
}
|
|
330
|
+
function add_point_to_live_stroke_internal(live, position, pressure, timestamp, next_stabilizer_state) {
|
|
331
|
+
const point = {
|
|
332
|
+
position: [position[0], position[1]],
|
|
333
|
+
pressure,
|
|
334
|
+
timestamp
|
|
335
|
+
};
|
|
336
|
+
return {
|
|
337
|
+
...live,
|
|
338
|
+
points: [...live.points, point],
|
|
339
|
+
stabilizer_state: next_stabilizer_state ?? {
|
|
340
|
+
...live.stabilizer_state,
|
|
341
|
+
history: live.stabilizer_state.history.map((p) => [p[0], p[1]])
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function get_points_from_live_stroke(live) {
|
|
346
|
+
return live.points.map((p) => p.position);
|
|
347
|
+
}
|
|
348
|
+
function get_pressure_from_live_stroke(live) {
|
|
349
|
+
if (live.points.length === 0)
|
|
350
|
+
return null;
|
|
351
|
+
return live.points.map((p) => p.pressure);
|
|
352
|
+
}
|
|
353
|
+
function render_live_stroke(live, renderer) {
|
|
354
|
+
if (live.points.length < 2) {
|
|
355
|
+
if (live.points.length === 1) {
|
|
356
|
+
const point = live.points[0];
|
|
357
|
+
const radius = live.style.width * (0.5 + point.pressure * live.style.pressure_sensitivity * 0.5);
|
|
358
|
+
renderer.draw_circle([point.position[0], point.position[1], radius], create_live_style(live.style, true));
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const points = get_points_from_live_stroke(live);
|
|
363
|
+
const style = create_live_style(live.style, false);
|
|
364
|
+
renderer.draw_polyline(points, style);
|
|
365
|
+
}
|
|
366
|
+
function create_live_style(style, is_dot) {
|
|
367
|
+
return {
|
|
368
|
+
fill: is_dot ? style.color : null,
|
|
369
|
+
stroke: style.color,
|
|
370
|
+
stroke_width: style.width,
|
|
371
|
+
line_cap: line_cap_round,
|
|
372
|
+
line_join: line_join_round,
|
|
373
|
+
miter_limit: 10,
|
|
374
|
+
alpha: style.opacity
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function finalize_live_stroke(live, z_index, layer_id) {
|
|
378
|
+
const points = get_points_from_live_stroke(live);
|
|
379
|
+
const pressure = get_pressure_from_live_stroke(live);
|
|
380
|
+
return {
|
|
381
|
+
id: live.id,
|
|
382
|
+
points,
|
|
383
|
+
pressure,
|
|
384
|
+
style: live.style,
|
|
385
|
+
z_index,
|
|
386
|
+
layer_id
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
// math/simplify.ts
|
|
390
|
+
function create_simplify_result() {
|
|
391
|
+
return {
|
|
392
|
+
points: [],
|
|
393
|
+
original_count: 0,
|
|
394
|
+
simplified_count: 0,
|
|
395
|
+
reduction_ratio: 0
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function clone_simplify_result(result) {
|
|
399
|
+
return {
|
|
400
|
+
points: result.points.map((point) => [point[0], point[1]]),
|
|
401
|
+
original_count: result.original_count,
|
|
402
|
+
simplified_count: result.simplified_count,
|
|
403
|
+
reduction_ratio: result.reduction_ratio
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function copy_simplify_result(result, out) {
|
|
407
|
+
out.points = result.points.map((point) => [point[0], point[1]]);
|
|
408
|
+
out.original_count = result.original_count;
|
|
409
|
+
out.simplified_count = result.simplified_count;
|
|
410
|
+
out.reduction_ratio = result.reduction_ratio;
|
|
411
|
+
return out;
|
|
412
|
+
}
|
|
413
|
+
function perpendicular_distance_to_line(point, line_start, line_end) {
|
|
414
|
+
const dx = line_end[0] - line_start[0];
|
|
415
|
+
const dy = line_end[1] - line_start[1];
|
|
416
|
+
if (dx === 0 && dy === 0) {
|
|
417
|
+
const px = point[0] - line_start[0];
|
|
418
|
+
const py = point[1] - line_start[1];
|
|
419
|
+
return Math.sqrt(px * px + py * py);
|
|
420
|
+
}
|
|
421
|
+
const numerator = Math.abs(dy * point[0] - dx * point[1] + line_end[0] * line_start[1] - line_end[1] * line_start[0]);
|
|
422
|
+
const denominator = Math.sqrt(dx * dx + dy * dy);
|
|
423
|
+
return numerator / denominator;
|
|
424
|
+
}
|
|
425
|
+
function find_farthest_point(points, start_index, end_index, out_result) {
|
|
426
|
+
let max_distance = 0;
|
|
427
|
+
let farthest_index = -1;
|
|
428
|
+
const line_start = points[start_index];
|
|
429
|
+
const line_end = points[end_index];
|
|
430
|
+
for (let i = start_index + 1;i < end_index; i++) {
|
|
431
|
+
const distance = perpendicular_distance_to_line(points[i], line_start, line_end);
|
|
432
|
+
if (distance > max_distance) {
|
|
433
|
+
max_distance = distance;
|
|
434
|
+
farthest_index = i;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
out_result.index = farthest_index;
|
|
438
|
+
out_result.distance = max_distance;
|
|
439
|
+
return out_result;
|
|
440
|
+
}
|
|
441
|
+
function douglas_peucker_recursive(points, start_index, end_index, epsilon, keep_flags) {
|
|
442
|
+
if (end_index <= start_index + 1) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const farthest_result = { index: -1, distance: 0 };
|
|
446
|
+
find_farthest_point(points, start_index, end_index, farthest_result);
|
|
447
|
+
if (farthest_result.index === -1 || farthest_result.distance <= epsilon) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
keep_flags[farthest_result.index] = true;
|
|
451
|
+
douglas_peucker_recursive(points, start_index, farthest_result.index, epsilon, keep_flags);
|
|
452
|
+
douglas_peucker_recursive(points, farthest_result.index, end_index, epsilon, keep_flags);
|
|
453
|
+
}
|
|
454
|
+
function simplify_douglas_peucker(points, epsilon, out_points) {
|
|
455
|
+
if (points.length <= 2) {
|
|
456
|
+
for (let i = 0;i < points.length; i++) {
|
|
457
|
+
const p = points[i];
|
|
458
|
+
const out = out_points[i];
|
|
459
|
+
if (out) {
|
|
460
|
+
out[0] = p[0];
|
|
461
|
+
out[1] = p[1];
|
|
462
|
+
} else {
|
|
463
|
+
out_points[i] = [p[0], p[1]];
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return points.length;
|
|
467
|
+
}
|
|
468
|
+
const keep_flags = Array.from({ length: points.length }, () => false);
|
|
469
|
+
keep_flags[0] = true;
|
|
470
|
+
keep_flags[points.length - 1] = true;
|
|
471
|
+
douglas_peucker_recursive(points, 0, points.length - 1, epsilon, keep_flags);
|
|
472
|
+
let result_count = 0;
|
|
473
|
+
for (let i = 0;i < points.length; i++) {
|
|
474
|
+
if (keep_flags[i]) {
|
|
475
|
+
const p = points[i];
|
|
476
|
+
const out = out_points[result_count];
|
|
477
|
+
if (out) {
|
|
478
|
+
out[0] = p[0];
|
|
479
|
+
out[1] = p[1];
|
|
480
|
+
} else {
|
|
481
|
+
out_points[result_count] = [p[0], p[1]];
|
|
482
|
+
}
|
|
483
|
+
result_count = result_count + 1;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return result_count;
|
|
487
|
+
}
|
|
488
|
+
function simplify_douglas_peucker_detailed(points, epsilon, out_result) {
|
|
489
|
+
const temp_points = Array.from({ length: points.length }, () => [0, 0]);
|
|
490
|
+
const simplified_count = simplify_douglas_peucker(points, epsilon, temp_points);
|
|
491
|
+
out_result.points = temp_points.slice(0, simplified_count);
|
|
492
|
+
out_result.original_count = points.length;
|
|
493
|
+
out_result.simplified_count = simplified_count;
|
|
494
|
+
out_result.reduction_ratio = points.length > 0 ? (points.length - simplified_count) / points.length : 0;
|
|
495
|
+
return out_result;
|
|
496
|
+
}
|
|
497
|
+
function estimate_epsilon_from_points(points, tolerance_factor = 0.1) {
|
|
498
|
+
if (points.length < 2) {
|
|
499
|
+
return 1;
|
|
500
|
+
}
|
|
501
|
+
let total_distance = 0;
|
|
502
|
+
let segment_count = 0;
|
|
503
|
+
for (let i = 1;i < points.length; i++) {
|
|
504
|
+
const dx = points[i][0] - points[i - 1][0];
|
|
505
|
+
const dy = points[i][1] - points[i - 1][1];
|
|
506
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
507
|
+
if (distance > 0) {
|
|
508
|
+
total_distance = total_distance + distance;
|
|
509
|
+
segment_count = segment_count + 1;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (segment_count === 0) {
|
|
513
|
+
return 1;
|
|
514
|
+
}
|
|
515
|
+
const average_distance = total_distance / segment_count;
|
|
516
|
+
return average_distance * tolerance_factor;
|
|
517
|
+
}
|
|
518
|
+
function polyline_length(points) {
|
|
519
|
+
if (points.length < 2) {
|
|
520
|
+
return 0;
|
|
521
|
+
}
|
|
522
|
+
let total_length = 0;
|
|
523
|
+
for (let i = 1;i < points.length; i++) {
|
|
524
|
+
const dx = points[i][0] - points[i - 1][0];
|
|
525
|
+
const dy = points[i][1] - points[i - 1][1];
|
|
526
|
+
total_length = total_length + Math.sqrt(dx * dx + dy * dy);
|
|
527
|
+
}
|
|
528
|
+
return total_length;
|
|
529
|
+
}
|
|
530
|
+
function polyline_area_under_curve(points) {
|
|
531
|
+
if (points.length < 2) {
|
|
532
|
+
return 0;
|
|
533
|
+
}
|
|
534
|
+
let area = 0;
|
|
535
|
+
for (let i = 1;i < points.length; i++) {
|
|
536
|
+
const x1 = points[i - 1][0];
|
|
537
|
+
const y1 = points[i - 1][1];
|
|
538
|
+
const x2 = points[i][0];
|
|
539
|
+
const y2 = points[i][1];
|
|
540
|
+
area = area + (x2 - x1) * (y1 + y2) * 0.5;
|
|
541
|
+
}
|
|
542
|
+
return Math.abs(area);
|
|
543
|
+
}
|
|
544
|
+
function validate_simplified_polyline(points) {
|
|
545
|
+
if (points.length < 4) {
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
for (let i = 0;i < points.length - 3; i++) {
|
|
549
|
+
for (let j = i + 2;j < points.length - 1; j++) {
|
|
550
|
+
const p1 = points[i];
|
|
551
|
+
const p2 = points[i + 1];
|
|
552
|
+
const p3 = points[j];
|
|
553
|
+
const p4 = points[j + 1];
|
|
554
|
+
if (line_segments_intersect(p1, p2, p3, p4)) {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
function line_segments_intersect(p1, p2, p3, p4) {
|
|
562
|
+
const d1 = direction(p3, p4, p1);
|
|
563
|
+
const d2 = direction(p3, p4, p2);
|
|
564
|
+
const d3 = direction(p1, p2, p3);
|
|
565
|
+
const d4 = direction(p1, p2, p4);
|
|
566
|
+
if ((d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0)) {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
if (d1 === 0 && on_segment(p3, p1, p4))
|
|
570
|
+
return true;
|
|
571
|
+
if (d2 === 0 && on_segment(p3, p2, p4))
|
|
572
|
+
return true;
|
|
573
|
+
if (d3 === 0 && on_segment(p1, p3, p2))
|
|
574
|
+
return true;
|
|
575
|
+
if (d4 === 0 && on_segment(p1, p4, p2))
|
|
576
|
+
return true;
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
function direction(pi, pj, pk) {
|
|
580
|
+
return (pk[0] - pi[0]) * (pj[1] - pi[1]) - (pj[0] - pi[0]) * (pk[1] - pi[1]);
|
|
581
|
+
}
|
|
582
|
+
function on_segment(pi, pj, pk) {
|
|
583
|
+
return Math.min(pi[0], pk[0]) <= pj[0] && pj[0] <= Math.max(pi[0], pk[0]) && Math.min(pi[1], pk[1]) <= pj[1] && pj[1] <= Math.max(pi[1], pk[1]);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// math/spline.ts
|
|
587
|
+
function create_spline() {
|
|
588
|
+
return {
|
|
589
|
+
segments_x: [],
|
|
590
|
+
segments_y: [],
|
|
591
|
+
point_count: 0
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function clone_spline(s) {
|
|
595
|
+
return {
|
|
596
|
+
segments_x: s.segments_x.map((seg) => ({ ...seg })),
|
|
597
|
+
segments_y: s.segments_y.map((seg) => ({ ...seg })),
|
|
598
|
+
point_count: s.point_count
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function build_natural_spline_1d(points, t_values) {
|
|
602
|
+
const n = points.length;
|
|
603
|
+
if (n < 2)
|
|
604
|
+
return [];
|
|
605
|
+
if (n === 2) {
|
|
606
|
+
const slope = (points[1] - points[0]) / (t_values[1] - t_values[0]);
|
|
607
|
+
return [
|
|
608
|
+
{
|
|
609
|
+
a: points[0],
|
|
610
|
+
b: slope,
|
|
611
|
+
c: 0,
|
|
612
|
+
d: 0,
|
|
613
|
+
x_start: t_values[0],
|
|
614
|
+
x_end: t_values[1]
|
|
615
|
+
}
|
|
616
|
+
];
|
|
617
|
+
}
|
|
618
|
+
const h = Array.from({ length: n - 1 }, () => 0);
|
|
619
|
+
for (let i = 0;i < n - 1; i++) {
|
|
620
|
+
h[i] = t_values[i + 1] - t_values[i];
|
|
621
|
+
}
|
|
622
|
+
const alpha = Array.from({ length: n - 1 }, () => 0);
|
|
623
|
+
for (let i = 1;i < n - 1; i++) {
|
|
624
|
+
alpha[i] = 3 / h[i] * (points[i + 1] - points[i]) - 3 / h[i - 1] * (points[i] - points[i - 1]);
|
|
625
|
+
}
|
|
626
|
+
const l = Array.from({ length: n }, () => 0);
|
|
627
|
+
const mu = Array.from({ length: n }, () => 0);
|
|
628
|
+
const z = Array.from({ length: n }, () => 0);
|
|
629
|
+
l[0] = 1;
|
|
630
|
+
mu[0] = 0;
|
|
631
|
+
z[0] = 0;
|
|
632
|
+
for (let i = 1;i < n - 1; i++) {
|
|
633
|
+
l[i] = 2 * (t_values[i + 1] - t_values[i - 1]) - h[i - 1] * mu[i - 1];
|
|
634
|
+
mu[i] = h[i] / l[i];
|
|
635
|
+
z[i] = (alpha[i] - h[i - 1] * z[i - 1]) / l[i];
|
|
636
|
+
}
|
|
637
|
+
l[n - 1] = 1;
|
|
638
|
+
z[n - 1] = 0;
|
|
639
|
+
const c = Array.from({ length: n }, () => 0);
|
|
640
|
+
c[n - 1] = 0;
|
|
641
|
+
for (let j = n - 2;j >= 0; j--) {
|
|
642
|
+
c[j] = z[j] - mu[j] * c[j + 1];
|
|
643
|
+
}
|
|
644
|
+
const segments = [];
|
|
645
|
+
for (let i = 0;i < n - 1; i++) {
|
|
646
|
+
const a = points[i];
|
|
647
|
+
const b = (points[i + 1] - points[i]) / h[i] - h[i] * (c[i + 1] + 2 * c[i]) / 3;
|
|
648
|
+
const d = (c[i + 1] - c[i]) / (3 * h[i]);
|
|
649
|
+
segments.push({
|
|
650
|
+
a,
|
|
651
|
+
b,
|
|
652
|
+
c: c[i],
|
|
653
|
+
d,
|
|
654
|
+
x_start: t_values[i],
|
|
655
|
+
x_end: t_values[i + 1]
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
return segments;
|
|
659
|
+
}
|
|
660
|
+
function build_natural_spline_from_points(points, spline) {
|
|
661
|
+
const n = points.length;
|
|
662
|
+
if (n < 2) {
|
|
663
|
+
spline.segments_x = [];
|
|
664
|
+
spline.segments_y = [];
|
|
665
|
+
spline.point_count = 0;
|
|
666
|
+
return spline;
|
|
667
|
+
}
|
|
668
|
+
const t_values = Array.from({ length: n }, () => 0);
|
|
669
|
+
t_values[0] = 0;
|
|
670
|
+
for (let i = 1;i < n; i++) {
|
|
671
|
+
const dx = points[i][0] - points[i - 1][0];
|
|
672
|
+
const dy = points[i][1] - points[i - 1][1];
|
|
673
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
674
|
+
t_values[i] = t_values[i - 1] + distance;
|
|
675
|
+
}
|
|
676
|
+
const x_coords = points.map((p) => p[0]);
|
|
677
|
+
const y_coords = points.map((p) => p[1]);
|
|
678
|
+
spline.segments_x = build_natural_spline_1d(x_coords, t_values);
|
|
679
|
+
spline.segments_y = build_natural_spline_1d(y_coords, t_values);
|
|
680
|
+
spline.point_count = n;
|
|
681
|
+
return spline;
|
|
682
|
+
}
|
|
683
|
+
function evaluate_spline_segment(segment, t) {
|
|
684
|
+
const dt = t - segment.x_start;
|
|
685
|
+
return segment.a + segment.b * dt + segment.c * dt * dt + segment.d * dt * dt * dt;
|
|
686
|
+
}
|
|
687
|
+
function evaluate_spline_at_t(spline, t, out) {
|
|
688
|
+
if (spline.segments_x.length === 0 || spline.segments_y.length === 0) {
|
|
689
|
+
return null;
|
|
690
|
+
}
|
|
691
|
+
let segment_x = null;
|
|
692
|
+
let segment_y = null;
|
|
693
|
+
for (let i = 0;i < spline.segments_x.length; i++) {
|
|
694
|
+
const seg_x = spline.segments_x[i];
|
|
695
|
+
const seg_y = spline.segments_y[i];
|
|
696
|
+
if (t >= seg_x.x_start && t <= seg_x.x_end) {
|
|
697
|
+
segment_x = seg_x;
|
|
698
|
+
segment_y = seg_y;
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (!segment_x || !segment_y) {
|
|
703
|
+
const last_idx = spline.segments_x.length - 1;
|
|
704
|
+
if (t > spline.segments_x[last_idx].x_end) {
|
|
705
|
+
segment_x = spline.segments_x[last_idx];
|
|
706
|
+
segment_y = spline.segments_y[last_idx];
|
|
707
|
+
t = segment_x.x_end;
|
|
708
|
+
} else {
|
|
709
|
+
segment_x = spline.segments_x[0];
|
|
710
|
+
segment_y = spline.segments_y[0];
|
|
711
|
+
t = segment_x.x_start;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
out[0] = evaluate_spline_segment(segment_x, t);
|
|
715
|
+
out[1] = evaluate_spline_segment(segment_y, t);
|
|
716
|
+
return out;
|
|
717
|
+
}
|
|
718
|
+
function evaluate_spline_at_points(spline, t_values, out_points) {
|
|
719
|
+
let valid_count = 0;
|
|
720
|
+
const temp_point = [0, 0];
|
|
721
|
+
for (let i = 0;i < t_values.length; i++) {
|
|
722
|
+
const t_val = t_values[i];
|
|
723
|
+
if (evaluate_spline_at_t(spline, t_val, temp_point)) {
|
|
724
|
+
out_points[valid_count][0] = temp_point[0];
|
|
725
|
+
out_points[valid_count][1] = temp_point[1];
|
|
726
|
+
valid_count = valid_count + 1;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return valid_count;
|
|
730
|
+
}
|
|
731
|
+
function get_spline_length(spline, steps = 100) {
|
|
732
|
+
if (spline.segments_x.length === 0)
|
|
733
|
+
return 0;
|
|
734
|
+
const first_segment = spline.segments_x[0];
|
|
735
|
+
const last_segment = spline.segments_x[spline.segments_x.length - 1];
|
|
736
|
+
const t_start = first_segment.x_start;
|
|
737
|
+
const t_end = last_segment.x_end;
|
|
738
|
+
const dt = (t_end - t_start) / steps;
|
|
739
|
+
let length = 0;
|
|
740
|
+
const prev = [0, 0];
|
|
741
|
+
const curr = [0, 0];
|
|
742
|
+
evaluate_spline_at_t(spline, t_start, prev);
|
|
743
|
+
for (let i = 1;i <= steps; i++) {
|
|
744
|
+
const t = t_start + i * dt;
|
|
745
|
+
if (evaluate_spline_at_t(spline, t, curr)) {
|
|
746
|
+
const dx = curr[0] - prev[0];
|
|
747
|
+
const dy = curr[1] - prev[1];
|
|
748
|
+
length = length + Math.sqrt(dx * dx + dy * dy);
|
|
749
|
+
prev[0] = curr[0];
|
|
750
|
+
prev[1] = curr[1];
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return length;
|
|
754
|
+
}
|
|
755
|
+
function simplify_points_for_spline(points, tolerance = 1) {
|
|
756
|
+
if (points.length <= 2)
|
|
757
|
+
return [...points];
|
|
758
|
+
const simplified = [points[0]];
|
|
759
|
+
for (let i = 1;i < points.length - 1; i++) {
|
|
760
|
+
const prev = points[i - 1];
|
|
761
|
+
const curr = points[i];
|
|
762
|
+
const next = points[i + 1];
|
|
763
|
+
const dx1 = curr[0] - prev[0];
|
|
764
|
+
const dy1 = curr[1] - prev[1];
|
|
765
|
+
const dx2 = next[0] - curr[0];
|
|
766
|
+
const dy2 = next[1] - curr[1];
|
|
767
|
+
const dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
768
|
+
const dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
769
|
+
if (dist1 < tolerance && dist2 < tolerance) {
|
|
770
|
+
if (dist1 > 0 && dist2 > 0) {
|
|
771
|
+
const dot = (dx1 * dx2 + dy1 * dy2) / (dist1 * dist2);
|
|
772
|
+
if (dot > 0.99) {
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
} else {
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
simplified.push(curr);
|
|
780
|
+
}
|
|
781
|
+
simplified.push(points[points.length - 1]);
|
|
782
|
+
return simplified;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// stroke/process.ts
|
|
786
|
+
var default_simplify_epsilon = 1;
|
|
787
|
+
var default_lod_simplify_factor = 3;
|
|
788
|
+
function simplify_stroke_points(points, epsilon = default_simplify_epsilon, out) {
|
|
789
|
+
return simplify_douglas_peucker(points, epsilon, out);
|
|
790
|
+
}
|
|
791
|
+
function simplify_stroke_points_auto(points, out) {
|
|
792
|
+
const epsilon = estimate_epsilon_from_points(points, 0.1);
|
|
793
|
+
return simplify_douglas_peucker(points, epsilon, out);
|
|
794
|
+
}
|
|
795
|
+
function fit_spline_to_stroke(points, out_spline) {
|
|
796
|
+
if (points.length < 2) {
|
|
797
|
+
out_spline.segments_x = [];
|
|
798
|
+
out_spline.segments_y = [];
|
|
799
|
+
out_spline.point_count = 0;
|
|
800
|
+
return out_spline;
|
|
801
|
+
}
|
|
802
|
+
const simplified_for_spline = simplify_points_for_spline(points, 2);
|
|
803
|
+
return build_natural_spline_from_points(simplified_for_spline, out_spline);
|
|
804
|
+
}
|
|
805
|
+
function compute_stroke_bounds(points, width, out) {
|
|
806
|
+
if (points.length === 0) {
|
|
807
|
+
out[0] = 0;
|
|
808
|
+
out[1] = 0;
|
|
809
|
+
out[2] = 0;
|
|
810
|
+
out[3] = 0;
|
|
811
|
+
return out;
|
|
812
|
+
}
|
|
813
|
+
let min_x = Infinity;
|
|
814
|
+
let min_y = Infinity;
|
|
815
|
+
let max_x = -Infinity;
|
|
816
|
+
let max_y = -Infinity;
|
|
817
|
+
for (let i = 0;i < points.length; i++) {
|
|
818
|
+
const point = points[i];
|
|
819
|
+
if (point === undefined)
|
|
820
|
+
continue;
|
|
821
|
+
min_x = Math.min(min_x, point[0]);
|
|
822
|
+
min_y = Math.min(min_y, point[1]);
|
|
823
|
+
max_x = Math.max(max_x, point[0]);
|
|
824
|
+
max_y = Math.max(max_y, point[1]);
|
|
825
|
+
}
|
|
826
|
+
const half_width = width / 2;
|
|
827
|
+
out[0] = min_x - half_width;
|
|
828
|
+
out[1] = min_y - half_width;
|
|
829
|
+
out[2] = max_x - min_x + width;
|
|
830
|
+
out[3] = max_y - min_y + width;
|
|
831
|
+
return out;
|
|
832
|
+
}
|
|
833
|
+
function process_stroke(points, pressure, style, out_simplified, out_spline) {
|
|
834
|
+
let epsilon = default_simplify_epsilon;
|
|
835
|
+
if (pressure && pressure.length > 1 && style.pressure_sensitivity > 0) {
|
|
836
|
+
const variance = calculate_pressure_variance(pressure);
|
|
837
|
+
epsilon = epsilon / (1 + variance * style.pressure_sensitivity * 2);
|
|
838
|
+
}
|
|
839
|
+
const simplified_count = simplify_stroke_points(points, epsilon, out_simplified);
|
|
840
|
+
const simplified = out_simplified.slice(0, simplified_count);
|
|
841
|
+
fit_spline_to_stroke(simplified, out_spline);
|
|
842
|
+
return {
|
|
843
|
+
simplified,
|
|
844
|
+
spline: out_spline
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function calculate_pressure_variance(pressure) {
|
|
848
|
+
if (pressure.length < 2)
|
|
849
|
+
return 0;
|
|
850
|
+
let sum = 0;
|
|
851
|
+
let sum_sq = 0;
|
|
852
|
+
for (let i = 0;i < pressure.length; i++) {
|
|
853
|
+
const p = pressure[i];
|
|
854
|
+
sum += p;
|
|
855
|
+
sum_sq += p * p;
|
|
856
|
+
}
|
|
857
|
+
const mean = sum / pressure.length;
|
|
858
|
+
return Math.sqrt(Math.max(0, sum_sq / pressure.length - mean * mean));
|
|
859
|
+
}
|
|
860
|
+
function get_simplified_for_lod(points, lod_level, out) {
|
|
861
|
+
const lod_epsilon = default_simplify_epsilon * (lod_level * default_lod_simplify_factor);
|
|
862
|
+
const simplified_count = simplify_douglas_peucker(points, lod_epsilon, out);
|
|
863
|
+
return out.slice(0, simplified_count);
|
|
864
|
+
}
|
|
865
|
+
// stroke/render.ts
|
|
866
|
+
var lod_scratch_buffer = [];
|
|
867
|
+
function ensure_lod_scratch(size) {
|
|
868
|
+
while (lod_scratch_buffer.length < size) {
|
|
869
|
+
lod_scratch_buffer.push([0, 0]);
|
|
870
|
+
}
|
|
871
|
+
return lod_scratch_buffer;
|
|
872
|
+
}
|
|
873
|
+
var lod_high = 1;
|
|
874
|
+
var lod_medium = 0.5;
|
|
875
|
+
var lod_low = 0.25;
|
|
876
|
+
var spline_evaluation_interval_high = 2;
|
|
877
|
+
var spline_evaluation_interval_medium = 4;
|
|
878
|
+
var spline_evaluation_interval_low = 8;
|
|
879
|
+
function select_lod_from_zoom(zoom) {
|
|
880
|
+
if (zoom >= 1.5)
|
|
881
|
+
return lod_high;
|
|
882
|
+
if (zoom >= 0.5)
|
|
883
|
+
return lod_medium;
|
|
884
|
+
return lod_low;
|
|
885
|
+
}
|
|
886
|
+
function get_spline_evaluation_interval(lod) {
|
|
887
|
+
if (lod >= lod_medium)
|
|
888
|
+
return spline_evaluation_interval_high;
|
|
889
|
+
if (lod >= lod_low)
|
|
890
|
+
return spline_evaluation_interval_medium;
|
|
891
|
+
return spline_evaluation_interval_low;
|
|
892
|
+
}
|
|
893
|
+
function stroke_to_path_commands(stroke, lod, out_commands) {
|
|
894
|
+
let command_count = 0;
|
|
895
|
+
if (stroke.points.length === 0)
|
|
896
|
+
return 0;
|
|
897
|
+
if (stroke.points.length === 1) {
|
|
898
|
+
out_commands[command_count++] = 0;
|
|
899
|
+
out_commands[command_count++] = stroke.points[0][0];
|
|
900
|
+
out_commands[command_count++] = stroke.points[0][1];
|
|
901
|
+
return command_count;
|
|
902
|
+
}
|
|
903
|
+
const use_spline = stroke.spline !== null && stroke.spline.point_count >= 2;
|
|
904
|
+
const use_lod = lod < lod_high;
|
|
905
|
+
if (use_spline && !use_lod) {
|
|
906
|
+
const interval = get_spline_evaluation_interval(lod);
|
|
907
|
+
const spline_length = get_spline_length(stroke.spline);
|
|
908
|
+
const first_segment = stroke.spline.segments_x[0];
|
|
909
|
+
const last_segment = stroke.spline.segments_x[stroke.spline.segments_x.length - 1];
|
|
910
|
+
const t_start = first_segment.x_start;
|
|
911
|
+
const t_end = last_segment.x_end;
|
|
912
|
+
const steps = Math.max(2, Math.floor(spline_length / interval));
|
|
913
|
+
const dt = (t_end - t_start) / steps;
|
|
914
|
+
const temp_point = [0, 0];
|
|
915
|
+
for (let i = 0;i <= steps; i++) {
|
|
916
|
+
const t = t_start + i * dt;
|
|
917
|
+
evaluate_spline_at_t(stroke.spline, t, temp_point);
|
|
918
|
+
if (i === 0) {
|
|
919
|
+
out_commands[command_count++] = 0;
|
|
920
|
+
} else {
|
|
921
|
+
out_commands[command_count++] = 1;
|
|
922
|
+
}
|
|
923
|
+
out_commands[command_count++] = temp_point[0];
|
|
924
|
+
out_commands[command_count++] = temp_point[1];
|
|
925
|
+
}
|
|
926
|
+
} else {
|
|
927
|
+
const points_to_use = use_lod ? get_simplified_for_lod(stroke.points, 1 / lod, ensure_lod_scratch(stroke.points.length)) : stroke.points;
|
|
928
|
+
for (let i = 0;i < points_to_use.length; i++) {
|
|
929
|
+
const point = points_to_use[i];
|
|
930
|
+
if (point === undefined)
|
|
931
|
+
continue;
|
|
932
|
+
if (i === 0) {
|
|
933
|
+
out_commands[command_count++] = 0;
|
|
934
|
+
} else {
|
|
935
|
+
out_commands[command_count++] = 1;
|
|
936
|
+
}
|
|
937
|
+
out_commands[command_count++] = point[0];
|
|
938
|
+
out_commands[command_count++] = point[1];
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
return command_count;
|
|
942
|
+
}
|
|
943
|
+
function render_stroke(stroke, renderer, zoom = 1) {
|
|
944
|
+
if (stroke.points.length === 0)
|
|
945
|
+
return;
|
|
946
|
+
const lod = select_lod_from_zoom(zoom);
|
|
947
|
+
const style = create_stroke_draw_style(stroke.style);
|
|
948
|
+
if (stroke.points.length === 1) {
|
|
949
|
+
const point = stroke.points[0];
|
|
950
|
+
const radius = stroke.style.width / 2;
|
|
951
|
+
renderer.draw_circle([point[0], point[1], radius], style);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const use_spline = stroke.spline !== null && stroke.spline.point_count >= 2;
|
|
955
|
+
const use_lod = lod < lod_high;
|
|
956
|
+
if (use_spline && !use_lod) {
|
|
957
|
+
const interval = get_spline_evaluation_interval(lod);
|
|
958
|
+
const spline_length = get_spline_length(stroke.spline);
|
|
959
|
+
const first_segment = stroke.spline.segments_x[0];
|
|
960
|
+
const last_segment = stroke.spline.segments_x[stroke.spline.segments_x.length - 1];
|
|
961
|
+
const t_start = first_segment.x_start;
|
|
962
|
+
const t_end = last_segment.x_end;
|
|
963
|
+
const steps = Math.max(2, Math.floor(spline_length / interval));
|
|
964
|
+
const dt = (t_end - t_start) / steps;
|
|
965
|
+
const temp_point = [0, 0];
|
|
966
|
+
const points = ensure_lod_scratch(steps + 1);
|
|
967
|
+
for (let i = 0;i <= steps; i++) {
|
|
968
|
+
const t = t_start + i * dt;
|
|
969
|
+
evaluate_spline_at_t(stroke.spline, t, temp_point);
|
|
970
|
+
const p = points[i];
|
|
971
|
+
p[0] = temp_point[0];
|
|
972
|
+
p[1] = temp_point[1];
|
|
973
|
+
}
|
|
974
|
+
renderer.draw_polyline(points.slice(0, steps + 1), style);
|
|
975
|
+
} else {
|
|
976
|
+
const points_to_use = use_lod ? get_simplified_for_lod(stroke.points, 1 / lod, ensure_lod_scratch(stroke.points.length)) : stroke.points;
|
|
977
|
+
renderer.draw_polyline(points_to_use, style);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
function create_stroke_draw_style(style) {
|
|
981
|
+
return {
|
|
982
|
+
fill: null,
|
|
983
|
+
stroke: style.color,
|
|
984
|
+
stroke_width: style.width,
|
|
985
|
+
line_cap: line_cap_round,
|
|
986
|
+
line_join: line_join_round,
|
|
987
|
+
miter_limit: 10,
|
|
988
|
+
alpha: style.opacity
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
function render_stroke_with_pressure(stroke, renderer, _zoom = 1) {
|
|
992
|
+
if (stroke.points.length < 2 || stroke.pressure === null) {
|
|
993
|
+
render_stroke(stroke, renderer, _zoom);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
const points = stroke.points;
|
|
997
|
+
const pressure = stroke.pressure;
|
|
998
|
+
const base_style = create_stroke_draw_style(stroke.style);
|
|
999
|
+
const base_width = stroke.style.width;
|
|
1000
|
+
const sensitivity = stroke.style.pressure_sensitivity;
|
|
1001
|
+
for (let i = 0;i < points.length - 1; i++) {
|
|
1002
|
+
const p1 = points[i];
|
|
1003
|
+
const p2 = points[i + 1];
|
|
1004
|
+
const pr1 = pressure[i] ?? 0.5;
|
|
1005
|
+
const pr2 = pressure[i + 1] ?? pr1;
|
|
1006
|
+
const avg_pressure = (pr1 + pr2) / 2;
|
|
1007
|
+
const width = base_width * (1 + avg_pressure * sensitivity);
|
|
1008
|
+
renderer.draw_line(p1, p2, { ...base_style, stroke_width: width });
|
|
1009
|
+
}
|
|
1010
|
+
}
|