@jax-data-science/sci-image-visualizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +404 -0
- package/esm2022/index.mjs +52 -0
- package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
- package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
- package/esm2022/lib/contracts/display-types.mjs +8 -0
- package/esm2022/lib/contracts/image.contract.mjs +11 -0
- package/esm2022/lib/contracts/intensity.mjs +28 -0
- package/esm2022/lib/contracts/plot-type.mjs +112 -0
- package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
- package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
- package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
- package/esm2022/lib/contracts/sam.contract.mjs +12 -0
- package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
- package/esm2022/lib/contracts/viz-config.mjs +3 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
- package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
- package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
- package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
- package/esm2022/lib/models/bezier.mjs +120 -0
- package/esm2022/lib/models/class-preset.mjs +46 -0
- package/esm2022/lib/models/geometry.mjs +198 -0
- package/esm2022/lib/models/region.mjs +166 -0
- package/esm2022/lib/models/shape.mjs +53 -0
- package/esm2022/lib/plot.utilities.mjs +693 -0
- package/esm2022/lib/processing/image-converter.service.mjs +90 -0
- package/esm2022/lib/processing/image-crop.mjs +62 -0
- package/esm2022/lib/processing/processing-image.mjs +50 -0
- package/esm2022/lib/provide-visualization.mjs +63 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
- package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
- package/esm2022/lib/region-ops.service.mjs +301 -0
- package/esm2022/lib/render-orchestrator.mjs +87 -0
- package/esm2022/lib/routing-visualizer.service.mjs +533 -0
- package/esm2022/lib/store/class-color.util.mjs +52 -0
- package/esm2022/lib/store/region-store.service.mjs +1029 -0
- package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
- package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
- package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
- package/esm2022/lib/visualization.module.mjs +162 -0
- package/esm2022/lib/visualizer.component.mjs +1597 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
- package/fesm2022/mask.worker.js +989 -0
- package/fesm2022/onnx-sam.worker.js +202 -0
- package/index.d.ts +39 -0
- package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
- package/lib/contracts/capabilities.contract.d.ts +30 -0
- package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
- package/lib/contracts/colormap-lut.d.ts +21 -0
- package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
- package/lib/contracts/display-types.d.ts +41 -0
- package/lib/contracts/image.contract.d.ts +72 -0
- package/lib/contracts/intensity.d.ts +18 -0
- package/lib/contracts/plot-type.d.ts +108 -0
- package/lib/contracts/ports/image-state.port.d.ts +29 -0
- package/lib/contracts/ports/preferences.port.d.ts +19 -0
- package/lib/contracts/ports/region-io.port.d.ts +29 -0
- package/lib/contracts/ports/tile-access.port.d.ts +27 -0
- package/lib/contracts/region-editor-api.contract.d.ts +83 -0
- package/lib/contracts/region-overlay.contract.d.ts +47 -0
- package/lib/contracts/region-store.contract.d.ts +74 -0
- package/lib/contracts/sam.contract.d.ts +98 -0
- package/lib/contracts/toolbar-config.d.ts +24 -0
- package/lib/contracts/visualizer.contract.d.ts +346 -0
- package/lib/contracts/viz-config.d.ts +25 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
- package/lib/implementations/base-store-visualizer.d.ts +71 -0
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
- package/lib/implementations/osd/display-pipeline.d.ts +47 -0
- package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
- package/lib/implementations/osd/osd-coords.d.ts +16 -0
- package/lib/implementations/osd/osd-lib.d.ts +19 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
- package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
- package/lib/implementations/osd/slice-cache.d.ts +161 -0
- package/lib/implementations/osd/tile-client.d.ts +32 -0
- package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
- package/lib/implementations/plotly/plotly.service.d.ts +594 -0
- package/lib/implementations/simple-slice-access.service.d.ts +64 -0
- package/lib/models/bezier.d.ts +59 -0
- package/lib/models/class-preset.d.ts +39 -0
- package/lib/models/geometry.d.ts +66 -0
- package/lib/models/region.d.ts +132 -0
- package/lib/models/shape.d.ts +44 -0
- package/lib/plot.utilities.d.ts +107 -0
- package/lib/processing/image-converter.service.d.ts +28 -0
- package/lib/processing/image-crop.d.ts +18 -0
- package/lib/processing/processing-image.d.ts +17 -0
- package/lib/provide-visualization.d.ts +34 -0
- package/lib/region-editor/mask-raster.d.ts +61 -0
- package/lib/region-editor/mask-worker.d.ts +7 -0
- package/lib/region-editor/region-editor.component.d.ts +305 -0
- package/lib/region-ops.service.d.ts +92 -0
- package/lib/render-orchestrator.d.ts +59 -0
- package/lib/routing-visualizer.service.d.ts +227 -0
- package/lib/store/class-color.util.d.ts +26 -0
- package/lib/store/region-store.service.d.ts +315 -0
- package/lib/store/visualizer-store.service.d.ts +123 -0
- package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
- package/lib/toolbar/crop/slide-crop.d.ts +30 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
- package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
- package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
- package/lib/toolbar/toolbar.component.d.ts +167 -0
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
- package/lib/toolbar/wand/wand.service.d.ts +133 -0
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
- package/lib/visualization.module.d.ts +45 -0
- package/lib/visualizer.component.d.ts +378 -0
- package/package.json +73 -0
- package/src/lib/assets/3d-coordinates.svg +49 -0
- package/src/lib/assets/cells.svg +1 -0
- package/src/lib/assets/click.svg +1 -0
- package/src/lib/assets/colormap-luts.json +1 -0
- package/src/lib/assets/contour.svg +48 -0
- package/src/lib/assets/cube-3d.svg +1 -0
- package/src/lib/assets/edit-selection-white.svg +47 -0
- package/src/lib/assets/heatmap.svg +1 -0
- package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
- package/src/lib/assets/icons/colormap-accent.png +0 -0
- package/src/lib/assets/icons/colormap-afmhot.png +0 -0
- package/src/lib/assets/icons/colormap-autumn.png +0 -0
- package/src/lib/assets/icons/colormap-berlin.png +0 -0
- package/src/lib/assets/icons/colormap-binary.png +0 -0
- package/src/lib/assets/icons/colormap-blackbody.png +0 -0
- package/src/lib/assets/icons/colormap-bluered.png +0 -0
- package/src/lib/assets/icons/colormap-blues.png +0 -0
- package/src/lib/assets/icons/colormap-bone.png +0 -0
- package/src/lib/assets/icons/colormap-brbg.png +0 -0
- package/src/lib/assets/icons/colormap-brg.png +0 -0
- package/src/lib/assets/icons/colormap-bugn.png +0 -0
- package/src/lib/assets/icons/colormap-bupu.png +0 -0
- package/src/lib/assets/icons/colormap-bwr.png +0 -0
- package/src/lib/assets/icons/colormap-cividis.png +0 -0
- package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
- package/src/lib/assets/icons/colormap-cool.png +0 -0
- package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
- package/src/lib/assets/icons/colormap-copper.png +0 -0
- package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
- package/src/lib/assets/icons/colormap-dark2.png +0 -0
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-electric.png +0 -0
- package/src/lib/assets/icons/colormap-flag.png +0 -0
- package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
- package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
- package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
- package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
- package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
- package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
- package/src/lib/assets/icons/colormap-gnbu.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
- package/src/lib/assets/icons/colormap-gray.png +0 -0
- package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greens.png +0 -0
- package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greys.png +0 -0
- package/src/lib/assets/icons/colormap-hot.png +0 -0
- package/src/lib/assets/icons/colormap-hsv.png +0 -0
- package/src/lib/assets/icons/colormap-inferno.png +0 -0
- package/src/lib/assets/icons/colormap-jet.png +0 -0
- package/src/lib/assets/icons/colormap-magma.png +0 -0
- package/src/lib/assets/icons/colormap-managua.png +0 -0
- package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
- package/src/lib/assets/icons/colormap-ocean.png +0 -0
- package/src/lib/assets/icons/colormap-oranges.png +0 -0
- package/src/lib/assets/icons/colormap-orrd.png +0 -0
- package/src/lib/assets/icons/colormap-pastel2.png +0 -0
- package/src/lib/assets/icons/colormap-picnic.png +0 -0
- package/src/lib/assets/icons/colormap-pink.png +0 -0
- package/src/lib/assets/icons/colormap-piyg.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-plasma.png +0 -0
- package/src/lib/assets/icons/colormap-portland.png +0 -0
- package/src/lib/assets/icons/colormap-prgn.png +0 -0
- package/src/lib/assets/icons/colormap-prism.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/icons/colormap-pubugn.png +0 -0
- package/src/lib/assets/icons/colormap-puor.png +0 -0
- package/src/lib/assets/icons/colormap-purd.png +0 -0
- package/src/lib/assets/icons/colormap-purples.png +0 -0
- package/src/lib/assets/icons/colormap-rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-rdbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdgy.png +0 -0
- package/src/lib/assets/icons/colormap-rdpu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
- package/src/lib/assets/icons/colormap-reds.png +0 -0
- package/src/lib/assets/icons/colormap-seismic.png +0 -0
- package/src/lib/assets/icons/colormap-set1.png +0 -0
- package/src/lib/assets/icons/colormap-set2.png +0 -0
- package/src/lib/assets/icons/colormap-set3.png +0 -0
- package/src/lib/assets/icons/colormap-spectral.png +0 -0
- package/src/lib/assets/icons/colormap-spring.png +0 -0
- package/src/lib/assets/icons/colormap-summer.png +0 -0
- package/src/lib/assets/icons/colormap-tab10.png +0 -0
- package/src/lib/assets/icons/colormap-tab20.png +0 -0
- package/src/lib/assets/icons/colormap-tab20b.png +0 -0
- package/src/lib/assets/icons/colormap-tab20c.png +0 -0
- package/src/lib/assets/icons/colormap-terrain.png +0 -0
- package/src/lib/assets/icons/colormap-turbo.png +0 -0
- package/src/lib/assets/icons/colormap-twilight.png +0 -0
- package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
- package/src/lib/assets/icons/colormap-vanimo.png +0 -0
- package/src/lib/assets/icons/colormap-viridis.png +0 -0
- package/src/lib/assets/icons/colormap-winter.png +0 -0
- package/src/lib/assets/icons/colormap-wistia.png +0 -0
- package/src/lib/assets/icons/colormap-ylgn.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
- package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
- package/src/lib/assets/invert.svg +1 -0
- package/src/lib/assets/isosurface.svg +7 -0
- package/src/lib/assets/mask.svg +1 -0
- package/src/lib/assets/paintbrush.svg +1 -0
- package/src/lib/assets/picture-segmentation.svg +43 -0
- package/src/lib/assets/polygon-vertices.svg +13 -0
- package/src/lib/assets/polyline.svg +3 -0
- package/src/lib/assets/redo.svg +39 -0
- package/src/lib/assets/region-editor.svg +37 -0
- package/src/lib/assets/region-move.svg +7 -0
- package/src/lib/assets/smooth.svg +56 -0
- package/src/lib/assets/spline-chart.svg +7 -0
- package/src/lib/assets/surface.svg +37 -0
- package/src/lib/assets/test/download-379.svg +1 -0
- package/src/lib/assets/test/download-98.svg +1 -0
- package/src/lib/assets/test/json-1.svg +1 -0
- package/src/lib/assets/test/load-53.svg +1 -0
- package/src/lib/assets/test/mask-44.svg +1 -0
- package/src/lib/assets/test/mask-download-44.svg +15 -0
- package/src/lib/assets/test/mask-save-44.svg +11 -0
- package/src/lib/assets/test/overlay-1.svg +1 -0
- package/src/lib/assets/test/overlay-4.svg +1 -0
- package/src/lib/assets/test/region-26.svg +1 -0
- package/src/lib/assets/test/save-56.svg +1 -0
- package/src/lib/assets/test/upload-43.svg +1 -0
- package/src/lib/assets/to-bezier.svg +15 -0
- package/src/lib/assets/to-polygon.svg +11 -0
- package/src/lib/assets/undo.svg +38 -0
- package/src/lib/assets/vertex-add.svg +12 -0
- package/src/lib/assets/vertex-delete.svg +12 -0
- package/src/lib/assets/wand.svg +54 -0
- package/src/lib/assets/zoom-box.svg +10 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { WandService } from '../wand/wand.service';
|
|
3
|
+
import { Region, Polygon } from '../../models/region';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "../wand/wand.service";
|
|
6
|
+
/**
|
|
7
|
+
* Vertex eraser. A custom canvas overlay that, on click/drag, removes any
|
|
8
|
+
* polygon vertex within `radius` matrix-pixels of the cursor from every
|
|
9
|
+
* `type: 'path'` shape on the plot. Polygons that fall below 3 vertices
|
|
10
|
+
* (or polylines below 2) are removed entirely.
|
|
11
|
+
*
|
|
12
|
+
* The cursor is rendered as a dashed-red circle on the overlay so the user
|
|
13
|
+
* can see the active radius while moving.
|
|
14
|
+
*/
|
|
15
|
+
export class VertexEraserToolService {
|
|
16
|
+
constructor(wandService) {
|
|
17
|
+
this.wandService = wandService;
|
|
18
|
+
this.overlay = null;
|
|
19
|
+
this.dragging = false;
|
|
20
|
+
/** Eraser radius in image-pixel (matrix) coordinates. */
|
|
21
|
+
this.radius = 20;
|
|
22
|
+
this.cursor = null;
|
|
23
|
+
this.boundMouseDown = (e) => this.onMouseDown(e);
|
|
24
|
+
this.boundMouseMove = (e) => this.onMouseMove(e);
|
|
25
|
+
this.boundMouseUp = (e) => this.onMouseUp(e);
|
|
26
|
+
}
|
|
27
|
+
bindHost(host) {
|
|
28
|
+
this.host = host;
|
|
29
|
+
}
|
|
30
|
+
// ── Public API ──────────────────────────────────────────────────────
|
|
31
|
+
setMode(active) {
|
|
32
|
+
if (active) {
|
|
33
|
+
this.createOverlay();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.destroyOverlay();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Set eraser radius in matrix-pixel (image pixel) coordinates. */
|
|
40
|
+
setRadius(radius) {
|
|
41
|
+
if (!Number.isFinite(radius) || radius <= 0)
|
|
42
|
+
return;
|
|
43
|
+
this.radius = radius;
|
|
44
|
+
this.drawCursor();
|
|
45
|
+
}
|
|
46
|
+
// ── Overlay lifecycle ───────────────────────────────────────────────
|
|
47
|
+
createOverlay() {
|
|
48
|
+
const plotEl = this.host.getOverlayContainer();
|
|
49
|
+
if (!plotEl || this.overlay)
|
|
50
|
+
return;
|
|
51
|
+
const canvas = document.createElement('canvas');
|
|
52
|
+
canvas.style.position = 'absolute';
|
|
53
|
+
canvas.style.top = '0';
|
|
54
|
+
canvas.style.left = '0';
|
|
55
|
+
canvas.style.width = '100%';
|
|
56
|
+
canvas.style.height = '100%';
|
|
57
|
+
canvas.style.cursor = 'crosshair';
|
|
58
|
+
canvas.style.zIndex = '100';
|
|
59
|
+
canvas.width = plotEl.offsetWidth;
|
|
60
|
+
canvas.height = plotEl.offsetHeight;
|
|
61
|
+
plotEl.appendChild(canvas);
|
|
62
|
+
this.overlay = canvas;
|
|
63
|
+
canvas.addEventListener('mousedown', this.boundMouseDown);
|
|
64
|
+
canvas.addEventListener('mousemove', this.boundMouseMove);
|
|
65
|
+
canvas.addEventListener('mouseup', this.boundMouseUp);
|
|
66
|
+
canvas.addEventListener('mouseleave', this.boundMouseUp);
|
|
67
|
+
}
|
|
68
|
+
destroyOverlay() {
|
|
69
|
+
if (!this.overlay)
|
|
70
|
+
return;
|
|
71
|
+
this.overlay.removeEventListener('mousedown', this.boundMouseDown);
|
|
72
|
+
this.overlay.removeEventListener('mousemove', this.boundMouseMove);
|
|
73
|
+
this.overlay.removeEventListener('mouseup', this.boundMouseUp);
|
|
74
|
+
this.overlay.removeEventListener('mouseleave', this.boundMouseUp);
|
|
75
|
+
this.overlay.remove();
|
|
76
|
+
this.overlay = null;
|
|
77
|
+
this.dragging = false;
|
|
78
|
+
this.cursor = null;
|
|
79
|
+
}
|
|
80
|
+
// ── Mouse handlers ──────────────────────────────────────────────────
|
|
81
|
+
onMouseDown(e) {
|
|
82
|
+
if (e.button !== 0)
|
|
83
|
+
return;
|
|
84
|
+
this.dragging = true;
|
|
85
|
+
this.updateCursor(e);
|
|
86
|
+
this.applyAtClient(e);
|
|
87
|
+
}
|
|
88
|
+
onMouseMove(e) {
|
|
89
|
+
this.updateCursor(e);
|
|
90
|
+
if (!this.dragging) {
|
|
91
|
+
this.drawCursor();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if ((e.buttons & 1) === 0) {
|
|
95
|
+
this.dragging = false;
|
|
96
|
+
this.drawCursor();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.applyAtClient(e);
|
|
100
|
+
this.drawCursor();
|
|
101
|
+
}
|
|
102
|
+
onMouseUp(_) {
|
|
103
|
+
this.dragging = false;
|
|
104
|
+
}
|
|
105
|
+
updateCursor(e) {
|
|
106
|
+
if (!this.overlay)
|
|
107
|
+
return;
|
|
108
|
+
const rect = this.overlay.getBoundingClientRect();
|
|
109
|
+
this.cursor = { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
110
|
+
}
|
|
111
|
+
/** Draw the eraser radius circle at the current cursor position. */
|
|
112
|
+
drawCursor() {
|
|
113
|
+
if (!this.overlay)
|
|
114
|
+
return;
|
|
115
|
+
const ctx = this.overlay.getContext('2d');
|
|
116
|
+
if (!ctx)
|
|
117
|
+
return;
|
|
118
|
+
ctx.clearRect(0, 0, this.overlay.width, this.overlay.height);
|
|
119
|
+
if (!this.cursor)
|
|
120
|
+
return;
|
|
121
|
+
const transform = this.host.getCoordinateTransform();
|
|
122
|
+
if (!transform.isReady())
|
|
123
|
+
return;
|
|
124
|
+
// Convert matrix-pixel radius to screen-pixel radius via the data scale.
|
|
125
|
+
const rx = this.host.getCachedImageRatio();
|
|
126
|
+
const screenRadius = transform.dataLengthToScreen(this.radius * rx);
|
|
127
|
+
if (!Number.isFinite(screenRadius) || screenRadius <= 0)
|
|
128
|
+
return;
|
|
129
|
+
ctx.save();
|
|
130
|
+
ctx.strokeStyle = 'rgba(255, 80, 80, 0.9)';
|
|
131
|
+
ctx.lineWidth = 1.5;
|
|
132
|
+
ctx.setLineDash([4, 3]);
|
|
133
|
+
ctx.beginPath();
|
|
134
|
+
ctx.arc(this.cursor.x, this.cursor.y, screenRadius, 0, Math.PI * 2);
|
|
135
|
+
ctx.stroke();
|
|
136
|
+
ctx.restore();
|
|
137
|
+
}
|
|
138
|
+
// ── Per-tick erase logic ────────────────────────────────────────────
|
|
139
|
+
/**
|
|
140
|
+
* Drop every vertex of every path-shape that lies within the eraser's
|
|
141
|
+
* radius of the cursor. Polygons reduced below 3 vertices (or polylines
|
|
142
|
+
* below 2) are removed entirely.
|
|
143
|
+
*/
|
|
144
|
+
applyAtClient(e) {
|
|
145
|
+
if (!this.overlay)
|
|
146
|
+
return;
|
|
147
|
+
const regions = this.host.getRegions();
|
|
148
|
+
if (!regions || regions.length === 0)
|
|
149
|
+
return;
|
|
150
|
+
const transform = this.host.getCoordinateTransform();
|
|
151
|
+
if (!transform.isReady())
|
|
152
|
+
return;
|
|
153
|
+
const { x: dataX, y: dataY } = transform.clientToData(e.clientX, e.clientY);
|
|
154
|
+
if (!Number.isFinite(dataX) || !Number.isFinite(dataY))
|
|
155
|
+
return;
|
|
156
|
+
const rx = this.host.getCachedImageRatio();
|
|
157
|
+
const cmx = dataX / rx;
|
|
158
|
+
const cmy = dataY / rx;
|
|
159
|
+
let anyChange = false;
|
|
160
|
+
for (let i = regions.length - 1; i >= 0; i--) {
|
|
161
|
+
const region = regions[i];
|
|
162
|
+
const b = region?.bounds;
|
|
163
|
+
if (!(b instanceof Polygon) || b.xpoints.length === 0)
|
|
164
|
+
continue;
|
|
165
|
+
const closed = b.closed !== false;
|
|
166
|
+
const xs = b.xpoints.map(x => x / rx);
|
|
167
|
+
const ys = b.ypoints.map(y => y / rx);
|
|
168
|
+
const result = this.wandService.dropVerticesWithinRadius(xs, ys, cmx, cmy, this.radius);
|
|
169
|
+
// Erase vertices on interior rings (a donut's inner outline) too, and drop
|
|
170
|
+
// a hole that degenerates below a triangle (jit-ui#85).
|
|
171
|
+
let holesChanged = false;
|
|
172
|
+
let newHoles;
|
|
173
|
+
if (b.holes) {
|
|
174
|
+
newHoles = [];
|
|
175
|
+
for (const ring of b.holes) {
|
|
176
|
+
const hr = this.wandService.dropVerticesWithinRadius(ring.map(p => p[0] / rx), ring.map(p => p[1] / rx), cmx, cmy, this.radius);
|
|
177
|
+
if (hr.removed === 0) {
|
|
178
|
+
newHoles.push(ring); // untouched — keep as-is
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
holesChanged = true;
|
|
182
|
+
if (hr.xpoints.length >= 3) {
|
|
183
|
+
newHoles.push(hr.xpoints.map((x, k) => [x * rx, hr.ypoints[k] * rx]));
|
|
184
|
+
} // else: hole collapsed — drop it
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (newHoles.length === 0)
|
|
188
|
+
newHoles = undefined;
|
|
189
|
+
}
|
|
190
|
+
if (result.removed === 0 && !holesChanged)
|
|
191
|
+
continue;
|
|
192
|
+
anyChange = true;
|
|
193
|
+
const minVerts = closed ? 3 : 2;
|
|
194
|
+
if (result.xpoints.length < minVerts) {
|
|
195
|
+
// Region became degenerate — remove it.
|
|
196
|
+
regions.splice(i, 1);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
// Rebuild the polygon in image/data coords. Drop any stored bezier
|
|
200
|
+
// handles (the anchor count changed) — they re-derive from the new anchors.
|
|
201
|
+
const xPlot = result.xpoints.map(x => x * rx);
|
|
202
|
+
const yPlot = result.ypoints.map(y => y * rx);
|
|
203
|
+
const poly = new Polygon();
|
|
204
|
+
poly.npoints = xPlot.length;
|
|
205
|
+
poly.xpoints = xPlot;
|
|
206
|
+
poly.ypoints = yPlot;
|
|
207
|
+
poly.coordinates = xPlot.map((x, k) => [x, yPlot[k]]);
|
|
208
|
+
poly.closed = closed;
|
|
209
|
+
poly.bezier = b.bezier;
|
|
210
|
+
if (newHoles && newHoles.length)
|
|
211
|
+
poly.holes = newHoles;
|
|
212
|
+
const nr = new Region();
|
|
213
|
+
nr.id = region.id;
|
|
214
|
+
nr.name = region.name;
|
|
215
|
+
nr.label = region.label;
|
|
216
|
+
nr.color = region.color;
|
|
217
|
+
nr.bounds = poly;
|
|
218
|
+
regions[i] = nr;
|
|
219
|
+
}
|
|
220
|
+
if (!anyChange)
|
|
221
|
+
return;
|
|
222
|
+
// The wand's stroke mask becomes stale once we trim vertices off any
|
|
223
|
+
// region — drop it so the next wand interaction re-adopts or restarts.
|
|
224
|
+
this.host.invalidateWandRegion();
|
|
225
|
+
this.host.setRegions(regions);
|
|
226
|
+
}
|
|
227
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: VertexEraserToolService, deps: [{ token: i1.WandService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
228
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: VertexEraserToolService, providedIn: 'root' }); }
|
|
229
|
+
}
|
|
230
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: VertexEraserToolService, decorators: [{
|
|
231
|
+
type: Injectable,
|
|
232
|
+
args: [{ providedIn: 'root' }]
|
|
233
|
+
}], ctorParameters: () => [{ type: i1.WandService }] });
|
|
234
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVydGV4LWVyYXNlci10b29sLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL3Rvb2xiYXIvdmVydGV4LWVyYXNlci92ZXJ0ZXgtZXJhc2VyLXRvb2wuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVuRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7QUFzQnREOzs7Ozs7OztHQVFHO0FBRUgsTUFBTSxPQUFPLHVCQUF1QjtJQWFsQyxZQUFvQixXQUF3QjtRQUF4QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQVZwQyxZQUFPLEdBQTZCLElBQUksQ0FBQztRQUN6QyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLHlEQUF5RDtRQUNqRCxXQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ1osV0FBTSxHQUFvQyxJQUFJLENBQUM7UUFPckQsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsY0FBYyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELFFBQVEsQ0FBQyxJQUEwQjtRQUNqQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNuQixDQUFDO0lBRUQsdUVBQXVFO0lBRXZFLE9BQU8sQ0FBQyxNQUFlO1FBQ3JCLElB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QUFDLEtBQUssQ0FBQztZQUN4QixFQUFFLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqQixPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLENBQUM7UUFFRCxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFDdkIscUVBQXFFO1FBQ3JFLHVFQUF1RTtRQUN2RSxJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDaEMsQ0FBQzs4R0FoT1UsdUJBQXVCO2tIQUF2Qix1QkFBdUIsY0FEVixNQUFNOzsyRkFDbkIsdUJBQXVCO2tCQURuQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgV2FuZFNlcnZpY2UgfSBmcm9tICcuLi93YW5kL3dhbmQuc2VydmljZSc7XG5pbXBvcnQgeyBJVmlld3BvcnRIb3N0LCBJUmVnaW9uRGF0YUhvc3QgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY29vcmRpbmF0ZS10cmFuc2Zvcm0uY29udHJhY3QnO1xuaW1wb3J0IHsgUmVnaW9uLCBQb2x5Z29uIH0gZnJvbSAnLi4vLi4vbW9kZWxzL3JlZ2lvbic7XG5cbi8qKlxuICogQ29sbGFib3JhdGlvbiBpbnRlcmZhY2UgdGhlIHZlcnRleCBlcmFzZXIgbmVlZHMgZnJvbSBpdHMgaG9zdCBiYWNrZW5kLlxuICpcbiAqIEV4dGVuZHMge0BsaW5rIElWaWV3cG9ydEhvc3R9IGZvciBjb29yZGluYXRlIGNvbnZlcnNpb24gKyBvdmVybGF5IGF0dGFjaG1lbnQsXG4gKiBzbyB0aGUgZXJhc2VyIGlzIGJhY2tlbmQtYWdub3N0aWMgKFBsb3RseSBhbmQgT3BlblNlYWRyYWdvbiBib3RoIHNhdGlzZnkgaXQpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZlcnRleEVyYXNlclRvb2xIb3N0IGV4dGVuZHMgSVZpZXdwb3J0SG9zdCwgSVJlZ2lvbkRhdGFIb3N0IHtcbiAgLyoqXG4gICAqIERyb3AgdGhlIHdhbmQncyBpbi1wcm9ncmVzcyBzdHJva2UuIENhbGxlZCBhZnRlciB0aGUgZXJhc2VyIG1vZGlmaWVzXG4gICAqIHJlZ2lvbnMg4oCUIHRoZSB3YW5kJ3MgYWNjdW11bGF0b3IgbWF5IG5vdyByZWZlcmVuY2Ugc3RhbGUgdmVydGljZXMuXG4gICAqL1xuICBpbnZhbGlkYXRlV2FuZFJlZ2lvbigpOiB2b2lkO1xuICAvKipcbiAgICogRGF0YS1jb29yZHMtcGVyLWltYWdlLXBpeGVsIHJhdGlvICg9PSBjYWNoZWRJbWFnZVJhdGlvc1swXSB8fCAxKS4gVXNlZCB0b1xuICAgKiBjb252ZXJ0IGJldHdlZW4gbWF0cml4IGNvb3JkaW5hdGVzICh0aGUgZXJhc2VyJ3MgbmF0aXZlIHNwYWNlKSBhbmQgdGhlXG4gICAqIGJhY2tlbmQncyBkYXRhIGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgZ2V0Q2FjaGVkSW1hZ2VSYXRpbygpOiBudW1iZXI7XG59XG5cbi8qKlxuICogVmVydGV4IGVyYXNlci4gQSBjdXN0b20gY2FudmFzIG92ZXJsYXkgdGhhdCwgb24gY2xpY2svZHJhZywgcmVtb3ZlcyBhbnlcbiAqIHBvbHlnb24gdmVydGV4IHdpdGhpbiBgcmFkaXVzYCBtYXRyaXgtcGl4ZWxzIG9mIHRoZSBjdXJzb3IgZnJvbSBldmVyeVxuICogYHR5cGU6ICdwYXRoJ2Agc2hhcGUgb24gdGhlIHBsb3QuIFBvbHlnb25zIHRoYXQgZmFsbCBiZWxvdyAzIHZlcnRpY2VzXG4gKiAob3IgcG9seWxpbmVzIGJlbG93IDIpIGFyZSByZW1vdmVkIGVudGlyZWx5LlxuICpcbiAqIFRoZSBjdXJzb3IgaXMgcmVuZGVyZWQgYXMgYSBkYXNoZWQtcmVkIGNpcmNsZSBvbiB0aGUgb3ZlcmxheSBzbyB0aGUgdXNlclxuICogY2FuIHNlZSB0aGUgYWN0aXZlIHJhZGl1cyB3aGlsZSBtb3ZpbmcuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVmVydGV4RXJhc2VyVG9vbFNlcnZpY2Uge1xuXG4gIHByaXZhdGUgaG9zdCE6IFZlcnRleEVyYXNlclRvb2xIb3N0O1xuICBwcml2YXRlIG92ZXJsYXk6IEhUTUxDYW52YXNFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZHJhZ2dpbmcgPSBmYWxzZTtcbiAgLyoqIEVyYXNlciByYWRpdXMgaW4gaW1hZ2UtcGl4ZWwgKG1hdHJpeCkgY29vcmRpbmF0ZXMuICovXG4gIHByaXZhdGUgcmFkaXVzID0gMjA7XG4gIHByaXZhdGUgY3Vyc29yOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJvdW5kTW91c2VEb3duOiAoZTogTW91c2VFdmVudCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBib3VuZE1vdXNlTW92ZTogKGU6IE1vdXNlRXZlbnQpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgYm91bmRNb3VzZVVwOiAoZTogTW91c2VFdmVudCkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHdhbmRTZXJ2aWNlOiBXYW5kU2VydmljZSkge1xuICAgIHRoaXMuYm91bmRNb3VzZURvd24gPSAoZSkgPT4gdGhpcy5vbk1vdXNlRG93bihlKTtcbiAgICB0aGlzLmJvdW5kTW91c2VNb3ZlID0gKGUpID0+IHRoaXMub25Nb3VzZU1vdmUoZSk7XG4gICAgdGhpcy5ib3VuZE1vdXNlVXAgPSAoZSkgPT4gdGhpcy5vbk1vdXNlVXAoZSk7XG4gIH1cblxuICBiaW5kSG9zdChob3N0OiBWZXJ0ZXhFcmFzZXJUb29sSG9zdCkge1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gIH1cblxuICAvLyDilIDilIAgUHVibGljIEFQSSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBzZXRNb2RlKGFjdGl2ZTogYm9vbGVhbikge1xuICAgIGlmIChhY3RpdmUpIHtcbiAgICAgIHRoaXMuY3JlYXRlT3ZlcmxheSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRlc3Ryb3lPdmVybGF5KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFNldCBlcmFzZXIgcmFkaXVzIGluIG1hdHJpeC1waXhlbCAoaW1hZ2UgcGl4ZWwpIGNvb3JkaW5hdGVzLiAqL1xuICBzZXRSYWRpdXMocmFkaXVzOiBudW1iZXIpIHtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShyYWRpdXMpIHx8IHJhZGl1cyA8PSAwKSByZXR1cm47XG4gICAgdGhpcy5yYWRpdXMgPSByYWRpdXM7XG4gICAgdGhpcy5kcmF3Q3Vyc29yKCk7XG4gIH1cblxuICAvLyDilIDilIAgT3ZlcmxheSBsaWZlY3ljbGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBjcmVhdGVPdmVybGF5KCkge1xuICAgIGNvbnN0IHBsb3RFbCA9IHRoaXMuaG9zdC5nZXRPdmVybGF5Q29udGFpbmVyKCk7XG4gICAgaWYgKCFwbG90RWwgfHwgdGhpcy5vdmVybGF5KSByZXR1cm47XG5cbiAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICBjYW52YXMuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGNhbnZhcy5zdHlsZS50b3AgPSAnMCc7XG4gICAgY2FudmFzLnN0eWxlLmxlZnQgPSAnMCc7XG4gICAgY2FudmFzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgY2FudmFzLnN0eWxlLmN1cnNvciA9ICdjcm9zc2hhaXInO1xuICAgIGNhbnZhcy5zdHlsZS56SW5kZXggPSAnMTAwJztcbiAgICBjYW52YXMud2lkdGggPSBwbG90RWwub2Zmc2V0V2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IHBsb3RFbC5vZmZzZXRIZWlnaHQ7XG5cbiAgICBwbG90RWwuYXBwZW5kQ2hpbGQoY2FudmFzKTtcbiAgICB0aGlzLm92ZXJsYXkgPSBjYW52YXM7XG5cbiAgICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5ib3VuZE1vdXNlRG93bik7XG4gICAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMuYm91bmRNb3VzZU1vdmUpO1xuICAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5ib3VuZE1vdXNlVXApO1xuICAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgdGhpcy5ib3VuZE1vdXNlVXApO1xuICB9XG5cbiAgcHJpdmF0ZSBkZXN0cm95T3ZlcmxheSgpIHtcbiAgICBpZiAoIXRoaXMub3ZlcmxheSkgcmV0dXJuO1xuICAgIHRoaXMub3ZlcmxheS5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB0aGlzLmJvdW5kTW91c2VEb3duKTtcbiAgICB0aGlzLm92ZXJsYXkucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5ib3VuZE1vdXNlTW92ZSk7XG4gICAgdGhpcy5vdmVybGF5LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLmJvdW5kTW91c2VVcCk7XG4gICAgdGhpcy5vdmVybGF5LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCB0aGlzLmJvdW5kTW91c2VVcCk7XG4gICAgdGhpcy5vdmVybGF5LnJlbW92ZSgpO1xuICAgIHRoaXMub3ZlcmxheSA9IG51bGw7XG4gICAgdGhpcy5kcmFnZ2luZyA9IGZhbHNlO1xuICAgIHRoaXMuY3Vyc29yID0gbnVsbDtcbiAgfVxuXG4gIC8vIOKUgOKUgCBNb3VzZSBoYW5kbGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcml2YXRlIG9uTW91c2VEb3duKGU6IE1vdXNlRXZlbnQpIHtcbiAgICBpZiAoZS5idXR0b24gIT09IDApIHJldHVybjtcbiAgICB0aGlzLmRyYWdnaW5nID0gdHJ1ZTtcbiAgICB0aGlzLnVwZGF0ZUN1cnNvcihlKTtcbiAgICB0aGlzLmFwcGx5QXRDbGllbnQoZSk7XG4gIH1cblxuICBwcml2YXRlIG9uTW91c2VNb3ZlKGU6IE1vdXNlRXZlbnQpIHtcbiAgICB0aGlzLnVwZGF0ZUN1cnNvcihlKTtcbiAgICBpZiAoIXRoaXMuZHJhZ2dpbmcpIHtcbiAgICAgIHRoaXMuZHJhd0N1cnNvcigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoKGUuYnV0dG9ucyAmIDEpID09PSAwKSB7XG4gICAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmRyYXdDdXJzb3IoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hcHBseUF0Q2xpZW50KGUpO1xuICAgIHRoaXMuZHJhd0N1cnNvcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBvbk1vdXNlVXAoXzogTW91c2VFdmVudCkge1xuICAgIHRoaXMuZHJhZ2dpbmcgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlQ3Vyc29yKGU6IE1vdXNlRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMub3ZlcmxheSkgcmV0dXJuO1xuICAgIGNvbnN0IHJlY3QgPSB0aGlzLm92ZXJsYXkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdGhpcy5jdXJzb3IgPSB7IHg6IGUuY2xpZW50WCAtIHJlY3QubGVmdCwgeTogZS5jbGllbnRZIC0gcmVjdC50b3AgfTtcbiAgfVxuXG4gIC8qKiBEcmF3IHRoZSBlcmFzZXIgcmFkaXVzIGNpcmNsZSBhdCB0aGUgY3VycmVudCBjdXJzb3IgcG9zaXRpb24uICovXG4gIHByaXZhdGUgZHJhd0N1cnNvcigpIHtcbiAgICBpZiAoIXRoaXMub3ZlcmxheSkgcmV0dXJuO1xuICAgIGNvbnN0IGN0eCA9IHRoaXMub3ZlcmxheS5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGlmICghY3R4KSByZXR1cm47XG4gICAgY3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLm92ZXJsYXkud2lkdGgsIHRoaXMub3ZlcmxheS5oZWlnaHQpO1xuICAgIGlmICghdGhpcy5jdXJzb3IpIHJldHVybjtcbiAgICBjb25zdCB0cmFuc2Zvcm0gPSB0aGlzLmhvc3QuZ2V0Q29vcmRpbmF0ZVRyYW5zZm9ybSgpO1xuICAgIGlmICghdHJhbnNmb3JtLmlzUmVhZHkoKSkgcmV0dXJuO1xuICAgIC8vIENvbnZlcnQgbWF0cml4LXBpeGVsIHJhZGl1cyB0byBzY3JlZW4tcGl4ZWwgcmFkaXVzIHZpYSB0aGUgZGF0YSBzY2FsZS5cbiAgICBjb25zdCByeCA9IHRoaXMuaG9zdC5nZXRDYWNoZWRJbWFnZVJhdGlvKCk7XG4gICAgY29uc3Qgc2NyZWVuUmFkaXVzID0gdHJhbnNmb3JtLmRhdGFMZW5ndGhUb1NjcmVlbih0aGlzLnJhZGl1cyAqIHJ4KTtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShzY3JlZW5SYWRpdXMpIHx8IHNjcmVlblJhZGl1cyA8PSAwKSByZXR1cm47XG4gICAgY3R4LnNhdmUoKTtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSAncmdiYSgyNTUsIDgwLCA4MCwgMC45KSc7XG4gICAgY3R4LmxpbmVXaWR0aCA9IDEuNTtcbiAgICBjdHguc2V0TGluZURhc2goWzQsIDNdKTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgY3R4LmFyYyh0aGlzLmN1cnNvci54LCB0aGlzLmN1cnNvci55LCBzY3JlZW5SYWRpdXMsIDAsIE1hdGguUEkgKiAyKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBQZXItdGljayBlcmFzZSBsb2dpYyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogRHJvcCBldmVyeSB2ZXJ0ZXggb2YgZXZlcnkgcGF0aC1zaGFwZSB0aGF0IGxpZXMgd2l0aGluIHRoZSBlcmFzZXInc1xuICAgKiByYWRpdXMgb2YgdGhlIGN1cnNvci4gUG9seWdvbnMgcmVkdWNlZCBiZWxvdyAzIHZlcnRpY2VzIChvciBwb2x5bGluZXNcbiAgICogYmVsb3cgMikgYXJlIHJlbW92ZWQgZW50aXJlbHkuXG4gICAqL1xuICBwcml2YXRlIGFwcGx5QXRDbGllbnQoZTogTW91c2VFdmVudCkge1xuICAgIGlmICghdGhpcy5vdmVybGF5KSByZXR1cm47XG4gICAgY29uc3QgcmVnaW9ucyA9IHRoaXMuaG9zdC5nZXRSZWdpb25zKCk7XG4gICAgaWYgKCFyZWdpb25zIHx8IHJlZ2lvbnMubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICBjb25zdCB0cmFuc2Zvcm0gPSB0aGlzLmhvc3QuZ2V0Q29vcmRpbmF0ZVRyYW5zZm9ybSgpO1xuICAgIGlmICghdHJhbnNmb3JtLmlzUmVhZHkoKSkgcmV0dXJuO1xuICAgIGNvbnN0IHsgeDogZGF0YVgsIHk6IGRhdGFZIH0gPSB0cmFuc2Zvcm0uY2xpZW50VG9EYXRhKGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShkYXRhWCkgfHwgIU51bWJlci5pc0Zpbml0ZShkYXRhWSkpIHJldHVybjtcbiAgICBjb25zdCByeCA9IHRoaXMuaG9zdC5nZXRDYWNoZWRJbWFnZVJhdGlvKCk7XG4gICAgY29uc3QgY214ID0gZGF0YVggLyByeDtcbiAgICBjb25zdCBjbXkgPSBkYXRhWSAvIHJ4O1xuXG4gICAgbGV0IGFueUNoYW5nZSA9IGZhbHNlO1xuICAgIGZvciAobGV0IGkgPSByZWdpb25zLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBjb25zdCByZWdpb24gPSByZWdpb25zW2ldO1xuICAgICAgY29uc3QgYiA9IHJlZ2lvbj8uYm91bmRzO1xuICAgICAgaWYgKCEoYiBpbnN0YW5jZW9mIFBvbHlnb24pIHx8IGIueHBvaW50cy5sZW5ndGggPT09IDApIGNvbnRpbnVlO1xuICAgICAgY29uc3QgY2xvc2VkID0gYi5jbG9zZWQgIT09IGZhbHNlO1xuICAgICAgY29uc3QgeHMgPSBiLnhwb2ludHMubWFwKHggPT4geCAvIHJ4KTtcbiAgICAgIGNvbnN0IHlzID0gYi55cG9pbnRzLm1hcCh5ID0+IHkgLyByeCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMud2FuZFNlcnZpY2UuZHJvcFZlcnRpY2VzV2l0aGluUmFkaXVzKHhzLCB5cywgY214LCBjbXksIHRoaXMucmFkaXVzKTtcblxuICAgICAgLy8gRXJhc2UgdmVydGljZXMgb24gaW50ZXJpb3IgcmluZ3MgKGEgZG9udXQncyBpbm5lciBvdXRsaW5lKSB0b28sIGFuZCBkcm9wXG4gICAgICAvLyBhIGhvbGUgdGhhdCBkZWdlbmVyYXRlcyBiZWxvdyBhIHRyaWFuZ2xlIChqaXQtdWkjODUpLlxuICAgICAgbGV0IGhvbGVzQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgbGV0IG5ld0hvbGVzOiBudW1iZXJbXVtdW10gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoYi5ob2xlcykge1xuICAgICAgICBuZXdIb2xlcyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHJpbmcgb2YgYi5ob2xlcykge1xuICAgICAgICAgIGNvbnN0IGhyID0gdGhpcy53YW5kU2VydmljZS5kcm9wVmVydGljZXNXaXRoaW5SYWRpdXMoXG4gICAgICAgICAgICByaW5nLm1hcChwID0+IHBbMF0gLyByeCksIHJpbmcubWFwKHAgPT4gcFsxXSAvIHJ4KSwgY214LCBjbXksIHRoaXMucmFkaXVzKTtcbiAgICAgICAgICBpZiAoaHIucmVtb3ZlZCA9PT0gMCkge1xuICAgICAgICAgICAgbmV3SG9sZXMucHVzaChyaW5nKTsgLy8gdW50b3VjaGVkIOKAlCBrZWVwIGFzLWlzXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhvbGVzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoaHIueHBvaW50cy5sZW5ndGggPj0gMykge1xuICAgICAgICAgICAgICBuZXdIb2xlcy5wdXNoKGhyLnhwb2ludHMubWFwKCh4LCBrKSA9PiBbeCAqIHJ4LCBoci55cG9pbnRzW2tdICogcnhdKSk7XG4gICAgICAgICAgICB9IC8vIGVsc2U6IGhvbGUgY29sbGFwc2VkIOKAlCBkcm9wIGl0XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdIb2xlcy5sZW5ndGggPT09IDApIG5ld0hvbGVzID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzdWx0LnJlbW92ZWQgPT09IDAgJiYgIWhvbGVzQ2hhbmdlZCkgY29udGludWU7XG5cbiAgICAgIGFueUNoYW5nZSA9IHRydWU7XG4gICAgICBjb25zdCBtaW5WZXJ0cyA9IGNsb3NlZCA/IDMgOiAyO1xuICAgICAgaWYgKHJlc3VsdC54cG9pbnRzLmxlbmd0aCA8IG1pblZlcnRzKSB7XG4gICAgICAgIC8vIFJlZ2lvbiBiZWNhbWUgZGVnZW5lcmF0ZSDigJQgcmVtb3ZlIGl0LlxuICAgICAgICByZWdpb25zLnNwbGljZShpLCAxKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlYnVpbGQgdGhlIHBvbHlnb24gaW4gaW1hZ2UvZGF0YSBjb29yZHMuIERyb3AgYW55IHN0b3JlZCBiZXppZXJcbiAgICAgIC8vIGhhbmRsZXMgKHRoZSBhbmNob3IgY291bnQgY2hhbmdlZCkg4oCUIHRoZXkgcmUtZGVyaXZlIGZyb20gdGhlIG5ldyBhbmNob3JzLlxuICAgICAgY29uc3QgeFBsb3QgPSByZXN1bHQueHBvaW50cy5tYXAoeCA9PiB4ICogcngpO1xuICAgICAgY29uc3QgeVBsb3QgPSByZXN1bHQueXBvaW50cy5tYXAoeSA9PiB5ICogcngpO1xuICAgICAgY29uc3QgcG9seSA9IG5ldyBQb2x5Z29uKCk7XG4gICAgICBwb2x5Lm5wb2ludHMgPSB4UGxvdC5sZW5ndGg7XG4gICAgICBwb2x5Lnhwb2ludHMgPSB4UGxvdDtcbiAgICAgIHBvbHkueXBvaW50cyA9IHlQbG90O1xuICAgICAgcG9seS5jb29yZGluYXRlcyA9IHhQbG90Lm1hcCgoeCwgaykgPT4gW3gsIHlQbG90W2tdXSk7XG4gICAgICBwb2x5LmNsb3NlZCA9IGNsb3NlZDtcbiAgICAgIHBvbHkuYmV6aWVyID0gYi5iZXppZXI7XG4gICAgICBpZiAobmV3SG9sZXMgJiYgbmV3SG9sZXMubGVuZ3RoKSBwb2x5LmhvbGVzID0gbmV3SG9sZXM7XG5cbiAgICAgIGNvbnN0IG5yID0gbmV3IFJlZ2lvbigpO1xuICAgICAgbnIuaWQgPSByZWdpb24uaWQ7XG4gICAgICBuci5uYW1lID0gcmVnaW9uLm5hbWU7XG4gICAgICBuci5sYWJlbCA9IHJlZ2lvbi5sYWJlbDtcbiAgICAgIG5yLmNvbG9yID0gcmVnaW9uLmNvbG9yO1xuICAgICAgbnIuYm91bmRzID0gcG9seTtcbiAgICAgIHJlZ2lvbnNbaV0gPSBucjtcbiAgICB9XG5cbiAgICBpZiAoIWFueUNoYW5nZSkgcmV0dXJuO1xuICAgIC8vIFRoZSB3YW5kJ3Mgc3Ryb2tlIG1hc2sgYmVjb21lcyBzdGFsZSBvbmNlIHdlIHRyaW0gdmVydGljZXMgb2ZmIGFueVxuICAgIC8vIHJlZ2lvbiDigJQgZHJvcCBpdCBzbyB0aGUgbmV4dCB3YW5kIGludGVyYWN0aW9uIHJlLWFkb3B0cyBvciByZXN0YXJ0cy5cbiAgICB0aGlzLmhvc3QuaW52YWxpZGF0ZVdhbmRSZWdpb24oKTtcbiAgICB0aGlzLmhvc3Quc2V0UmVnaW9ucyhyZWdpb25zKTtcbiAgfVxufVxuIl19
|