@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.
Files changed (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +404 -0
  3. package/esm2022/index.mjs +52 -0
  4. package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
  5. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
  6. package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
  7. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
  8. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
  9. package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
  10. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
  11. package/esm2022/lib/contracts/display-types.mjs +8 -0
  12. package/esm2022/lib/contracts/image.contract.mjs +11 -0
  13. package/esm2022/lib/contracts/intensity.mjs +28 -0
  14. package/esm2022/lib/contracts/plot-type.mjs +112 -0
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
  18. package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
  19. package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
  20. package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
  21. package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
  22. package/esm2022/lib/contracts/sam.contract.mjs +12 -0
  23. package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
  24. package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
  25. package/esm2022/lib/contracts/viz-config.mjs +3 -0
  26. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
  27. package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
  28. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
  29. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
  30. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
  31. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
  32. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
  33. package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
  34. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
  35. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
  36. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
  37. package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
  38. package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
  39. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
  40. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
  41. package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
  42. package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
  43. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
  44. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
  45. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
  46. package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
  47. package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
  48. package/esm2022/lib/models/bezier.mjs +120 -0
  49. package/esm2022/lib/models/class-preset.mjs +46 -0
  50. package/esm2022/lib/models/geometry.mjs +198 -0
  51. package/esm2022/lib/models/region.mjs +166 -0
  52. package/esm2022/lib/models/shape.mjs +53 -0
  53. package/esm2022/lib/plot.utilities.mjs +693 -0
  54. package/esm2022/lib/processing/image-converter.service.mjs +90 -0
  55. package/esm2022/lib/processing/image-crop.mjs +62 -0
  56. package/esm2022/lib/processing/processing-image.mjs +50 -0
  57. package/esm2022/lib/provide-visualization.mjs +63 -0
  58. package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
  59. package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
  60. package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
  61. package/esm2022/lib/region-ops.service.mjs +301 -0
  62. package/esm2022/lib/render-orchestrator.mjs +87 -0
  63. package/esm2022/lib/routing-visualizer.service.mjs +533 -0
  64. package/esm2022/lib/store/class-color.util.mjs +52 -0
  65. package/esm2022/lib/store/region-store.service.mjs +1029 -0
  66. package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
  67. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
  68. package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
  69. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
  70. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
  71. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
  72. package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
  73. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
  74. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
  75. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
  76. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
  77. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
  78. package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
  79. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
  80. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
  81. package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
  82. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
  83. package/esm2022/lib/visualization.module.mjs +162 -0
  84. package/esm2022/lib/visualizer.component.mjs +1597 -0
  85. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
  86. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
  87. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
  88. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
  89. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
  90. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
  91. package/fesm2022/mask.worker.js +989 -0
  92. package/fesm2022/onnx-sam.worker.js +202 -0
  93. package/index.d.ts +39 -0
  94. package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
  95. package/lib/contracts/capabilities.contract.d.ts +30 -0
  96. package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
  97. package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
  98. package/lib/contracts/colormap-lut.d.ts +21 -0
  99. package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
  100. package/lib/contracts/display-types.d.ts +41 -0
  101. package/lib/contracts/image.contract.d.ts +72 -0
  102. package/lib/contracts/intensity.d.ts +18 -0
  103. package/lib/contracts/plot-type.d.ts +108 -0
  104. package/lib/contracts/ports/image-state.port.d.ts +29 -0
  105. package/lib/contracts/ports/preferences.port.d.ts +19 -0
  106. package/lib/contracts/ports/region-io.port.d.ts +29 -0
  107. package/lib/contracts/ports/tile-access.port.d.ts +27 -0
  108. package/lib/contracts/region-editor-api.contract.d.ts +83 -0
  109. package/lib/contracts/region-overlay.contract.d.ts +47 -0
  110. package/lib/contracts/region-store.contract.d.ts +74 -0
  111. package/lib/contracts/sam.contract.d.ts +98 -0
  112. package/lib/contracts/toolbar-config.d.ts +24 -0
  113. package/lib/contracts/visualizer.contract.d.ts +346 -0
  114. package/lib/contracts/viz-config.d.ts +25 -0
  115. package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
  116. package/lib/implementations/base-store-visualizer.d.ts +71 -0
  117. package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
  118. package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
  119. package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
  120. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
  121. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
  122. package/lib/implementations/osd/display-pipeline.d.ts +47 -0
  123. package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
  124. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
  125. package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
  126. package/lib/implementations/osd/osd-coords.d.ts +16 -0
  127. package/lib/implementations/osd/osd-lib.d.ts +19 -0
  128. package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
  129. package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
  130. package/lib/implementations/osd/slice-cache.d.ts +161 -0
  131. package/lib/implementations/osd/tile-client.d.ts +32 -0
  132. package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
  133. package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
  134. package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
  135. package/lib/implementations/plotly/plotly.service.d.ts +594 -0
  136. package/lib/implementations/simple-slice-access.service.d.ts +64 -0
  137. package/lib/models/bezier.d.ts +59 -0
  138. package/lib/models/class-preset.d.ts +39 -0
  139. package/lib/models/geometry.d.ts +66 -0
  140. package/lib/models/region.d.ts +132 -0
  141. package/lib/models/shape.d.ts +44 -0
  142. package/lib/plot.utilities.d.ts +107 -0
  143. package/lib/processing/image-converter.service.d.ts +28 -0
  144. package/lib/processing/image-crop.d.ts +18 -0
  145. package/lib/processing/processing-image.d.ts +17 -0
  146. package/lib/provide-visualization.d.ts +34 -0
  147. package/lib/region-editor/mask-raster.d.ts +61 -0
  148. package/lib/region-editor/mask-worker.d.ts +7 -0
  149. package/lib/region-editor/region-editor.component.d.ts +305 -0
  150. package/lib/region-ops.service.d.ts +92 -0
  151. package/lib/render-orchestrator.d.ts +59 -0
  152. package/lib/routing-visualizer.service.d.ts +227 -0
  153. package/lib/store/class-color.util.d.ts +26 -0
  154. package/lib/store/region-store.service.d.ts +315 -0
  155. package/lib/store/visualizer-store.service.d.ts +123 -0
  156. package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
  157. package/lib/toolbar/crop/slide-crop.d.ts +30 -0
  158. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
  159. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
  160. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
  161. package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
  162. package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
  163. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
  164. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
  165. package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
  166. package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
  167. package/lib/toolbar/toolbar.component.d.ts +167 -0
  168. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
  169. package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
  170. package/lib/toolbar/wand/wand.service.d.ts +133 -0
  171. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
  172. package/lib/visualization.module.d.ts +45 -0
  173. package/lib/visualizer.component.d.ts +378 -0
  174. package/package.json +73 -0
  175. package/src/lib/assets/3d-coordinates.svg +49 -0
  176. package/src/lib/assets/cells.svg +1 -0
  177. package/src/lib/assets/click.svg +1 -0
  178. package/src/lib/assets/colormap-luts.json +1 -0
  179. package/src/lib/assets/contour.svg +48 -0
  180. package/src/lib/assets/cube-3d.svg +1 -0
  181. package/src/lib/assets/edit-selection-white.svg +47 -0
  182. package/src/lib/assets/heatmap.svg +1 -0
  183. package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
  184. package/src/lib/assets/icons/colormap-accent.png +0 -0
  185. package/src/lib/assets/icons/colormap-afmhot.png +0 -0
  186. package/src/lib/assets/icons/colormap-autumn.png +0 -0
  187. package/src/lib/assets/icons/colormap-berlin.png +0 -0
  188. package/src/lib/assets/icons/colormap-binary.png +0 -0
  189. package/src/lib/assets/icons/colormap-blackbody.png +0 -0
  190. package/src/lib/assets/icons/colormap-bluered.png +0 -0
  191. package/src/lib/assets/icons/colormap-blues.png +0 -0
  192. package/src/lib/assets/icons/colormap-bone.png +0 -0
  193. package/src/lib/assets/icons/colormap-brbg.png +0 -0
  194. package/src/lib/assets/icons/colormap-brg.png +0 -0
  195. package/src/lib/assets/icons/colormap-bugn.png +0 -0
  196. package/src/lib/assets/icons/colormap-bupu.png +0 -0
  197. package/src/lib/assets/icons/colormap-bwr.png +0 -0
  198. package/src/lib/assets/icons/colormap-cividis.png +0 -0
  199. package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
  200. package/src/lib/assets/icons/colormap-cool.png +0 -0
  201. package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
  202. package/src/lib/assets/icons/colormap-copper.png +0 -0
  203. package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
  204. package/src/lib/assets/icons/colormap-dark2.png +0 -0
  205. package/src/lib/assets/icons/colormap-earth.png +0 -0
  206. package/src/lib/assets/icons/colormap-electric.png +0 -0
  207. package/src/lib/assets/icons/colormap-flag.png +0 -0
  208. package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
  209. package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
  210. package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
  211. package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
  212. package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
  213. package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
  214. package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
  215. package/src/lib/assets/icons/colormap-gnbu.png +0 -0
  216. package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
  217. package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
  218. package/src/lib/assets/icons/colormap-gray.png +0 -0
  219. package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
  220. package/src/lib/assets/icons/colormap-greens.png +0 -0
  221. package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
  222. package/src/lib/assets/icons/colormap-greys.png +0 -0
  223. package/src/lib/assets/icons/colormap-hot.png +0 -0
  224. package/src/lib/assets/icons/colormap-hsv.png +0 -0
  225. package/src/lib/assets/icons/colormap-inferno.png +0 -0
  226. package/src/lib/assets/icons/colormap-jet.png +0 -0
  227. package/src/lib/assets/icons/colormap-magma.png +0 -0
  228. package/src/lib/assets/icons/colormap-managua.png +0 -0
  229. package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
  230. package/src/lib/assets/icons/colormap-ocean.png +0 -0
  231. package/src/lib/assets/icons/colormap-oranges.png +0 -0
  232. package/src/lib/assets/icons/colormap-orrd.png +0 -0
  233. package/src/lib/assets/icons/colormap-pastel2.png +0 -0
  234. package/src/lib/assets/icons/colormap-picnic.png +0 -0
  235. package/src/lib/assets/icons/colormap-pink.png +0 -0
  236. package/src/lib/assets/icons/colormap-piyg.png +0 -0
  237. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  238. package/src/lib/assets/icons/colormap-plasma.png +0 -0
  239. package/src/lib/assets/icons/colormap-portland.png +0 -0
  240. package/src/lib/assets/icons/colormap-prgn.png +0 -0
  241. package/src/lib/assets/icons/colormap-prism.png +0 -0
  242. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  243. package/src/lib/assets/icons/colormap-pubugn.png +0 -0
  244. package/src/lib/assets/icons/colormap-puor.png +0 -0
  245. package/src/lib/assets/icons/colormap-purd.png +0 -0
  246. package/src/lib/assets/icons/colormap-purples.png +0 -0
  247. package/src/lib/assets/icons/colormap-rainbow.png +0 -0
  248. package/src/lib/assets/icons/colormap-rdbu.png +0 -0
  249. package/src/lib/assets/icons/colormap-rdgy.png +0 -0
  250. package/src/lib/assets/icons/colormap-rdpu.png +0 -0
  251. package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
  252. package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
  253. package/src/lib/assets/icons/colormap-reds.png +0 -0
  254. package/src/lib/assets/icons/colormap-seismic.png +0 -0
  255. package/src/lib/assets/icons/colormap-set1.png +0 -0
  256. package/src/lib/assets/icons/colormap-set2.png +0 -0
  257. package/src/lib/assets/icons/colormap-set3.png +0 -0
  258. package/src/lib/assets/icons/colormap-spectral.png +0 -0
  259. package/src/lib/assets/icons/colormap-spring.png +0 -0
  260. package/src/lib/assets/icons/colormap-summer.png +0 -0
  261. package/src/lib/assets/icons/colormap-tab10.png +0 -0
  262. package/src/lib/assets/icons/colormap-tab20.png +0 -0
  263. package/src/lib/assets/icons/colormap-tab20b.png +0 -0
  264. package/src/lib/assets/icons/colormap-tab20c.png +0 -0
  265. package/src/lib/assets/icons/colormap-terrain.png +0 -0
  266. package/src/lib/assets/icons/colormap-turbo.png +0 -0
  267. package/src/lib/assets/icons/colormap-twilight.png +0 -0
  268. package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
  269. package/src/lib/assets/icons/colormap-vanimo.png +0 -0
  270. package/src/lib/assets/icons/colormap-viridis.png +0 -0
  271. package/src/lib/assets/icons/colormap-winter.png +0 -0
  272. package/src/lib/assets/icons/colormap-wistia.png +0 -0
  273. package/src/lib/assets/icons/colormap-ylgn.png +0 -0
  274. package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
  275. package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
  276. package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
  277. package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
  278. package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
  279. package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
  280. package/src/lib/assets/invert.svg +1 -0
  281. package/src/lib/assets/isosurface.svg +7 -0
  282. package/src/lib/assets/mask.svg +1 -0
  283. package/src/lib/assets/paintbrush.svg +1 -0
  284. package/src/lib/assets/picture-segmentation.svg +43 -0
  285. package/src/lib/assets/polygon-vertices.svg +13 -0
  286. package/src/lib/assets/polyline.svg +3 -0
  287. package/src/lib/assets/redo.svg +39 -0
  288. package/src/lib/assets/region-editor.svg +37 -0
  289. package/src/lib/assets/region-move.svg +7 -0
  290. package/src/lib/assets/smooth.svg +56 -0
  291. package/src/lib/assets/spline-chart.svg +7 -0
  292. package/src/lib/assets/surface.svg +37 -0
  293. package/src/lib/assets/test/download-379.svg +1 -0
  294. package/src/lib/assets/test/download-98.svg +1 -0
  295. package/src/lib/assets/test/json-1.svg +1 -0
  296. package/src/lib/assets/test/load-53.svg +1 -0
  297. package/src/lib/assets/test/mask-44.svg +1 -0
  298. package/src/lib/assets/test/mask-download-44.svg +15 -0
  299. package/src/lib/assets/test/mask-save-44.svg +11 -0
  300. package/src/lib/assets/test/overlay-1.svg +1 -0
  301. package/src/lib/assets/test/overlay-4.svg +1 -0
  302. package/src/lib/assets/test/region-26.svg +1 -0
  303. package/src/lib/assets/test/save-56.svg +1 -0
  304. package/src/lib/assets/test/upload-43.svg +1 -0
  305. package/src/lib/assets/to-bezier.svg +15 -0
  306. package/src/lib/assets/to-polygon.svg +11 -0
  307. package/src/lib/assets/undo.svg +38 -0
  308. package/src/lib/assets/vertex-add.svg +12 -0
  309. package/src/lib/assets/vertex-delete.svg +12 -0
  310. package/src/lib/assets/wand.svg +54 -0
  311. 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