velo-plot 3.0.0 → 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -15
- package/dist/ChartCore-KYG2HTcK.js +7474 -0
- package/dist/ChartCore-KYG2HTcK.js.map +1 -0
- package/dist/GpuChartRenderer-Dxc0hrQA.js +75 -0
- package/dist/GpuChartRenderer-Dxc0hrQA.js.map +1 -0
- package/dist/{index.core-BmZe2jRQ.js → PluginRegistry-CDf_jcnp.js} +19 -33
- package/dist/PluginRegistry-CDf_jcnp.js.map +1 -0
- package/dist/SVGDocumentBuilder-C-uLkcFW.js +83 -0
- package/dist/SVGDocumentBuilder-C-uLkcFW.js.map +1 -0
- package/dist/angular-hooks.js +1 -1
- package/dist/angular.js +8 -8
- package/dist/{axisFormat-CzumxpCL.js → axisFormat-Sz4WIJfQ.js} +2 -2
- package/dist/{axisFormat-CzumxpCL.js.map → axisFormat-Sz4WIJfQ.js.map} +1 -1
- package/dist/{chartSyncBridge-DbWrwtyP.js → chartSyncBridge-C1uRy0ZS.js} +12 -11
- package/dist/{chartSyncBridge-DbWrwtyP.js.map → chartSyncBridge-C1uRy0ZS.js.map} +1 -1
- package/dist/core/ChartStatistics.d.ts +1 -1
- package/dist/core/chart/ChartCore.d.ts +19 -20
- package/dist/core/chart/ChartFeatureHooks.d.ts +7 -0
- package/dist/core/chart/ChartRenderLoop.d.ts +5 -0
- package/dist/core/chart/ChartRenderer.d.ts +9 -0
- package/dist/core/chart/ChartSetup.d.ts +1 -0
- package/dist/core/chart/chartExportPatch.d.ts +2 -0
- package/dist/core/chart/exporter/SVGExporter.d.ts +9 -7
- package/dist/core/chart/exporter/svg/SVGDocumentBuilder.d.ts +27 -0
- package/dist/core/chart/exporter/svg/SVGExportContext.d.ts +147 -0
- package/dist/core/chart/exporter/svg/SVGOrchestrator.d.ts +3 -0
- package/dist/core/chart/exporter/svg/SVGThemeAdapter.d.ts +22 -0
- package/dist/core/chart/exporter/svg/__tests__/testFixtures.d.ts +46 -0
- package/dist/core/chart/exporter/svg/__tests__/visualTestUtils.d.ts +12 -0
- package/dist/core/chart/exporter/svg/overlay/axes.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/border.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/errorBars.d.ts +7 -0
- package/dist/core/chart/exporter/svg/overlay/grid.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/index.d.ts +12 -0
- package/dist/core/chart/exporter/svg/overlay/legend.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/pluginCharts.d.ts +6 -0
- package/dist/core/chart/exporter/svg/overlay/polarGrid.d.ts +4 -0
- package/dist/core/chart/exporter/svg/overlay/specialChart.d.ts +15 -0
- package/dist/core/chart/exporter/svg/overlay/title.d.ts +4 -0
- package/dist/core/chart/exporter/svg/plugins/annotations.d.ts +5 -0
- package/dist/core/chart/exporter/svg/plugins/brokenAxis.d.ts +20 -0
- package/dist/core/chart/exporter/svg/plugins/latex.d.ts +9 -0
- package/dist/core/chart/exporter/svg/plugins/register.d.ts +8 -0
- package/dist/core/chart/exporter/svg/plugins/regression.d.ts +33 -0
- package/dist/core/chart/exporter/svg/plugins/roi.d.ts +12 -0
- package/dist/core/chart/exporter/svg/plugins/tradeMarkers.d.ts +3 -0
- package/dist/core/chart/exporter/svg/plugins/types.d.ts +28 -0
- package/dist/core/chart/exporter/svg/plugins/watermark.d.ts +13 -0
- package/dist/core/chart/exporter/svg/series/band.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/bar.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/boxplot.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/candlestick.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/finitePoints.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/gauge.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/heatmap.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/indicator.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/line.d.ts +12 -0
- package/dist/core/chart/exporter/svg/series/polar.d.ts +6 -0
- package/dist/core/chart/exporter/svg/series/radar.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/registry.d.ts +10 -0
- package/dist/core/chart/exporter/svg/series/sankey.d.ts +5 -0
- package/dist/core/chart/exporter/svg/series/scatter.d.ts +1 -0
- package/dist/core/chart/exporter/svg/series/ternary.d.ts +7 -0
- package/dist/core/chart/exporter/svg/series/waterfall.d.ts +6 -0
- package/dist/core/chart/exporter/svg/seriesAtTimestamp.d.ts +4 -0
- package/dist/core/chart/exporter/svg/seriesUtils.d.ts +3 -0
- package/dist/core/chart/exporter/svg/symbols.d.ts +5 -0
- package/dist/core/chart/exporter/svg/tickUtils.d.ts +9 -0
- package/dist/core/chart/mountSVGString.d.ts +5 -0
- package/dist/core/chart/overlaySeriesRegistry.d.ts +7 -0
- package/dist/core/chart/series/SeriesActions.d.ts +1 -0
- package/dist/core/chart/series/SeriesBufferLite.d.ts +13 -0
- package/dist/core/chart/series/seriesOptionsRegistry.d.ts +8 -0
- package/dist/core/chart/series/seriesTypeRegistry.d.ts +5 -0
- package/dist/core/chart/types.d.ts +2 -2
- package/dist/core/stacked/StackSVGComposer.d.ts +14 -0
- package/dist/core/stacked/index.d.ts +3 -2
- package/dist/core/stacked/types.d.ts +12 -4
- package/dist/createStackedChart-DjA3aJAu.js +2761 -0
- package/dist/createStackedChart-DjA3aJAu.js.map +1 -0
- package/dist/{hooks-CYPCxoZx.js → hooks-4wQH27r9.js} +7 -7
- package/dist/{hooks-CYPCxoZx.js.map → hooks-4wQH27r9.js.map} +1 -1
- package/dist/{index-qunX30Xu.js → index-B7PTX94B.js} +2133 -2133
- package/dist/index-B7PTX94B.js.map +1 -0
- package/dist/{index-BMiZoKmm.js → index-BgrvqltV.js} +67 -67
- package/dist/index-BgrvqltV.js.map +1 -0
- package/dist/index-Bj-xyXY6.js +582 -0
- package/dist/index-Bj-xyXY6.js.map +1 -0
- package/dist/index-qhscKTDy.js.map +1 -1
- package/dist/index.core.d.ts +8 -6
- package/dist/index.d.ts +1 -14
- package/dist/plugins/3d.js +3 -1
- package/dist/plugins/3d.js.map +1 -1
- package/dist/plugins/PluginManager.d.ts +5 -0
- package/dist/plugins/analysis.js.map +1 -1
- package/dist/plugins/annotations.js +8 -7
- package/dist/plugins/annotations.js.map +1 -1
- package/dist/plugins/broken-axis.js +198 -152
- package/dist/plugins/broken-axis.js.map +1 -1
- package/dist/plugins/createPlugin.d.ts +8 -0
- package/dist/plugins/debug.js +32 -32
- package/dist/plugins/debug.js.map +1 -1
- package/dist/plugins/forecasting.js +273 -258
- package/dist/plugins/forecasting.js.map +1 -1
- package/dist/plugins/gpu.js +2033 -209
- package/dist/plugins/gpu.js.map +1 -1
- package/dist/plugins/i18n.js +286 -23
- package/dist/plugins/i18n.js.map +1 -1
- package/dist/plugins/latex.js +766 -207
- package/dist/plugins/latex.js.map +1 -1
- package/dist/plugins/loading/index.d.ts +1 -2
- package/dist/plugins/loading.js +3 -4
- package/dist/plugins/ml-integration.js +107 -93
- package/dist/plugins/ml-integration.js.map +1 -1
- package/dist/plugins/offscreen.js +11 -10
- package/dist/plugins/offscreen.js.map +1 -1
- package/dist/plugins/radar/types.d.ts +11 -0
- package/dist/plugins/radar.js +64 -53
- package/dist/plugins/radar.js.map +1 -1
- package/dist/plugins/regression.js +254 -256
- package/dist/plugins/regression.js.map +1 -1
- package/dist/plugins/roi/index.d.ts +2 -0
- package/dist/plugins/roi.js +184 -145
- package/dist/plugins/roi.js.map +1 -1
- package/dist/plugins/snapshot.js +20 -15
- package/dist/plugins/snapshot.js.map +1 -1
- package/dist/plugins/streaming.js +1 -1
- package/dist/plugins/tools.js +1 -1
- package/dist/plugins/types.d.ts +4 -0
- package/dist/react.js +55 -58
- package/dist/react.js.map +1 -1
- package/dist/regression-HNdyk1Dm.js +28 -0
- package/dist/regression-HNdyk1Dm.js.map +1 -0
- package/dist/renderer/ChartSeriesRenderer.d.ts +3 -2
- package/dist/renderer/NativeWebGLRenderer.d.ts +2 -1
- package/dist/renderer/SVGChartRenderer.d.ts +15 -0
- package/dist/renderer/SankeyRenderer.d.ts +1 -0
- package/dist/renderer/native/NativeWebGLRenderer.d.ts +5 -1
- package/dist/renderer/native/draw.d.ts +2 -47
- package/dist/renderer/native/drawCore.d.ts +27 -0
- package/dist/renderer/native/drawExtended.d.ts +29 -0
- package/dist/renderer/native/frameRenderExtended.d.ts +1 -0
- package/dist/renderer/native/frameRenderRegistry.d.ts +27 -0
- package/dist/renderer/native/programFactoryCore.d.ts +6 -0
- package/dist/renderer/native/programFactoryExtended.d.ts +4 -0
- package/dist/renderer/native/utils.d.ts +3 -29
- package/dist/renderer/native/utilsCore.d.ts +14 -0
- package/dist/renderer/native/utilsExtended.d.ts +17 -0
- package/dist/renderer/overlaySeriesExtended.d.ts +1 -0
- package/dist/renderer/registerExtendedSeries.d.ts +1 -0
- package/dist/renderer/registerSVG.d.ts +5 -0
- package/dist/renderer/registerWebGPU.d.ts +2 -0
- package/dist/renderer/sankeyLayout.d.ts +29 -0
- package/dist/renderer/seriesBufferExtended.d.ts +4 -0
- package/dist/scientific/index.d.ts +1 -5
- package/dist/scientific/registerScientific.d.ts +1 -0
- package/dist/scientific.js +41 -41
- package/dist/solid.js +56 -59
- package/dist/solid.js.map +1 -1
- package/dist/svelte.js +26 -29
- package/dist/svelte.js.map +1 -1
- package/dist/tickUtils-B_X-ha13.js +41 -0
- package/dist/tickUtils-B_X-ha13.js.map +1 -0
- package/dist/trading/index.d.ts +1 -4
- package/dist/trading/registerTrading.d.ts +3 -0
- package/dist/trading.js +42 -42
- package/dist/types.d.ts +5 -4
- package/dist/velo-plot.full.js +1951 -1275
- package/dist/velo-plot.full.js.map +1 -1
- package/dist/velo-plot.js +33 -28
- package/dist/velo-plot.js.map +1 -1
- package/dist/vue/VeloPlot.vue.d.ts +1 -1
- package/dist/vue/index.d.ts +33 -33
- package/dist/vue.js +17 -20
- package/dist/vue.js.map +1 -1
- package/package.json +14 -1
- package/dist/ChartCore-BpzRvN4Y.js +0 -8467
- package/dist/ChartCore-BpzRvN4Y.js.map +0 -1
- package/dist/createStackedChart-Dm-YqUT7.js +0 -756
- package/dist/createStackedChart-Dm-YqUT7.js.map +0 -1
- package/dist/gpuRenderer-BpaMYz-k.js +0 -1848
- package/dist/gpuRenderer-BpaMYz-k.js.map +0 -1
- package/dist/index-BMiZoKmm.js.map +0 -1
- package/dist/index-qunX30Xu.js.map +0 -1
- package/dist/index-x4stH3jD.js +0 -282
- package/dist/index-x4stH3jD.js.map +0 -1
- package/dist/index.core-BmZe2jRQ.js.map +0 -1
- package/dist/mockDatafeed-DHIDPcpX.js +0 -515
- package/dist/mockDatafeed-DHIDPcpX.js.map +0 -1
- package/dist/symbols-DT0eLlpW.js +0 -568
- package/dist/symbols-DT0eLlpW.js.map +0 -1
package/dist/plugins/roi.js
CHANGED
|
@@ -1,223 +1,262 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { f as M } from "../SVGDocumentBuilder-C-uLkcFW.js";
|
|
2
|
+
import { p as j } from "../tickUtils-B_X-ha13.js";
|
|
3
|
+
function O(p, i) {
|
|
4
|
+
if (!p.builder || i.length === 0) return;
|
|
5
|
+
const h = j(p.yScales);
|
|
6
|
+
if (!h) return;
|
|
7
|
+
const m = (u) => ({
|
|
8
|
+
x: p.xScale.transform(u.x),
|
|
9
|
+
y: h.transform(u.y)
|
|
10
|
+
});
|
|
11
|
+
for (const u of i) {
|
|
12
|
+
const l = u.color ?? "#00f2ff", w = u.fill ?? "rgba(0, 242, 255, 0.15)", c = u.points.map(m);
|
|
13
|
+
if (!(c.length < 2)) {
|
|
14
|
+
if (u.tool === "rectangle") {
|
|
15
|
+
const g = Math.min(c[0].x, c[1].x), d = Math.min(c[0].y, c[1].y), P = Math.abs(c[1].x - c[0].x), S = Math.abs(c[1].y - c[0].y);
|
|
16
|
+
p.builder.push(
|
|
17
|
+
"plugins",
|
|
18
|
+
`<rect x="${M(g)}" y="${M(d)}" width="${M(P)}" height="${M(S)}" fill="${w}" stroke="${l}" stroke-width="1.5"/>`
|
|
19
|
+
);
|
|
20
|
+
} else if (u.tool === "circle") {
|
|
21
|
+
const g = c[1].x - c[0].x, d = c[1].y - c[0].y, P = Math.sqrt(g * g + d * d);
|
|
22
|
+
p.builder.push(
|
|
23
|
+
"plugins",
|
|
24
|
+
`<circle cx="${M(c[0].x)}" cy="${M(c[0].y)}" r="${M(P)}" fill="${w}" stroke="${l}" stroke-width="1.5"/>`
|
|
25
|
+
);
|
|
26
|
+
} else if (u.tool === "polygon" || u.tool === "lasso") {
|
|
27
|
+
const g = c.map((d) => `${M(d.x)},${M(d.y)}`).join(" ");
|
|
28
|
+
p.builder.push(
|
|
29
|
+
"plugins",
|
|
30
|
+
`<polygon points="${g}" fill="${w}" stroke="${l}" stroke-width="1.5"/>`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const _ = (p = {}) => {
|
|
37
|
+
let i = null, h = p.defaultTool || "rectangle", m = [], u = !1, l = null, w = p.enabled !== !1, c = p.mask === !0;
|
|
3
38
|
const g = /* @__PURE__ */ new Map();
|
|
4
|
-
let
|
|
5
|
-
const
|
|
39
|
+
let d = null, P = null;
|
|
40
|
+
const S = {
|
|
6
41
|
name: "roi",
|
|
7
42
|
description: "Region of Interest selection tool and masking",
|
|
8
43
|
version: "1.1.0",
|
|
9
44
|
author: "VeloPlot"
|
|
10
45
|
};
|
|
11
|
-
function D(
|
|
46
|
+
function D(e) {
|
|
12
47
|
return {
|
|
13
48
|
id: Math.random().toString(36).substring(2, 11),
|
|
14
|
-
tool:
|
|
49
|
+
tool: e,
|
|
15
50
|
points: [],
|
|
16
|
-
color:
|
|
17
|
-
fill:
|
|
51
|
+
color: p.stroke || "#00f2ff",
|
|
52
|
+
fill: p.fill || "rgba(0, 242, 255, 0.15)"
|
|
18
53
|
};
|
|
19
54
|
}
|
|
20
|
-
function
|
|
21
|
-
return
|
|
22
|
-
x:
|
|
23
|
-
y:
|
|
55
|
+
function R(e) {
|
|
56
|
+
return i ? {
|
|
57
|
+
x: i.coords.pixelToDataX(e.x),
|
|
58
|
+
y: i.coords.pixelToDataY(e.y)
|
|
24
59
|
} : { x: 0, y: 0 };
|
|
25
60
|
}
|
|
26
|
-
function
|
|
27
|
-
return
|
|
28
|
-
x:
|
|
29
|
-
y:
|
|
61
|
+
function Y(e) {
|
|
62
|
+
return i ? {
|
|
63
|
+
x: i.coords.dataToPixelX(e.x),
|
|
64
|
+
y: i.coords.dataToPixelY(e.y)
|
|
30
65
|
} : { x: 0, y: 0 };
|
|
31
66
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
67
|
+
function A(e) {
|
|
68
|
+
return m.length === 0 ? !0 : m.some((t) => T(e, t));
|
|
34
69
|
}
|
|
35
|
-
function
|
|
36
|
-
if (!(!
|
|
37
|
-
for (const [
|
|
70
|
+
function k() {
|
|
71
|
+
if (!(!i || !c))
|
|
72
|
+
for (const [e, t] of g.entries()) {
|
|
38
73
|
const n = [];
|
|
39
|
-
for (let s = 0; s <
|
|
40
|
-
|
|
41
|
-
const
|
|
74
|
+
for (let s = 0; s < t.x.length; s++)
|
|
75
|
+
A({ x: t.x[s], y: t.y[s] }) && n.push(s);
|
|
76
|
+
const o = new Float32Array(n.length), a = new Float32Array(n.length);
|
|
42
77
|
for (let s = 0; s < n.length; s++)
|
|
43
|
-
|
|
44
|
-
|
|
78
|
+
o[s] = t.x[n[s]], a[s] = t.y[n[s]];
|
|
79
|
+
d && d(e, { x: o, y: a });
|
|
45
80
|
}
|
|
46
81
|
}
|
|
47
|
-
function
|
|
48
|
-
const { tool: n, points:
|
|
49
|
-
if (
|
|
82
|
+
function T(e, t) {
|
|
83
|
+
const { tool: n, points: o } = t;
|
|
84
|
+
if (o.length < 2) return !1;
|
|
50
85
|
if (n === "rectangle") {
|
|
51
|
-
const
|
|
52
|
-
return
|
|
86
|
+
const a = Math.min(o[0].x, o[1].x), s = Math.max(o[0].x, o[1].x), r = Math.min(o[0].y, o[1].y), y = Math.max(o[0].y, o[1].y);
|
|
87
|
+
return e.x >= a && e.x <= s && e.y >= r && e.y <= y;
|
|
53
88
|
}
|
|
54
89
|
if (n === "circle") {
|
|
55
|
-
const
|
|
56
|
-
Math.pow(
|
|
90
|
+
const a = e.x - o[0].x, s = e.y - o[0].y, r = Math.sqrt(
|
|
91
|
+
Math.pow(o[1].x - o[0].x, 2) + Math.pow(o[1].y - o[0].y, 2)
|
|
57
92
|
);
|
|
58
|
-
return Math.sqrt(
|
|
93
|
+
return Math.sqrt(a * a + s * s) <= r;
|
|
59
94
|
}
|
|
60
95
|
if (n === "polygon" || n === "lasso") {
|
|
61
|
-
let
|
|
62
|
-
for (let s = 0, r =
|
|
63
|
-
const
|
|
64
|
-
f >
|
|
96
|
+
let a = !1;
|
|
97
|
+
for (let s = 0, r = o.length - 1; s < o.length; r = s++) {
|
|
98
|
+
const y = o[s].x, f = o[s].y, x = o[r].x, b = o[r].y;
|
|
99
|
+
f > e.y != b > e.y && e.x < (x - y) * (e.y - f) / (b - f) + y && (a = !a);
|
|
65
100
|
}
|
|
66
|
-
return
|
|
101
|
+
return a;
|
|
67
102
|
}
|
|
68
103
|
return !1;
|
|
69
104
|
}
|
|
70
|
-
function I(
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
105
|
+
function I(e) {
|
|
106
|
+
const t = m.find((o) => o.id === e);
|
|
107
|
+
if (!t || !i) return [];
|
|
73
108
|
const n = [];
|
|
74
|
-
return
|
|
75
|
-
const
|
|
76
|
-
if (!
|
|
77
|
-
const s = new Array(
|
|
78
|
-
for (let r = 0; r <
|
|
79
|
-
s[r] =
|
|
109
|
+
return i.chart.getAllSeries().forEach((o) => {
|
|
110
|
+
const a = o.getData();
|
|
111
|
+
if (!a) return;
|
|
112
|
+
const s = new Array(a.x.length);
|
|
113
|
+
for (let r = 0; r < a.x.length; r++)
|
|
114
|
+
s[r] = T({ x: a.x[r], y: a.y[r] }, t);
|
|
80
115
|
n.push({
|
|
81
|
-
regionId:
|
|
82
|
-
seriesId:
|
|
116
|
+
regionId: e,
|
|
117
|
+
seriesId: o.getId(),
|
|
83
118
|
masks: s
|
|
84
119
|
});
|
|
85
120
|
}), n;
|
|
86
121
|
}
|
|
87
|
-
function
|
|
88
|
-
if (!
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
region:
|
|
92
|
-
seriesIds:
|
|
93
|
-
masks: I(
|
|
122
|
+
function $() {
|
|
123
|
+
if (!l || !i) return;
|
|
124
|
+
l.tool === "polygon" && l.points.length > 1 && l.points.pop(), m.push(l), c && k();
|
|
125
|
+
const e = {
|
|
126
|
+
region: l,
|
|
127
|
+
seriesIds: i.chart.getAllSeries().map((t) => t.getId()),
|
|
128
|
+
masks: I(l.id)
|
|
94
129
|
};
|
|
95
|
-
|
|
96
|
-
region:
|
|
97
|
-
seriesIds:
|
|
98
|
-
}),
|
|
130
|
+
i.events.emit("roi:selected", e), i.chart.events && i.chart.events.emit("roi:selected", e), i.events.emit("roi:created", {
|
|
131
|
+
region: l,
|
|
132
|
+
seriesIds: e.seriesIds
|
|
133
|
+
}), l = null, u = !1, i.requestRender();
|
|
99
134
|
}
|
|
100
|
-
function
|
|
101
|
-
if (!
|
|
102
|
-
if (
|
|
103
|
-
const n =
|
|
104
|
-
|
|
135
|
+
function F(e) {
|
|
136
|
+
if (!w || !e.inPlotArea) return;
|
|
137
|
+
if (h === "polygon" && l) {
|
|
138
|
+
const n = R({ x: e.pixelX, y: e.pixelY });
|
|
139
|
+
l.points.push(n), e.preventDefault(), i == null || i.requestRender();
|
|
105
140
|
return;
|
|
106
141
|
}
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
142
|
+
u = !0, l = D(h);
|
|
143
|
+
const t = R({ x: e.pixelX, y: e.pixelY });
|
|
144
|
+
l.points.push(t), h === "rectangle" || h === "circle" ? l.points.push({ ...t }) : h === "polygon" && l.points.push({ ...t }), e.preventDefault(), i == null || i.requestRender();
|
|
110
145
|
}
|
|
111
|
-
function
|
|
112
|
-
if (!(!
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
else if (
|
|
116
|
-
const
|
|
117
|
-
Math.sqrt(
|
|
118
|
-
} else if (
|
|
119
|
-
const
|
|
120
|
-
|
|
146
|
+
function X(e) {
|
|
147
|
+
if (!(!w || !u || !l)) {
|
|
148
|
+
if (h === "rectangle" || h === "circle")
|
|
149
|
+
l.points[1] = R({ x: e.pixelX, y: e.pixelY });
|
|
150
|
+
else if (h === "lasso") {
|
|
151
|
+
const t = l.points[l.points.length - 1], n = R({ x: e.pixelX, y: e.pixelY }), o = i.coords.dataToPixelX(n.x) - i.coords.dataToPixelX(t.x), a = i.coords.dataToPixelY(n.y) - i.coords.dataToPixelY(t.y);
|
|
152
|
+
Math.sqrt(o * o + a * a) > 5 && l.points.push(n);
|
|
153
|
+
} else if (h === "polygon") {
|
|
154
|
+
const t = l.points.length - 1;
|
|
155
|
+
t >= 0 && (l.points[t] = R({ x: e.pixelX, y: e.pixelY }));
|
|
121
156
|
}
|
|
122
|
-
|
|
157
|
+
i == null || i.requestRender();
|
|
123
158
|
}
|
|
124
159
|
}
|
|
125
|
-
function E(
|
|
126
|
-
!
|
|
160
|
+
function E(e) {
|
|
161
|
+
!u || !l || h !== "polygon" && $();
|
|
127
162
|
}
|
|
128
|
-
function
|
|
129
|
-
const { tool: n, points:
|
|
130
|
-
if (
|
|
131
|
-
const r =
|
|
132
|
-
if (
|
|
133
|
-
const
|
|
134
|
-
|
|
163
|
+
function q(e, t) {
|
|
164
|
+
const { tool: n, points: o, color: a, fill: s } = e;
|
|
165
|
+
if (o.length < 1) return;
|
|
166
|
+
const r = o.map((y) => Y(y));
|
|
167
|
+
if (t.strokeStyle = a || "#00f2ff", t.fillStyle = s || "rgba(0, 242, 255, 0.15)", t.lineWidth = 2, n === "rectangle" && r.length >= 2) {
|
|
168
|
+
const y = Math.min(r[0].x, r[1].x), f = Math.min(r[0].y, r[1].y), x = Math.abs(r[0].x - r[1].x), b = Math.abs(r[0].y - r[1].y);
|
|
169
|
+
t.fillRect(y, f, x, b), t.strokeRect(y, f, x, b);
|
|
135
170
|
} else if (n === "circle" && r.length >= 2) {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
} else (n === "polygon" || n === "lasso") && r.length >= 2 && (
|
|
171
|
+
const y = r[1].x - r[0].x, f = r[1].y - r[0].y, x = Math.sqrt(y * y + f * f);
|
|
172
|
+
t.beginPath(), t.arc(r[0].x, r[0].y, x, 0, Math.PI * 2), t.fill(), t.stroke();
|
|
173
|
+
} else (n === "polygon" || n === "lasso") && r.length >= 2 && (t.beginPath(), t.moveTo(r[0].x, r[0].y), r.slice(1).forEach((y) => t.lineTo(y.x, y.y)), (n === "lasso" || !u || e !== l) && t.closePath(), t.fill(), t.stroke());
|
|
139
174
|
}
|
|
140
175
|
return {
|
|
141
|
-
manifest:
|
|
142
|
-
onInit(
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
var
|
|
147
|
-
if (n.id && ((
|
|
176
|
+
manifest: S,
|
|
177
|
+
onInit(e) {
|
|
178
|
+
i = e;
|
|
179
|
+
const t = i.chart;
|
|
180
|
+
d = t.updateSeries.bind(t), P = t.addSeries.bind(t), t.addSeries = (n) => {
|
|
181
|
+
var o, a;
|
|
182
|
+
if (n.id && ((o = n.data) != null && o.x) && g.set(n.id, {
|
|
148
183
|
x: new Float32Array(n.data.x),
|
|
149
184
|
y: new Float32Array(n.data.y)
|
|
150
|
-
}),
|
|
185
|
+
}), c && ((a = n.data) != null && a.x)) {
|
|
151
186
|
const s = g.get(n.id), r = [];
|
|
152
|
-
for (let
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
for (let
|
|
156
|
-
|
|
157
|
-
|
|
187
|
+
for (let x = 0; x < s.x.length; x++)
|
|
188
|
+
A({ x: s.x[x], y: s.y[x] }) && r.push(x);
|
|
189
|
+
const y = new Float32Array(r.length), f = new Float32Array(r.length);
|
|
190
|
+
for (let x = 0; x < r.length; x++)
|
|
191
|
+
y[x] = s.x[r[x]], f[x] = s.y[r[x]];
|
|
192
|
+
P({ ...n, data: { ...n.data, x: y, y: f } });
|
|
158
193
|
} else
|
|
159
|
-
|
|
160
|
-
},
|
|
161
|
-
if (
|
|
162
|
-
x: new Float32Array(
|
|
163
|
-
y: new Float32Array(
|
|
164
|
-
}),
|
|
165
|
-
const
|
|
166
|
-
for (let f = 0; f <
|
|
167
|
-
|
|
168
|
-
const r = new Float32Array(s.length),
|
|
194
|
+
P(n);
|
|
195
|
+
}, t.updateSeries = (n, o) => {
|
|
196
|
+
if (o.x && g.set(n, {
|
|
197
|
+
x: new Float32Array(o.x),
|
|
198
|
+
y: new Float32Array(o.y)
|
|
199
|
+
}), c && o.x) {
|
|
200
|
+
const a = g.get(n), s = [];
|
|
201
|
+
for (let f = 0; f < a.x.length; f++)
|
|
202
|
+
A({ x: a.x[f], y: a.y[f] }) && s.push(f);
|
|
203
|
+
const r = new Float32Array(s.length), y = new Float32Array(s.length);
|
|
169
204
|
for (let f = 0; f < s.length; f++)
|
|
170
|
-
r[f] =
|
|
171
|
-
|
|
205
|
+
r[f] = a.x[s[f]], y[f] = a.y[s[f]];
|
|
206
|
+
d(n, { ...o, x: r, y });
|
|
172
207
|
} else
|
|
173
|
-
|
|
208
|
+
d(n, o);
|
|
174
209
|
};
|
|
175
210
|
},
|
|
176
211
|
onDestroy() {
|
|
177
|
-
if (
|
|
178
|
-
const
|
|
179
|
-
|
|
212
|
+
if (i) {
|
|
213
|
+
const e = i.chart;
|
|
214
|
+
e.addSeries = P, e.updateSeries = d;
|
|
180
215
|
}
|
|
181
|
-
|
|
216
|
+
i = null, g.clear();
|
|
217
|
+
},
|
|
218
|
+
onInteraction(e, t) {
|
|
219
|
+
t.type === "mousedown" && F(t), t.type === "mousemove" && X(t), t.type === "mouseup" && E(), t.type, t.originalEvent instanceof MouseEvent && t.originalEvent.detail === 2 && h === "polygon" && ($(), t.preventDefault());
|
|
182
220
|
},
|
|
183
|
-
|
|
184
|
-
|
|
221
|
+
onRenderOverlay(e) {
|
|
222
|
+
const t = e.render.ctx2d;
|
|
223
|
+
t && (m.forEach((n) => q(n, t)), l && q(l, t));
|
|
185
224
|
},
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
e
|
|
225
|
+
onExportSVG(e) {
|
|
226
|
+
var t;
|
|
227
|
+
!e.builder || ((t = e.exportContext) == null ? void 0 : t.options.includeOverlays) === !1 || O(e, m);
|
|
189
228
|
},
|
|
190
229
|
api: {
|
|
191
|
-
setTool(
|
|
192
|
-
|
|
230
|
+
setTool(e) {
|
|
231
|
+
h = e, u && $();
|
|
193
232
|
},
|
|
194
233
|
clear() {
|
|
195
|
-
|
|
234
|
+
m = [], l = null, u = !1, c && k(), i && (i.events.emit("roi:cleared", {}), i.requestRender());
|
|
196
235
|
},
|
|
197
236
|
getRegions() {
|
|
198
|
-
return [...
|
|
237
|
+
return [...m];
|
|
199
238
|
},
|
|
200
|
-
removeRegion(
|
|
201
|
-
|
|
239
|
+
removeRegion(e) {
|
|
240
|
+
m = m.filter((t) => t.id !== e), c && k(), i && i.requestRender();
|
|
202
241
|
},
|
|
203
242
|
calculateMasks: I,
|
|
204
|
-
isEnabled: () =>
|
|
205
|
-
setEnabled: (
|
|
206
|
-
|
|
243
|
+
isEnabled: () => w,
|
|
244
|
+
setEnabled: (e) => {
|
|
245
|
+
w = e;
|
|
207
246
|
},
|
|
208
|
-
setMasking(
|
|
209
|
-
if (
|
|
210
|
-
|
|
211
|
-
else if (
|
|
212
|
-
for (const [
|
|
213
|
-
|
|
214
|
-
|
|
247
|
+
setMasking(e) {
|
|
248
|
+
if (c = e, e)
|
|
249
|
+
k();
|
|
250
|
+
else if (i) {
|
|
251
|
+
for (const [t, n] of g.entries())
|
|
252
|
+
d(t, n);
|
|
253
|
+
i.requestRender();
|
|
215
254
|
}
|
|
216
255
|
}
|
|
217
256
|
}
|
|
218
257
|
};
|
|
219
258
|
};
|
|
220
259
|
export {
|
|
221
|
-
|
|
260
|
+
_ as PluginROI
|
|
222
261
|
};
|
|
223
262
|
//# sourceMappingURL=roi.js.map
|
package/dist/plugins/roi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roi.js","sources":["../../src/plugins/roi/index.ts"],"sourcesContent":["import type { PluginContext, InteractionEvent, PluginManifest } from \"../types\";\n\nexport interface RoiPoint {\n x: number;\n y: number;\n}\n\nexport interface RoiRegion {\n id: string;\n tool: \"rectangle\" | \"circle\" | \"polygon\" | \"lasso\";\n points: RoiPoint[];\n color?: string;\n fill?: string;\n}\n\nexport interface RoiMaskResult {\n regionId: string;\n seriesId: string;\n masks: boolean[];\n}\n\nexport interface RoiSelectedEvent {\n region: RoiRegion;\n seriesIds: string[];\n masks: RoiMaskResult[];\n}\n\nexport interface RoiAPI {\n setTool(tool: RoiTool): void;\n clear(): void;\n getRegions(): RoiRegion[];\n removeRegion(id: string): void;\n calculateMasks(regionId: string): RoiMaskResult[];\n isEnabled(): boolean;\n setEnabled(enabled: boolean): void;\n}\n\nexport type RoiTool = \"rectangle\" | \"circle\" | \"polygon\" | \"lasso\";\n\nexport interface PluginROIConfig {\n defaultTool?: RoiTool;\n stroke?: string;\n fill?: string;\n enabled?: boolean;\n mask?: boolean;\n}\n\nexport const PluginROI = (config: PluginROIConfig = {}) => {\n let ctx: PluginContext | null = null;\n let activeTool: RoiTool = config.defaultTool || \"rectangle\";\n let regions: RoiRegion[] = [];\n let isDrawing = false;\n let activeRegion: RoiRegion | null = null;\n let enabled = config.enabled !== false;\n let isMasking = config.mask === true;\n\n // Store for original data when masking is active\n const rawDataStore = new Map<string, { x: Float32Array; y: Float32Array }>();\n let originalUpdateSeries: any = null;\n let originalAddSeries: any = null;\n\n const manifest: PluginManifest = {\n name: \"roi\",\n description: \"Region of Interest selection tool and masking\",\n version: \"1.1.0\",\n author: \"VeloPlot\",\n };\n\n function createRegion(tool: RoiTool): RoiRegion {\n return {\n id: Math.random().toString(36).substring(2, 11),\n tool,\n points: [],\n color: config.stroke || \"#00f2ff\",\n fill: config.fill || \"rgba(0, 242, 255, 0.15)\",\n };\n }\n\n function pixelToData(pixel: { x: number; y: number }): RoiPoint {\n if (!ctx) return { x: 0, y: 0 };\n return {\n x: ctx.coords.pixelToDataX(pixel.x),\n y: ctx.coords.pixelToDataY(pixel.y),\n };\n }\n\n function dataToPixel(point: RoiPoint): { x: number; y: number } {\n if (!ctx) return { x: 0, y: 0 };\n return {\n x: ctx.coords.dataToPixelX(point.x),\n y: ctx.coords.dataToPixelY(point.y),\n };\n }\n\n function isPointInAnyRegion(point: RoiPoint): boolean {\n if (regions.length === 0) return true; // Show all if no regions defined\n return regions.some((r) => isPointInRegion(point, r));\n }\n\n function applyMasking(): void {\n if (!ctx || !isMasking) return;\n\n for (const [id, raw] of rawDataStore.entries()) {\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) {\n indices.push(i);\n }\n }\n\n const filteredX = new Float32Array(indices.length);\n const filteredY = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n filteredX[i] = raw.x[indices[i]];\n filteredY[i] = raw.y[indices[i]];\n }\n\n if (originalUpdateSeries) {\n originalUpdateSeries(id, { x: filteredX, y: filteredY });\n }\n }\n }\n\n function isPointInRegion(point: RoiPoint, region: RoiRegion): boolean {\n const { tool, points } = region;\n if (points.length < 2) return false;\n\n if (tool === \"rectangle\") {\n const xMin = Math.min(points[0].x, points[1].x);\n const xMax = Math.max(points[0].x, points[1].x);\n const yMin = Math.min(points[0].y, points[1].y);\n const yMax = Math.max(points[0].y, points[1].y);\n return point.x >= xMin && point.x <= xMax && point.y >= yMin && point.y <= yMax;\n }\n\n if (tool === \"circle\") {\n const dx = point.x - points[0].x;\n const dy = point.y - points[0].y;\n const r = Math.sqrt(\n Math.pow(points[1].x - points[0].x, 2) + Math.pow(points[1].y - points[0].y, 2)\n );\n return Math.sqrt(dx * dx + dy * dy) <= r;\n }\n\n if (tool === \"polygon\" || tool === \"lasso\") {\n // Ray casting algorithm\n let inside = false;\n for (let i = 0, j = points.length - 1; i < points.length; j = i++) {\n const xi = points[i].x, yi = points[i].y;\n const xj = points[j].x, yj = points[j].y;\n const intersect = yi > point.y !== yj > point.y &&\n point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n }\n\n return false;\n }\n\n function calculateMasks(regionId: string): RoiMaskResult[] {\n const region = regions.find((r) => r.id === regionId);\n if (!region || !ctx) return [];\n\n const results: RoiMaskResult[] = [];\n ctx.chart.getAllSeries().forEach((series) => {\n const data = series.getData();\n if (!data) return;\n\n const masks = new Array(data.x.length);\n for (let i = 0; i < data.x.length; i++) {\n masks[i] = isPointInRegion({ x: data.x[i], y: data.y[i] }, region);\n }\n\n results.push({\n regionId,\n seriesId: series.getId(),\n masks,\n });\n });\n\n return results;\n }\n\n function finishRegion(): void {\n if (!activeRegion || !ctx) return;\n \n // Clean up preview points for polygon\n if (activeRegion.tool === \"polygon\" && activeRegion.points.length > 1) {\n // Remove the preview point\n activeRegion.points.pop();\n }\n\n regions.push(activeRegion);\n\n if (isMasking) {\n applyMasking();\n }\n\n const event: RoiSelectedEvent = {\n region: activeRegion,\n seriesIds: ctx.chart.getAllSeries().map((s) => s.getId()),\n masks: calculateMasks(activeRegion.id),\n };\n\n // Emit on both plugin context and chart\n ctx.events.emit(\"roi:selected\", event);\n if (ctx.chart.events) {\n ctx.chart.events.emit(\"roi:selected\" as any, event);\n }\n \n ctx.events.emit(\"roi:created\", {\n region: activeRegion,\n seriesIds: event.seriesIds,\n });\n\n activeRegion = null;\n isDrawing = false;\n ctx.requestRender();\n }\n\n function handlePointerDown(event: InteractionEvent): void {\n if (!enabled || !event.inPlotArea) return;\n\n if (activeTool === \"polygon\" && activeRegion) {\n // For polygon, we keep adding points on click\n // But first, replace the preview point with a permanent one\n const previewPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n activeRegion.points.push(previewPoint);\n event.preventDefault();\n ctx?.requestRender();\n return;\n }\n\n isDrawing = true;\n activeRegion = createRegion(activeTool);\n const startPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n activeRegion.points.push(startPoint);\n \n if (activeTool === \"rectangle\" || activeTool === \"circle\") {\n activeRegion.points.push({ ...startPoint });\n } else if (activeTool === \"polygon\") {\n // Add a second point for preview\n activeRegion.points.push({ ...startPoint });\n }\n \n event.preventDefault(); // Stop chart from panning\n ctx?.requestRender();\n }\n\n function handlePointerMove(event: InteractionEvent): void {\n if (!enabled || !isDrawing || !activeRegion) return;\n\n if (activeTool === \"rectangle\" || activeTool === \"circle\") {\n activeRegion.points[1] = pixelToData({ x: event.pixelX, y: event.pixelY });\n } else if (activeTool === \"lasso\") {\n // For lasso, we capture points during movement\n const lastPoint = activeRegion.points[activeRegion.points.length - 1];\n const newPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n \n // Basic distance filter to avoid too many points\n const dx = ctx!.coords.dataToPixelX(newPoint.x) - ctx!.coords.dataToPixelX(lastPoint.x);\n const dy = ctx!.coords.dataToPixelY(newPoint.y) - ctx!.coords.dataToPixelY(lastPoint.y);\n if (Math.sqrt(dx*dx + dy*dy) > 5) {\n activeRegion.points.push(newPoint);\n }\n } else if (activeTool === \"polygon\") {\n // Update the preview point (the last one)\n const lastIndex = activeRegion.points.length - 1;\n if (lastIndex >= 0) {\n activeRegion.points[lastIndex] = pixelToData({ x: event.pixelX, y: event.pixelY });\n }\n }\n ctx?.requestRender();\n }\n\n function handlePointerUp(_event: InteractionEvent): void {\n if (!isDrawing || !activeRegion) return;\n\n if (activeTool !== \"polygon\") {\n finishRegion();\n }\n }\n\n function drawRegion(region: RoiRegion, ctx2d: CanvasRenderingContext2D): void {\n const { tool, points, color, fill } = region;\n if (points.length < 1) return;\n\n const pixels = points.map((p) => dataToPixel(p));\n\n ctx2d.strokeStyle = color || \"#00f2ff\";\n ctx2d.fillStyle = fill || \"rgba(0, 242, 255, 0.15)\";\n ctx2d.lineWidth = 2;\n\n if (tool === \"rectangle\" && pixels.length >= 2) {\n const x = Math.min(pixels[0].x, pixels[1].x);\n const y = Math.min(pixels[0].y, pixels[1].y);\n const w = Math.abs(pixels[0].x - pixels[1].x);\n const h = Math.abs(pixels[0].y - pixels[1].y);\n ctx2d.fillRect(x, y, w, h);\n ctx2d.strokeRect(x, y, w, h);\n } else if (tool === \"circle\" && pixels.length >= 2) {\n const dx = pixels[1].x - pixels[0].x;\n const dy = pixels[1].y - pixels[0].y;\n const r = Math.sqrt(dx * dx + dy * dy);\n ctx2d.beginPath();\n ctx2d.arc(pixels[0].x, pixels[0].y, r, 0, Math.PI * 2);\n ctx2d.fill();\n ctx2d.stroke();\n } else if ((tool === \"polygon\" || tool === \"lasso\") && pixels.length >= 2) {\n ctx2d.beginPath();\n ctx2d.moveTo(pixels[0].x, pixels[0].y);\n pixels.slice(1).forEach((p) => ctx2d.lineTo(p.x, p.y));\n if (tool === \"lasso\") {\n ctx2d.closePath();\n } else if (!isDrawing || region !== activeRegion) {\n ctx2d.closePath();\n }\n ctx2d.fill();\n ctx2d.stroke();\n }\n }\n\n return {\n manifest,\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n const chart = ctx.chart as any;\n\n // Hijack series methods if masking is enabled\n originalUpdateSeries = chart.updateSeries.bind(chart);\n originalAddSeries = chart.addSeries.bind(chart);\n\n chart.addSeries = (options: any) => {\n if (options.id && options.data?.x) {\n rawDataStore.set(options.id, {\n x: new Float32Array(options.data.x),\n y: new Float32Array(options.data.y),\n });\n }\n if (isMasking && options.data?.x) {\n // Apply initial mask\n const raw = rawDataStore.get(options.id)!;\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) indices.push(i);\n }\n const fx = new Float32Array(indices.length);\n const fy = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n fx[i] = raw.x[indices[i]];\n fy[i] = raw.y[indices[i]];\n }\n originalAddSeries({ ...options, data: { ...options.data, x: fx, y: fy } });\n } else {\n originalAddSeries(options);\n }\n };\n\n chart.updateSeries = (id: string, data: any) => {\n if (data.x) {\n rawDataStore.set(id, {\n x: new Float32Array(data.x),\n y: new Float32Array(data.y),\n });\n }\n if (isMasking && data.x) {\n const raw = rawDataStore.get(id)!;\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) indices.push(i);\n }\n const fx = new Float32Array(indices.length);\n const fy = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n fx[i] = raw.x[indices[i]];\n fy[i] = raw.y[indices[i]];\n }\n originalUpdateSeries(id, { ...data, x: fx, y: fy });\n } else {\n originalUpdateSeries(id, data);\n }\n };\n },\n onDestroy() {\n if (ctx) {\n const chart = ctx.chart as any;\n chart.addSeries = originalAddSeries;\n chart.updateSeries = originalUpdateSeries;\n }\n ctx = null;\n rawDataStore.clear();\n },\n onInteraction(_pluginCtx: PluginContext, event: InteractionEvent) {\n if (event.type === \"mousedown\") handlePointerDown(event);\n if (event.type === \"mousemove\") handlePointerMove(event);\n if (event.type === \"mouseup\") handlePointerUp(event);\n \n // Handle double click to finish polygon\n if (event.type === \"mouseup\" && activeTool === \"polygon\" && isDrawing) {\n // Simple double click detection\n // For now, let's just use a more complex logic or a button if needed.\n // In this implementation, let's say 3 clicks on the same area or just let it be.\n }\n \n // Special: right click or double click to finish polygon\n if (event.originalEvent instanceof MouseEvent && event.originalEvent.detail === 2 && activeTool === \"polygon\") {\n finishRegion();\n event.preventDefault();\n }\n },\n onRenderOverlay(pluginCtx: PluginContext) {\n const ctx2d = pluginCtx.render.ctx2d;\n if (!ctx2d) return;\n\n regions.forEach((region) => drawRegion(region, ctx2d));\n if (activeRegion) drawRegion(activeRegion, ctx2d);\n },\n api: {\n setTool(tool: RoiTool) {\n activeTool = tool;\n if (isDrawing) finishRegion();\n },\n clear() {\n regions = [];\n activeRegion = null;\n isDrawing = false;\n if (isMasking) applyMasking();\n if (ctx) {\n ctx.events.emit(\"roi:cleared\", {});\n ctx.requestRender();\n }\n },\n getRegions() {\n return [...regions];\n },\n removeRegion(id: string) {\n regions = regions.filter((r) => r.id !== id);\n if (isMasking) applyMasking();\n if (ctx) ctx.requestRender();\n },\n calculateMasks,\n isEnabled: () => enabled,\n setEnabled: (e: boolean) => {\n enabled = e;\n },\n setMasking(mask: boolean) {\n isMasking = mask;\n if (mask) {\n applyMasking();\n } else {\n // Restore all original data\n if (ctx) {\n for (const [id, raw] of rawDataStore.entries()) {\n originalUpdateSeries(id, raw);\n }\n ctx.requestRender();\n }\n }\n },\n } as RoiAPI,\n };\n};\n\nexport type RoiEvent = \"roi:selected\" | \"roi:created\" | \"roi:cleared\";\n"],"names":["PluginROI","config","ctx","activeTool","regions","isDrawing","activeRegion","enabled","isMasking","rawDataStore","originalUpdateSeries","originalAddSeries","manifest","createRegion","tool","pixelToData","pixel","dataToPixel","point","isPointInAnyRegion","r","isPointInRegion","applyMasking","id","raw","indices","i","filteredX","filteredY","region","points","xMin","xMax","yMin","yMax","dx","dy","inside","j","xi","yi","xj","yj","calculateMasks","regionId","results","series","data","masks","finishRegion","event","s","handlePointerDown","previewPoint","startPoint","handlePointerMove","lastPoint","newPoint","lastIndex","handlePointerUp","_event","drawRegion","ctx2d","color","fill","pixels","p","x","y","w","h","pluginCtx","chart","options","_a","_b","fx","fy","_pluginCtx","e","mask"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"roi.js","sources":["../../src/core/chart/exporter/svg/plugins/roi.ts","../../src/plugins/roi/index.ts"],"sourcesContent":["import type { SVGExportPluginContext } from \"./types\";\nimport { fmt } from \"../SVGDocumentBuilder\";\nimport { primaryYScale } from \"../tickUtils\";\n\nexport interface RoiExportRegion {\n tool: \"rectangle\" | \"circle\" | \"polygon\" | \"lasso\";\n points: Array<{ x: number; y: number }>;\n color?: string;\n fill?: string;\n}\n\nexport function exportRoiRegions(ctx: SVGExportPluginContext, regions: RoiExportRegion[]): void {\n if (!ctx.builder || regions.length === 0) return;\n\n const yScale = primaryYScale(ctx.yScales);\n if (!yScale) return;\n\n const toPx = (p: { x: number; y: number }) => ({\n x: ctx.xScale.transform(p.x),\n y: yScale.transform(p.y),\n });\n\n for (const region of regions) {\n const stroke = region.color ?? \"#00f2ff\";\n const fill = region.fill ?? \"rgba(0, 242, 255, 0.15)\";\n const pixels = region.points.map(toPx);\n if (pixels.length < 2) continue;\n\n if (region.tool === \"rectangle\") {\n const x = Math.min(pixels[0].x, pixels[1].x);\n const y = Math.min(pixels[0].y, pixels[1].y);\n const w = Math.abs(pixels[1].x - pixels[0].x);\n const h = Math.abs(pixels[1].y - pixels[0].y);\n ctx.builder.push(\n \"plugins\",\n `<rect x=\"${fmt(x)}\" y=\"${fmt(y)}\" width=\"${fmt(w)}\" height=\"${fmt(h)}\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\"/>`,\n );\n } else if (region.tool === \"circle\") {\n const dx = pixels[1].x - pixels[0].x;\n const dy = pixels[1].y - pixels[0].y;\n const r = Math.sqrt(dx * dx + dy * dy);\n ctx.builder.push(\n \"plugins\",\n `<circle cx=\"${fmt(pixels[0].x)}\" cy=\"${fmt(pixels[0].y)}\" r=\"${fmt(r)}\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\"/>`,\n );\n } else if (region.tool === \"polygon\" || region.tool === \"lasso\") {\n const pts = pixels.map((p) => `${fmt(p.x)},${fmt(p.y)}`).join(\" \");\n ctx.builder.push(\n \"plugins\",\n `<polygon points=\"${pts}\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\"/>`,\n );\n }\n }\n}\n","import type { PluginContext, InteractionEvent, PluginManifest } from \"../types\";\nimport type { SVGExportPluginContext } from \"../../core/chart/exporter/svg/plugins/types\";\nimport { exportRoiRegions } from \"../../core/chart/exporter/svg/plugins/roi\";\n\nexport interface RoiPoint {\n x: number;\n y: number;\n}\n\nexport interface RoiRegion {\n id: string;\n tool: \"rectangle\" | \"circle\" | \"polygon\" | \"lasso\";\n points: RoiPoint[];\n color?: string;\n fill?: string;\n}\n\nexport interface RoiMaskResult {\n regionId: string;\n seriesId: string;\n masks: boolean[];\n}\n\nexport interface RoiSelectedEvent {\n region: RoiRegion;\n seriesIds: string[];\n masks: RoiMaskResult[];\n}\n\nexport interface RoiAPI {\n setTool(tool: RoiTool): void;\n clear(): void;\n getRegions(): RoiRegion[];\n removeRegion(id: string): void;\n calculateMasks(regionId: string): RoiMaskResult[];\n isEnabled(): boolean;\n setEnabled(enabled: boolean): void;\n}\n\nexport type RoiTool = \"rectangle\" | \"circle\" | \"polygon\" | \"lasso\";\n\nexport interface PluginROIConfig {\n defaultTool?: RoiTool;\n stroke?: string;\n fill?: string;\n enabled?: boolean;\n mask?: boolean;\n}\n\nexport const PluginROI = (config: PluginROIConfig = {}) => {\n let ctx: PluginContext | null = null;\n let activeTool: RoiTool = config.defaultTool || \"rectangle\";\n let regions: RoiRegion[] = [];\n let isDrawing = false;\n let activeRegion: RoiRegion | null = null;\n let enabled = config.enabled !== false;\n let isMasking = config.mask === true;\n\n // Store for original data when masking is active\n const rawDataStore = new Map<string, { x: Float32Array; y: Float32Array }>();\n let originalUpdateSeries: any = null;\n let originalAddSeries: any = null;\n\n const manifest: PluginManifest = {\n name: \"roi\",\n description: \"Region of Interest selection tool and masking\",\n version: \"1.1.0\",\n author: \"VeloPlot\",\n };\n\n function createRegion(tool: RoiTool): RoiRegion {\n return {\n id: Math.random().toString(36).substring(2, 11),\n tool,\n points: [],\n color: config.stroke || \"#00f2ff\",\n fill: config.fill || \"rgba(0, 242, 255, 0.15)\",\n };\n }\n\n function pixelToData(pixel: { x: number; y: number }): RoiPoint {\n if (!ctx) return { x: 0, y: 0 };\n return {\n x: ctx.coords.pixelToDataX(pixel.x),\n y: ctx.coords.pixelToDataY(pixel.y),\n };\n }\n\n function dataToPixel(point: RoiPoint): { x: number; y: number } {\n if (!ctx) return { x: 0, y: 0 };\n return {\n x: ctx.coords.dataToPixelX(point.x),\n y: ctx.coords.dataToPixelY(point.y),\n };\n }\n\n function isPointInAnyRegion(point: RoiPoint): boolean {\n if (regions.length === 0) return true; // Show all if no regions defined\n return regions.some((r) => isPointInRegion(point, r));\n }\n\n function applyMasking(): void {\n if (!ctx || !isMasking) return;\n\n for (const [id, raw] of rawDataStore.entries()) {\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) {\n indices.push(i);\n }\n }\n\n const filteredX = new Float32Array(indices.length);\n const filteredY = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n filteredX[i] = raw.x[indices[i]];\n filteredY[i] = raw.y[indices[i]];\n }\n\n if (originalUpdateSeries) {\n originalUpdateSeries(id, { x: filteredX, y: filteredY });\n }\n }\n }\n\n function isPointInRegion(point: RoiPoint, region: RoiRegion): boolean {\n const { tool, points } = region;\n if (points.length < 2) return false;\n\n if (tool === \"rectangle\") {\n const xMin = Math.min(points[0].x, points[1].x);\n const xMax = Math.max(points[0].x, points[1].x);\n const yMin = Math.min(points[0].y, points[1].y);\n const yMax = Math.max(points[0].y, points[1].y);\n return point.x >= xMin && point.x <= xMax && point.y >= yMin && point.y <= yMax;\n }\n\n if (tool === \"circle\") {\n const dx = point.x - points[0].x;\n const dy = point.y - points[0].y;\n const r = Math.sqrt(\n Math.pow(points[1].x - points[0].x, 2) + Math.pow(points[1].y - points[0].y, 2)\n );\n return Math.sqrt(dx * dx + dy * dy) <= r;\n }\n\n if (tool === \"polygon\" || tool === \"lasso\") {\n // Ray casting algorithm\n let inside = false;\n for (let i = 0, j = points.length - 1; i < points.length; j = i++) {\n const xi = points[i].x, yi = points[i].y;\n const xj = points[j].x, yj = points[j].y;\n const intersect = yi > point.y !== yj > point.y &&\n point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n }\n\n return false;\n }\n\n function calculateMasks(regionId: string): RoiMaskResult[] {\n const region = regions.find((r) => r.id === regionId);\n if (!region || !ctx) return [];\n\n const results: RoiMaskResult[] = [];\n ctx.chart.getAllSeries().forEach((series) => {\n const data = series.getData();\n if (!data) return;\n\n const masks = new Array(data.x.length);\n for (let i = 0; i < data.x.length; i++) {\n masks[i] = isPointInRegion({ x: data.x[i], y: data.y[i] }, region);\n }\n\n results.push({\n regionId,\n seriesId: series.getId(),\n masks,\n });\n });\n\n return results;\n }\n\n function finishRegion(): void {\n if (!activeRegion || !ctx) return;\n \n // Clean up preview points for polygon\n if (activeRegion.tool === \"polygon\" && activeRegion.points.length > 1) {\n // Remove the preview point\n activeRegion.points.pop();\n }\n\n regions.push(activeRegion);\n\n if (isMasking) {\n applyMasking();\n }\n\n const event: RoiSelectedEvent = {\n region: activeRegion,\n seriesIds: ctx.chart.getAllSeries().map((s) => s.getId()),\n masks: calculateMasks(activeRegion.id),\n };\n\n // Emit on both plugin context and chart\n ctx.events.emit(\"roi:selected\", event);\n if (ctx.chart.events) {\n ctx.chart.events.emit(\"roi:selected\" as any, event);\n }\n \n ctx.events.emit(\"roi:created\", {\n region: activeRegion,\n seriesIds: event.seriesIds,\n });\n\n activeRegion = null;\n isDrawing = false;\n ctx.requestRender();\n }\n\n function handlePointerDown(event: InteractionEvent): void {\n if (!enabled || !event.inPlotArea) return;\n\n if (activeTool === \"polygon\" && activeRegion) {\n // For polygon, we keep adding points on click\n // But first, replace the preview point with a permanent one\n const previewPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n activeRegion.points.push(previewPoint);\n event.preventDefault();\n ctx?.requestRender();\n return;\n }\n\n isDrawing = true;\n activeRegion = createRegion(activeTool);\n const startPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n activeRegion.points.push(startPoint);\n \n if (activeTool === \"rectangle\" || activeTool === \"circle\") {\n activeRegion.points.push({ ...startPoint });\n } else if (activeTool === \"polygon\") {\n // Add a second point for preview\n activeRegion.points.push({ ...startPoint });\n }\n \n event.preventDefault(); // Stop chart from panning\n ctx?.requestRender();\n }\n\n function handlePointerMove(event: InteractionEvent): void {\n if (!enabled || !isDrawing || !activeRegion) return;\n\n if (activeTool === \"rectangle\" || activeTool === \"circle\") {\n activeRegion.points[1] = pixelToData({ x: event.pixelX, y: event.pixelY });\n } else if (activeTool === \"lasso\") {\n // For lasso, we capture points during movement\n const lastPoint = activeRegion.points[activeRegion.points.length - 1];\n const newPoint = pixelToData({ x: event.pixelX, y: event.pixelY });\n \n // Basic distance filter to avoid too many points\n const dx = ctx!.coords.dataToPixelX(newPoint.x) - ctx!.coords.dataToPixelX(lastPoint.x);\n const dy = ctx!.coords.dataToPixelY(newPoint.y) - ctx!.coords.dataToPixelY(lastPoint.y);\n if (Math.sqrt(dx*dx + dy*dy) > 5) {\n activeRegion.points.push(newPoint);\n }\n } else if (activeTool === \"polygon\") {\n // Update the preview point (the last one)\n const lastIndex = activeRegion.points.length - 1;\n if (lastIndex >= 0) {\n activeRegion.points[lastIndex] = pixelToData({ x: event.pixelX, y: event.pixelY });\n }\n }\n ctx?.requestRender();\n }\n\n function handlePointerUp(_event: InteractionEvent): void {\n if (!isDrawing || !activeRegion) return;\n\n if (activeTool !== \"polygon\") {\n finishRegion();\n }\n }\n\n function drawRegion(region: RoiRegion, ctx2d: CanvasRenderingContext2D): void {\n const { tool, points, color, fill } = region;\n if (points.length < 1) return;\n\n const pixels = points.map((p) => dataToPixel(p));\n\n ctx2d.strokeStyle = color || \"#00f2ff\";\n ctx2d.fillStyle = fill || \"rgba(0, 242, 255, 0.15)\";\n ctx2d.lineWidth = 2;\n\n if (tool === \"rectangle\" && pixels.length >= 2) {\n const x = Math.min(pixels[0].x, pixels[1].x);\n const y = Math.min(pixels[0].y, pixels[1].y);\n const w = Math.abs(pixels[0].x - pixels[1].x);\n const h = Math.abs(pixels[0].y - pixels[1].y);\n ctx2d.fillRect(x, y, w, h);\n ctx2d.strokeRect(x, y, w, h);\n } else if (tool === \"circle\" && pixels.length >= 2) {\n const dx = pixels[1].x - pixels[0].x;\n const dy = pixels[1].y - pixels[0].y;\n const r = Math.sqrt(dx * dx + dy * dy);\n ctx2d.beginPath();\n ctx2d.arc(pixels[0].x, pixels[0].y, r, 0, Math.PI * 2);\n ctx2d.fill();\n ctx2d.stroke();\n } else if ((tool === \"polygon\" || tool === \"lasso\") && pixels.length >= 2) {\n ctx2d.beginPath();\n ctx2d.moveTo(pixels[0].x, pixels[0].y);\n pixels.slice(1).forEach((p) => ctx2d.lineTo(p.x, p.y));\n if (tool === \"lasso\") {\n ctx2d.closePath();\n } else if (!isDrawing || region !== activeRegion) {\n ctx2d.closePath();\n }\n ctx2d.fill();\n ctx2d.stroke();\n }\n }\n\n return {\n manifest,\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n const chart = ctx.chart as any;\n\n // Hijack series methods if masking is enabled\n originalUpdateSeries = chart.updateSeries.bind(chart);\n originalAddSeries = chart.addSeries.bind(chart);\n\n chart.addSeries = (options: any) => {\n if (options.id && options.data?.x) {\n rawDataStore.set(options.id, {\n x: new Float32Array(options.data.x),\n y: new Float32Array(options.data.y),\n });\n }\n if (isMasking && options.data?.x) {\n // Apply initial mask\n const raw = rawDataStore.get(options.id)!;\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) indices.push(i);\n }\n const fx = new Float32Array(indices.length);\n const fy = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n fx[i] = raw.x[indices[i]];\n fy[i] = raw.y[indices[i]];\n }\n originalAddSeries({ ...options, data: { ...options.data, x: fx, y: fy } });\n } else {\n originalAddSeries(options);\n }\n };\n\n chart.updateSeries = (id: string, data: any) => {\n if (data.x) {\n rawDataStore.set(id, {\n x: new Float32Array(data.x),\n y: new Float32Array(data.y),\n });\n }\n if (isMasking && data.x) {\n const raw = rawDataStore.get(id)!;\n const indices: number[] = [];\n for (let i = 0; i < raw.x.length; i++) {\n if (isPointInAnyRegion({ x: raw.x[i], y: raw.y[i] })) indices.push(i);\n }\n const fx = new Float32Array(indices.length);\n const fy = new Float32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n fx[i] = raw.x[indices[i]];\n fy[i] = raw.y[indices[i]];\n }\n originalUpdateSeries(id, { ...data, x: fx, y: fy });\n } else {\n originalUpdateSeries(id, data);\n }\n };\n },\n onDestroy() {\n if (ctx) {\n const chart = ctx.chart as any;\n chart.addSeries = originalAddSeries;\n chart.updateSeries = originalUpdateSeries;\n }\n ctx = null;\n rawDataStore.clear();\n },\n onInteraction(_pluginCtx: PluginContext, event: InteractionEvent) {\n if (event.type === \"mousedown\") handlePointerDown(event);\n if (event.type === \"mousemove\") handlePointerMove(event);\n if (event.type === \"mouseup\") handlePointerUp(event);\n \n // Handle double click to finish polygon\n if (event.type === \"mouseup\" && activeTool === \"polygon\" && isDrawing) {\n // Simple double click detection\n // For now, let's just use a more complex logic or a button if needed.\n // In this implementation, let's say 3 clicks on the same area or just let it be.\n }\n \n // Special: right click or double click to finish polygon\n if (event.originalEvent instanceof MouseEvent && event.originalEvent.detail === 2 && activeTool === \"polygon\") {\n finishRegion();\n event.preventDefault();\n }\n },\n onRenderOverlay(pluginCtx: PluginContext) {\n const ctx2d = pluginCtx.render.ctx2d;\n if (!ctx2d) return;\n\n regions.forEach((region) => drawRegion(region, ctx2d));\n if (activeRegion) drawRegion(activeRegion, ctx2d);\n },\n onExportSVG(svgCtx: SVGExportPluginContext) {\n if (!svgCtx.builder || svgCtx.exportContext?.options.includeOverlays === false) return;\n exportRoiRegions(svgCtx, regions);\n },\n api: {\n setTool(tool: RoiTool) {\n activeTool = tool;\n if (isDrawing) finishRegion();\n },\n clear() {\n regions = [];\n activeRegion = null;\n isDrawing = false;\n if (isMasking) applyMasking();\n if (ctx) {\n ctx.events.emit(\"roi:cleared\", {});\n ctx.requestRender();\n }\n },\n getRegions() {\n return [...regions];\n },\n removeRegion(id: string) {\n regions = regions.filter((r) => r.id !== id);\n if (isMasking) applyMasking();\n if (ctx) ctx.requestRender();\n },\n calculateMasks,\n isEnabled: () => enabled,\n setEnabled: (e: boolean) => {\n enabled = e;\n },\n setMasking(mask: boolean) {\n isMasking = mask;\n if (mask) {\n applyMasking();\n } else {\n // Restore all original data\n if (ctx) {\n for (const [id, raw] of rawDataStore.entries()) {\n originalUpdateSeries(id, raw);\n }\n ctx.requestRender();\n }\n }\n },\n } as RoiAPI,\n };\n};\n\nexport type RoiEvent = \"roi:selected\" | \"roi:created\" | \"roi:cleared\";\n"],"names":["exportRoiRegions","ctx","regions","yScale","primaryYScale","toPx","p","region","stroke","fill","pixels","x","y","w","h","fmt","dx","dy","r","pts","PluginROI","config","activeTool","isDrawing","activeRegion","enabled","isMasking","rawDataStore","originalUpdateSeries","originalAddSeries","manifest","createRegion","tool","pixelToData","pixel","dataToPixel","point","isPointInAnyRegion","isPointInRegion","applyMasking","id","raw","indices","i","filteredX","filteredY","points","xMin","xMax","yMin","yMax","inside","j","xi","yi","xj","yj","calculateMasks","regionId","results","series","data","masks","finishRegion","event","s","handlePointerDown","previewPoint","startPoint","handlePointerMove","lastPoint","newPoint","lastIndex","handlePointerUp","_event","drawRegion","ctx2d","color","pluginCtx","chart","options","_a","_b","fx","fy","_pluginCtx","svgCtx","mask"],"mappings":"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"}
|