@vitessce/scatterplot-gating 4.0.8 → 4.0.10

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.
@@ -2824,11 +2824,11 @@ function requireConcaveman() {
2824
2824
  while (node2) {
2825
2825
  for (var i2 = 0; i2 < node2.children.length; i2++) {
2826
2826
  var child = node2.children[i2];
2827
- var dist = node2.leaf ? sqSegDist(child, b, c2) : sqSegBoxDist(b, c2, child);
2828
- if (dist > maxDist) continue;
2827
+ var dist2 = node2.leaf ? sqSegDist(child, b, c2) : sqSegBoxDist(b, c2, child);
2828
+ if (dist2 > maxDist) continue;
2829
2829
  queue.push({
2830
2830
  node: child,
2831
- dist
2831
+ dist: dist2
2832
2832
  });
2833
2833
  }
2834
2834
  while (queue.length && !queue.peek().node.children) {
@@ -6977,7 +6977,7 @@ const latestFileDefSchema = z.object({
6977
6977
  options: fileOptionsSchema.optional(),
6978
6978
  requestInit: requestInit.optional(),
6979
6979
  // New: file def can have coordinationValues.
6980
- coordinationValues: z.record(z.string()).optional()
6980
+ coordinationValues: z.record(z.any()).optional()
6981
6981
  });
6982
6982
  const datasetsSchema1_0_13 = z.array(z.object({
6983
6983
  uid: z.string(),
@@ -7008,7 +7008,8 @@ const configSchema1_0_16 = configSchema1_0_13.extend({
7008
7008
  h: z.number().int().optional(),
7009
7009
  // Updates coordinationScopes and coordinationScopesBy
7010
7010
  coordinationScopes: componentCoordinationScopes.optional(),
7011
- coordinationScopesBy: componentCoordinationScopesBy.optional()
7011
+ coordinationScopesBy: componentCoordinationScopesBy.optional(),
7012
+ coordinationValues: z.record(z.any()).optional()
7012
7013
  }))
7013
7014
  });
7014
7015
  const configSchema1_0_17 = configSchema1_0_16.extend({
@@ -9515,7 +9516,8 @@ const ViewType$1 = {
9515
9516
  TREEMAP: "treemap",
9516
9517
  SAMPLE_SET_PAIR_MANAGER: "sampleSetPairManager",
9517
9518
  FEATURE_STATS_TABLE: "featureStatsTable",
9518
- SINGLE_OBS_SET_SELECTOR: "singleObsSetSelector"
9519
+ SINGLE_OBS_SET_SELECTOR: "singleObsSetSelector",
9520
+ ANNOTATION_CONTROLLER: "annotationController"
9519
9521
  };
9520
9522
  const DataType$2 = {
9521
9523
  OBS_LABELS: "obsLabels",
@@ -9536,7 +9538,8 @@ const DataType$2 = {
9536
9538
  COMPARISON_METADATA: "comparisonMetadata",
9537
9539
  FEATURE_STATS: "featureStats",
9538
9540
  FEATURE_SET_STATS: "featureSetStats",
9539
- OBS_SET_STATS: "obsSetStats"
9541
+ OBS_SET_STATS: "obsSetStats",
9542
+ ANNOTATION_STORY: "annotationStory"
9540
9543
  };
9541
9544
  const FileType$1 = {
9542
9545
  // Joint file types
@@ -9558,6 +9561,7 @@ const FileType$1 = {
9558
9561
  OBS_SETS_CSV: "obsSets.csv",
9559
9562
  OBS_SETS_JSON: "obsSets.json",
9560
9563
  SAMPLE_SETS_CSV: "sampleSets.csv",
9564
+ ANNOTATION_STORY_JSON: "annotationStory.json",
9561
9565
  // OME-Zarr
9562
9566
  IMAGE_OME_ZARR: "image.ome-zarr",
9563
9567
  OBS_SEGMENTATIONS_OME_ZARR: "obsSegmentations.ome-zarr",
@@ -9842,7 +9846,15 @@ const CoordinationType$1 = {
9842
9846
  FEATURE_POINT_FOLD_CHANGE_THRESHOLD: "featurePointFoldChangeThreshold",
9843
9847
  FEATURE_LABEL_FOLD_CHANGE_THRESHOLD: "featureLabelFoldChangeThreshold",
9844
9848
  // Treemap
9845
- HIERARCHY_LEVELS: "hierarchyLevels"
9849
+ HIERARCHY_LEVELS: "hierarchyLevels",
9850
+ // Annotation frames
9851
+ ANNOTATION_STORY: "annotationStory",
9852
+ ANNOTATION_FRAME_INDEX: "annotationFrameIndex",
9853
+ ANNOTATION_SHAPES: "annotationShapes",
9854
+ ANNOTATION_OVERLAY_VISIBLE: "annotationOverlayVisible",
9855
+ ANNOTATION_TRANSITION_DURATION: "annotationTransitionDuration",
9856
+ ANNOTATION_SEMANTIC_ZOOM: "annotationSemanticZoom",
9857
+ ANNOTATION_EDITABLE: "annotationEditable"
9846
9858
  };
9847
9859
  const ViewHelpMapping = {
9848
9860
  GATING: "The gating scatterplot displays expression data for two genes (along the X and Y axes). Users can select two genes, and the scatterplot is dynamically generated using observation-by-feature matrix data. Gating can then be performed by using the lasso or box select tools."
@@ -9861,6 +9873,7 @@ const ViewHelpMapping = {
9861
9873
  [FileType$1.OBS_SEGMENTATIONS_JSON]: DataType$2.OBS_SEGMENTATIONS,
9862
9874
  [FileType$1.OBS_SETS_CSV]: DataType$2.OBS_SETS,
9863
9875
  [FileType$1.OBS_SETS_JSON]: DataType$2.OBS_SETS,
9876
+ [FileType$1.ANNOTATION_STORY_JSON]: DataType$2.ANNOTATION_STORY,
9864
9877
  [FileType$1.IMAGE_OME_ZARR]: DataType$2.IMAGE,
9865
9878
  [FileType$1.OBS_SEGMENTATIONS_OME_ZARR]: DataType$2.OBS_SEGMENTATIONS,
9866
9879
  [FileType$1.OBS_FEATURE_MATRIX_ANNDATA_ZARR]: DataType$2.OBS_FEATURE_MATRIX,
@@ -9983,7 +9996,8 @@ const ViewHelpMapping = {
9983
9996
  [DataType$2.OBS_SET_STATS]: [
9984
9997
  CoordinationType$1.OBS_TYPE
9985
9998
  // TODO: should sampleType, obsSetSelection, and/or sampleSetSelection be used here?
9986
- ]
9999
+ ],
10000
+ [DataType$2.ANNOTATION_STORY]: []
9987
10001
  });
9988
10002
  ({
9989
10003
  // For AnnData:
@@ -10116,7 +10130,9 @@ const ViewHelpMapping = {
10116
10130
  CoordinationType$1.SPATIAL_TARGET_Z,
10117
10131
  CoordinationType$1.SPATIAL_AXIS_FIXED,
10118
10132
  CoordinationType$1.SPATIAL_ORBIT_AXIS,
10119
- CoordinationType$1.FEATURE_AGGREGATION_STRATEGY
10133
+ CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
10134
+ // Annotation shapes are specific to a view's coordinate system.
10135
+ CoordinationType$1.ANNOTATION_SHAPES
10120
10136
  ];
10121
10137
  const COMPONENT_COORDINATION_TYPES = {
10122
10138
  [ViewType$1.NEUROGLANCER]: [
@@ -10208,7 +10224,14 @@ const COMPONENT_COORDINATION_TYPES = {
10208
10224
  CoordinationType$1.EMBEDDING_CONTOURS_FILLED,
10209
10225
  CoordinationType$1.EMBEDDING_CONTOUR_PERCENTILES,
10210
10226
  CoordinationType$1.CONTOUR_COLOR_ENCODING,
10211
- CoordinationType$1.CONTOUR_COLOR
10227
+ CoordinationType$1.CONTOUR_COLOR,
10228
+ CoordinationType$1.ANNOTATION_STORY,
10229
+ CoordinationType$1.ANNOTATION_SHAPES,
10230
+ CoordinationType$1.ANNOTATION_FRAME_INDEX,
10231
+ CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
10232
+ CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
10233
+ CoordinationType$1.ANNOTATION_EDITABLE,
10234
+ CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
10212
10235
  ],
10213
10236
  [ViewType$1.DUAL_SCATTERPLOT]: [
10214
10237
  CoordinationType$1.DATASET,
@@ -10324,7 +10347,14 @@ const COMPONENT_COORDINATION_TYPES = {
10324
10347
  CoordinationType$1.ADDITIONAL_OBS_SETS,
10325
10348
  CoordinationType$1.MOLECULE_HIGHLIGHT,
10326
10349
  CoordinationType$1.TOOLTIPS_VISIBLE,
10327
- CoordinationType$1.PHOTOMETRIC_INTERPRETATION
10350
+ CoordinationType$1.PHOTOMETRIC_INTERPRETATION,
10351
+ CoordinationType$1.ANNOTATION_STORY,
10352
+ CoordinationType$1.ANNOTATION_SHAPES,
10353
+ CoordinationType$1.ANNOTATION_FRAME_INDEX,
10354
+ CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
10355
+ CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
10356
+ CoordinationType$1.ANNOTATION_EDITABLE,
10357
+ CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
10328
10358
  ],
10329
10359
  [ViewType$1.SPATIAL_BETA]: [
10330
10360
  CoordinationType$1.META_COORDINATION_SCOPES,
@@ -10402,7 +10432,27 @@ const COMPONENT_COORDINATION_TYPES = {
10402
10432
  CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
10403
10433
  CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
10404
10434
  CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER,
10405
- CoordinationType$1.PHOTOMETRIC_INTERPRETATION
10435
+ CoordinationType$1.PHOTOMETRIC_INTERPRETATION,
10436
+ CoordinationType$1.ANNOTATION_STORY,
10437
+ CoordinationType$1.ANNOTATION_SHAPES,
10438
+ CoordinationType$1.ANNOTATION_FRAME_INDEX,
10439
+ CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
10440
+ CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
10441
+ CoordinationType$1.ANNOTATION_EDITABLE,
10442
+ CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
10443
+ ],
10444
+ [ViewType$1.ANNOTATION_CONTROLLER]: [
10445
+ CoordinationType$1.DATASET,
10446
+ CoordinationType$1.ANNOTATION_STORY,
10447
+ CoordinationType$1.ANNOTATION_FRAME_INDEX,
10448
+ CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
10449
+ CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
10450
+ CoordinationType$1.ANNOTATION_EDITABLE,
10451
+ CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
10452
+ // Note: the annotation controller also needs to read the coordination state
10453
+ // of all other views/coordination types via the full config.
10454
+ // Note: we get/set the CoordinationType.ANNOTATION_SHAPES from the full config,
10455
+ // as this info is view-specific rather than global to the story.
10406
10456
  ],
10407
10457
  [ViewType$1.HEATMAP]: [
10408
10458
  CoordinationType$1.DATASET,
@@ -11420,6 +11470,124 @@ z.object({
11420
11470
  radius: z.number(),
11421
11471
  opacity: z.number()
11422
11472
  });
11473
+ const shapeBaseObj = z.object({
11474
+ uid: z.string(),
11475
+ text: z.string().optional(),
11476
+ strokeColor: z.array(z.number()).length(3).optional(),
11477
+ strokeWidth: z.number().optional(),
11478
+ // SVG-style dash pattern, e.g. "10 5" or "10 20 30 10". "none" or omitted = solid.
11479
+ strokeDashArray: z.string().optional(),
11480
+ visible: z.boolean().optional()
11481
+ // TODO: define unit modes for x and y axes
11482
+ // ("pixels" vs "normalized" vs "physical" etc.)
11483
+ // TODO: a coordinate system identifier (e.g., "DeckGL" for now,
11484
+ // but a coordinate system from OME-NGFF/SpatialData eventually?)
11485
+ });
11486
+ const rectangleShapeObj = shapeBaseObj.extend({
11487
+ type: z.literal("rectangle"),
11488
+ // OME-XML field names verbatim (upper-left origin)
11489
+ x: z.number(),
11490
+ y: z.number(),
11491
+ width: z.number(),
11492
+ height: z.number(),
11493
+ fillColor: z.array(z.number()).length(3).optional(),
11494
+ fillOpacity: z.number().optional()
11495
+ });
11496
+ const lineShapeObj = shapeBaseObj.extend({
11497
+ type: z.literal("line"),
11498
+ // OME-XML field names verbatim
11499
+ x1: z.number(),
11500
+ y1: z.number(),
11501
+ x2: z.number(),
11502
+ y2: z.number(),
11503
+ markerStart: z.enum(["Arrow", "Tick"]).nullable().optional(),
11504
+ markerEnd: z.enum(["Arrow", "Tick"]).nullable().optional(),
11505
+ textPosition: z.enum(["start", "middle", "end"]).optional(),
11506
+ textBufferPx: z.number().optional()
11507
+ });
11508
+ const ellipseShapeObj = shapeBaseObj.extend({
11509
+ type: z.literal("ellipse"),
11510
+ // OME-XML field names verbatim (centre point + radii)
11511
+ x1: z.number(),
11512
+ y1: z.number(),
11513
+ radiusX: z.number(),
11514
+ radiusY: z.number(),
11515
+ fillColor: z.array(z.number()).length(3).optional(),
11516
+ fillOpacity: z.number().optional()
11517
+ });
11518
+ const polygonShapeObj = shapeBaseObj.extend({
11519
+ type: z.literal("polygon"),
11520
+ // OME-XML: array of [x, y] coordinate pairs, closed automatically
11521
+ points: z.array(z.tuple([z.number(), z.number()])),
11522
+ fillColor: z.array(z.number()).length(3).optional(),
11523
+ fillOpacity: z.number().optional()
11524
+ });
11525
+ const polylineShapeObj = shapeBaseObj.extend({
11526
+ type: z.literal("polyline"),
11527
+ // OME-XML: array of [x, y] coordinate pairs, open (not closed)
11528
+ points: z.array(z.tuple([z.number(), z.number()])),
11529
+ markerStart: z.enum(["Arrow", "Tick"]).nullable().optional(),
11530
+ markerEnd: z.enum(["Arrow", "Tick"]).nullable().optional()
11531
+ });
11532
+ const annotationShapeObj = z.discriminatedUnion("type", [
11533
+ rectangleShapeObj,
11534
+ lineShapeObj,
11535
+ ellipseShapeObj,
11536
+ polygonShapeObj,
11537
+ polylineShapeObj
11538
+ ]);
11539
+ z.array(annotationShapeObj);
11540
+ const annotationFrameObj = z.object({
11541
+ uid: z.string(),
11542
+ title: z.string().optional(),
11543
+ description: z.string().optional(),
11544
+ descriptionType: z.enum(["text", "markdown"]).optional(),
11545
+ // A frame can define per-view: coordinationValues
11546
+ // (if the view's state should not be coordinated with other views)
11547
+ // or per-view coordinationScopes/coordinationScopesBy
11548
+ // (if at this frame, the view should be coordinated with other views).
11549
+ // We can also define a frame-level coordination space,
11550
+ // which will be merged with the global coordination space.
11551
+ // TODO: datasets
11552
+ // TODO: coordinationSpace
11553
+ layout: z.array(
11554
+ // Note: for now, we will infer view objects which have a uid
11555
+ // that is present in the global layout, and do NOT have x/y/w/h defined,
11556
+ // to mean that in this frame, the layout and set of views is unchanged
11557
+ // from the global layout.
11558
+ // This will allow each frame to omit the full list of views from the layout,
11559
+ // and only specify the views whose coordination state is changing in this frame.
11560
+ // If a frame includes a view with a uid that is not present
11561
+ // in the global layout, then that view will be added to the layout at this frame.
11562
+ // This frame should also define x/y/w/h for all views,
11563
+ // since it will otherwise be ambiguous how to layout the updated set of views
11564
+ // for this frame.
11565
+ z.object({
11566
+ // The view UID. If this view uid is not present in the global layout,
11567
+ // it will be added to the layout at this frame,
11568
+ // and will need to have its coordination values initialized to their defaults
11569
+ // for any that were not fully specified.
11570
+ uid: z.string(),
11571
+ coordinationValues: z.record(
11572
+ z.string(),
11573
+ // The coordination type name, e.g. "embeddingType"
11574
+ z.any()
11575
+ ).optional()
11576
+ // TODO: support coordinationScopes/coordinationScopesBy for per-view coordination
11577
+ // at this frame.
11578
+ // TODO: view x/y/w/h once we support view layout changes per-frame.
11579
+ })
11580
+ ).optional()
11581
+ });
11582
+ z.object({
11583
+ // TODO: schema version for the story schema?
11584
+ // Same as current Vitessce schema version?
11585
+ uid: z.string(),
11586
+ title: z.string().optional(),
11587
+ description: z.string().optional(),
11588
+ descriptionType: z.enum(["text", "markdown"]).optional(),
11589
+ frames: z.array(annotationFrameObj)
11590
+ });
11423
11591
  const SETS_DATATYPE_OBS = "obs";
11424
11592
  const HIERARCHICAL_SCHEMAS = {
11425
11593
  latestVersion: "0.1.3"
@@ -24240,8 +24408,8 @@ class Vector extends MathArray {
24240
24408
  distanceSquared(mathArray) {
24241
24409
  let length2 = 0;
24242
24410
  for (let i2 = 0; i2 < this.ELEMENTS; ++i2) {
24243
- const dist = this[i2] - mathArray[i2];
24244
- length2 += dist * dist;
24411
+ const dist2 = this[i2] - mathArray[i2];
24412
+ length2 += dist2 * dist2;
24245
24413
  }
24246
24414
  return checkNumber(length2);
24247
24415
  }
@@ -24562,6 +24730,12 @@ function multiply$3(out, a2, b) {
24562
24730
  out[2] = a2[2] * b[2];
24563
24731
  return out;
24564
24732
  }
24733
+ function distance$3(a2, b) {
24734
+ var x = b[0] - a2[0];
24735
+ var y = b[1] - a2[1];
24736
+ var z2 = b[2] - a2[2];
24737
+ return Math.hypot(x, y, z2);
24738
+ }
24565
24739
  function squaredLength$2(a2) {
24566
24740
  var x = a2[0];
24567
24741
  var y = a2[1];
@@ -24685,6 +24859,7 @@ function angle$2(a2, b) {
24685
24859
  }
24686
24860
  var sub = subtract;
24687
24861
  var mul = multiply$3;
24862
+ var dist = distance$3;
24688
24863
  var len = length$5;
24689
24864
  var sqrLen = squaredLength$2;
24690
24865
  (function() {
@@ -39155,7 +39330,7 @@ function noop$4() {
39155
39330
  const getCursor$1 = ({
39156
39331
  isDragging
39157
39332
  }) => isDragging ? "grabbing" : "grab";
39158
- const defaultProps$O = {
39333
+ const defaultProps$P = {
39159
39334
  id: "",
39160
39335
  width: "100%",
39161
39336
  height: "100%",
@@ -39286,7 +39461,7 @@ class Deck {
39286
39461
  this._lastPointerDownInfo = pickedInfo.result[0] || pickedInfo.emptyInfo;
39287
39462
  });
39288
39463
  this.props = {
39289
- ...defaultProps$O,
39464
+ ...defaultProps$P,
39290
39465
  ...props
39291
39466
  };
39292
39467
  props = this.props;
@@ -39788,7 +39963,7 @@ class Deck {
39788
39963
  metrics.gpuMemory = memoryStats.get("GPU Memory").count;
39789
39964
  }
39790
39965
  }
39791
- _defineProperty(Deck, "defaultProps", defaultProps$O);
39966
+ _defineProperty(Deck, "defaultProps", defaultProps$P);
39792
39967
  _defineProperty(Deck, "VERSION", deckGlobal.VERSION);
39793
39968
  class ShaderAttribute {
39794
39969
  constructor(dataColumn, opts) {
@@ -42543,7 +42718,7 @@ const areViewportsEqual = memoize$3(({
42543
42718
  return oldViewport.equals(viewport);
42544
42719
  });
42545
42720
  let pickingColorCache = new Uint8ClampedArray(0);
42546
- const defaultProps$N = {
42721
+ const defaultProps$O = {
42547
42722
  data: {
42548
42723
  type: "data",
42549
42724
  value: EMPTY_ARRAY$1,
@@ -43418,7 +43593,7 @@ class Layer extends Component {
43418
43593
  this.setNeedsUpdate();
43419
43594
  }
43420
43595
  }
43421
- _defineProperty(Layer, "defaultProps", defaultProps$N);
43596
+ _defineProperty(Layer, "defaultProps", defaultProps$O);
43422
43597
  _defineProperty(Layer, "layerName", "Layer");
43423
43598
  const TRACE_RENDER_LAYERS = "compositeLayer.renderLayers";
43424
43599
  class CompositeLayer extends Layer {
@@ -44454,6 +44629,124 @@ const esm$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
44454
44629
  project32,
44455
44630
  shadow
44456
44631
  }, Symbol.toStringTag, { value: "Module" }));
44632
+ const dashShaders = {
44633
+ inject: {
44634
+ "vs:#decl": "\nattribute vec2 instanceDashArrays;\nattribute float instanceDashOffsets;\nvarying vec2 vDashArray;\nvarying float vDashOffset;\n",
44635
+ "vs:#main-end": "\nvDashArray = instanceDashArrays;\nvDashOffset = instanceDashOffsets / width.x;\n",
44636
+ "fs:#decl": "\nuniform float dashAlignMode;\nuniform float capType;\nuniform bool dashGapPickable;\nvarying vec2 vDashArray;\nvarying float vDashOffset;\n\nfloat round(float x) {\n return floor(x + 0.5);\n}\n",
44637
+ "fs:#main-start": "\n float solidLength = vDashArray.x;\n float gapLength = vDashArray.y;\n float unitLength = solidLength + gapLength;\n\n float offset;\n\n if (unitLength > 0.0) {\n if (dashAlignMode == 0.0) {\n offset = vDashOffset;\n } else {\n unitLength = vPathLength / round(vPathLength / unitLength);\n offset = solidLength / 2.0;\n }\n\n float unitOffset = mod(clamp(vPathPosition.y, 0.0, vPathLength) + offset, unitLength);\n\n if (gapLength > 0.0 && unitOffset > solidLength) {\n if (capType <= 0.5) {\n if (!(dashGapPickable && picking_uActive)) {\n discard;\n }\n } else {\n // caps are rounded, test the distance to solid ends\n float distToEnd = length(vec2(\n min(unitOffset - solidLength, unitLength - unitOffset),\n vPathPosition.x\n ));\n if (distToEnd > 1.0) {\n if (!(dashGapPickable && picking_uActive)) {\n discard;\n }\n }\n }\n }\n }\n"
44638
+ }
44639
+ };
44640
+ const offsetShaders = {
44641
+ inject: {
44642
+ "vs:#decl": "\nattribute float instanceOffsets;\n",
44643
+ "vs:DECKGL_FILTER_SIZE": "\n float offsetWidth = abs(instanceOffsets * 2.0) + 1.0;\n size *= offsetWidth;\n",
44644
+ "vCornerOffset = offsetVec;": "\n float offsetWidth = abs(instanceOffsets * 2.0) + 1.0;\n vec2 offsetCenter = -instanceOffsets * (isCap ? perp : miterVec * miterSize) * 2.0;\n vCornerOffset = vCornerOffset * offsetWidth - offsetCenter;\n",
44645
+ "fs:#main-start": "\n float isInside;\n isInside = step(-1.0, vPathPosition.x) * step(vPathPosition.x, 1.0);\n if (isInside == 0.0) {\n discard;\n }\n"
44646
+ }
44647
+ };
44648
+ const defaultProps$N = {
44649
+ getDashArray: {
44650
+ type: "accessor",
44651
+ value: [0, 0]
44652
+ },
44653
+ getOffset: {
44654
+ type: "accessor",
44655
+ value: 0
44656
+ },
44657
+ dashJustified: false,
44658
+ dashGapPickable: false
44659
+ };
44660
+ class PathStyleExtension extends LayerExtension {
44661
+ constructor({
44662
+ dash = false,
44663
+ offset: offset2 = false,
44664
+ highPrecisionDash = false
44665
+ } = {}) {
44666
+ super({
44667
+ dash: dash || highPrecisionDash,
44668
+ offset: offset2,
44669
+ highPrecisionDash
44670
+ });
44671
+ }
44672
+ isEnabled(layer) {
44673
+ return "pathTesselator" in layer.state;
44674
+ }
44675
+ getShaders(extension) {
44676
+ if (!extension.isEnabled(this)) {
44677
+ return null;
44678
+ }
44679
+ let result = {};
44680
+ if (extension.opts.dash) {
44681
+ result = mergeShaders(result, dashShaders);
44682
+ }
44683
+ if (extension.opts.offset) {
44684
+ result = mergeShaders(result, offsetShaders);
44685
+ }
44686
+ return result;
44687
+ }
44688
+ initializeState(context, extension) {
44689
+ const attributeManager = this.getAttributeManager();
44690
+ if (!attributeManager || !extension.isEnabled(this)) {
44691
+ return;
44692
+ }
44693
+ if (extension.opts.dash) {
44694
+ attributeManager.addInstanced({
44695
+ instanceDashArrays: {
44696
+ size: 2,
44697
+ accessor: "getDashArray"
44698
+ }
44699
+ });
44700
+ }
44701
+ if (extension.opts.highPrecisionDash) {
44702
+ attributeManager.addInstanced({
44703
+ instanceDashOffsets: {
44704
+ size: 1,
44705
+ accessor: "getPath",
44706
+ transform: extension.getDashOffsets.bind(this)
44707
+ }
44708
+ });
44709
+ }
44710
+ if (extension.opts.offset) {
44711
+ attributeManager.addInstanced({
44712
+ instanceOffsets: {
44713
+ size: 1,
44714
+ accessor: "getOffset"
44715
+ }
44716
+ });
44717
+ }
44718
+ }
44719
+ updateState(params, extension) {
44720
+ if (!extension.isEnabled(this)) {
44721
+ return;
44722
+ }
44723
+ const uniforms = {};
44724
+ if (extension.opts.dash) {
44725
+ uniforms.dashAlignMode = this.props.dashJustified ? 1 : 0;
44726
+ uniforms.dashGapPickable = Boolean(this.props.dashGapPickable);
44727
+ }
44728
+ this.state.model.setUniforms(uniforms);
44729
+ }
44730
+ getDashOffsets(path) {
44731
+ const result = [0];
44732
+ const positionSize = this.props.positionFormat === "XY" ? 2 : 3;
44733
+ const isNested2 = Array.isArray(path[0]);
44734
+ const geometrySize = isNested2 ? path.length : path.length / positionSize;
44735
+ let p;
44736
+ let prevP;
44737
+ for (let i2 = 0; i2 < geometrySize - 1; i2++) {
44738
+ p = isNested2 ? path[i2] : path.slice(i2 * positionSize, i2 * positionSize + positionSize);
44739
+ p = this.projectPosition(p);
44740
+ if (i2 > 0) {
44741
+ result[i2] = result[i2 - 1] + dist(prevP, p);
44742
+ }
44743
+ prevP = p;
44744
+ }
44745
+ return result;
44746
+ }
44747
+ }
44748
+ _defineProperty(PathStyleExtension, "defaultProps", defaultProps$N);
44749
+ _defineProperty(PathStyleExtension, "extensionName", "PathStyleExtension");
44457
44750
  const defaultProps$M = {
44458
44751
  clipBounds: [0, 0, 1, 1]
44459
44752
  };
@@ -100541,8 +100834,8 @@ function requireJs$b() {
100541
100834
  var DeltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi12 / 2 + Math.PI / 4));
100542
100835
  var q = Math.abs(DeltaPsi) > 1e-11 ? DeltaPhi / DeltaPsi : Math.cos(phi12);
100543
100836
  var delta = Math.sqrt(DeltaPhi * DeltaPhi + q * q * DeltaLambda * DeltaLambda);
100544
- var dist = delta * R;
100545
- return dist;
100837
+ var dist2 = delta * R;
100838
+ return dist2;
100546
100839
  }
100547
100840
  js$a.default = rhumbDistance;
100548
100841
  return js$a;
@@ -100855,7 +101148,7 @@ function requireUtils$2() {
100855
101148
  var x;
100856
101149
  var y;
100857
101150
  var segmentIdx;
100858
- var dist;
101151
+ var dist2;
100859
101152
  if (coords.length > 1 && pointCoords.length) {
100860
101153
  var lineCoordinates;
100861
101154
  var pointCoordinate;
@@ -100872,17 +101165,17 @@ function requireUtils$2() {
100872
101165
  if (lineCoordinates[n2][0] !== lineCoordinates[n2 - 1][0]) {
100873
101166
  var slope = (lineCoordinates[n2][1] - lineCoordinates[n2 - 1][1]) / (lineCoordinates[n2][0] - lineCoordinates[n2 - 1][0]);
100874
101167
  var inverseSlope = lineCoordinates[n2][1] - slope * lineCoordinates[n2][0];
100875
- dist = Math.abs(slope * pointCoordinate[0] + inverseSlope - pointCoordinate[1]) / Math.sqrt(slope * slope + 1);
100876
- } else dist = Math.abs(pointCoordinate[0] - lineCoordinates[n2][0]);
101168
+ dist2 = Math.abs(slope * pointCoordinate[0] + inverseSlope - pointCoordinate[1]) / Math.sqrt(slope * slope + 1);
101169
+ } else dist2 = Math.abs(pointCoordinate[0] - lineCoordinates[n2][0]);
100877
101170
  var rl2 = Math.pow(lineCoordinates[n2][1] - lineCoordinates[n2 - 1][1], 2) + Math.pow(lineCoordinates[n2][0] - lineCoordinates[n2 - 1][0], 2);
100878
101171
  var ln2 = Math.pow(lineCoordinates[n2][1] - pointCoordinate[1], 2) + Math.pow(lineCoordinates[n2][0] - pointCoordinate[0], 2);
100879
101172
  var lnm12 = Math.pow(lineCoordinates[n2 - 1][1] - pointCoordinate[1], 2) + Math.pow(lineCoordinates[n2 - 1][0] - pointCoordinate[0], 2);
100880
- var dist2 = Math.pow(dist, 2);
100881
- var calcrl2 = ln2 - dist2 + lnm12 - dist2;
101173
+ var dist22 = Math.pow(dist2, 2);
101174
+ var calcrl2 = ln2 - dist22 + lnm12 - dist22;
100882
101175
  if (calcrl2 > rl2) {
100883
- dist = Math.sqrt(Math.min(ln2, lnm12));
101176
+ dist2 = Math.sqrt(Math.min(ln2, lnm12));
100884
101177
  }
100885
- if (minDist === null || minDist === void 0 || minDist > dist) {
101178
+ if (minDist === null || minDist === void 0 || minDist > dist2) {
100886
101179
  if (calcrl2 > rl2) {
100887
101180
  if (lnm12 < ln2) {
100888
101181
  to = 0;
@@ -100892,10 +101185,10 @@ function requireUtils$2() {
100892
101185
  to = 1;
100893
101186
  }
100894
101187
  } else {
100895
- to = Math.sqrt(lnm12 - dist2) / Math.sqrt(rl2);
100896
- from2 = Math.sqrt(ln2 - dist2) / Math.sqrt(rl2);
101188
+ to = Math.sqrt(lnm12 - dist22) / Math.sqrt(rl2);
101189
+ from2 = Math.sqrt(ln2 - dist22) / Math.sqrt(rl2);
100897
101190
  }
100898
- minDist = dist;
101191
+ minDist = dist2;
100899
101192
  segmentIdx = n2;
100900
101193
  }
100901
101194
  }
@@ -117226,22 +117519,22 @@ function addDecoder(cases, importFn) {
117226
117519
  }
117227
117520
  cases.forEach((c2) => registry$1.set(c2, importFn));
117228
117521
  }
117229
- addDecoder([void 0, 1], () => import("./raw-DrK5oUaJ.js").then((m2) => m2.default));
117230
- addDecoder(5, () => import("./lzw-DFW6fqhq.js").then((m2) => m2.default));
117522
+ addDecoder([void 0, 1], () => import("./raw-AvZwnBim.js").then((m2) => m2.default));
117523
+ addDecoder(5, () => import("./lzw-BpQ8dLUH.js").then((m2) => m2.default));
117231
117524
  addDecoder(6, () => {
117232
117525
  throw new Error("old style JPEG compression is not supported.");
117233
117526
  });
117234
- addDecoder(7, () => import("./jpeg-CT7-gAJ7.js").then((m2) => m2.default));
117235
- addDecoder([8, 32946], () => import("./deflate-LSUUttUX.js").then((m2) => m2.default));
117236
- addDecoder(32773, () => import("./packbits-D_9HcbKf.js").then((m2) => m2.default));
117527
+ addDecoder(7, () => import("./jpeg-DdAMSG2w.js").then((m2) => m2.default));
117528
+ addDecoder([8, 32946], () => import("./deflate-DUmHvVPz.js").then((m2) => m2.default));
117529
+ addDecoder(32773, () => import("./packbits-Cb8CXJgl.js").then((m2) => m2.default));
117237
117530
  addDecoder(
117238
117531
  34887,
117239
- () => import("./lerc-CVzJtTuz.js").then(async (m2) => {
117532
+ () => import("./lerc-D4PnY1mB.js").then(async (m2) => {
117240
117533
  await m2.zstd.init();
117241
117534
  return m2;
117242
117535
  }).then((m2) => m2.default)
117243
117536
  );
117244
- addDecoder(50001, () => import("./webimage-D2nsaIi_.js").then((m2) => m2.default));
117537
+ addDecoder(50001, () => import("./webimage-Di-764UM.js").then((m2) => m2.default));
117245
117538
  function decodeRowAcc(row, stride) {
117246
117539
  let length2 = row.length - stride;
117247
117540
  let offset2 = 0;
@@ -117656,8 +117949,8 @@ function TreeDesc(dyn_tree, stat_desc) {
117656
117949
  this.max_code = 0;
117657
117950
  this.stat_desc = stat_desc;
117658
117951
  }
117659
- const d_code = (dist) => {
117660
- return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
117952
+ const d_code = (dist2) => {
117953
+ return dist2 < 256 ? _dist_code[dist2] : _dist_code[256 + (dist2 >>> 7)];
117661
117954
  };
117662
117955
  const put_short = (s2, w2) => {
117663
117956
  s2.pending_buf[s2.pending++] = w2 & 255;
@@ -117791,7 +118084,7 @@ const tr_static_init = () => {
117791
118084
  let bits;
117792
118085
  let length2;
117793
118086
  let code;
117794
- let dist;
118087
+ let dist2;
117795
118088
  const bl_count = new Array(MAX_BITS + 1);
117796
118089
  length2 = 0;
117797
118090
  for (code = 0; code < LENGTH_CODES - 1; code++) {
@@ -117801,18 +118094,18 @@ const tr_static_init = () => {
117801
118094
  }
117802
118095
  }
117803
118096
  _length_code[length2 - 1] = code;
117804
- dist = 0;
118097
+ dist2 = 0;
117805
118098
  for (code = 0; code < 16; code++) {
117806
- base_dist[code] = dist;
118099
+ base_dist[code] = dist2;
117807
118100
  for (n2 = 0; n2 < 1 << extra_dbits[code]; n2++) {
117808
- _dist_code[dist++] = code;
118101
+ _dist_code[dist2++] = code;
117809
118102
  }
117810
118103
  }
117811
- dist >>= 7;
118104
+ dist2 >>= 7;
117812
118105
  for (; code < D_CODES; code++) {
117813
- base_dist[code] = dist << 7;
118106
+ base_dist[code] = dist2 << 7;
117814
118107
  for (n2 = 0; n2 < 1 << extra_dbits[code] - 7; n2++) {
117815
- _dist_code[256 + dist++] = code;
118108
+ _dist_code[256 + dist2++] = code;
117816
118109
  }
117817
118110
  }
117818
118111
  for (bits = 0; bits <= MAX_BITS; bits++) {
@@ -117903,17 +118196,17 @@ const pqdownheap = (s2, tree, k) => {
117903
118196
  s2.heap[k] = v;
117904
118197
  };
117905
118198
  const compress_block = (s2, ltree, dtree) => {
117906
- let dist;
118199
+ let dist2;
117907
118200
  let lc;
117908
118201
  let lx = 0;
117909
118202
  let code;
117910
118203
  let extra;
117911
118204
  if (s2.last_lit !== 0) {
117912
118205
  do {
117913
- dist = s2.pending_buf[s2.d_buf + lx * 2] << 8 | s2.pending_buf[s2.d_buf + lx * 2 + 1];
118206
+ dist2 = s2.pending_buf[s2.d_buf + lx * 2] << 8 | s2.pending_buf[s2.d_buf + lx * 2 + 1];
117914
118207
  lc = s2.pending_buf[s2.l_buf + lx];
117915
118208
  lx++;
117916
- if (dist === 0) {
118209
+ if (dist2 === 0) {
117917
118210
  send_code(s2, lc, ltree);
117918
118211
  } else {
117919
118212
  code = _length_code[lc];
@@ -117923,13 +118216,13 @@ const compress_block = (s2, ltree, dtree) => {
117923
118216
  lc -= base_length[code];
117924
118217
  send_bits(s2, lc, extra);
117925
118218
  }
117926
- dist--;
117927
- code = d_code(dist);
118219
+ dist2--;
118220
+ code = d_code(dist2);
117928
118221
  send_code(s2, code, dtree);
117929
118222
  extra = extra_dbits[code];
117930
118223
  if (extra !== 0) {
117931
- dist -= base_dist[code];
117932
- send_bits(s2, dist, extra);
118224
+ dist2 -= base_dist[code];
118225
+ send_bits(s2, dist2, extra);
117933
118226
  }
117934
118227
  }
117935
118228
  } while (lx < s2.last_lit);
@@ -118200,18 +118493,18 @@ const _tr_flush_block = (s2, buf, stored_len, last) => {
118200
118493
  bi_windup(s2);
118201
118494
  }
118202
118495
  };
118203
- const _tr_tally = (s2, dist, lc) => {
118204
- s2.pending_buf[s2.d_buf + s2.last_lit * 2] = dist >>> 8 & 255;
118205
- s2.pending_buf[s2.d_buf + s2.last_lit * 2 + 1] = dist & 255;
118496
+ const _tr_tally = (s2, dist2, lc) => {
118497
+ s2.pending_buf[s2.d_buf + s2.last_lit * 2] = dist2 >>> 8 & 255;
118498
+ s2.pending_buf[s2.d_buf + s2.last_lit * 2 + 1] = dist2 & 255;
118206
118499
  s2.pending_buf[s2.l_buf + s2.last_lit] = lc & 255;
118207
118500
  s2.last_lit++;
118208
- if (dist === 0) {
118501
+ if (dist2 === 0) {
118209
118502
  s2.dyn_ltree[lc * 2]++;
118210
118503
  } else {
118211
118504
  s2.matches++;
118212
- dist--;
118505
+ dist2--;
118213
118506
  s2.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]++;
118214
- s2.dyn_dtree[d_code(dist) * 2]++;
118507
+ s2.dyn_dtree[d_code(dist2) * 2]++;
118215
118508
  }
118216
118509
  return s2.last_lit === s2.lit_bufsize - 1;
118217
118510
  };
@@ -119716,7 +120009,7 @@ var inffast = function inflate_fast(strm, start) {
119716
120009
  let here;
119717
120010
  let op;
119718
120011
  let len2;
119719
- let dist;
120012
+ let dist2;
119720
120013
  let from2;
119721
120014
  let from_source;
119722
120015
  let input, output;
@@ -119782,7 +120075,7 @@ var inffast = function inflate_fast(strm, start) {
119782
120075
  bits -= op;
119783
120076
  op = here >>> 16 & 255;
119784
120077
  if (op & 16) {
119785
- dist = here & 65535;
120078
+ dist2 = here & 65535;
119786
120079
  op &= 15;
119787
120080
  if (bits < op) {
119788
120081
  hold += input[_in++] << bits;
@@ -119792,8 +120085,8 @@ var inffast = function inflate_fast(strm, start) {
119792
120085
  bits += 8;
119793
120086
  }
119794
120087
  }
119795
- dist += hold & (1 << op) - 1;
119796
- if (dist > dmax) {
120088
+ dist2 += hold & (1 << op) - 1;
120089
+ if (dist2 > dmax) {
119797
120090
  strm.msg = "invalid distance too far back";
119798
120091
  state.mode = BAD;
119799
120092
  break top;
@@ -119801,8 +120094,8 @@ var inffast = function inflate_fast(strm, start) {
119801
120094
  hold >>>= op;
119802
120095
  bits -= op;
119803
120096
  op = _out - beg;
119804
- if (dist > op) {
119805
- op = dist - op;
120097
+ if (dist2 > op) {
120098
+ op = dist2 - op;
119806
120099
  if (op > whave) {
119807
120100
  if (state.sane) {
119808
120101
  strm.msg = "invalid distance too far back";
@@ -119819,7 +120112,7 @@ var inffast = function inflate_fast(strm, start) {
119819
120112
  do {
119820
120113
  output[_out++] = s_window[from2++];
119821
120114
  } while (--op);
119822
- from2 = _out - dist;
120115
+ from2 = _out - dist2;
119823
120116
  from_source = output;
119824
120117
  }
119825
120118
  } else if (wnext < op) {
@@ -119837,7 +120130,7 @@ var inffast = function inflate_fast(strm, start) {
119837
120130
  do {
119838
120131
  output[_out++] = s_window[from2++];
119839
120132
  } while (--op);
119840
- from2 = _out - dist;
120133
+ from2 = _out - dist2;
119841
120134
  from_source = output;
119842
120135
  }
119843
120136
  }
@@ -119848,7 +120141,7 @@ var inffast = function inflate_fast(strm, start) {
119848
120141
  do {
119849
120142
  output[_out++] = s_window[from2++];
119850
120143
  } while (--op);
119851
- from2 = _out - dist;
120144
+ from2 = _out - dist2;
119852
120145
  from_source = output;
119853
120146
  }
119854
120147
  }
@@ -119865,7 +120158,7 @@ var inffast = function inflate_fast(strm, start) {
119865
120158
  }
119866
120159
  }
119867
120160
  } else {
119868
- from2 = _out - dist;
120161
+ from2 = _out - dist2;
119869
120162
  do {
119870
120163
  output[_out++] = output[from2++];
119871
120164
  output[_out++] = output[from2++];
@@ -120423,7 +120716,7 @@ const fixedtables = (state) => {
120423
120716
  state.distbits = 5;
120424
120717
  };
120425
120718
  const updatewindow = (strm, src, end, copy2) => {
120426
- let dist;
120719
+ let dist2;
120427
120720
  const state = strm.state;
120428
120721
  if (state.window === null) {
120429
120722
  state.wsize = 1 << state.wbits;
@@ -120436,23 +120729,23 @@ const updatewindow = (strm, src, end, copy2) => {
120436
120729
  state.wnext = 0;
120437
120730
  state.whave = state.wsize;
120438
120731
  } else {
120439
- dist = state.wsize - state.wnext;
120440
- if (dist > copy2) {
120441
- dist = copy2;
120732
+ dist2 = state.wsize - state.wnext;
120733
+ if (dist2 > copy2) {
120734
+ dist2 = copy2;
120442
120735
  }
120443
- state.window.set(src.subarray(end - copy2, end - copy2 + dist), state.wnext);
120444
- copy2 -= dist;
120736
+ state.window.set(src.subarray(end - copy2, end - copy2 + dist2), state.wnext);
120737
+ copy2 -= dist2;
120445
120738
  if (copy2) {
120446
120739
  state.window.set(src.subarray(end - copy2, end), 0);
120447
120740
  state.wnext = copy2;
120448
120741
  state.whave = state.wsize;
120449
120742
  } else {
120450
- state.wnext += dist;
120743
+ state.wnext += dist2;
120451
120744
  if (state.wnext === state.wsize) {
120452
120745
  state.wnext = 0;
120453
120746
  }
120454
120747
  if (state.whave < state.wsize) {
120455
- state.whave += dist;
120748
+ state.whave += dist2;
120456
120749
  }
120457
120750
  }
120458
120751
  }
@@ -124331,14 +124624,14 @@ vec4 colormap(float intensity) {
124331
124624
  }
124332
124625
  };
124333
124626
  }
124334
- const defaultProps$4$1 = {
124627
+ const defaultProps$4$2 = {
124335
124628
  colormap: { type: "string", value: "viridis", compare: true },
124336
124629
  opacity: { type: "number", value: 1, compare: true },
124337
124630
  useTransparentColor: { type: "boolean", value: false, compare: true }
124338
124631
  };
124339
124632
  const AdditiveColormapExtension = class extends LayerExtension {
124340
124633
  getShaders() {
124341
- const name2 = this?.props?.colormap || defaultProps$4$1.colormap.value;
124634
+ const name2 = this?.props?.colormap || defaultProps$4$2.colormap.value;
124342
124635
  const apply_cmap = cmaps[name2];
124343
124636
  if (!apply_cmap) {
124344
124637
  throw Error(`No colormap named ${name2} found in registry`);
@@ -124357,8 +124650,8 @@ const AdditiveColormapExtension = class extends LayerExtension {
124357
124650
  }
124358
124651
  draw() {
124359
124652
  const {
124360
- useTransparentColor = defaultProps$4$1.useTransparentColor.value,
124361
- opacity = defaultProps$4$1.opacity.value
124653
+ useTransparentColor = defaultProps$4$2.useTransparentColor.value,
124654
+ opacity = defaultProps$4$2.opacity.value
124362
124655
  } = this.props;
124363
124656
  const uniforms = {
124364
124657
  opacity,
@@ -124368,7 +124661,7 @@ const AdditiveColormapExtension = class extends LayerExtension {
124368
124661
  }
124369
124662
  };
124370
124663
  AdditiveColormapExtension.extensionName = "AdditiveColormapExtension";
124371
- AdditiveColormapExtension.defaultProps = defaultProps$4$1;
124664
+ AdditiveColormapExtension.defaultProps = defaultProps$4$2;
124372
124665
  const fs$1$2 = `uniform vec3 transparentColor;
124373
124666
  uniform bool useTransparentColor;
124374
124667
  uniform float opacity;
@@ -125661,7 +125954,7 @@ const ImageLayer = class extends CompositeLayer {
125661
125954
  };
125662
125955
  ImageLayer.layerName = "ImageLayer";
125663
125956
  ImageLayer.defaultProps = defaultProps$5;
125664
- const defaultProps$4 = {
125957
+ const defaultProps$4$1 = {
125665
125958
  pickable: { type: "boolean", value: true, compare: true },
125666
125959
  onHover: { type: "function", value: null, compare: false },
125667
125960
  contrastLimits: { type: "array", value: [], compare: true },
@@ -125773,7 +126066,7 @@ const MultiscaleImageLayer = class extends CompositeLayer {
125773
126066
  }
125774
126067
  };
125775
126068
  MultiscaleImageLayer.layerName = "MultiscaleImageLayer";
125776
- MultiscaleImageLayer.defaultProps = defaultProps$4;
126069
+ MultiscaleImageLayer.defaultProps = defaultProps$4$1;
125777
126070
  const defaultProps$3$1 = {
125778
126071
  pickable: { type: "boolean", value: true, compare: true },
125779
126072
  loader: {
@@ -126849,7 +127142,7 @@ function padWithDefault$1(arr, defaultValue2, padWidth) {
126849
127142
  }
126850
127143
  return newArr;
126851
127144
  }
126852
- const defaultProps$3 = {
127145
+ const defaultProps$4 = {
126853
127146
  hoveredCell: { type: "number", value: null, compare: true },
126854
127147
  // We do not want to deep-compare cellColorData,
126855
127148
  // as it is potentially a TypedArray with millions of elements.
@@ -126966,7 +127259,7 @@ let BitmaskLayer$1 = class BitmaskLayer extends XRLayer {
126966
127259
  }
126967
127260
  };
126968
127261
  BitmaskLayer$1.layerName = "BitmaskLayer";
126969
- BitmaskLayer$1.defaultProps = defaultProps$3;
127262
+ BitmaskLayer$1.defaultProps = defaultProps$4;
126970
127263
  const vs = `
126971
127264
  #define SHADER_NAME bitmask-layer-vertex-shader
126972
127265
 
@@ -127308,7 +127601,7 @@ function isEqualShallow(prevArr, nextArr) {
127308
127601
  }
127309
127602
  return prevArr === nextArr;
127310
127603
  }
127311
- const defaultProps$2 = {
127604
+ const defaultProps$3 = {
127312
127605
  channelStrokeWidths: { type: "array", value: null, compare: true },
127313
127606
  channelsFilled: { type: "array", value: null, compare: true },
127314
127607
  channelOpacities: { type: "array", value: null, compare: true },
@@ -127572,7 +127865,7 @@ class BitmaskLayer2 extends XRLayer {
127572
127865
  }
127573
127866
  }
127574
127867
  BitmaskLayer2.layerName = "BitmaskLayer";
127575
- BitmaskLayer2.defaultProps = defaultProps$2;
127868
+ BitmaskLayer2.defaultProps = defaultProps$3;
127576
127869
  var isNumeric$1 = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, mathceil = Math.ceil, mathfloor = Math.floor, bignumberError = "[BigNumber Error] ", tooManyDigits = bignumberError + "Number primitive has more than 15 significant digits: ", BASE = 1e14, LOG_BASE = 14, MAX_SAFE_INTEGER = 9007199254740991, POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], SQRT_BASE = 1e7, MAX = 1e9;
127577
127870
  function clone(configObject) {
127578
127871
  var div, convertBase, parseNumeric, P = BigNumber2.prototype = { constructor: BigNumber2, toString: null, valueOf: null }, ONE = new BigNumber2(1), DECIMAL_PLACES = 20, ROUNDING_MODE = 4, TO_EXP_NEG = -7, TO_EXP_POS = 21, MIN_EXP = -1e7, MAX_EXP = 1e7, CRYPTO = false, MODULO_MODE = 1, POW_PRECISION = 0, FORMAT = {
@@ -130515,7 +130808,7 @@ function ringArea(coords) {
130515
130808
  return total * FACTOR;
130516
130809
  }
130517
130810
  const DEFAULT_THRESHOLD = 1;
130518
- const defaultProps$1 = {
130811
+ const defaultProps$2 = {
130519
130812
  // for text
130520
130813
  obsSetPath: { type: "object" },
130521
130814
  sampleSetPath: { type: "object" },
@@ -130610,9 +130903,9 @@ class ContourLayerWithText extends ContourLayer {
130610
130903
  const circlePoint = point(circleCoord);
130611
130904
  polygonVertices.forEach((polyCoord) => {
130612
130905
  const polyPoint = point(polyCoord);
130613
- const dist = distance$1(circlePoint, polyPoint);
130614
- if (dist < minDist) {
130615
- minDist = dist;
130906
+ const dist2 = distance$1(circlePoint, polyPoint);
130907
+ if (dist2 < minDist) {
130908
+ minDist = dist2;
130616
130909
  minCirclePoint = circleCoord;
130617
130910
  minCirclePointI = circlePointI;
130618
130911
  minPolygonPoint = polyCoord;
@@ -130689,7 +130982,1077 @@ class ContourLayerWithText extends ContourLayer {
130689
130982
  }
130690
130983
  }
130691
130984
  ContourLayerWithText.layerName = "ContourLayerWithText";
130692
- ContourLayerWithText.defaultProps = defaultProps$1;
130985
+ ContourLayerWithText.defaultProps = defaultProps$2;
130986
+ const ARROW_SCREEN_PX = 14;
130987
+ const LABEL_FONT_FAMILY$1 = '"Roboto", "Helvetica", "Arial", sans-serif';
130988
+ const LABEL_FONT_WEIGHT = "bold";
130989
+ const LABEL_FONT_SIZE = 14;
130990
+ const RATIO_CLUSTER = 0.1;
130991
+ const RATIO_DOT = 0.3;
130992
+ const RATIO_GEO_FADE = 0.55;
130993
+ const RATIO_TIPS = 0.7;
130994
+ const RATIO_LABEL = 0.55;
130995
+ const RATIO_LABEL_FULL = 0.75;
130996
+ function textBgColor(strokeColor) {
130997
+ const [r2, g2, b] = strokeColor;
130998
+ const lum = (0.299 * r2 + 0.587 * g2 + 0.114 * b) / 255;
130999
+ return lum > 0.45 ? [20, 20, 20, 210] : [245, 245, 245, 210];
131000
+ }
131001
+ function parseDashArray(strokeDashArray) {
131002
+ if (!strokeDashArray || strokeDashArray === "none")
131003
+ return null;
131004
+ const nums = strokeDashArray.trim().split(/\s+/).map(Number).filter((n2) => !Number.isNaN(n2) && n2 >= 0);
131005
+ return nums.length >= 2 ? [nums[0], nums[1]] : null;
131006
+ }
131007
+ function computeEllipsePolygon(cx, cy, rx, ry, numSegments = 64) {
131008
+ const pts = [];
131009
+ for (let i2 = 0; i2 < numSegments; i2++) {
131010
+ const angle2 = 2 * Math.PI * i2 / numSegments;
131011
+ pts.push([cx + rx * Math.cos(angle2), cy + ry * Math.sin(angle2)]);
131012
+ }
131013
+ return pts;
131014
+ }
131015
+ function createPreviewLayer(inProgress, hoverCoord, strokeColor = [255, 255, 0]) {
131016
+ if (!inProgress || inProgress.vertices.length === 0)
131017
+ return null;
131018
+ const { type, vertices } = inProgress;
131019
+ const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN };
131020
+ const previewColor = [...strokeColor, 160];
131021
+ const cursor2 = hoverCoord ?? vertices[vertices.length - 1];
131022
+ if (type === "rectangle" && vertices.length === 1) {
131023
+ const [ax, ay] = vertices[0];
131024
+ const [bx, by] = cursor2;
131025
+ const path = [[ax, ay], [bx, ay], [bx, by], [ax, by], [ax, ay]];
131026
+ return new PathLayer({
131027
+ ...base,
131028
+ id: "annotation-preview-rectangle",
131029
+ data: [{ path }],
131030
+ getPath: (d) => d.path,
131031
+ getColor: previewColor,
131032
+ getWidth: 1,
131033
+ widthUnits: "pixels",
131034
+ extensions: [new PathStyleExtension({ dash: true })],
131035
+ getDashArray: [8, 4]
131036
+ });
131037
+ }
131038
+ if (type === "line" && vertices.length === 1) {
131039
+ const path = [vertices[0], cursor2];
131040
+ return new PathLayer({
131041
+ ...base,
131042
+ id: "annotation-preview-line",
131043
+ data: [{ path }],
131044
+ getPath: (d) => d.path,
131045
+ getColor: previewColor,
131046
+ getWidth: 1,
131047
+ widthUnits: "pixels",
131048
+ extensions: [new PathStyleExtension({ dash: true })],
131049
+ getDashArray: [8, 4]
131050
+ });
131051
+ }
131052
+ if (type === "ellipse" && vertices.length === 1) {
131053
+ const [cx, cy] = vertices[0];
131054
+ const [ex, ey] = cursor2;
131055
+ const rx = Math.abs(ex - cx);
131056
+ const ry = Math.abs(ey - cy);
131057
+ if (rx < 1 && ry < 1)
131058
+ return null;
131059
+ const pts = computeEllipsePolygon(cx, cy, Math.max(rx, 1), Math.max(ry, 1));
131060
+ const path = [...pts, pts[0]];
131061
+ return new PathLayer({
131062
+ ...base,
131063
+ id: "annotation-preview-ellipse",
131064
+ data: [{ path }],
131065
+ getPath: (d) => d.path,
131066
+ getColor: previewColor,
131067
+ getWidth: 1,
131068
+ widthUnits: "pixels",
131069
+ extensions: [new PathStyleExtension({ dash: true })],
131070
+ getDashArray: [8, 4]
131071
+ });
131072
+ }
131073
+ if ((type === "polygon" || type === "polyline") && vertices.length >= 1) {
131074
+ const path = [...vertices, cursor2];
131075
+ if (type === "polygon" && vertices.length >= 2)
131076
+ path.push(vertices[0]);
131077
+ return new PathLayer({
131078
+ ...base,
131079
+ id: `annotation-preview-${type}`,
131080
+ data: [{ path }],
131081
+ getPath: (d) => d.path,
131082
+ getColor: previewColor,
131083
+ getWidth: 1,
131084
+ widthUnits: "pixels",
131085
+ jointRounded: true,
131086
+ capRounded: true,
131087
+ extensions: [new PathStyleExtension({ dash: true })],
131088
+ getDashArray: [8, 4]
131089
+ });
131090
+ }
131091
+ return null;
131092
+ }
131093
+ function computeTickCap(tipX, tipY, dirX, dirY, dataSize) {
131094
+ const len2 = Math.sqrt(dirX * dirX + dirY * dirY);
131095
+ if (len2 === 0)
131096
+ return null;
131097
+ const ux = dirX / len2;
131098
+ const uy = dirY / len2;
131099
+ const px = -uy;
131100
+ const py = ux;
131101
+ const half = dataSize * 0.55;
131102
+ return [
131103
+ [tipX + px * half, tipY + py * half],
131104
+ [tipX - px * half, tipY - py * half]
131105
+ ];
131106
+ }
131107
+ function computeArrowhead(tipX, tipY, dirX, dirY, dataSize) {
131108
+ const len2 = Math.sqrt(dirX * dirX + dirY * dirY);
131109
+ if (len2 === 0)
131110
+ return null;
131111
+ const ux = dirX / len2;
131112
+ const uy = dirY / len2;
131113
+ const px = -uy;
131114
+ const py = ux;
131115
+ const halfBase = dataSize * 0.4;
131116
+ const bx = tipX - ux * dataSize;
131117
+ const by = tipY - uy * dataSize;
131118
+ return [
131119
+ [tipX, tipY],
131120
+ [bx + px * halfBase, by + py * halfBase],
131121
+ [bx - px * halfBase, by - py * halfBase]
131122
+ ];
131123
+ }
131124
+ function fmtCommas(n2) {
131125
+ return Math.round(n2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
131126
+ }
131127
+ function getMeasurementLabel(shape2, physicalPixelSize, viewType = ViewType$1.SPATIAL) {
131128
+ const pps = physicalPixelSize;
131129
+ const px = pps?.x ?? 1;
131130
+ const py = pps?.y ?? 1;
131131
+ const unit = pps ? pps.unit ?? "" : null;
131132
+ const hasPhys = !!pps;
131133
+ const isEmbedding = viewType === ViewType$1.SCATTERPLOT;
131134
+ const fmtDist = (d) => {
131135
+ if (hasPhys)
131136
+ return `${d.toFixed(2)} ${unit}`;
131137
+ if (isEmbedding)
131138
+ return d.toFixed(2);
131139
+ return `${fmtCommas(d)} px`;
131140
+ };
131141
+ const fmtArea = (a2) => {
131142
+ if (hasPhys)
131143
+ return `${a2.toFixed(2)} ${unit}²`;
131144
+ if (isEmbedding)
131145
+ return a2.toFixed(2);
131146
+ return `${fmtCommas(a2)} px²`;
131147
+ };
131148
+ if (shape2.type === "line") {
131149
+ const dx = (shape2.x2 ?? 0) - (shape2.x1 ?? 0);
131150
+ const dy = (shape2.y2 ?? 0) - (shape2.y1 ?? 0);
131151
+ const dist2 = hasPhys ? Math.sqrt((dx * px) ** 2 + (dy * py) ** 2) : Math.sqrt(dx * dx + dy * dy);
131152
+ return fmtDist(dist2);
131153
+ }
131154
+ if (shape2.type === "rectangle") {
131155
+ return fmtArea(hasPhys ? Math.abs(shape2.width ?? 0) * px * Math.abs(shape2.height ?? 0) * py : Math.abs((shape2.width ?? 0) * (shape2.height ?? 0)));
131156
+ }
131157
+ if (shape2.type === "ellipse") {
131158
+ const rx = Math.abs(shape2.radiusX ?? 0);
131159
+ const ry = Math.abs(shape2.radiusY ?? 0);
131160
+ return fmtArea(hasPhys ? Math.PI * rx * px * ry * py : Math.PI * rx * ry);
131161
+ }
131162
+ if (shape2.type === "polygon" && shape2.points?.length >= 3) {
131163
+ const pts = shape2.points;
131164
+ let shoelace = 0;
131165
+ for (let i2 = 0; i2 < pts.length; i2++) {
131166
+ const [ax, ay] = pts[i2];
131167
+ const [bx, by] = pts[(i2 + 1) % pts.length];
131168
+ shoelace += (hasPhys ? ax * px : ax) * (hasPhys ? by * py : by) - (hasPhys ? bx * px : bx) * (hasPhys ? ay * py : ay);
131169
+ }
131170
+ return fmtArea(Math.abs(shoelace / 2));
131171
+ }
131172
+ if (shape2.type === "polyline" && shape2.points?.length >= 2) {
131173
+ let total = 0;
131174
+ for (let i2 = 0; i2 < shape2.points.length - 1; i2++) {
131175
+ const [ax, ay] = shape2.points[i2];
131176
+ const [bx, by] = shape2.points[i2 + 1];
131177
+ total += hasPhys ? Math.sqrt(((bx - ax) * px) ** 2 + ((by - ay) * py) ** 2) : Math.sqrt((bx - ax) ** 2 + (by - ay) ** 2);
131178
+ }
131179
+ return fmtDist(total);
131180
+ }
131181
+ return null;
131182
+ }
131183
+ function pickBelowPerp(ux, uy) {
131184
+ const rp = [uy, -ux];
131185
+ const lp = [-uy, ux];
131186
+ return rp[1] > lp[1] || rp[1] === lp[1] && rp[0] > lp[0] ? rp : lp;
131187
+ }
131188
+ function readableAngle(deg) {
131189
+ let a2 = deg;
131190
+ if (a2 > 90)
131191
+ a2 -= 180;
131192
+ if (a2 < -90)
131193
+ a2 += 180;
131194
+ return a2;
131195
+ }
131196
+ function getShapeCentroid(shape2) {
131197
+ if (shape2.type === "rectangle") {
131198
+ return [(shape2.x ?? 0) + (shape2.width ?? 0) / 2, (shape2.y ?? 0) + (shape2.height ?? 0) / 2];
131199
+ }
131200
+ if (shape2.type === "line") {
131201
+ return [((shape2.x1 ?? 0) + (shape2.x2 ?? 0)) / 2, ((shape2.y1 ?? 0) + (shape2.y2 ?? 0)) / 2];
131202
+ }
131203
+ if (shape2.type === "ellipse") {
131204
+ return [shape2.x1 ?? 0, shape2.y1 ?? 0];
131205
+ }
131206
+ if ((shape2.type === "polygon" || shape2.type === "polyline") && shape2.points?.length >= 1) {
131207
+ const mx = shape2.points.reduce((s2, p) => s2 + p[0], 0) / shape2.points.length;
131208
+ const my = shape2.points.reduce((s2, p) => s2 + p[1], 0) / shape2.points.length;
131209
+ return [mx, my];
131210
+ }
131211
+ return [0, 0];
131212
+ }
131213
+ function computeClusters(shapeList, zoom, cellPx = 50) {
131214
+ const cellSize = cellPx / 2 ** Math.floor(zoom);
131215
+ const cells = /* @__PURE__ */ new Map();
131216
+ shapeList.forEach(({ shape: shape2 }) => {
131217
+ const [cx, cy] = getShapeCentroid(shape2);
131218
+ const key = `${Math.floor(cx / cellSize)},${Math.floor(cy / cellSize)}`;
131219
+ if (!cells.has(key)) {
131220
+ cells.set(key, { sumX: 0, sumY: 0, count: 0, color: shape2.strokeColor ?? [255, 255, 255] });
131221
+ }
131222
+ const c2 = cells.get(key);
131223
+ c2.sumX += cx;
131224
+ c2.sumY += cy;
131225
+ c2.count++;
131226
+ });
131227
+ return Array.from(cells.values()).map((c2) => ({
131228
+ position: [c2.sumX / c2.count, c2.sumY / c2.count, 0],
131229
+ count: c2.count,
131230
+ color: c2.color
131231
+ }));
131232
+ }
131233
+ function createAnnotationLayers(shapes = [], zoom = 0, selectedShapeUid = null, physicalPixelSize = null, authoredZoom = null, semanticZoom = true, viewType = ViewType$1.SPATIAL) {
131234
+ const selectionLayers = [];
131235
+ if (selectedShapeUid) {
131236
+ const sel = shapes.find((s2) => s2.uid === selectedShapeUid);
131237
+ if (sel) {
131238
+ const { uid: sUid, type: sType, strokeWidth: sStrokeWidth = 3 } = sel;
131239
+ const haloColor = [255, 220, 50, 70];
131240
+ const haloWidth = Math.max(sStrokeWidth + 8, 10);
131241
+ const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN };
131242
+ if (sType === "rectangle") {
131243
+ const { x, y, width: width2, height: height2 } = sel;
131244
+ selectionLayers.push(new PathLayer({
131245
+ ...base,
131246
+ id: `annotation-select-${sUid}`,
131247
+ data: [{
131248
+ path: [
131249
+ [x, y],
131250
+ [x + width2, y],
131251
+ [x + width2, y + height2],
131252
+ [x, y + height2],
131253
+ [x, y]
131254
+ ]
131255
+ }],
131256
+ getPath: (d) => d.path,
131257
+ getColor: haloColor,
131258
+ getWidth: haloWidth,
131259
+ widthUnits: "pixels",
131260
+ jointRounded: true,
131261
+ capRounded: true
131262
+ }));
131263
+ }
131264
+ if (sType === "line") {
131265
+ const { x1: x12, y1: y12, x2, y2 } = sel;
131266
+ selectionLayers.push(new PathLayer({
131267
+ ...base,
131268
+ id: `annotation-select-${sUid}`,
131269
+ data: [{ path: [[x12, y12], [x2, y2]] }],
131270
+ getPath: (d) => d.path,
131271
+ getColor: haloColor,
131272
+ getWidth: haloWidth,
131273
+ widthUnits: "pixels",
131274
+ capRounded: true
131275
+ }));
131276
+ }
131277
+ if (sType === "ellipse") {
131278
+ const polygon2 = computeEllipsePolygon(sel.x1, sel.y1, sel.radiusX, sel.radiusY);
131279
+ selectionLayers.push(new PathLayer({
131280
+ ...base,
131281
+ id: `annotation-select-${sUid}`,
131282
+ data: [{ path: [...polygon2, polygon2[0]] }],
131283
+ getPath: (d) => d.path,
131284
+ getColor: haloColor,
131285
+ getWidth: haloWidth,
131286
+ widthUnits: "pixels",
131287
+ jointRounded: true
131288
+ }));
131289
+ }
131290
+ if (sType === "polygon" && sel.points?.length >= 3) {
131291
+ selectionLayers.push(new PathLayer({
131292
+ ...base,
131293
+ id: `annotation-select-${sUid}`,
131294
+ data: [{ path: [...sel.points, sel.points[0]] }],
131295
+ getPath: (d) => d.path,
131296
+ getColor: haloColor,
131297
+ getWidth: haloWidth,
131298
+ widthUnits: "pixels",
131299
+ jointRounded: true
131300
+ }));
131301
+ }
131302
+ if (sType === "polyline" && sel.points?.length >= 2) {
131303
+ selectionLayers.push(new PathLayer({
131304
+ ...base,
131305
+ id: `annotation-select-${sUid}`,
131306
+ data: [{ path: sel.points }],
131307
+ getPath: (d) => d.path,
131308
+ getColor: haloColor,
131309
+ getWidth: haloWidth,
131310
+ widthUnits: "pixels",
131311
+ jointRounded: true,
131312
+ capRounded: true
131313
+ }));
131314
+ }
131315
+ }
131316
+ }
131317
+ const layers = [];
131318
+ const dotShapes = [];
131319
+ const clusterDotShapes = [];
131320
+ shapes.forEach((shape2, i2) => {
131321
+ const { uid: uid2, type, strokeColor = [255, 255, 255], strokeWidth = 3, strokeDashArray } = shape2;
131322
+ const isSelected = uid2 === selectedShapeUid;
131323
+ let shapeOpacity = 1;
131324
+ let tipsOpacity = 1;
131325
+ let labelOpacity = 0;
131326
+ if (isSelected || !semanticZoom || authoredZoom === null) {
131327
+ tipsOpacity = 1;
131328
+ labelOpacity = 1;
131329
+ } else {
131330
+ const zoomRatio = 2 ** (zoom - authoredZoom);
131331
+ if (zoomRatio < RATIO_CLUSTER) {
131332
+ clusterDotShapes.push({ shape: shape2 });
131333
+ return;
131334
+ }
131335
+ if (zoomRatio < RATIO_DOT) {
131336
+ dotShapes.push({ shape: shape2, alpha: 200 });
131337
+ return;
131338
+ }
131339
+ if (zoomRatio < RATIO_GEO_FADE) {
131340
+ const t = (zoomRatio - RATIO_DOT) / (RATIO_GEO_FADE - RATIO_DOT);
131341
+ shapeOpacity = t;
131342
+ dotShapes.push({ shape: shape2, alpha: Math.round((1 - t) * 200) });
131343
+ }
131344
+ tipsOpacity = zoomRatio >= RATIO_TIPS ? shapeOpacity : Math.max(0, (zoomRatio - RATIO_GEO_FADE) / (RATIO_TIPS - RATIO_GEO_FADE) * shapeOpacity);
131345
+ if (zoomRatio >= RATIO_LABEL_FULL) {
131346
+ labelOpacity = shapeOpacity;
131347
+ } else if (zoomRatio >= RATIO_LABEL) {
131348
+ labelOpacity = (zoomRatio - RATIO_LABEL) / (RATIO_LABEL_FULL - RATIO_LABEL) * shapeOpacity;
131349
+ }
131350
+ }
131351
+ const arrowDataSize = Math.max(ARROW_SCREEN_PX, strokeWidth * 4) / 2 ** zoom;
131352
+ const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: shapeOpacity };
131353
+ const tipsBase = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: tipsOpacity };
131354
+ const labelBase = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: labelOpacity };
131355
+ const labelBgProps = shape2.labelBackground ? {
131356
+ background: true,
131357
+ getBackgroundColor: textBgColor(strokeColor),
131358
+ backgroundPadding: [3, 1, 3, 2]
131359
+ } : {};
131360
+ const labelProps = { ...labelBgProps };
131361
+ const dashArray = parseDashArray(strokeDashArray);
131362
+ const dashExt = [new PathStyleExtension({ dash: true })];
131363
+ const getDash = dashArray ?? [0, 0];
131364
+ if (type === "rectangle") {
131365
+ const { x, y, width: width2, height: height2, fillColor = strokeColor, fillOpacity = 0 } = shape2;
131366
+ const filled = fillOpacity > 0;
131367
+ const rectPolygon = [[x, y], [x + width2, y], [x + width2, y + height2], [x, y + height2]];
131368
+ layers.push(new PolygonLayer({
131369
+ ...base,
131370
+ id: `annotation-rect-${uid2}-${i2}`,
131371
+ data: [{ polygon: rectPolygon }],
131372
+ getPolygon: (d) => d.polygon,
131373
+ filled,
131374
+ stroked: true,
131375
+ getFillColor: filled ? [...fillColor, Math.round(fillOpacity * 255)] : [0, 0, 0, 0],
131376
+ getLineColor: strokeColor,
131377
+ getLineWidth: strokeWidth,
131378
+ lineWidthUnits: "pixels",
131379
+ ...dashArray ? {
131380
+ extensions: [new PathStyleExtension({ dash: true })],
131381
+ getDashArray: dashArray
131382
+ } : {}
131383
+ }));
131384
+ if (shape2.text && labelOpacity > 0) {
131385
+ layers.push(new TextLayer({
131386
+ ...labelBase,
131387
+ ...labelProps,
131388
+ id: `annotation-rect-text-${uid2}-${i2}`,
131389
+ data: [{ position: [x, y], text: shape2.text }],
131390
+ getPosition: (d) => d.position,
131391
+ getText: (d) => d.text,
131392
+ getColor: strokeColor,
131393
+ getSize: LABEL_FONT_SIZE,
131394
+ sizeUnits: "pixels",
131395
+ fontFamily: LABEL_FONT_FAMILY$1,
131396
+ fontWeight: LABEL_FONT_WEIGHT,
131397
+ getPixelOffset: [3, -7],
131398
+ getTextAnchor: "start",
131399
+ getAlignmentBaseline: "bottom"
131400
+ }));
131401
+ }
131402
+ }
131403
+ if (type === "line") {
131404
+ const { x1: x12, y1: y12, x2, y2, markerStart, markerEnd } = shape2;
131405
+ const dx = x2 - x12;
131406
+ const dy = y2 - y12;
131407
+ const len2 = Math.sqrt(dx * dx + dy * dy);
131408
+ const ux = len2 > 0 ? dx / len2 : 0;
131409
+ const uy = len2 > 0 ? dy / len2 : 0;
131410
+ const srcX = markerStart === "Arrow" ? x12 + ux * arrowDataSize : x12;
131411
+ const srcY = markerStart === "Arrow" ? y12 + uy * arrowDataSize : y12;
131412
+ const tgtX = markerEnd === "Arrow" ? x2 - ux * arrowDataSize : x2;
131413
+ const tgtY = markerEnd === "Arrow" ? y2 - uy * arrowDataSize : y2;
131414
+ layers.push(new PathLayer({
131415
+ ...base,
131416
+ id: `annotation-line-${uid2}-${i2}`,
131417
+ extensions: [new PathStyleExtension({ dash: true })],
131418
+ getDashArray: dashArray ?? [0, 0],
131419
+ data: [{ path: [[srcX, srcY], [tgtX, tgtY]] }],
131420
+ getPath: (d) => d.path,
131421
+ getColor: strokeColor,
131422
+ getWidth: strokeWidth,
131423
+ widthUnits: "pixels",
131424
+ capRounded: true
131425
+ }));
131426
+ if (markerEnd === "Arrow" && tipsOpacity > 0) {
131427
+ const head = computeArrowhead(x2, y2, x2 - x12, y2 - y12, arrowDataSize);
131428
+ if (head) {
131429
+ layers.push(new PolygonLayer({
131430
+ ...tipsBase,
131431
+ id: `annotation-end-arrow-${uid2}-${i2}`,
131432
+ data: [{ polygon: head }],
131433
+ getPolygon: (d) => d.polygon,
131434
+ filled: true,
131435
+ stroked: false,
131436
+ getFillColor: strokeColor
131437
+ }));
131438
+ }
131439
+ }
131440
+ if (markerStart === "Arrow" && tipsOpacity > 0) {
131441
+ const head = computeArrowhead(x12, y12, x12 - x2, y12 - y2, arrowDataSize);
131442
+ if (head) {
131443
+ layers.push(new PolygonLayer({
131444
+ ...tipsBase,
131445
+ id: `annotation-start-arrow-${uid2}-${i2}`,
131446
+ data: [{ polygon: head }],
131447
+ getPolygon: (d) => d.polygon,
131448
+ filled: true,
131449
+ stroked: false,
131450
+ getFillColor: strokeColor
131451
+ }));
131452
+ }
131453
+ }
131454
+ if (markerEnd === "Tick" && tipsOpacity > 0) {
131455
+ const tick = computeTickCap(x2, y2, x2 - x12, y2 - y12, arrowDataSize);
131456
+ if (tick) {
131457
+ layers.push(new PathLayer({
131458
+ ...tipsBase,
131459
+ id: `annotation-end-tick-${uid2}-${i2}`,
131460
+ data: [{ path: tick }],
131461
+ getPath: (d) => d.path,
131462
+ getColor: strokeColor,
131463
+ getWidth: strokeWidth,
131464
+ widthUnits: "pixels",
131465
+ capRounded: true
131466
+ }));
131467
+ }
131468
+ }
131469
+ if (markerStart === "Tick" && tipsOpacity > 0) {
131470
+ const tick = computeTickCap(x12, y12, x12 - x2, y12 - y2, arrowDataSize);
131471
+ if (tick) {
131472
+ layers.push(new PathLayer({
131473
+ ...tipsBase,
131474
+ id: `annotation-start-tick-${uid2}-${i2}`,
131475
+ data: [{ path: tick }],
131476
+ getPath: (d) => d.path,
131477
+ getColor: strokeColor,
131478
+ getWidth: strokeWidth,
131479
+ widthUnits: "pixels",
131480
+ capRounded: true
131481
+ }));
131482
+ }
131483
+ }
131484
+ if (shape2.text) {
131485
+ const pos = shape2.textPosition ?? "start";
131486
+ let textX;
131487
+ let textY;
131488
+ if (pos === "start") {
131489
+ textX = x12;
131490
+ textY = y12;
131491
+ } else if (pos === "end") {
131492
+ textX = x2;
131493
+ textY = y2;
131494
+ } else {
131495
+ textX = (x12 + x2) / 2;
131496
+ textY = (y12 + y2) / 2;
131497
+ }
131498
+ let pixelOffset = [0, 0];
131499
+ let textAnchor = "middle";
131500
+ let alignmentBaseline = "center";
131501
+ if (pos !== "middle") {
131502
+ const dxT = x2 - x12;
131503
+ const dyT = y2 - y12;
131504
+ const lenT = Math.sqrt(dxT * dxT + dyT * dyT);
131505
+ if (lenT > 0) {
131506
+ const uxT = dxT / lenT;
131507
+ const uyT = dyT / lenT;
131508
+ const sign2 = pos === "start" ? -1 : 1;
131509
+ const bufferPx = shape2.textBufferPx ?? 8;
131510
+ const offsetX = sign2 * uxT * bufferPx;
131511
+ const offsetY = sign2 * uyT * bufferPx;
131512
+ pixelOffset = [offsetX, offsetY];
131513
+ const absX = Math.abs(offsetX);
131514
+ const absY = Math.abs(offsetY);
131515
+ if (absX >= absY) {
131516
+ textAnchor = offsetX > 0 ? "start" : "end";
131517
+ }
131518
+ if (absY >= absX) {
131519
+ alignmentBaseline = offsetY > 0 ? "top" : "bottom";
131520
+ }
131521
+ }
131522
+ } else if (len2 > 0) {
131523
+ const belowPerp = pickBelowPerp(ux, uy);
131524
+ const bufferPx = shape2.textBufferPx ?? 14;
131525
+ pixelOffset = [-belowPerp[0] * bufferPx, -belowPerp[1] * bufferPx];
131526
+ textAnchor = "middle";
131527
+ alignmentBaseline = "center";
131528
+ }
131529
+ const middleAngle = pos === "middle" && len2 > 0 ? -readableAngle(Math.atan2(dy, dx) * 180 / Math.PI) : null;
131530
+ if (labelOpacity <= 0)
131531
+ return;
131532
+ layers.push(new TextLayer({
131533
+ ...labelBase,
131534
+ ...labelProps,
131535
+ id: `annotation-line-text-${uid2}-${i2}`,
131536
+ data: [{ position: [textX, textY], text: shape2.text }],
131537
+ getPosition: (d) => d.position,
131538
+ getText: (d) => d.text,
131539
+ getColor: strokeColor,
131540
+ getSize: LABEL_FONT_SIZE,
131541
+ sizeUnits: "pixels",
131542
+ fontFamily: LABEL_FONT_FAMILY$1,
131543
+ fontWeight: LABEL_FONT_WEIGHT,
131544
+ getPixelOffset: pixelOffset,
131545
+ getTextAnchor: textAnchor,
131546
+ getAlignmentBaseline: alignmentBaseline,
131547
+ ...middleAngle !== null && { getAngle: middleAngle }
131548
+ }));
131549
+ }
131550
+ }
131551
+ if (type === "ellipse") {
131552
+ const { x1: x12, y1: y12, radiusX, radiusY, fillColor = strokeColor, fillOpacity = 0 } = shape2;
131553
+ const polygon2 = computeEllipsePolygon(x12, y12, radiusX, radiusY);
131554
+ const filled = fillOpacity > 0;
131555
+ layers.push(new PolygonLayer({
131556
+ ...base,
131557
+ id: `annotation-ellipse-${uid2}-${i2}`,
131558
+ data: [{ polygon: polygon2 }],
131559
+ getPolygon: (d) => d.polygon,
131560
+ filled,
131561
+ stroked: true,
131562
+ getFillColor: filled ? [...fillColor, Math.round(fillOpacity * 255)] : [0, 0, 0, 0],
131563
+ getLineColor: strokeColor,
131564
+ getLineWidth: strokeWidth,
131565
+ lineWidthUnits: "pixels",
131566
+ ...dashArray ? {
131567
+ extensions: [new PathStyleExtension({ dash: true })],
131568
+ getDashArray: dashArray
131569
+ } : {}
131570
+ }));
131571
+ if (shape2.text && labelOpacity > 0) {
131572
+ layers.push(new TextLayer({
131573
+ ...labelBase,
131574
+ ...labelProps,
131575
+ id: `annotation-ellipse-text-${uid2}-${i2}`,
131576
+ data: [{ position: [x12, y12 - radiusY], text: shape2.text }],
131577
+ getPosition: (d) => d.position,
131578
+ getText: (d) => d.text,
131579
+ getColor: strokeColor,
131580
+ getSize: LABEL_FONT_SIZE,
131581
+ sizeUnits: "pixels",
131582
+ fontFamily: LABEL_FONT_FAMILY$1,
131583
+ fontWeight: LABEL_FONT_WEIGHT,
131584
+ getPixelOffset: [0, -4],
131585
+ getTextAnchor: "middle",
131586
+ getAlignmentBaseline: "bottom"
131587
+ }));
131588
+ }
131589
+ }
131590
+ if (type === "polygon") {
131591
+ const { points, fillColor = strokeColor, fillOpacity = 0 } = shape2;
131592
+ if (!points || points.length < 3)
131593
+ return;
131594
+ const closedPath = [...points, points[0]];
131595
+ if (fillOpacity > 0) {
131596
+ layers.push(new PolygonLayer({
131597
+ ...base,
131598
+ id: `annotation-polygon-fill-${uid2}-${i2}`,
131599
+ data: [{ polygon: points }],
131600
+ getPolygon: (d) => d.polygon,
131601
+ stroked: false,
131602
+ filled: true,
131603
+ getFillColor: [...fillColor, Math.round(fillOpacity * 255)]
131604
+ }));
131605
+ }
131606
+ layers.push(new PathLayer({
131607
+ ...base,
131608
+ id: `annotation-polygon-${uid2}-${i2}`,
131609
+ extensions: dashExt,
131610
+ getDashArray: getDash,
131611
+ data: [{ path: closedPath }],
131612
+ getPath: (d) => d.path,
131613
+ getColor: strokeColor,
131614
+ getWidth: strokeWidth,
131615
+ widthUnits: "pixels",
131616
+ jointRounded: true
131617
+ }));
131618
+ if (shape2.text && labelOpacity > 0) {
131619
+ const minX = Math.min(...points.map((p) => p[0]));
131620
+ const maxX = Math.max(...points.map((p) => p[0]));
131621
+ const minY = Math.min(...points.map((p) => p[1]));
131622
+ const topCenterX = (minX + maxX) / 2;
131623
+ layers.push(new TextLayer({
131624
+ ...labelBase,
131625
+ ...labelProps,
131626
+ id: `annotation-polygon-text-${uid2}-${i2}`,
131627
+ data: [{ position: [topCenterX, minY], text: shape2.text }],
131628
+ getPosition: (d) => d.position,
131629
+ getText: (d) => d.text,
131630
+ getColor: strokeColor,
131631
+ getSize: LABEL_FONT_SIZE,
131632
+ sizeUnits: "pixels",
131633
+ fontFamily: LABEL_FONT_FAMILY$1,
131634
+ fontWeight: LABEL_FONT_WEIGHT,
131635
+ getPixelOffset: [0, -4],
131636
+ getTextAnchor: "middle",
131637
+ getAlignmentBaseline: "bottom"
131638
+ }));
131639
+ }
131640
+ }
131641
+ if (type === "polyline") {
131642
+ const { points, markerStart, markerEnd } = shape2;
131643
+ if (!points || points.length < 2)
131644
+ return;
131645
+ let pathPoints = points;
131646
+ if (markerStart === "Arrow") {
131647
+ const [x02, y02] = points[0];
131648
+ const [x12, y12] = points[1];
131649
+ const dx = x02 - x12;
131650
+ const dy = y02 - y12;
131651
+ const len2 = Math.sqrt(dx * dx + dy * dy);
131652
+ if (len2 > 0) {
131653
+ const ux = dx / len2;
131654
+ const uy = dy / len2;
131655
+ pathPoints = [[x02 - ux * arrowDataSize, y02 - uy * arrowDataSize], ...pathPoints.slice(1)];
131656
+ }
131657
+ }
131658
+ if (markerEnd === "Arrow") {
131659
+ const last = pathPoints[pathPoints.length - 1];
131660
+ const prev2 = pathPoints[pathPoints.length - 2];
131661
+ const dx = last[0] - prev2[0];
131662
+ const dy = last[1] - prev2[1];
131663
+ const len2 = Math.sqrt(dx * dx + dy * dy);
131664
+ if (len2 > 0) {
131665
+ const ux = dx / len2;
131666
+ const uy = dy / len2;
131667
+ const shortened = [last[0] - ux * arrowDataSize, last[1] - uy * arrowDataSize];
131668
+ pathPoints = [...pathPoints.slice(0, -1), shortened];
131669
+ }
131670
+ }
131671
+ layers.push(new PathLayer({
131672
+ ...base,
131673
+ id: `annotation-polyline-${uid2}-${i2}`,
131674
+ extensions: dashExt,
131675
+ getDashArray: getDash,
131676
+ data: [{ path: pathPoints }],
131677
+ getPath: (d) => d.path,
131678
+ getColor: strokeColor,
131679
+ getWidth: strokeWidth,
131680
+ widthUnits: "pixels",
131681
+ jointRounded: true,
131682
+ capRounded: true
131683
+ }));
131684
+ if (markerStart === "Arrow" && tipsOpacity > 0) {
131685
+ const [x02, y02] = points[0];
131686
+ const [x12, y12] = points[1];
131687
+ const head = computeArrowhead(x02, y02, x02 - x12, y02 - y12, arrowDataSize);
131688
+ if (head) {
131689
+ layers.push(new PolygonLayer({
131690
+ ...tipsBase,
131691
+ id: `annotation-polyline-start-arrow-${uid2}-${i2}`,
131692
+ data: [{ polygon: head }],
131693
+ getPolygon: (d) => d.polygon,
131694
+ filled: true,
131695
+ stroked: false,
131696
+ getFillColor: strokeColor
131697
+ }));
131698
+ }
131699
+ }
131700
+ if (markerEnd === "Arrow" && tipsOpacity > 0) {
131701
+ const last = points[points.length - 1];
131702
+ const prev2 = points[points.length - 2];
131703
+ const dxArrow = last[0] - prev2[0];
131704
+ const dyArrow = last[1] - prev2[1];
131705
+ const head = computeArrowhead(last[0], last[1], dxArrow, dyArrow, arrowDataSize);
131706
+ if (head) {
131707
+ layers.push(new PolygonLayer({
131708
+ ...tipsBase,
131709
+ id: `annotation-polyline-end-arrow-${uid2}-${i2}`,
131710
+ data: [{ polygon: head }],
131711
+ getPolygon: (d) => d.polygon,
131712
+ filled: true,
131713
+ stroked: false,
131714
+ getFillColor: strokeColor
131715
+ }));
131716
+ }
131717
+ }
131718
+ if (markerStart === "Tick" && tipsOpacity > 0) {
131719
+ const [x02, y02] = points[0];
131720
+ const [x12, y12] = points[1];
131721
+ const tick = computeTickCap(x02, y02, x02 - x12, y02 - y12, arrowDataSize);
131722
+ if (tick) {
131723
+ layers.push(new PathLayer({
131724
+ ...tipsBase,
131725
+ id: `annotation-polyline-start-tick-${uid2}-${i2}`,
131726
+ data: [{ path: tick }],
131727
+ getPath: (d) => d.path,
131728
+ getColor: strokeColor,
131729
+ getWidth: strokeWidth,
131730
+ widthUnits: "pixels",
131731
+ capRounded: true
131732
+ }));
131733
+ }
131734
+ }
131735
+ if (markerEnd === "Tick" && tipsOpacity > 0) {
131736
+ const last = points[points.length - 1];
131737
+ const prev2 = points[points.length - 2];
131738
+ const dxTick = last[0] - prev2[0];
131739
+ const dyTick = last[1] - prev2[1];
131740
+ const tick = computeTickCap(last[0], last[1], dxTick, dyTick, arrowDataSize);
131741
+ if (tick) {
131742
+ layers.push(new PathLayer({
131743
+ ...tipsBase,
131744
+ id: `annotation-polyline-end-tick-${uid2}-${i2}`,
131745
+ data: [{ path: tick }],
131746
+ getPath: (d) => d.path,
131747
+ getColor: strokeColor,
131748
+ getWidth: strokeWidth,
131749
+ widthUnits: "pixels",
131750
+ capRounded: true
131751
+ }));
131752
+ }
131753
+ }
131754
+ if (shape2.text) {
131755
+ const pos = shape2.textPosition ?? "start";
131756
+ const bufferPx = shape2.textBufferPx ?? 8;
131757
+ let textPt;
131758
+ let dirX;
131759
+ let dirY;
131760
+ if (pos === "end") {
131761
+ const last = points[points.length - 1];
131762
+ const prev2 = points[points.length - 2];
131763
+ textPt = last;
131764
+ dirX = last[0] - prev2[0];
131765
+ dirY = last[1] - prev2[1];
131766
+ } else if (pos === "middle") {
131767
+ const mx = points.reduce((s2, p) => s2 + p[0], 0) / points.length;
131768
+ const my = points.reduce((s2, p) => s2 + p[1], 0) / points.length;
131769
+ textPt = [mx, my];
131770
+ dirX = 0;
131771
+ dirY = 0;
131772
+ } else {
131773
+ [textPt] = points;
131774
+ dirX = points[0][0] - points[1][0];
131775
+ dirY = points[0][1] - points[1][1];
131776
+ }
131777
+ const [textX, textY] = textPt;
131778
+ const lenT = Math.sqrt(dirX * dirX + dirY * dirY);
131779
+ let polylinePixelOffset = [0, 0];
131780
+ let polylineTextAnchor = "middle";
131781
+ let polylineAlignmentBaseline = pos === "middle" ? "center" : "bottom";
131782
+ if (lenT > 0) {
131783
+ const uxT = dirX / lenT;
131784
+ const uyT = dirY / lenT;
131785
+ const offX = uxT * bufferPx;
131786
+ const offY = uyT * bufferPx;
131787
+ polylinePixelOffset = [offX, offY];
131788
+ if (Math.abs(offX) >= Math.abs(offY)) {
131789
+ polylineTextAnchor = offX > 0 ? "start" : "end";
131790
+ }
131791
+ if (Math.abs(offY) >= Math.abs(offX)) {
131792
+ polylineAlignmentBaseline = offY > 0 ? "top" : "bottom";
131793
+ }
131794
+ }
131795
+ if (labelOpacity <= 0)
131796
+ return;
131797
+ layers.push(new TextLayer({
131798
+ ...labelBase,
131799
+ ...labelProps,
131800
+ id: `annotation-polyline-text-${uid2}-${i2}`,
131801
+ data: [{ position: [textX, textY], text: shape2.text }],
131802
+ getPosition: (d) => d.position,
131803
+ getText: (d) => d.text,
131804
+ getColor: strokeColor,
131805
+ getSize: LABEL_FONT_SIZE,
131806
+ sizeUnits: "pixels",
131807
+ fontFamily: LABEL_FONT_FAMILY$1,
131808
+ fontWeight: LABEL_FONT_WEIGHT,
131809
+ getPixelOffset: polylinePixelOffset,
131810
+ getTextAnchor: polylineTextAnchor,
131811
+ getAlignmentBaseline: polylineAlignmentBaseline
131812
+ }));
131813
+ }
131814
+ }
131815
+ });
131816
+ if (dotShapes.length > 0) {
131817
+ layers.push(new ScatterplotLayer({
131818
+ coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
131819
+ id: "annotation-dots",
131820
+ data: dotShapes.map(({ shape: s2, alpha: alpha2 }) => ({
131821
+ position: getShapeCentroid(s2),
131822
+ color: [...s2.strokeColor ?? [255, 255, 255], alpha2]
131823
+ })),
131824
+ getPosition: (d) => d.position,
131825
+ getFillColor: (d) => d.color,
131826
+ getRadius: 4,
131827
+ radiusUnits: "pixels",
131828
+ filled: true,
131829
+ stroked: false
131830
+ }));
131831
+ }
131832
+ if (clusterDotShapes.length > 0) {
131833
+ const clusters = computeClusters(clusterDotShapes, zoom);
131834
+ layers.push(new ScatterplotLayer({
131835
+ coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
131836
+ id: "annotation-clusters",
131837
+ data: clusters,
131838
+ getPosition: (d) => d.position,
131839
+ getFillColor: (d) => [...d.color, 180],
131840
+ getRadius: (d) => Math.max(6, 4 + Math.sqrt(d.count) * 2),
131841
+ radiusUnits: "pixels",
131842
+ filled: true,
131843
+ stroked: true,
131844
+ getLineColor: (d) => [...d.color, 220],
131845
+ lineWidthMinPixels: 1.5
131846
+ }));
131847
+ const multiClusters = clusters.filter((c2) => c2.count > 1);
131848
+ if (multiClusters.length > 0) {
131849
+ layers.push(new TextLayer({
131850
+ coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
131851
+ id: "annotation-cluster-counts",
131852
+ data: multiClusters,
131853
+ getPosition: (d) => d.position,
131854
+ getText: (d) => String(d.count),
131855
+ getColor: [255, 255, 255],
131856
+ getSize: 10,
131857
+ sizeUnits: "pixels",
131858
+ fontWeight: "bold",
131859
+ getTextAnchor: "middle",
131860
+ getAlignmentBaseline: "center"
131861
+ }));
131862
+ }
131863
+ }
131864
+ const measureLayers = [];
131865
+ shapes.forEach((shape2) => {
131866
+ if (!shape2.showMeasure)
131867
+ return;
131868
+ const mIsSelected = shape2.uid === selectedShapeUid;
131869
+ const label = getMeasurementLabel(shape2, physicalPixelSize, viewType);
131870
+ if (!label)
131871
+ return;
131872
+ const color2 = shape2.strokeColor ?? [255, 255, 255];
131873
+ let mShapeOpacity = 1;
131874
+ let mLabelFactor = 0;
131875
+ if (mIsSelected || !semanticZoom || authoredZoom === null) {
131876
+ mLabelFactor = 1;
131877
+ } else {
131878
+ const mZoomRatio = 2 ** (zoom - authoredZoom);
131879
+ if (mZoomRatio < RATIO_DOT)
131880
+ return;
131881
+ if (mZoomRatio < RATIO_GEO_FADE) {
131882
+ mShapeOpacity = (mZoomRatio - RATIO_DOT) / (RATIO_GEO_FADE - RATIO_DOT);
131883
+ }
131884
+ if (mZoomRatio >= RATIO_LABEL_FULL) {
131885
+ mLabelFactor = 1;
131886
+ } else if (mZoomRatio >= RATIO_LABEL) {
131887
+ mLabelFactor = (mZoomRatio - RATIO_LABEL) / (RATIO_LABEL_FULL - RATIO_LABEL);
131888
+ }
131889
+ }
131890
+ const measureOpacity = mShapeOpacity * mLabelFactor;
131891
+ if (measureOpacity <= 0)
131892
+ return;
131893
+ const base = {
131894
+ coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
131895
+ opacity: measureOpacity,
131896
+ getText: (d) => d.text,
131897
+ getPosition: (d) => d.position,
131898
+ getColor: color2,
131899
+ getSize: 13,
131900
+ sizeUnits: "pixels",
131901
+ fontFamily: LABEL_FONT_FAMILY$1,
131902
+ fontWeight: "bold",
131903
+ // 'auto' builds the font atlas from the actual rendered characters (e.g. µ, ²)
131904
+ // instead of deck.gl's default ASCII-only atlas.
131905
+ characterSet: "auto",
131906
+ ...shape2.measureBackground ? {
131907
+ background: true,
131908
+ getBackgroundColor: textBgColor(color2),
131909
+ backgroundPadding: [3, 1, 3, 2]
131910
+ } : {}
131911
+ };
131912
+ if (shape2.type === "line") {
131913
+ const mx = ((shape2.x1 ?? 0) + (shape2.x2 ?? 0)) / 2;
131914
+ const my = ((shape2.y1 ?? 0) + (shape2.y2 ?? 0)) / 2;
131915
+ const dx = (shape2.x2 ?? 0) - (shape2.x1 ?? 0);
131916
+ const dy = (shape2.y2 ?? 0) - (shape2.y1 ?? 0);
131917
+ const len2 = Math.sqrt(dx * dx + dy * dy);
131918
+ if (len2 === 0)
131919
+ return;
131920
+ const perp = pickBelowPerp(dx / len2, dy / len2);
131921
+ const angle2 = readableAngle(Math.atan2(dy, dx) * 180 / Math.PI);
131922
+ measureLayers.push(new TextLayer({
131923
+ ...base,
131924
+ id: `annotation-measure-${shape2.uid}`,
131925
+ data: [{ position: [mx, my], text: label }],
131926
+ getAngle: -angle2,
131927
+ getTextAnchor: "middle",
131928
+ getAlignmentBaseline: "center",
131929
+ getPixelOffset: [perp[0] * 16, perp[1] * 16]
131930
+ }));
131931
+ } else if (shape2.type === "polyline" && shape2.points?.length >= 2) {
131932
+ const pts = shape2.points;
131933
+ const mi = Math.floor((pts.length - 1) / 2);
131934
+ const [ax, ay] = pts[mi];
131935
+ const [bx, by] = pts[mi + 1];
131936
+ const dx = bx - ax;
131937
+ const dy = by - ay;
131938
+ const len2 = Math.sqrt(dx * dx + dy * dy);
131939
+ if (len2 === 0)
131940
+ return;
131941
+ const perp = pickBelowPerp(dx / len2, dy / len2);
131942
+ const angle2 = readableAngle(Math.atan2(dy, dx) * 180 / Math.PI);
131943
+ measureLayers.push(new TextLayer({
131944
+ ...base,
131945
+ id: `annotation-measure-${shape2.uid}`,
131946
+ data: [{ position: [(ax + bx) / 2, (ay + by) / 2], text: label }],
131947
+ getAngle: -angle2,
131948
+ getTextAnchor: "middle",
131949
+ getAlignmentBaseline: "center",
131950
+ getPixelOffset: [perp[0] * 16, perp[1] * 16]
131951
+ }));
131952
+ } else if (shape2.type === "rectangle") {
131953
+ const x02 = shape2.x ?? 0;
131954
+ const y02 = shape2.y ?? 0;
131955
+ const w2 = shape2.width ?? 0;
131956
+ const h = shape2.height ?? 0;
131957
+ const rx = x02 + (w2 >= 0 ? w2 : 0);
131958
+ const ry = y02 + (h >= 0 ? h : 0);
131959
+ measureLayers.push(new TextLayer({
131960
+ ...base,
131961
+ id: `annotation-measure-${shape2.uid}`,
131962
+ data: [{ position: [rx, ry], text: label }],
131963
+ getTextAnchor: "end",
131964
+ getAlignmentBaseline: "bottom",
131965
+ getPixelOffset: [-6, -6]
131966
+ }));
131967
+ } else if (shape2.type === "ellipse") {
131968
+ const cx = shape2.x1 ?? 0;
131969
+ const cy = shape2.y1 ?? 0;
131970
+ const ry = Math.abs(shape2.radiusY ?? 0);
131971
+ measureLayers.push(new TextLayer({
131972
+ ...base,
131973
+ id: `annotation-measure-${shape2.uid}`,
131974
+ data: [{ position: [cx, cy + ry], text: label }],
131975
+ getTextAnchor: "middle",
131976
+ getAlignmentBaseline: "top",
131977
+ getPixelOffset: [0, 8]
131978
+ }));
131979
+ } else if (shape2.type === "polygon" && shape2.points?.length >= 3) {
131980
+ const xs = shape2.points.map((p) => p[0]);
131981
+ const ys = shape2.points.map((p) => p[1]);
131982
+ const cx = (Math.min(...xs) + Math.max(...xs)) / 2;
131983
+ const maxY = Math.max(...ys);
131984
+ measureLayers.push(new TextLayer({
131985
+ ...base,
131986
+ id: `annotation-measure-${shape2.uid}`,
131987
+ data: [{ position: [cx, maxY], text: label }],
131988
+ getTextAnchor: "middle",
131989
+ getAlignmentBaseline: "top",
131990
+ getPixelOffset: [0, 8]
131991
+ }));
131992
+ }
131993
+ });
131994
+ return [...selectionLayers, ...layers, ...measureLayers];
131995
+ }
131996
+ const defaultProps$1 = {
131997
+ // Array of annotation shape objects (see annotationShapeObj in @vitessce/schemas).
131998
+ data: { type: "object", value: [], compare: true },
131999
+ // UID of the shape to highlight with a selection halo.
132000
+ selectedShapeUid: { type: "string", value: null },
132001
+ // { x, y, unit } used to format measurement labels in physical units.
132002
+ physicalPixelSize: { type: "object", value: null, compare: true },
132003
+ // The zoom level at which the shapes were authored (reference for semantic zoom).
132004
+ authoredZoom: { type: "number", value: null },
132005
+ // Whether to apply semantic zoom (level-of-detail) based on authoredZoom.
132006
+ semanticZoom: { type: "boolean", value: true },
132007
+ // The view type in which the layer is rendered (affects measurement label formatting).
132008
+ viewType: { type: "string", value: ViewType$1.SPATIAL },
132009
+ // In-progress shape being drawn, as { type, vertices }.
132010
+ inProgressShape: { type: "object", value: null, compare: true },
132011
+ // Current mouse position (in data coordinates) while drawing.
132012
+ hoverCoord: { type: "array", value: null, compare: true },
132013
+ // Stroke color [r, g, b] of the in-progress shape preview.
132014
+ previewStrokeColor: { type: "color", value: [255, 255, 0] }
132015
+ };
132016
+ class AnnotationLayer extends CompositeLayer {
132017
+ // The semantic zoom and arrowhead sizes depend on the current zoom level,
132018
+ // so the sublayers must also be re-rendered when the viewport changes.
132019
+ // eslint-disable-next-line class-methods-use-this
132020
+ shouldUpdateState({ changeFlags }) {
132021
+ return changeFlags.propsOrDataChanged || changeFlags.viewportChanged;
132022
+ }
132023
+ /**
132024
+ * Prefix the sublayer ID with this layer's ID (so that multiple
132025
+ * AnnotationLayers can co-exist), and combine this layer's
132026
+ * opacity with the per-shape opacity of the sublayer.
132027
+ * Note: we avoid getSubLayerProps here, since it would
132028
+ * overwrite the sublayer extensions (e.g., PathStyleExtension)
132029
+ * and opacity values.
132030
+ * @param {object} layer A DeckGL layer instance.
132031
+ * @returns {object} The cloned layer instance.
132032
+ */
132033
+ wrapSubLayer(layer) {
132034
+ const { id, opacity, pickable, visible } = this.props;
132035
+ return layer.clone({
132036
+ id: `${id}-${layer.id}`,
132037
+ opacity: layer.props.opacity * opacity,
132038
+ pickable,
132039
+ visible
132040
+ });
132041
+ }
132042
+ renderLayers() {
132043
+ const { data, selectedShapeUid, physicalPixelSize, authoredZoom, semanticZoom, viewType, inProgressShape, hoverCoord, previewStrokeColor } = this.props;
132044
+ const zoom = this.context.viewport?.zoom ?? 0;
132045
+ const visibleShapes = (data ?? []).filter((shape2) => shape2.visible !== false);
132046
+ const annotationLayers = createAnnotationLayers(visibleShapes, zoom, selectedShapeUid, physicalPixelSize, authoredZoom, semanticZoom, viewType);
132047
+ const previewLayer = createPreviewLayer(inProgressShape, hoverCoord, previewStrokeColor.slice(0, 3));
132048
+ return [
132049
+ ...annotationLayers,
132050
+ ...previewLayer ? [previewLayer] : []
132051
+ ].map((layer) => this.wrapSubLayer(layer));
132052
+ }
132053
+ }
132054
+ AnnotationLayer.layerName = "AnnotationLayer";
132055
+ AnnotationLayer.defaultProps = defaultProps$1;
130693
132056
  function r$1(e2) {
130694
132057
  var t, f2, n2 = "";
130695
132058
  if ("string" == typeof e2 || "number" == typeof e2) n2 += e2;
@@ -153607,11 +154970,13 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
153607
154970
  this.cellSetsLabelPrevZoom = null;
153608
154971
  this.cellSetsLayers = [];
153609
154972
  this.contourLayers = [];
154973
+ this.annotationLayer = null;
153610
154974
  this.onUpdateCellsData();
153611
154975
  this.onUpdateCellsLayer();
153612
154976
  this.onUpdateCellSetsLayers();
153613
154977
  this.onUpdateStratifiedData();
153614
154978
  this.onUpdateContourLayers();
154979
+ this.onUpdateAnnotationLayer();
153615
154980
  }
153616
154981
  // Want to support multiple types of contour layers
153617
154982
  // - One layer for all data points (no filtering)
@@ -153675,6 +155040,21 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
153675
155040
  }));
153676
155041
  return layers;
153677
155042
  }
155043
+ createAnnotationLayer() {
155044
+ const { annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationShapeSelection } = this.props;
155045
+ return new AnnotationLayer({
155046
+ data: annotationShapes,
155047
+ visible: annotationOverlayVisible,
155048
+ semanticZoom: annotationSemanticZoom,
155049
+ selectedShapeUid: annotationShapeSelection,
155050
+ viewType: ViewType$1.SCATTERPLOT
155051
+ // TODO: is this needed?
155052
+ // TODO: these are view-level properties, rather than layer-level.
155053
+ // annotationTransitionDuration,
155054
+ // annotationEditable,
155055
+ // Other coordination types related to editing...
155056
+ });
155057
+ }
153678
155058
  createCellsLayer() {
153679
155059
  const {
153680
155060
  obsEmbeddingIndex: obsIndex,
@@ -153808,12 +155188,13 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
153808
155188
  ], flipYTooltip, this.props.onSelectionBusy);
153809
155189
  }
153810
155190
  getLayers() {
153811
- const { cellsLayer, cellSetsLayers, contourLayers } = this;
155191
+ const { cellsLayer, cellSetsLayers, contourLayers, annotationLayer } = this;
153812
155192
  return [
153813
155193
  cellsLayer,
153814
155194
  ...contourLayers,
153815
155195
  ...cellSetsLayers,
153816
- this.createSelectionLayer()
155196
+ this.createSelectionLayer(),
155197
+ annotationLayer
153817
155198
  ];
153818
155199
  }
153819
155200
  /**
@@ -153850,6 +155231,14 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
153850
155231
  this.cellsLayer = null;
153851
155232
  }
153852
155233
  }
155234
+ onUpdateAnnotationLayer() {
155235
+ const { annotationShapes } = this.props;
155236
+ if (annotationShapes) {
155237
+ this.annotationLayer = this.createAnnotationLayer();
155238
+ } else {
155239
+ this.annotationLayer = null;
155240
+ }
155241
+ }
153853
155242
  onUpdateStratifiedData() {
153854
155243
  const { stratifiedData } = this.props;
153855
155244
  if (stratifiedData) {
@@ -153965,6 +155354,16 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
153965
155354
  this.onUpdateCellSetsLayers(true);
153966
155355
  forceUpdate = true;
153967
155356
  }
155357
+ if ([
155358
+ "annotationShapes",
155359
+ "annotationOverlayVisible",
155360
+ "annotationSemanticZoom",
155361
+ "annotationTransitionDuration",
155362
+ "annotationEditable"
155363
+ ].some(shallowDiff)) {
155364
+ this.onUpdateAnnotationLayer();
155365
+ forceUpdate = true;
155366
+ }
153968
155367
  if (forceUpdate) {
153969
155368
  this.forceUpdate();
153970
155369
  }