@invinite-org/chartlang-adapter-kit 1.2.1 → 1.4.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/CHANGELOG.md +157 -0
- package/README.md +7 -0
- package/dist/canvas/index.d.ts +5 -0
- package/dist/canvas/index.d.ts.map +1 -0
- package/dist/canvas/index.js +5 -0
- package/dist/canvas/index.js.map +1 -0
- package/dist/canvas/mockContext.d.ts +168 -0
- package/dist/canvas/mockContext.d.ts.map +1 -0
- package/dist/canvas/mockContext.js +198 -0
- package/dist/canvas/mockContext.js.map +1 -0
- package/dist/canvas/paintPrimitive.d.ts +35 -0
- package/dist/canvas/paintPrimitive.d.ts.map +1 -0
- package/dist/canvas/paintPrimitive.js +171 -0
- package/dist/canvas/paintPrimitive.js.map +1 -0
- package/dist/canvas/renderCtx.d.ts +40 -0
- package/dist/canvas/renderCtx.d.ts.map +1 -0
- package/dist/canvas/renderCtx.js +4 -0
- package/dist/canvas/renderCtx.js.map +1 -0
- package/dist/capabilities/capabilities.d.ts +9 -7
- package/dist/capabilities/capabilities.d.ts.map +1 -1
- package/dist/capabilities/capabilities.js +14 -8
- package/dist/capabilities/capabilities.js.map +1 -1
- package/dist/geometry/_lib/arrowhead.d.ts +18 -0
- package/dist/geometry/_lib/arrowhead.d.ts.map +1 -0
- package/dist/geometry/_lib/arrowhead.js +38 -0
- package/dist/geometry/_lib/arrowhead.js.map +1 -0
- package/dist/geometry/_lib/bezier.d.ts +57 -0
- package/dist/geometry/_lib/bezier.d.ts.map +1 -0
- package/dist/geometry/_lib/bezier.js +84 -0
- package/dist/geometry/_lib/bezier.js.map +1 -0
- package/dist/geometry/_lib/chevron.d.ts +29 -0
- package/dist/geometry/_lib/chevron.d.ts.map +1 -0
- package/dist/geometry/_lib/chevron.js +37 -0
- package/dist/geometry/_lib/chevron.js.map +1 -0
- package/dist/geometry/_lib/dash.d.ts +30 -0
- package/dist/geometry/_lib/dash.d.ts.map +1 -0
- package/dist/geometry/_lib/dash.js +40 -0
- package/dist/geometry/_lib/dash.js.map +1 -0
- package/dist/geometry/_lib/fibLevels.d.ts +36 -0
- package/dist/geometry/_lib/fibLevels.d.ts.map +1 -0
- package/dist/geometry/_lib/fibLevels.js +44 -0
- package/dist/geometry/_lib/fibLevels.js.map +1 -0
- package/dist/geometry/_lib/gannLevels.d.ts +54 -0
- package/dist/geometry/_lib/gannLevels.d.ts.map +1 -0
- package/dist/geometry/_lib/gannLevels.js +88 -0
- package/dist/geometry/_lib/gannLevels.js.map +1 -0
- package/dist/geometry/_lib/lineExtend.d.ts +31 -0
- package/dist/geometry/_lib/lineExtend.d.ts.map +1 -0
- package/dist/geometry/_lib/lineExtend.js +48 -0
- package/dist/geometry/_lib/lineExtend.js.map +1 -0
- package/dist/geometry/_lib/namedPolyline.d.ts +25 -0
- package/dist/geometry/_lib/namedPolyline.d.ts.map +1 -0
- package/dist/geometry/_lib/namedPolyline.js +64 -0
- package/dist/geometry/_lib/namedPolyline.js.map +1 -0
- package/dist/geometry/_lib/pitchforkGeom.d.ts +46 -0
- package/dist/geometry/_lib/pitchforkGeom.d.ts.map +1 -0
- package/dist/geometry/_lib/pitchforkGeom.js +70 -0
- package/dist/geometry/_lib/pitchforkGeom.js.map +1 -0
- package/dist/geometry/_lib/shapeStyle.d.ts +21 -0
- package/dist/geometry/_lib/shapeStyle.d.ts.map +1 -0
- package/dist/geometry/_lib/shapeStyle.js +41 -0
- package/dist/geometry/_lib/shapeStyle.js.map +1 -0
- package/dist/geometry/_lib/strokeStyle.d.ts +34 -0
- package/dist/geometry/_lib/strokeStyle.d.ts.map +1 -0
- package/dist/geometry/_lib/strokeStyle.js +26 -0
- package/dist/geometry/_lib/strokeStyle.js.map +1 -0
- package/dist/geometry/_lib/textStyle.d.ts +70 -0
- package/dist/geometry/_lib/textStyle.d.ts.map +1 -0
- package/dist/geometry/_lib/textStyle.js +78 -0
- package/dist/geometry/_lib/textStyle.js.map +1 -0
- package/dist/geometry/decompose.d.ts +28 -0
- package/dist/geometry/decompose.d.ts.map +1 -0
- package/dist/geometry/decompose.js +176 -0
- package/dist/geometry/decompose.js.map +1 -0
- package/dist/geometry/index.d.ts +4 -0
- package/dist/geometry/index.d.ts.map +1 -0
- package/dist/geometry/index.js +5 -0
- package/dist/geometry/index.js.map +1 -0
- package/dist/geometry/kinds/annotations.d.ts +77 -0
- package/dist/geometry/kinds/annotations.d.ts.map +1 -0
- package/dist/geometry/kinds/annotations.js +219 -0
- package/dist/geometry/kinds/annotations.js.map +1 -0
- package/dist/geometry/kinds/boxes.d.ts +116 -0
- package/dist/geometry/kinds/boxes.d.ts.map +1 -0
- package/dist/geometry/kinds/boxes.js +285 -0
- package/dist/geometry/kinds/boxes.js.map +1 -0
- package/dist/geometry/kinds/channels.d.ts +72 -0
- package/dist/geometry/kinds/channels.d.ts.map +1 -0
- package/dist/geometry/kinds/channels.js +148 -0
- package/dist/geometry/kinds/channels.js.map +1 -0
- package/dist/geometry/kinds/containers.d.ts +54 -0
- package/dist/geometry/kinds/containers.d.ts.map +1 -0
- package/dist/geometry/kinds/containers.js +268 -0
- package/dist/geometry/kinds/containers.js.map +1 -0
- package/dist/geometry/kinds/curves.d.ts +53 -0
- package/dist/geometry/kinds/curves.d.ts.map +1 -0
- package/dist/geometry/kinds/curves.js +110 -0
- package/dist/geometry/kinds/curves.js.map +1 -0
- package/dist/geometry/kinds/cycles.d.ts +52 -0
- package/dist/geometry/kinds/cycles.d.ts.map +1 -0
- package/dist/geometry/kinds/cycles.js +158 -0
- package/dist/geometry/kinds/cycles.js.map +1 -0
- package/dist/geometry/kinds/elliott.d.ts +73 -0
- package/dist/geometry/kinds/elliott.d.ts.map +1 -0
- package/dist/geometry/kinds/elliott.js +116 -0
- package/dist/geometry/kinds/elliott.js.map +1 -0
- package/dist/geometry/kinds/fibonacci.d.ts +166 -0
- package/dist/geometry/kinds/fibonacci.d.ts.map +1 -0
- package/dist/geometry/kinds/fibonacci.js +458 -0
- package/dist/geometry/kinds/fibonacci.js.map +1 -0
- package/dist/geometry/kinds/freehand.d.ts +53 -0
- package/dist/geometry/kinds/freehand.d.ts.map +1 -0
- package/dist/geometry/kinds/freehand.js +115 -0
- package/dist/geometry/kinds/freehand.js.map +1 -0
- package/dist/geometry/kinds/gann.d.ts +63 -0
- package/dist/geometry/kinds/gann.d.ts.map +1 -0
- package/dist/geometry/kinds/gann.js +153 -0
- package/dist/geometry/kinds/gann.js.map +1 -0
- package/dist/geometry/kinds/lines.d.ts +90 -0
- package/dist/geometry/kinds/lines.d.ts.map +1 -0
- package/dist/geometry/kinds/lines.js +201 -0
- package/dist/geometry/kinds/lines.js.map +1 -0
- package/dist/geometry/kinds/marker.d.ts +21 -0
- package/dist/geometry/kinds/marker.d.ts.map +1 -0
- package/dist/geometry/kinds/marker.js +47 -0
- package/dist/geometry/kinds/marker.js.map +1 -0
- package/dist/geometry/kinds/patterns.d.ts +85 -0
- package/dist/geometry/kinds/patterns.d.ts.map +1 -0
- package/dist/geometry/kinds/patterns.js +133 -0
- package/dist/geometry/kinds/patterns.js.map +1 -0
- package/dist/geometry/kinds/pitchforks.d.ts +36 -0
- package/dist/geometry/kinds/pitchforks.d.ts.map +1 -0
- package/dist/geometry/kinds/pitchforks.js +109 -0
- package/dist/geometry/kinds/pitchforks.js.map +1 -0
- package/dist/geometry/project.d.ts +50 -0
- package/dist/geometry/project.d.ts.map +1 -0
- package/dist/geometry/project.js +62 -0
- package/dist/geometry/project.js.map +1 -0
- package/dist/geometry/types.d.ts +146 -0
- package/dist/geometry/types.d.ts.map +1 -0
- package/dist/geometry/types.js +4 -0
- package/dist/geometry/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validation/validateEmission.d.ts.map +1 -1
- package/dist/validation/validateEmission.js +47 -0
- package/dist/validation/validateEmission.js.map +1 -1
- package/package.json +9 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { CircleState, EllipseState, FillBetweenState, PathState, PolylineState, RectangleState, RotatedRectangleState, TriangleState } from "@invinite-org/chartlang-core";
|
|
2
|
+
import type { DrawPrimitive, Viewport } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Decompose a `rectangle` drawing — a closed 4-corner polygon derived
|
|
5
|
+
* from the axis-aligned bounding box of the two projected anchors.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.3
|
|
8
|
+
* @stable
|
|
9
|
+
* @example
|
|
10
|
+
* declare const s: RectangleState;
|
|
11
|
+
* declare const v: Viewport;
|
|
12
|
+
* const prims = decomposeRectangle(s, v);
|
|
13
|
+
* // prims[0].kind === "polyline"; prims[0].closed === true
|
|
14
|
+
* void prims;
|
|
15
|
+
*/
|
|
16
|
+
export declare function decomposeRectangle(state: RectangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
17
|
+
/**
|
|
18
|
+
* Decompose a `rotated-rectangle` drawing — a closed polygon through
|
|
19
|
+
* the four projected anchors (carried in stroke order, so no matrix
|
|
20
|
+
* math is needed).
|
|
21
|
+
*
|
|
22
|
+
* @since 1.3
|
|
23
|
+
* @stable
|
|
24
|
+
* @example
|
|
25
|
+
* declare const s: RotatedRectangleState;
|
|
26
|
+
* declare const v: Viewport;
|
|
27
|
+
* const prims = decomposeRotatedRectangle(s, v);
|
|
28
|
+
* void prims;
|
|
29
|
+
*/
|
|
30
|
+
export declare function decomposeRotatedRectangle(state: RotatedRectangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
31
|
+
/**
|
|
32
|
+
* Decompose a `triangle` drawing — a closed 3-vertex polygon.
|
|
33
|
+
*
|
|
34
|
+
* @since 1.3
|
|
35
|
+
* @stable
|
|
36
|
+
* @example
|
|
37
|
+
* declare const s: TriangleState;
|
|
38
|
+
* declare const v: Viewport;
|
|
39
|
+
* const prims = decomposeTriangle(s, v);
|
|
40
|
+
* void prims;
|
|
41
|
+
*/
|
|
42
|
+
export declare function decomposeTriangle(state: TriangleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
43
|
+
/**
|
|
44
|
+
* Decompose a `polyline` drawing — a closed N-vertex polyline carrying
|
|
45
|
+
* a `LineDrawStyle` (no fill).
|
|
46
|
+
*
|
|
47
|
+
* @since 1.3
|
|
48
|
+
* @stable
|
|
49
|
+
* @example
|
|
50
|
+
* declare const s: PolylineState;
|
|
51
|
+
* declare const v: Viewport;
|
|
52
|
+
* const prims = decomposePolyline(s, v);
|
|
53
|
+
* // prims[0].closed === true
|
|
54
|
+
* void prims;
|
|
55
|
+
*/
|
|
56
|
+
export declare function decomposePolyline(state: PolylineState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
57
|
+
/**
|
|
58
|
+
* Decompose a `circle` drawing — an arc whose radius is the projected
|
|
59
|
+
* pixel distance between the centre anchor and the radius anchor (so
|
|
60
|
+
* the stroke keeps the same apparent thickness across zoom changes).
|
|
61
|
+
*
|
|
62
|
+
* @since 1.3
|
|
63
|
+
* @stable
|
|
64
|
+
* @example
|
|
65
|
+
* declare const s: CircleState;
|
|
66
|
+
* declare const v: Viewport;
|
|
67
|
+
* const prims = decomposeCircle(s, v);
|
|
68
|
+
* // prims[0].kind === "arc"
|
|
69
|
+
* void prims;
|
|
70
|
+
*/
|
|
71
|
+
export declare function decomposeCircle(state: CircleState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
72
|
+
/**
|
|
73
|
+
* Decompose an axis-aligned `ellipse` drawing — a closed
|
|
74
|
+
* {@link ELLIPSE_SEGMENTS}-segment polyline inscribed in the bounding
|
|
75
|
+
* box of the two anchors. Rotated ellipses are out of scope.
|
|
76
|
+
*
|
|
77
|
+
* @since 1.3
|
|
78
|
+
* @stable
|
|
79
|
+
* @example
|
|
80
|
+
* declare const s: EllipseState;
|
|
81
|
+
* declare const v: Viewport;
|
|
82
|
+
* const prims = decomposeEllipse(s, v);
|
|
83
|
+
* void prims;
|
|
84
|
+
*/
|
|
85
|
+
export declare function decomposeEllipse(state: EllipseState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
86
|
+
/**
|
|
87
|
+
* Decompose a `path` drawing — an OPEN N-vertex polyline (unless
|
|
88
|
+
* `style.closed === true`) carrying a `PathOpts` style (no fill).
|
|
89
|
+
*
|
|
90
|
+
* @since 1.3
|
|
91
|
+
* @stable
|
|
92
|
+
* @example
|
|
93
|
+
* declare const s: PathState;
|
|
94
|
+
* declare const v: Viewport;
|
|
95
|
+
* const prims = decomposePath(s, v);
|
|
96
|
+
* void prims;
|
|
97
|
+
*/
|
|
98
|
+
export declare function decomposePath(state: PathState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
99
|
+
/**
|
|
100
|
+
* Decompose a `fill-between` drawing — a closed filled polygon walking
|
|
101
|
+
* `edgeA` forward then `edgeB` in reverse. The optional outline strokes
|
|
102
|
+
* only when `style.color` is set; the band fills only when `style.fill`
|
|
103
|
+
* is set. A degenerate edge (`< 1` point) or a non-finite mapped anchor
|
|
104
|
+
* is a silent no-op (returns `[]`), matching the source renderer's
|
|
105
|
+
* warmup behaviour.
|
|
106
|
+
*
|
|
107
|
+
* @since 1.3
|
|
108
|
+
* @stable
|
|
109
|
+
* @example
|
|
110
|
+
* declare const s: FillBetweenState;
|
|
111
|
+
* declare const v: Viewport;
|
|
112
|
+
* const prims = decomposeFillBetween(s, v);
|
|
113
|
+
* void prims;
|
|
114
|
+
*/
|
|
115
|
+
export declare function decomposeFillBetween(state: FillBetweenState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
116
|
+
//# sourceMappingURL=boxes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boxes.d.ts","sourceRoot":"","sources":["../../../src/geometry/kinds/boxes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACR,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,EAChB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,EAAE,aAAa,EAAU,QAAQ,EAAE,MAAM,aAAa,CAAC;AAcnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAsB9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACrC,KAAK,EAAE,qBAAqB,EAC5B,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAY9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAY9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAc9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,CAkBhG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC5B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAsB9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,CAc5F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CA4B9B"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
|
+
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
//
|
|
4
|
+
// Stroke + fill geometry moved from the canvas2d adapter's per-kind
|
|
5
|
+
// shape renderers
|
|
6
|
+
// examples/canvas2d-adapter/src/render/draw/{rectangle,
|
|
7
|
+
// rotatedRectangle,triangle,polyline,circle,ellipse,path,
|
|
8
|
+
// fillBetween}.ts.
|
|
9
|
+
// The originating math is invinite's rectangle / rotated-rectangle /
|
|
10
|
+
// triangle / polyline / circle / ellipse / path tools (commit
|
|
11
|
+
// 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed
|
|
12
|
+
// MIT for chartlang.
|
|
13
|
+
import { dashPattern } from "../_lib/dash.js";
|
|
14
|
+
import { resolveShapeStyle } from "../_lib/shapeStyle.js";
|
|
15
|
+
import { worldPointToPixel } from "../project.js";
|
|
16
|
+
const DEFAULT_LINE_WIDTH = 1;
|
|
17
|
+
const DEFAULT_FILL_ALPHA = 1;
|
|
18
|
+
const TWO_PI = Math.PI * 2;
|
|
19
|
+
/**
|
|
20
|
+
* Number of polyline segments used to approximate an `ellipse`. 64
|
|
21
|
+
* segments give visually smooth strokes at typical viewport widths
|
|
22
|
+
* (≈800 px) while keeping the primitive list bounded — matching the
|
|
23
|
+
* canvas2d source renderer exactly.
|
|
24
|
+
*/
|
|
25
|
+
const ELLIPSE_SEGMENTS = 64;
|
|
26
|
+
/**
|
|
27
|
+
* Decompose a `rectangle` drawing — a closed 4-corner polygon derived
|
|
28
|
+
* from the axis-aligned bounding box of the two projected anchors.
|
|
29
|
+
*
|
|
30
|
+
* @since 1.3
|
|
31
|
+
* @stable
|
|
32
|
+
* @example
|
|
33
|
+
* declare const s: RectangleState;
|
|
34
|
+
* declare const v: Viewport;
|
|
35
|
+
* const prims = decomposeRectangle(s, v);
|
|
36
|
+
* // prims[0].kind === "polyline"; prims[0].closed === true
|
|
37
|
+
* void prims;
|
|
38
|
+
*/
|
|
39
|
+
export function decomposeRectangle(state, view) {
|
|
40
|
+
const a = worldPointToPixel(state.anchors[0], view);
|
|
41
|
+
const b = worldPointToPixel(state.anchors[1], view);
|
|
42
|
+
const xMin = Math.min(a.x, b.x);
|
|
43
|
+
const xMax = Math.max(a.x, b.x);
|
|
44
|
+
const yMin = Math.min(a.y, b.y);
|
|
45
|
+
const yMax = Math.max(a.y, b.y);
|
|
46
|
+
const { stroke, fill } = resolveShapeStyle(state.style);
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
kind: "polyline",
|
|
50
|
+
points: [
|
|
51
|
+
{ x: xMin, y: yMin },
|
|
52
|
+
{ x: xMax, y: yMin },
|
|
53
|
+
{ x: xMax, y: yMax },
|
|
54
|
+
{ x: xMin, y: yMax },
|
|
55
|
+
],
|
|
56
|
+
closed: true,
|
|
57
|
+
stroke,
|
|
58
|
+
...(fill === undefined ? {} : { fill }),
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decompose a `rotated-rectangle` drawing — a closed polygon through
|
|
64
|
+
* the four projected anchors (carried in stroke order, so no matrix
|
|
65
|
+
* math is needed).
|
|
66
|
+
*
|
|
67
|
+
* @since 1.3
|
|
68
|
+
* @stable
|
|
69
|
+
* @example
|
|
70
|
+
* declare const s: RotatedRectangleState;
|
|
71
|
+
* declare const v: Viewport;
|
|
72
|
+
* const prims = decomposeRotatedRectangle(s, v);
|
|
73
|
+
* void prims;
|
|
74
|
+
*/
|
|
75
|
+
export function decomposeRotatedRectangle(state, view) {
|
|
76
|
+
const points = state.anchors.map((p) => worldPointToPixel(p, view));
|
|
77
|
+
const { stroke, fill } = resolveShapeStyle(state.style);
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
kind: "polyline",
|
|
81
|
+
points,
|
|
82
|
+
closed: true,
|
|
83
|
+
stroke,
|
|
84
|
+
...(fill === undefined ? {} : { fill }),
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decompose a `triangle` drawing — a closed 3-vertex polygon.
|
|
90
|
+
*
|
|
91
|
+
* @since 1.3
|
|
92
|
+
* @stable
|
|
93
|
+
* @example
|
|
94
|
+
* declare const s: TriangleState;
|
|
95
|
+
* declare const v: Viewport;
|
|
96
|
+
* const prims = decomposeTriangle(s, v);
|
|
97
|
+
* void prims;
|
|
98
|
+
*/
|
|
99
|
+
export function decomposeTriangle(state, view) {
|
|
100
|
+
const points = state.anchors.map((p) => worldPointToPixel(p, view));
|
|
101
|
+
const { stroke, fill } = resolveShapeStyle(state.style);
|
|
102
|
+
return [
|
|
103
|
+
{
|
|
104
|
+
kind: "polyline",
|
|
105
|
+
points,
|
|
106
|
+
closed: true,
|
|
107
|
+
stroke,
|
|
108
|
+
...(fill === undefined ? {} : { fill }),
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Decompose a `polyline` drawing — a closed N-vertex polyline carrying
|
|
114
|
+
* a `LineDrawStyle` (no fill).
|
|
115
|
+
*
|
|
116
|
+
* @since 1.3
|
|
117
|
+
* @stable
|
|
118
|
+
* @example
|
|
119
|
+
* declare const s: PolylineState;
|
|
120
|
+
* declare const v: Viewport;
|
|
121
|
+
* const prims = decomposePolyline(s, v);
|
|
122
|
+
* // prims[0].closed === true
|
|
123
|
+
* void prims;
|
|
124
|
+
*/
|
|
125
|
+
export function decomposePolyline(state, view) {
|
|
126
|
+
const points = state.anchors.map((p) => worldPointToPixel(p, view));
|
|
127
|
+
return [
|
|
128
|
+
{
|
|
129
|
+
kind: "polyline",
|
|
130
|
+
points,
|
|
131
|
+
closed: true,
|
|
132
|
+
stroke: {
|
|
133
|
+
color: state.style.color ?? "#000000",
|
|
134
|
+
width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
|
|
135
|
+
dash: dashPattern(state.style.lineStyle ?? "solid"),
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Decompose a `circle` drawing — an arc whose radius is the projected
|
|
142
|
+
* pixel distance between the centre anchor and the radius anchor (so
|
|
143
|
+
* the stroke keeps the same apparent thickness across zoom changes).
|
|
144
|
+
*
|
|
145
|
+
* @since 1.3
|
|
146
|
+
* @stable
|
|
147
|
+
* @example
|
|
148
|
+
* declare const s: CircleState;
|
|
149
|
+
* declare const v: Viewport;
|
|
150
|
+
* const prims = decomposeCircle(s, v);
|
|
151
|
+
* // prims[0].kind === "arc"
|
|
152
|
+
* void prims;
|
|
153
|
+
*/
|
|
154
|
+
export function decomposeCircle(state, view) {
|
|
155
|
+
const centre = worldPointToPixel(state.anchors[0], view);
|
|
156
|
+
const edge = worldPointToPixel(state.anchors[1], view);
|
|
157
|
+
const radius = Math.hypot(edge.x - centre.x, edge.y - centre.y);
|
|
158
|
+
const { stroke, fill } = resolveShapeStyle(state.style);
|
|
159
|
+
return [
|
|
160
|
+
{
|
|
161
|
+
kind: "arc",
|
|
162
|
+
cx: centre.x,
|
|
163
|
+
cy: centre.y,
|
|
164
|
+
r: radius,
|
|
165
|
+
start: 0,
|
|
166
|
+
end: TWO_PI,
|
|
167
|
+
closed: true,
|
|
168
|
+
stroke,
|
|
169
|
+
...(fill === undefined ? {} : { fill }),
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Decompose an axis-aligned `ellipse` drawing — a closed
|
|
175
|
+
* {@link ELLIPSE_SEGMENTS}-segment polyline inscribed in the bounding
|
|
176
|
+
* box of the two anchors. Rotated ellipses are out of scope.
|
|
177
|
+
*
|
|
178
|
+
* @since 1.3
|
|
179
|
+
* @stable
|
|
180
|
+
* @example
|
|
181
|
+
* declare const s: EllipseState;
|
|
182
|
+
* declare const v: Viewport;
|
|
183
|
+
* const prims = decomposeEllipse(s, v);
|
|
184
|
+
* void prims;
|
|
185
|
+
*/
|
|
186
|
+
export function decomposeEllipse(state, view) {
|
|
187
|
+
const a = worldPointToPixel(state.anchors[0], view);
|
|
188
|
+
const b = worldPointToPixel(state.anchors[1], view);
|
|
189
|
+
const cx = (a.x + b.x) / 2;
|
|
190
|
+
const cy = (a.y + b.y) / 2;
|
|
191
|
+
const rx = Math.abs(b.x - a.x) / 2;
|
|
192
|
+
const ry = Math.abs(b.y - a.y) / 2;
|
|
193
|
+
const points = [{ x: cx + rx, y: cy }];
|
|
194
|
+
for (let i = 1; i < ELLIPSE_SEGMENTS; i++) {
|
|
195
|
+
const theta = (i / ELLIPSE_SEGMENTS) * TWO_PI;
|
|
196
|
+
points.push({ x: cx + rx * Math.cos(theta), y: cy + ry * Math.sin(theta) });
|
|
197
|
+
}
|
|
198
|
+
const { stroke, fill } = resolveShapeStyle(state.style);
|
|
199
|
+
return [
|
|
200
|
+
{
|
|
201
|
+
kind: "polyline",
|
|
202
|
+
points,
|
|
203
|
+
closed: true,
|
|
204
|
+
stroke,
|
|
205
|
+
...(fill === undefined ? {} : { fill }),
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Decompose a `path` drawing — an OPEN N-vertex polyline (unless
|
|
211
|
+
* `style.closed === true`) carrying a `PathOpts` style (no fill).
|
|
212
|
+
*
|
|
213
|
+
* @since 1.3
|
|
214
|
+
* @stable
|
|
215
|
+
* @example
|
|
216
|
+
* declare const s: PathState;
|
|
217
|
+
* declare const v: Viewport;
|
|
218
|
+
* const prims = decomposePath(s, v);
|
|
219
|
+
* void prims;
|
|
220
|
+
*/
|
|
221
|
+
export function decomposePath(state, view) {
|
|
222
|
+
const points = state.anchors.map((p) => worldPointToPixel(p, view));
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
kind: "polyline",
|
|
226
|
+
points,
|
|
227
|
+
closed: state.style.closed === true,
|
|
228
|
+
stroke: {
|
|
229
|
+
color: state.style.color ?? "#000000",
|
|
230
|
+
width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
|
|
231
|
+
dash: dashPattern(state.style.lineStyle ?? "solid"),
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Decompose a `fill-between` drawing — a closed filled polygon walking
|
|
238
|
+
* `edgeA` forward then `edgeB` in reverse. The optional outline strokes
|
|
239
|
+
* only when `style.color` is set; the band fills only when `style.fill`
|
|
240
|
+
* is set. A degenerate edge (`< 1` point) or a non-finite mapped anchor
|
|
241
|
+
* is a silent no-op (returns `[]`), matching the source renderer's
|
|
242
|
+
* warmup behaviour.
|
|
243
|
+
*
|
|
244
|
+
* @since 1.3
|
|
245
|
+
* @stable
|
|
246
|
+
* @example
|
|
247
|
+
* declare const s: FillBetweenState;
|
|
248
|
+
* declare const v: Viewport;
|
|
249
|
+
* const prims = decomposeFillBetween(s, v);
|
|
250
|
+
* void prims;
|
|
251
|
+
*/
|
|
252
|
+
export function decomposeFillBetween(state, view) {
|
|
253
|
+
const a = state.edgeA.map((p) => worldPointToPixel(p, view));
|
|
254
|
+
const b = state.edgeB.map((p) => worldPointToPixel(p, view));
|
|
255
|
+
if (a.length < 1 || b.length < 1)
|
|
256
|
+
return [];
|
|
257
|
+
if (a.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y)))
|
|
258
|
+
return [];
|
|
259
|
+
if (b.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y)))
|
|
260
|
+
return [];
|
|
261
|
+
const points = [...a];
|
|
262
|
+
for (let i = b.length - 1; i >= 0; i--)
|
|
263
|
+
points.push(b[i]);
|
|
264
|
+
const { color, fill } = state.style;
|
|
265
|
+
return [
|
|
266
|
+
{
|
|
267
|
+
kind: "polyline",
|
|
268
|
+
points,
|
|
269
|
+
closed: true,
|
|
270
|
+
...(color === undefined
|
|
271
|
+
? {}
|
|
272
|
+
: {
|
|
273
|
+
stroke: {
|
|
274
|
+
color,
|
|
275
|
+
width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,
|
|
276
|
+
dash: dashPattern(state.style.lineStyle ?? "solid"),
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
...(fill === undefined
|
|
280
|
+
? {}
|
|
281
|
+
: { fill: { color: fill, alpha: state.style.fillAlpha ?? DEFAULT_FILL_ALPHA } }),
|
|
282
|
+
},
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=boxes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boxes.js","sourceRoot":"","sources":["../../../src/geometry/kinds/boxes.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAC/D,EAAE;AACF,oEAAoE;AACpE,kBAAkB;AAClB,0DAA0D;AAC1D,4DAA4D;AAC5D,qBAAqB;AACrB,qEAAqE;AACrE,8DAA8D;AAC9D,qEAAqE;AACrE,qBAAqB;AAarB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAC9B,KAAqB,EACrB,IAAc;IAEd,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE;gBACJ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACpB,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACpB,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;gBACpB,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE;aACvB;YACD,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SAC1C;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,yBAAyB,CACrC,KAA4B,EAC5B,IAAc;IAEd,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SAC1C;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC7B,KAAoB,EACpB,IAAc;IAEd,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SAC1C;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC7B,KAAoB,EACpB,IAAc;IAEd,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS;gBACrC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,kBAAkB;gBAClD,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC;aACtD;SACJ;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB,EAAE,IAAc;IAC9D,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO;QACH;YACI,IAAI,EAAE,KAAK;YACX,EAAE,EAAE,MAAM,CAAC,CAAC;YACZ,EAAE,EAAE,MAAM,CAAC,CAAC;YACZ,CAAC,EAAE,MAAM;YACT,KAAK,EAAE,CAAC;YACR,GAAG,EAAE,MAAM;YACX,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SAC1C;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC5B,KAAmB,EACnB,IAAc;IAEd,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,MAAM,GAAa,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,MAAM,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxD,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SAC1C;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgB,EAAE,IAAc;IAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI;YACnC,MAAM,EAAE;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS;gBACrC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,kBAAkB;gBAClD,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC;aACtD;SACJ;KACJ,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,oBAAoB,CAChC,KAAuB,EACvB,IAAc;IAEd,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7E,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7E,MAAM,MAAM,GAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;IACpC,OAAO;QACH;YACI,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,MAAM,EAAE,IAAI;YACZ,GAAG,CAAC,KAAK,KAAK,SAAS;gBACnB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACI,MAAM,EAAE;wBACJ,KAAK;wBACL,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,kBAAkB;wBAClD,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC;qBACtD;iBACJ,CAAC;YACR,GAAG,CAAC,IAAI,KAAK,SAAS;gBAClB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,IAAI,kBAAkB,EAAE,EAAE,CAAC;SACvF;KACJ,CAAC;AACN,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n//\n// Stroke + fill geometry moved from the canvas2d adapter's per-kind\n// shape renderers\n// examples/canvas2d-adapter/src/render/draw/{rectangle,\n// rotatedRectangle,triangle,polyline,circle,ellipse,path,\n// fillBetween}.ts.\n// The originating math is invinite's rectangle / rotated-rectangle /\n// triangle / polyline / circle / ellipse / path tools (commit\n// 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed\n// MIT for chartlang.\n\nimport type {\n CircleState,\n EllipseState,\n FillBetweenState,\n PathState,\n PolylineState,\n RectangleState,\n RotatedRectangleState,\n TriangleState,\n} from \"@invinite-org/chartlang-core\";\n\nimport { dashPattern } from \"../_lib/dash.js\";\nimport { resolveShapeStyle } from \"../_lib/shapeStyle.js\";\nimport { worldPointToPixel } from \"../project.js\";\nimport type { DrawPrimitive, Point2, Viewport } from \"../types.js\";\n\nconst DEFAULT_LINE_WIDTH = 1;\nconst DEFAULT_FILL_ALPHA = 1;\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Number of polyline segments used to approximate an `ellipse`. 64\n * segments give visually smooth strokes at typical viewport widths\n * (≈800 px) while keeping the primitive list bounded — matching the\n * canvas2d source renderer exactly.\n */\nconst ELLIPSE_SEGMENTS = 64;\n\n/**\n * Decompose a `rectangle` drawing — a closed 4-corner polygon derived\n * from the axis-aligned bounding box of the two projected anchors.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: RectangleState;\n * declare const v: Viewport;\n * const prims = decomposeRectangle(s, v);\n * // prims[0].kind === \"polyline\"; prims[0].closed === true\n * void prims;\n */\nexport function decomposeRectangle(\n state: RectangleState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const a = worldPointToPixel(state.anchors[0], view);\n const b = worldPointToPixel(state.anchors[1], view);\n const xMin = Math.min(a.x, b.x);\n const xMax = Math.max(a.x, b.x);\n const yMin = Math.min(a.y, b.y);\n const yMax = Math.max(a.y, b.y);\n const { stroke, fill } = resolveShapeStyle(state.style);\n return [\n {\n kind: \"polyline\",\n points: [\n { x: xMin, y: yMin },\n { x: xMax, y: yMin },\n { x: xMax, y: yMax },\n { x: xMin, y: yMax },\n ],\n closed: true,\n stroke,\n ...(fill === undefined ? {} : { fill }),\n },\n ];\n}\n\n/**\n * Decompose a `rotated-rectangle` drawing — a closed polygon through\n * the four projected anchors (carried in stroke order, so no matrix\n * math is needed).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: RotatedRectangleState;\n * declare const v: Viewport;\n * const prims = decomposeRotatedRectangle(s, v);\n * void prims;\n */\nexport function decomposeRotatedRectangle(\n state: RotatedRectangleState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const points = state.anchors.map((p) => worldPointToPixel(p, view));\n const { stroke, fill } = resolveShapeStyle(state.style);\n return [\n {\n kind: \"polyline\",\n points,\n closed: true,\n stroke,\n ...(fill === undefined ? {} : { fill }),\n },\n ];\n}\n\n/**\n * Decompose a `triangle` drawing — a closed 3-vertex polygon.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: TriangleState;\n * declare const v: Viewport;\n * const prims = decomposeTriangle(s, v);\n * void prims;\n */\nexport function decomposeTriangle(\n state: TriangleState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const points = state.anchors.map((p) => worldPointToPixel(p, view));\n const { stroke, fill } = resolveShapeStyle(state.style);\n return [\n {\n kind: \"polyline\",\n points,\n closed: true,\n stroke,\n ...(fill === undefined ? {} : { fill }),\n },\n ];\n}\n\n/**\n * Decompose a `polyline` drawing — a closed N-vertex polyline carrying\n * a `LineDrawStyle` (no fill).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: PolylineState;\n * declare const v: Viewport;\n * const prims = decomposePolyline(s, v);\n * // prims[0].closed === true\n * void prims;\n */\nexport function decomposePolyline(\n state: PolylineState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const points = state.anchors.map((p) => worldPointToPixel(p, view));\n return [\n {\n kind: \"polyline\",\n points,\n closed: true,\n stroke: {\n color: state.style.color ?? \"#000000\",\n width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,\n dash: dashPattern(state.style.lineStyle ?? \"solid\"),\n },\n },\n ];\n}\n\n/**\n * Decompose a `circle` drawing — an arc whose radius is the projected\n * pixel distance between the centre anchor and the radius anchor (so\n * the stroke keeps the same apparent thickness across zoom changes).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: CircleState;\n * declare const v: Viewport;\n * const prims = decomposeCircle(s, v);\n * // prims[0].kind === \"arc\"\n * void prims;\n */\nexport function decomposeCircle(state: CircleState, view: Viewport): ReadonlyArray<DrawPrimitive> {\n const centre = worldPointToPixel(state.anchors[0], view);\n const edge = worldPointToPixel(state.anchors[1], view);\n const radius = Math.hypot(edge.x - centre.x, edge.y - centre.y);\n const { stroke, fill } = resolveShapeStyle(state.style);\n return [\n {\n kind: \"arc\",\n cx: centre.x,\n cy: centre.y,\n r: radius,\n start: 0,\n end: TWO_PI,\n closed: true,\n stroke,\n ...(fill === undefined ? {} : { fill }),\n },\n ];\n}\n\n/**\n * Decompose an axis-aligned `ellipse` drawing — a closed\n * {@link ELLIPSE_SEGMENTS}-segment polyline inscribed in the bounding\n * box of the two anchors. Rotated ellipses are out of scope.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: EllipseState;\n * declare const v: Viewport;\n * const prims = decomposeEllipse(s, v);\n * void prims;\n */\nexport function decomposeEllipse(\n state: EllipseState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const a = worldPointToPixel(state.anchors[0], view);\n const b = worldPointToPixel(state.anchors[1], view);\n const cx = (a.x + b.x) / 2;\n const cy = (a.y + b.y) / 2;\n const rx = Math.abs(b.x - a.x) / 2;\n const ry = Math.abs(b.y - a.y) / 2;\n const points: Point2[] = [{ x: cx + rx, y: cy }];\n for (let i = 1; i < ELLIPSE_SEGMENTS; i++) {\n const theta = (i / ELLIPSE_SEGMENTS) * TWO_PI;\n points.push({ x: cx + rx * Math.cos(theta), y: cy + ry * Math.sin(theta) });\n }\n const { stroke, fill } = resolveShapeStyle(state.style);\n return [\n {\n kind: \"polyline\",\n points,\n closed: true,\n stroke,\n ...(fill === undefined ? {} : { fill }),\n },\n ];\n}\n\n/**\n * Decompose a `path` drawing — an OPEN N-vertex polyline (unless\n * `style.closed === true`) carrying a `PathOpts` style (no fill).\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: PathState;\n * declare const v: Viewport;\n * const prims = decomposePath(s, v);\n * void prims;\n */\nexport function decomposePath(state: PathState, view: Viewport): ReadonlyArray<DrawPrimitive> {\n const points = state.anchors.map((p) => worldPointToPixel(p, view));\n return [\n {\n kind: \"polyline\",\n points,\n closed: state.style.closed === true,\n stroke: {\n color: state.style.color ?? \"#000000\",\n width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,\n dash: dashPattern(state.style.lineStyle ?? \"solid\"),\n },\n },\n ];\n}\n\n/**\n * Decompose a `fill-between` drawing — a closed filled polygon walking\n * `edgeA` forward then `edgeB` in reverse. The optional outline strokes\n * only when `style.color` is set; the band fills only when `style.fill`\n * is set. A degenerate edge (`< 1` point) or a non-finite mapped anchor\n * is a silent no-op (returns `[]`), matching the source renderer's\n * warmup behaviour.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const s: FillBetweenState;\n * declare const v: Viewport;\n * const prims = decomposeFillBetween(s, v);\n * void prims;\n */\nexport function decomposeFillBetween(\n state: FillBetweenState,\n view: Viewport,\n): ReadonlyArray<DrawPrimitive> {\n const a = state.edgeA.map((p) => worldPointToPixel(p, view));\n const b = state.edgeB.map((p) => worldPointToPixel(p, view));\n if (a.length < 1 || b.length < 1) return [];\n if (a.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y))) return [];\n if (b.some((p) => !Number.isFinite(p.x) || !Number.isFinite(p.y))) return [];\n const points: Point2[] = [...a];\n for (let i = b.length - 1; i >= 0; i--) points.push(b[i]);\n const { color, fill } = state.style;\n return [\n {\n kind: \"polyline\",\n points,\n closed: true,\n ...(color === undefined\n ? {}\n : {\n stroke: {\n color,\n width: state.style.lineWidth ?? DEFAULT_LINE_WIDTH,\n dash: dashPattern(state.style.lineStyle ?? \"solid\"),\n },\n }),\n ...(fill === undefined\n ? {}\n : { fill: { color: fill, alpha: state.style.fillAlpha ?? DEFAULT_FILL_ALPHA } }),\n },\n ];\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { DisjointChannelState, FlatTopBottomState, RegressionTrendState, TrendChannelState } from "@invinite-org/chartlang-core";
|
|
2
|
+
import type { DrawPrimitive, Viewport } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Decompose a `trend-channel` drawing — two parallel line segments. The
|
|
5
|
+
* primary rail runs `anchors[0]` → `anchors[1]`; the second rail is its
|
|
6
|
+
* translate by the offset vector `anchors[2] − anchors[0]`, keeping the
|
|
7
|
+
* pair strictly parallel. Stroke-only — `LineDrawStyle` carries no fill,
|
|
8
|
+
* so there is no inter-rail band (matching the canvas2d source).
|
|
9
|
+
*
|
|
10
|
+
* @since 1.3
|
|
11
|
+
* @stable
|
|
12
|
+
* @example
|
|
13
|
+
* declare const s: TrendChannelState;
|
|
14
|
+
* declare const v: Viewport;
|
|
15
|
+
* const prims = decomposeTrendChannel(s, v);
|
|
16
|
+
* // prims.length === 2
|
|
17
|
+
* void prims;
|
|
18
|
+
*/
|
|
19
|
+
export declare function decomposeTrendChannel(state: TrendChannelState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
20
|
+
/**
|
|
21
|
+
* Decompose a `flat-top-bottom` drawing — two horizontal rails. The top
|
|
22
|
+
* rail sits at `max(anchors[0].price, anchors[2].price)` and the bottom
|
|
23
|
+
* at `min(...)`; both span the time range `anchors[0].time` →
|
|
24
|
+
* `anchors[1].time`. Stroke-only.
|
|
25
|
+
*
|
|
26
|
+
* @since 1.3
|
|
27
|
+
* @stable
|
|
28
|
+
* @example
|
|
29
|
+
* declare const s: FlatTopBottomState;
|
|
30
|
+
* declare const v: Viewport;
|
|
31
|
+
* const prims = decomposeFlatTopBottom(s, v);
|
|
32
|
+
* // prims.length === 2
|
|
33
|
+
* void prims;
|
|
34
|
+
*/
|
|
35
|
+
export declare function decomposeFlatTopBottom(state: FlatTopBottomState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
36
|
+
/**
|
|
37
|
+
* Decompose a `disjoint-channel` drawing — two independent line segments
|
|
38
|
+
* with no shared geometry constraint: `anchors[0]` → `anchors[1]` and
|
|
39
|
+
* `anchors[2]` → `anchors[3]`. Stroke-only.
|
|
40
|
+
*
|
|
41
|
+
* @since 1.3
|
|
42
|
+
* @stable
|
|
43
|
+
* @example
|
|
44
|
+
* declare const s: DisjointChannelState;
|
|
45
|
+
* declare const v: Viewport;
|
|
46
|
+
* const prims = decomposeDisjointChannel(s, v);
|
|
47
|
+
* // prims.length === 2
|
|
48
|
+
* void prims;
|
|
49
|
+
*/
|
|
50
|
+
export declare function decomposeDisjointChannel(state: DisjointChannelState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
51
|
+
/**
|
|
52
|
+
* Decompose a `regression-trend` drawing — a single placeholder line
|
|
53
|
+
* between the two anchors, colour `style.color ?? "#3b82f6"`, width 1,
|
|
54
|
+
* solid. The OLS fit + ±σ bands the `RegressionTrendOpts` flags
|
|
55
|
+
* (`source` / `stdevMultiplier` / `showUpperBand` / `showLowerBand`)
|
|
56
|
+
* describe require a bar buffer the `Viewport` does not expose and band
|
|
57
|
+
* anchors the 2-point `state.anchors` does not carry; the canvas2d
|
|
58
|
+
* source renders the same placeholder line, so this decomposer preserves
|
|
59
|
+
* that geometry. Those style fields are accepted but unused here —
|
|
60
|
+
* consumer adapters with a bar buffer can compute the fit themselves.
|
|
61
|
+
*
|
|
62
|
+
* @since 1.3
|
|
63
|
+
* @stable
|
|
64
|
+
* @example
|
|
65
|
+
* declare const s: RegressionTrendState;
|
|
66
|
+
* declare const v: Viewport;
|
|
67
|
+
* const prims = decomposeRegressionTrend(s, v);
|
|
68
|
+
* // prims.length === 1; prims[0].kind === "polyline"
|
|
69
|
+
* void prims;
|
|
70
|
+
*/
|
|
71
|
+
export declare function decomposeRegressionTrend(state: RegressionTrendState, view: Viewport): ReadonlyArray<DrawPrimitive>;
|
|
72
|
+
//# sourceMappingURL=channels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/geometry/kinds/channels.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACR,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACpB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAU3D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAmB9B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,kBAAkB,EACzB,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAe9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAU9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,QAAQ,GACf,aAAa,CAAC,aAAa,CAAC,CAe9B"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
|
+
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
//
|
|
4
|
+
// Channel geometry moved from the canvas2d adapter's per-kind renderers
|
|
5
|
+
// examples/canvas2d-adapter/src/render/draw/{trendChannel,
|
|
6
|
+
// flatTopBottom,disjointChannel,regressionTrend}.ts.
|
|
7
|
+
// The originating math is invinite's trend-channel / flat-top-bottom /
|
|
8
|
+
// disjoint-channel / regression-trend tools (commit
|
|
9
|
+
// 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite); re-licensed
|
|
10
|
+
// MIT for chartlang.
|
|
11
|
+
import { dashPattern } from "../_lib/dash.js";
|
|
12
|
+
import { strokeOf } from "../_lib/strokeStyle.js";
|
|
13
|
+
import { worldPointToPixel } from "../project.js";
|
|
14
|
+
const DEFAULT_LINE_WIDTH = 1;
|
|
15
|
+
/**
|
|
16
|
+
* Default stroke colour of a `regression-trend` placeholder line —
|
|
17
|
+
* `#3b82f6`, matching the canvas2d source renderer.
|
|
18
|
+
*/
|
|
19
|
+
const REGRESSION_DEFAULT_COLOR = "#3b82f6";
|
|
20
|
+
/**
|
|
21
|
+
* Decompose a `trend-channel` drawing — two parallel line segments. The
|
|
22
|
+
* primary rail runs `anchors[0]` → `anchors[1]`; the second rail is its
|
|
23
|
+
* translate by the offset vector `anchors[2] − anchors[0]`, keeping the
|
|
24
|
+
* pair strictly parallel. Stroke-only — `LineDrawStyle` carries no fill,
|
|
25
|
+
* so there is no inter-rail band (matching the canvas2d source).
|
|
26
|
+
*
|
|
27
|
+
* @since 1.3
|
|
28
|
+
* @stable
|
|
29
|
+
* @example
|
|
30
|
+
* declare const s: TrendChannelState;
|
|
31
|
+
* declare const v: Viewport;
|
|
32
|
+
* const prims = decomposeTrendChannel(s, v);
|
|
33
|
+
* // prims.length === 2
|
|
34
|
+
* void prims;
|
|
35
|
+
*/
|
|
36
|
+
export function decomposeTrendChannel(state, view) {
|
|
37
|
+
const a = worldPointToPixel(state.anchors[0], view);
|
|
38
|
+
const b = worldPointToPixel(state.anchors[1], view);
|
|
39
|
+
const hook = worldPointToPixel(state.anchors[2], view);
|
|
40
|
+
const dx = hook.x - a.x;
|
|
41
|
+
const dy = hook.y - a.y;
|
|
42
|
+
const stroke = strokeOf(state.style);
|
|
43
|
+
return [
|
|
44
|
+
{ kind: "polyline", points: [a, b], closed: false, stroke },
|
|
45
|
+
{
|
|
46
|
+
kind: "polyline",
|
|
47
|
+
points: [
|
|
48
|
+
{ x: a.x + dx, y: a.y + dy },
|
|
49
|
+
{ x: b.x + dx, y: b.y + dy },
|
|
50
|
+
],
|
|
51
|
+
closed: false,
|
|
52
|
+
stroke,
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Decompose a `flat-top-bottom` drawing — two horizontal rails. The top
|
|
58
|
+
* rail sits at `max(anchors[0].price, anchors[2].price)` and the bottom
|
|
59
|
+
* at `min(...)`; both span the time range `anchors[0].time` →
|
|
60
|
+
* `anchors[1].time`. Stroke-only.
|
|
61
|
+
*
|
|
62
|
+
* @since 1.3
|
|
63
|
+
* @stable
|
|
64
|
+
* @example
|
|
65
|
+
* declare const s: FlatTopBottomState;
|
|
66
|
+
* declare const v: Viewport;
|
|
67
|
+
* const prims = decomposeFlatTopBottom(s, v);
|
|
68
|
+
* // prims.length === 2
|
|
69
|
+
* void prims;
|
|
70
|
+
*/
|
|
71
|
+
export function decomposeFlatTopBottom(state, view) {
|
|
72
|
+
const p0 = state.anchors[0];
|
|
73
|
+
const p1 = state.anchors[1];
|
|
74
|
+
const p2 = state.anchors[2];
|
|
75
|
+
const topPrice = Math.max(p0.price, p2.price);
|
|
76
|
+
const bottomPrice = Math.min(p0.price, p2.price);
|
|
77
|
+
const topLeft = worldPointToPixel({ time: p0.time, price: topPrice }, view);
|
|
78
|
+
const topRight = worldPointToPixel({ time: p1.time, price: topPrice }, view);
|
|
79
|
+
const bottomLeft = worldPointToPixel({ time: p0.time, price: bottomPrice }, view);
|
|
80
|
+
const bottomRight = worldPointToPixel({ time: p1.time, price: bottomPrice }, view);
|
|
81
|
+
const stroke = strokeOf(state.style);
|
|
82
|
+
return [
|
|
83
|
+
{ kind: "polyline", points: [topLeft, topRight], closed: false, stroke },
|
|
84
|
+
{ kind: "polyline", points: [bottomLeft, bottomRight], closed: false, stroke },
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Decompose a `disjoint-channel` drawing — two independent line segments
|
|
89
|
+
* with no shared geometry constraint: `anchors[0]` → `anchors[1]` and
|
|
90
|
+
* `anchors[2]` → `anchors[3]`. Stroke-only.
|
|
91
|
+
*
|
|
92
|
+
* @since 1.3
|
|
93
|
+
* @stable
|
|
94
|
+
* @example
|
|
95
|
+
* declare const s: DisjointChannelState;
|
|
96
|
+
* declare const v: Viewport;
|
|
97
|
+
* const prims = decomposeDisjointChannel(s, v);
|
|
98
|
+
* // prims.length === 2
|
|
99
|
+
* void prims;
|
|
100
|
+
*/
|
|
101
|
+
export function decomposeDisjointChannel(state, view) {
|
|
102
|
+
const a = worldPointToPixel(state.anchors[0], view);
|
|
103
|
+
const b = worldPointToPixel(state.anchors[1], view);
|
|
104
|
+
const c = worldPointToPixel(state.anchors[2], view);
|
|
105
|
+
const d = worldPointToPixel(state.anchors[3], view);
|
|
106
|
+
const stroke = strokeOf(state.style);
|
|
107
|
+
return [
|
|
108
|
+
{ kind: "polyline", points: [a, b], closed: false, stroke },
|
|
109
|
+
{ kind: "polyline", points: [c, d], closed: false, stroke },
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Decompose a `regression-trend` drawing — a single placeholder line
|
|
114
|
+
* between the two anchors, colour `style.color ?? "#3b82f6"`, width 1,
|
|
115
|
+
* solid. The OLS fit + ±σ bands the `RegressionTrendOpts` flags
|
|
116
|
+
* (`source` / `stdevMultiplier` / `showUpperBand` / `showLowerBand`)
|
|
117
|
+
* describe require a bar buffer the `Viewport` does not expose and band
|
|
118
|
+
* anchors the 2-point `state.anchors` does not carry; the canvas2d
|
|
119
|
+
* source renders the same placeholder line, so this decomposer preserves
|
|
120
|
+
* that geometry. Those style fields are accepted but unused here —
|
|
121
|
+
* consumer adapters with a bar buffer can compute the fit themselves.
|
|
122
|
+
*
|
|
123
|
+
* @since 1.3
|
|
124
|
+
* @stable
|
|
125
|
+
* @example
|
|
126
|
+
* declare const s: RegressionTrendState;
|
|
127
|
+
* declare const v: Viewport;
|
|
128
|
+
* const prims = decomposeRegressionTrend(s, v);
|
|
129
|
+
* // prims.length === 1; prims[0].kind === "polyline"
|
|
130
|
+
* void prims;
|
|
131
|
+
*/
|
|
132
|
+
export function decomposeRegressionTrend(state, view) {
|
|
133
|
+
const a = worldPointToPixel(state.anchors[0], view);
|
|
134
|
+
const b = worldPointToPixel(state.anchors[1], view);
|
|
135
|
+
return [
|
|
136
|
+
{
|
|
137
|
+
kind: "polyline",
|
|
138
|
+
points: [a, b],
|
|
139
|
+
closed: false,
|
|
140
|
+
stroke: {
|
|
141
|
+
color: state.style.color ?? REGRESSION_DEFAULT_COLOR,
|
|
142
|
+
width: DEFAULT_LINE_WIDTH,
|
|
143
|
+
dash: dashPattern("solid"),
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=channels.js.map
|