@vitessce/scatterplot-embedding 4.0.8 → 4.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{deflate-D1w4oupf.js → deflate-CHWmGKzs.js} +1 -1
- package/dist/{index-Cf5zo2l6.js → index-DoXbfOn2.js} +1545 -107
- package/dist/index.js +1 -1
- package/dist/{jpeg-DkDHRRxb.js → jpeg-DfpY4ESw.js} +1 -1
- package/dist/{lerc-WlrBcKr7.js → lerc-zU6xDjk2.js} +1 -1
- package/dist/{lzw-B1Ve5CoF.js → lzw-qjsUiTV8.js} +1 -1
- package/dist/{packbits-DkxsQnHM.js → packbits-DpcvKlj_.js} +1 -1
- package/dist/{raw-BO651BQa.js → raw-DWdrKuNt.js} +1 -1
- package/dist/{webimage-j5GKznX1.js → webimage-DP9dgaA0.js} +1 -1
- package/dist-tsc/EmbeddingScatterplotSubscriber.d.ts +2 -4
- package/dist-tsc/EmbeddingScatterplotSubscriber.d.ts.map +1 -1
- package/dist-tsc/EmbeddingScatterplotSubscriber.js +29 -9
- package/dist-tsc/EmbeddingScatterplotSubscriber.js.map +1 -1
- package/package.json +8 -8
- package/src/EmbeddingScatterplotSubscriber.js +56 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import React__default, { useLayoutEffect, useEffect, cloneElement, createElement, forwardRef, useState, useRef, useMemo, useImperativeHandle, useContext, createContext, isValidElement, Children, PureComponent, useCallback, useDeferredValue } from "react";
|
|
3
|
-
import { usePlotOptionsStyles, OptionsContainer, CellColorEncodingOption, OptionSelect, useVitessceContainer, useComponentHover, useComponentViewInfo, useLoaders,
|
|
3
|
+
import { usePlotOptionsStyles, OptionsContainer, CellColorEncodingOption, OptionSelect, useVitessceContainer, useComponentHover, useComponentViewInfo, useLoaders, useViewMapping, useSetComponentHover, useSetComponentViewInfo, useAnnotationFrameCoordination, useCoordination, useInitialCoordination, useDeckCanvasSize, useAnnotationStoryData, useMultiObsLabels, useObsEmbeddingData, useObsSetsData, useFeatureSelection, useObsFeatureMatrixIndices, useFeatureLabelsData, useExpandedFeatureLabelsMap, useSampleSetsData, useSampleEdgesData, useReady, useUrls, useGetObsInfo, useUint8FeatureSelection, useExpressionValueGetter, TitleInfo, useCoordinationScopes } from "@vitessce/vit-s";
|
|
4
4
|
import { jsxs, jsx as jsx$1, Fragment } from "react/jsx-runtime";
|
|
5
5
|
import * as ReactDOM from "react-dom";
|
|
6
6
|
function _mergeNamespaces(n2, m2) {
|
|
@@ -2214,11 +2214,11 @@ function requireConcaveman() {
|
|
|
2214
2214
|
while (node2) {
|
|
2215
2215
|
for (var i2 = 0; i2 < node2.children.length; i2++) {
|
|
2216
2216
|
var child = node2.children[i2];
|
|
2217
|
-
var
|
|
2218
|
-
if (
|
|
2217
|
+
var dist2 = node2.leaf ? sqSegDist(child, b, c2) : sqSegBoxDist(b, c2, child);
|
|
2218
|
+
if (dist2 > maxDist) continue;
|
|
2219
2219
|
queue.push({
|
|
2220
2220
|
node: child,
|
|
2221
|
-
dist
|
|
2221
|
+
dist: dist2
|
|
2222
2222
|
});
|
|
2223
2223
|
}
|
|
2224
2224
|
while (queue.length && !queue.peek().node.children) {
|
|
@@ -7096,7 +7096,7 @@ const latestFileDefSchema = z.object({
|
|
|
7096
7096
|
options: fileOptionsSchema.optional(),
|
|
7097
7097
|
requestInit: requestInit.optional(),
|
|
7098
7098
|
// New: file def can have coordinationValues.
|
|
7099
|
-
coordinationValues: z.record(z.
|
|
7099
|
+
coordinationValues: z.record(z.any()).optional()
|
|
7100
7100
|
});
|
|
7101
7101
|
const datasetsSchema1_0_13 = z.array(z.object({
|
|
7102
7102
|
uid: z.string(),
|
|
@@ -7127,7 +7127,8 @@ const configSchema1_0_16 = configSchema1_0_13.extend({
|
|
|
7127
7127
|
h: z.number().int().optional(),
|
|
7128
7128
|
// Updates coordinationScopes and coordinationScopesBy
|
|
7129
7129
|
coordinationScopes: componentCoordinationScopes.optional(),
|
|
7130
|
-
coordinationScopesBy: componentCoordinationScopesBy.optional()
|
|
7130
|
+
coordinationScopesBy: componentCoordinationScopesBy.optional(),
|
|
7131
|
+
coordinationValues: z.record(z.any()).optional()
|
|
7131
7132
|
}))
|
|
7132
7133
|
});
|
|
7133
7134
|
const configSchema1_0_17 = configSchema1_0_16.extend({
|
|
@@ -9634,7 +9635,8 @@ const ViewType$1 = {
|
|
|
9634
9635
|
TREEMAP: "treemap",
|
|
9635
9636
|
SAMPLE_SET_PAIR_MANAGER: "sampleSetPairManager",
|
|
9636
9637
|
FEATURE_STATS_TABLE: "featureStatsTable",
|
|
9637
|
-
SINGLE_OBS_SET_SELECTOR: "singleObsSetSelector"
|
|
9638
|
+
SINGLE_OBS_SET_SELECTOR: "singleObsSetSelector",
|
|
9639
|
+
ANNOTATION_CONTROLLER: "annotationController"
|
|
9638
9640
|
};
|
|
9639
9641
|
const DataType$2 = {
|
|
9640
9642
|
OBS_LABELS: "obsLabels",
|
|
@@ -9655,7 +9657,8 @@ const DataType$2 = {
|
|
|
9655
9657
|
COMPARISON_METADATA: "comparisonMetadata",
|
|
9656
9658
|
FEATURE_STATS: "featureStats",
|
|
9657
9659
|
FEATURE_SET_STATS: "featureSetStats",
|
|
9658
|
-
OBS_SET_STATS: "obsSetStats"
|
|
9660
|
+
OBS_SET_STATS: "obsSetStats",
|
|
9661
|
+
ANNOTATION_STORY: "annotationStory"
|
|
9659
9662
|
};
|
|
9660
9663
|
const FileType$1 = {
|
|
9661
9664
|
// Joint file types
|
|
@@ -9677,6 +9680,7 @@ const FileType$1 = {
|
|
|
9677
9680
|
OBS_SETS_CSV: "obsSets.csv",
|
|
9678
9681
|
OBS_SETS_JSON: "obsSets.json",
|
|
9679
9682
|
SAMPLE_SETS_CSV: "sampleSets.csv",
|
|
9683
|
+
ANNOTATION_STORY_JSON: "annotationStory.json",
|
|
9680
9684
|
// OME-Zarr
|
|
9681
9685
|
IMAGE_OME_ZARR: "image.ome-zarr",
|
|
9682
9686
|
OBS_SEGMENTATIONS_OME_ZARR: "obsSegmentations.ome-zarr",
|
|
@@ -9961,7 +9965,15 @@ const CoordinationType$1 = {
|
|
|
9961
9965
|
FEATURE_POINT_FOLD_CHANGE_THRESHOLD: "featurePointFoldChangeThreshold",
|
|
9962
9966
|
FEATURE_LABEL_FOLD_CHANGE_THRESHOLD: "featureLabelFoldChangeThreshold",
|
|
9963
9967
|
// Treemap
|
|
9964
|
-
HIERARCHY_LEVELS: "hierarchyLevels"
|
|
9968
|
+
HIERARCHY_LEVELS: "hierarchyLevels",
|
|
9969
|
+
// Annotation frames
|
|
9970
|
+
ANNOTATION_STORY: "annotationStory",
|
|
9971
|
+
ANNOTATION_FRAME_INDEX: "annotationFrameIndex",
|
|
9972
|
+
ANNOTATION_SHAPES: "annotationShapes",
|
|
9973
|
+
ANNOTATION_OVERLAY_VISIBLE: "annotationOverlayVisible",
|
|
9974
|
+
ANNOTATION_TRANSITION_DURATION: "annotationTransitionDuration",
|
|
9975
|
+
ANNOTATION_SEMANTIC_ZOOM: "annotationSemanticZoom",
|
|
9976
|
+
ANNOTATION_EDITABLE: "annotationEditable"
|
|
9965
9977
|
};
|
|
9966
9978
|
const ViewHelpMapping = {
|
|
9967
9979
|
SCATTERPLOT: "The scatterplot displays two-dimensional (pre-computed) dimensionality reduction results (such as from t-SNE or UMAP). Each point on the scatterplot represents an observation (e.g., cell)."
|
|
@@ -9980,6 +9992,7 @@ const ViewHelpMapping = {
|
|
|
9980
9992
|
[FileType$1.OBS_SEGMENTATIONS_JSON]: DataType$2.OBS_SEGMENTATIONS,
|
|
9981
9993
|
[FileType$1.OBS_SETS_CSV]: DataType$2.OBS_SETS,
|
|
9982
9994
|
[FileType$1.OBS_SETS_JSON]: DataType$2.OBS_SETS,
|
|
9995
|
+
[FileType$1.ANNOTATION_STORY_JSON]: DataType$2.ANNOTATION_STORY,
|
|
9983
9996
|
[FileType$1.IMAGE_OME_ZARR]: DataType$2.IMAGE,
|
|
9984
9997
|
[FileType$1.OBS_SEGMENTATIONS_OME_ZARR]: DataType$2.OBS_SEGMENTATIONS,
|
|
9985
9998
|
[FileType$1.OBS_FEATURE_MATRIX_ANNDATA_ZARR]: DataType$2.OBS_FEATURE_MATRIX,
|
|
@@ -10102,7 +10115,8 @@ const ViewHelpMapping = {
|
|
|
10102
10115
|
[DataType$2.OBS_SET_STATS]: [
|
|
10103
10116
|
CoordinationType$1.OBS_TYPE
|
|
10104
10117
|
// TODO: should sampleType, obsSetSelection, and/or sampleSetSelection be used here?
|
|
10105
|
-
]
|
|
10118
|
+
],
|
|
10119
|
+
[DataType$2.ANNOTATION_STORY]: []
|
|
10106
10120
|
});
|
|
10107
10121
|
({
|
|
10108
10122
|
// For AnnData:
|
|
@@ -10235,7 +10249,9 @@ const ViewHelpMapping = {
|
|
|
10235
10249
|
CoordinationType$1.SPATIAL_TARGET_Z,
|
|
10236
10250
|
CoordinationType$1.SPATIAL_AXIS_FIXED,
|
|
10237
10251
|
CoordinationType$1.SPATIAL_ORBIT_AXIS,
|
|
10238
|
-
CoordinationType$1.FEATURE_AGGREGATION_STRATEGY
|
|
10252
|
+
CoordinationType$1.FEATURE_AGGREGATION_STRATEGY,
|
|
10253
|
+
// Annotation shapes are specific to a view's coordinate system.
|
|
10254
|
+
CoordinationType$1.ANNOTATION_SHAPES
|
|
10239
10255
|
];
|
|
10240
10256
|
const COMPONENT_COORDINATION_TYPES = {
|
|
10241
10257
|
[ViewType$1.NEUROGLANCER]: [
|
|
@@ -10327,7 +10343,14 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10327
10343
|
CoordinationType$1.EMBEDDING_CONTOURS_FILLED,
|
|
10328
10344
|
CoordinationType$1.EMBEDDING_CONTOUR_PERCENTILES,
|
|
10329
10345
|
CoordinationType$1.CONTOUR_COLOR_ENCODING,
|
|
10330
|
-
CoordinationType$1.CONTOUR_COLOR
|
|
10346
|
+
CoordinationType$1.CONTOUR_COLOR,
|
|
10347
|
+
CoordinationType$1.ANNOTATION_STORY,
|
|
10348
|
+
CoordinationType$1.ANNOTATION_SHAPES,
|
|
10349
|
+
CoordinationType$1.ANNOTATION_FRAME_INDEX,
|
|
10350
|
+
CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
|
|
10351
|
+
CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
|
|
10352
|
+
CoordinationType$1.ANNOTATION_EDITABLE,
|
|
10353
|
+
CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
|
|
10331
10354
|
],
|
|
10332
10355
|
[ViewType$1.DUAL_SCATTERPLOT]: [
|
|
10333
10356
|
CoordinationType$1.DATASET,
|
|
@@ -10443,7 +10466,14 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10443
10466
|
CoordinationType$1.ADDITIONAL_OBS_SETS,
|
|
10444
10467
|
CoordinationType$1.MOLECULE_HIGHLIGHT,
|
|
10445
10468
|
CoordinationType$1.TOOLTIPS_VISIBLE,
|
|
10446
|
-
CoordinationType$1.PHOTOMETRIC_INTERPRETATION
|
|
10469
|
+
CoordinationType$1.PHOTOMETRIC_INTERPRETATION,
|
|
10470
|
+
CoordinationType$1.ANNOTATION_STORY,
|
|
10471
|
+
CoordinationType$1.ANNOTATION_SHAPES,
|
|
10472
|
+
CoordinationType$1.ANNOTATION_FRAME_INDEX,
|
|
10473
|
+
CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
|
|
10474
|
+
CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
|
|
10475
|
+
CoordinationType$1.ANNOTATION_EDITABLE,
|
|
10476
|
+
CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
|
|
10447
10477
|
],
|
|
10448
10478
|
[ViewType$1.SPATIAL_BETA]: [
|
|
10449
10479
|
CoordinationType$1.META_COORDINATION_SCOPES,
|
|
@@ -10521,7 +10551,27 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
10521
10551
|
CoordinationType$1.SPATIAL_CHANNEL_LABELS_ORIENTATION,
|
|
10522
10552
|
CoordinationType$1.SPATIAL_CHANNEL_LABEL_SIZE,
|
|
10523
10553
|
CoordinationType$1.SPATIAL_CHANNELS_SORT_ORDER,
|
|
10524
|
-
CoordinationType$1.PHOTOMETRIC_INTERPRETATION
|
|
10554
|
+
CoordinationType$1.PHOTOMETRIC_INTERPRETATION,
|
|
10555
|
+
CoordinationType$1.ANNOTATION_STORY,
|
|
10556
|
+
CoordinationType$1.ANNOTATION_SHAPES,
|
|
10557
|
+
CoordinationType$1.ANNOTATION_FRAME_INDEX,
|
|
10558
|
+
CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
|
|
10559
|
+
CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
|
|
10560
|
+
CoordinationType$1.ANNOTATION_EDITABLE,
|
|
10561
|
+
CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
|
|
10562
|
+
],
|
|
10563
|
+
[ViewType$1.ANNOTATION_CONTROLLER]: [
|
|
10564
|
+
CoordinationType$1.DATASET,
|
|
10565
|
+
CoordinationType$1.ANNOTATION_STORY,
|
|
10566
|
+
CoordinationType$1.ANNOTATION_FRAME_INDEX,
|
|
10567
|
+
CoordinationType$1.ANNOTATION_OVERLAY_VISIBLE,
|
|
10568
|
+
CoordinationType$1.ANNOTATION_TRANSITION_DURATION,
|
|
10569
|
+
CoordinationType$1.ANNOTATION_EDITABLE,
|
|
10570
|
+
CoordinationType$1.ANNOTATION_SEMANTIC_ZOOM
|
|
10571
|
+
// Note: the annotation controller also needs to read the coordination state
|
|
10572
|
+
// of all other views/coordination types via the full config.
|
|
10573
|
+
// Note: we get/set the CoordinationType.ANNOTATION_SHAPES from the full config,
|
|
10574
|
+
// as this info is view-specific rather than global to the story.
|
|
10525
10575
|
],
|
|
10526
10576
|
[ViewType$1.HEATMAP]: [
|
|
10527
10577
|
CoordinationType$1.DATASET,
|
|
@@ -11539,6 +11589,124 @@ z.object({
|
|
|
11539
11589
|
radius: z.number(),
|
|
11540
11590
|
opacity: z.number()
|
|
11541
11591
|
});
|
|
11592
|
+
const shapeBaseObj = z.object({
|
|
11593
|
+
uid: z.string(),
|
|
11594
|
+
text: z.string().optional(),
|
|
11595
|
+
strokeColor: z.array(z.number()).length(3).optional(),
|
|
11596
|
+
strokeWidth: z.number().optional(),
|
|
11597
|
+
// SVG-style dash pattern, e.g. "10 5" or "10 20 30 10". "none" or omitted = solid.
|
|
11598
|
+
strokeDashArray: z.string().optional(),
|
|
11599
|
+
visible: z.boolean().optional()
|
|
11600
|
+
// TODO: define unit modes for x and y axes
|
|
11601
|
+
// ("pixels" vs "normalized" vs "physical" etc.)
|
|
11602
|
+
// TODO: a coordinate system identifier (e.g., "DeckGL" for now,
|
|
11603
|
+
// but a coordinate system from OME-NGFF/SpatialData eventually?)
|
|
11604
|
+
});
|
|
11605
|
+
const rectangleShapeObj = shapeBaseObj.extend({
|
|
11606
|
+
type: z.literal("rectangle"),
|
|
11607
|
+
// OME-XML field names verbatim (upper-left origin)
|
|
11608
|
+
x: z.number(),
|
|
11609
|
+
y: z.number(),
|
|
11610
|
+
width: z.number(),
|
|
11611
|
+
height: z.number(),
|
|
11612
|
+
fillColor: z.array(z.number()).length(3).optional(),
|
|
11613
|
+
fillOpacity: z.number().optional()
|
|
11614
|
+
});
|
|
11615
|
+
const lineShapeObj = shapeBaseObj.extend({
|
|
11616
|
+
type: z.literal("line"),
|
|
11617
|
+
// OME-XML field names verbatim
|
|
11618
|
+
x1: z.number(),
|
|
11619
|
+
y1: z.number(),
|
|
11620
|
+
x2: z.number(),
|
|
11621
|
+
y2: z.number(),
|
|
11622
|
+
markerStart: z.enum(["Arrow", "Tick"]).nullable().optional(),
|
|
11623
|
+
markerEnd: z.enum(["Arrow", "Tick"]).nullable().optional(),
|
|
11624
|
+
textPosition: z.enum(["start", "middle", "end"]).optional(),
|
|
11625
|
+
textBufferPx: z.number().optional()
|
|
11626
|
+
});
|
|
11627
|
+
const ellipseShapeObj = shapeBaseObj.extend({
|
|
11628
|
+
type: z.literal("ellipse"),
|
|
11629
|
+
// OME-XML field names verbatim (centre point + radii)
|
|
11630
|
+
x1: z.number(),
|
|
11631
|
+
y1: z.number(),
|
|
11632
|
+
radiusX: z.number(),
|
|
11633
|
+
radiusY: z.number(),
|
|
11634
|
+
fillColor: z.array(z.number()).length(3).optional(),
|
|
11635
|
+
fillOpacity: z.number().optional()
|
|
11636
|
+
});
|
|
11637
|
+
const polygonShapeObj = shapeBaseObj.extend({
|
|
11638
|
+
type: z.literal("polygon"),
|
|
11639
|
+
// OME-XML: array of [x, y] coordinate pairs, closed automatically
|
|
11640
|
+
points: z.array(z.tuple([z.number(), z.number()])),
|
|
11641
|
+
fillColor: z.array(z.number()).length(3).optional(),
|
|
11642
|
+
fillOpacity: z.number().optional()
|
|
11643
|
+
});
|
|
11644
|
+
const polylineShapeObj = shapeBaseObj.extend({
|
|
11645
|
+
type: z.literal("polyline"),
|
|
11646
|
+
// OME-XML: array of [x, y] coordinate pairs, open (not closed)
|
|
11647
|
+
points: z.array(z.tuple([z.number(), z.number()])),
|
|
11648
|
+
markerStart: z.enum(["Arrow", "Tick"]).nullable().optional(),
|
|
11649
|
+
markerEnd: z.enum(["Arrow", "Tick"]).nullable().optional()
|
|
11650
|
+
});
|
|
11651
|
+
const annotationShapeObj = z.discriminatedUnion("type", [
|
|
11652
|
+
rectangleShapeObj,
|
|
11653
|
+
lineShapeObj,
|
|
11654
|
+
ellipseShapeObj,
|
|
11655
|
+
polygonShapeObj,
|
|
11656
|
+
polylineShapeObj
|
|
11657
|
+
]);
|
|
11658
|
+
z.array(annotationShapeObj);
|
|
11659
|
+
const annotationFrameObj = z.object({
|
|
11660
|
+
uid: z.string(),
|
|
11661
|
+
title: z.string().optional(),
|
|
11662
|
+
description: z.string().optional(),
|
|
11663
|
+
descriptionType: z.enum(["text", "markdown"]).optional(),
|
|
11664
|
+
// A frame can define per-view: coordinationValues
|
|
11665
|
+
// (if the view's state should not be coordinated with other views)
|
|
11666
|
+
// or per-view coordinationScopes/coordinationScopesBy
|
|
11667
|
+
// (if at this frame, the view should be coordinated with other views).
|
|
11668
|
+
// We can also define a frame-level coordination space,
|
|
11669
|
+
// which will be merged with the global coordination space.
|
|
11670
|
+
// TODO: datasets
|
|
11671
|
+
// TODO: coordinationSpace
|
|
11672
|
+
layout: z.array(
|
|
11673
|
+
// Note: for now, we will infer view objects which have a uid
|
|
11674
|
+
// that is present in the global layout, and do NOT have x/y/w/h defined,
|
|
11675
|
+
// to mean that in this frame, the layout and set of views is unchanged
|
|
11676
|
+
// from the global layout.
|
|
11677
|
+
// This will allow each frame to omit the full list of views from the layout,
|
|
11678
|
+
// and only specify the views whose coordination state is changing in this frame.
|
|
11679
|
+
// If a frame includes a view with a uid that is not present
|
|
11680
|
+
// in the global layout, then that view will be added to the layout at this frame.
|
|
11681
|
+
// This frame should also define x/y/w/h for all views,
|
|
11682
|
+
// since it will otherwise be ambiguous how to layout the updated set of views
|
|
11683
|
+
// for this frame.
|
|
11684
|
+
z.object({
|
|
11685
|
+
// The view UID. If this view uid is not present in the global layout,
|
|
11686
|
+
// it will be added to the layout at this frame,
|
|
11687
|
+
// and will need to have its coordination values initialized to their defaults
|
|
11688
|
+
// for any that were not fully specified.
|
|
11689
|
+
uid: z.string(),
|
|
11690
|
+
coordinationValues: z.record(
|
|
11691
|
+
z.string(),
|
|
11692
|
+
// The coordination type name, e.g. "embeddingType"
|
|
11693
|
+
z.any()
|
|
11694
|
+
).optional()
|
|
11695
|
+
// TODO: support coordinationScopes/coordinationScopesBy for per-view coordination
|
|
11696
|
+
// at this frame.
|
|
11697
|
+
// TODO: view x/y/w/h once we support view layout changes per-frame.
|
|
11698
|
+
})
|
|
11699
|
+
).optional()
|
|
11700
|
+
});
|
|
11701
|
+
z.object({
|
|
11702
|
+
// TODO: schema version for the story schema?
|
|
11703
|
+
// Same as current Vitessce schema version?
|
|
11704
|
+
uid: z.string(),
|
|
11705
|
+
title: z.string().optional(),
|
|
11706
|
+
description: z.string().optional(),
|
|
11707
|
+
descriptionType: z.enum(["text", "markdown"]).optional(),
|
|
11708
|
+
frames: z.array(annotationFrameObj)
|
|
11709
|
+
});
|
|
11542
11710
|
const SETS_DATATYPE_OBS = "obs";
|
|
11543
11711
|
const HIERARCHICAL_SCHEMAS = {
|
|
11544
11712
|
latestVersion: "0.1.3"
|
|
@@ -24592,8 +24760,8 @@ class Vector extends MathArray {
|
|
|
24592
24760
|
distanceSquared(mathArray) {
|
|
24593
24761
|
let length2 = 0;
|
|
24594
24762
|
for (let i2 = 0; i2 < this.ELEMENTS; ++i2) {
|
|
24595
|
-
const
|
|
24596
|
-
length2 +=
|
|
24763
|
+
const dist2 = this[i2] - mathArray[i2];
|
|
24764
|
+
length2 += dist2 * dist2;
|
|
24597
24765
|
}
|
|
24598
24766
|
return checkNumber(length2);
|
|
24599
24767
|
}
|
|
@@ -24914,6 +25082,12 @@ function multiply$3(out, a2, b) {
|
|
|
24914
25082
|
out[2] = a2[2] * b[2];
|
|
24915
25083
|
return out;
|
|
24916
25084
|
}
|
|
25085
|
+
function distance$3(a2, b) {
|
|
25086
|
+
var x = b[0] - a2[0];
|
|
25087
|
+
var y = b[1] - a2[1];
|
|
25088
|
+
var z2 = b[2] - a2[2];
|
|
25089
|
+
return Math.hypot(x, y, z2);
|
|
25090
|
+
}
|
|
24917
25091
|
function squaredLength$2(a2) {
|
|
24918
25092
|
var x = a2[0];
|
|
24919
25093
|
var y = a2[1];
|
|
@@ -25037,6 +25211,7 @@ function angle$2(a2, b) {
|
|
|
25037
25211
|
}
|
|
25038
25212
|
var sub = subtract;
|
|
25039
25213
|
var mul = multiply$3;
|
|
25214
|
+
var dist = distance$3;
|
|
25040
25215
|
var len = length$5;
|
|
25041
25216
|
var sqrLen = squaredLength$2;
|
|
25042
25217
|
(function() {
|
|
@@ -39507,7 +39682,7 @@ function noop$2() {
|
|
|
39507
39682
|
const getCursor$1 = ({
|
|
39508
39683
|
isDragging
|
|
39509
39684
|
}) => isDragging ? "grabbing" : "grab";
|
|
39510
|
-
const defaultProps$
|
|
39685
|
+
const defaultProps$P = {
|
|
39511
39686
|
id: "",
|
|
39512
39687
|
width: "100%",
|
|
39513
39688
|
height: "100%",
|
|
@@ -39638,7 +39813,7 @@ class Deck {
|
|
|
39638
39813
|
this._lastPointerDownInfo = pickedInfo.result[0] || pickedInfo.emptyInfo;
|
|
39639
39814
|
});
|
|
39640
39815
|
this.props = {
|
|
39641
|
-
...defaultProps$
|
|
39816
|
+
...defaultProps$P,
|
|
39642
39817
|
...props
|
|
39643
39818
|
};
|
|
39644
39819
|
props = this.props;
|
|
@@ -40140,7 +40315,7 @@ class Deck {
|
|
|
40140
40315
|
metrics.gpuMemory = memoryStats.get("GPU Memory").count;
|
|
40141
40316
|
}
|
|
40142
40317
|
}
|
|
40143
|
-
_defineProperty(Deck, "defaultProps", defaultProps$
|
|
40318
|
+
_defineProperty(Deck, "defaultProps", defaultProps$P);
|
|
40144
40319
|
_defineProperty(Deck, "VERSION", deckGlobal.VERSION);
|
|
40145
40320
|
class ShaderAttribute {
|
|
40146
40321
|
constructor(dataColumn, opts) {
|
|
@@ -42895,7 +43070,7 @@ const areViewportsEqual = memoize$3(({
|
|
|
42895
43070
|
return oldViewport.equals(viewport);
|
|
42896
43071
|
});
|
|
42897
43072
|
let pickingColorCache = new Uint8ClampedArray(0);
|
|
42898
|
-
const defaultProps$
|
|
43073
|
+
const defaultProps$O = {
|
|
42899
43074
|
data: {
|
|
42900
43075
|
type: "data",
|
|
42901
43076
|
value: EMPTY_ARRAY$1,
|
|
@@ -43770,7 +43945,7 @@ class Layer extends Component {
|
|
|
43770
43945
|
this.setNeedsUpdate();
|
|
43771
43946
|
}
|
|
43772
43947
|
}
|
|
43773
|
-
_defineProperty(Layer, "defaultProps", defaultProps$
|
|
43948
|
+
_defineProperty(Layer, "defaultProps", defaultProps$O);
|
|
43774
43949
|
_defineProperty(Layer, "layerName", "Layer");
|
|
43775
43950
|
const TRACE_RENDER_LAYERS = "compositeLayer.renderLayers";
|
|
43776
43951
|
class CompositeLayer extends Layer {
|
|
@@ -44806,6 +44981,124 @@ const esm$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
44806
44981
|
project32,
|
|
44807
44982
|
shadow
|
|
44808
44983
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
44984
|
+
const dashShaders = {
|
|
44985
|
+
inject: {
|
|
44986
|
+
"vs:#decl": "\nattribute vec2 instanceDashArrays;\nattribute float instanceDashOffsets;\nvarying vec2 vDashArray;\nvarying float vDashOffset;\n",
|
|
44987
|
+
"vs:#main-end": "\nvDashArray = instanceDashArrays;\nvDashOffset = instanceDashOffsets / width.x;\n",
|
|
44988
|
+
"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",
|
|
44989
|
+
"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"
|
|
44990
|
+
}
|
|
44991
|
+
};
|
|
44992
|
+
const offsetShaders = {
|
|
44993
|
+
inject: {
|
|
44994
|
+
"vs:#decl": "\nattribute float instanceOffsets;\n",
|
|
44995
|
+
"vs:DECKGL_FILTER_SIZE": "\n float offsetWidth = abs(instanceOffsets * 2.0) + 1.0;\n size *= offsetWidth;\n",
|
|
44996
|
+
"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",
|
|
44997
|
+
"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"
|
|
44998
|
+
}
|
|
44999
|
+
};
|
|
45000
|
+
const defaultProps$N = {
|
|
45001
|
+
getDashArray: {
|
|
45002
|
+
type: "accessor",
|
|
45003
|
+
value: [0, 0]
|
|
45004
|
+
},
|
|
45005
|
+
getOffset: {
|
|
45006
|
+
type: "accessor",
|
|
45007
|
+
value: 0
|
|
45008
|
+
},
|
|
45009
|
+
dashJustified: false,
|
|
45010
|
+
dashGapPickable: false
|
|
45011
|
+
};
|
|
45012
|
+
class PathStyleExtension extends LayerExtension {
|
|
45013
|
+
constructor({
|
|
45014
|
+
dash = false,
|
|
45015
|
+
offset: offset2 = false,
|
|
45016
|
+
highPrecisionDash = false
|
|
45017
|
+
} = {}) {
|
|
45018
|
+
super({
|
|
45019
|
+
dash: dash || highPrecisionDash,
|
|
45020
|
+
offset: offset2,
|
|
45021
|
+
highPrecisionDash
|
|
45022
|
+
});
|
|
45023
|
+
}
|
|
45024
|
+
isEnabled(layer) {
|
|
45025
|
+
return "pathTesselator" in layer.state;
|
|
45026
|
+
}
|
|
45027
|
+
getShaders(extension) {
|
|
45028
|
+
if (!extension.isEnabled(this)) {
|
|
45029
|
+
return null;
|
|
45030
|
+
}
|
|
45031
|
+
let result = {};
|
|
45032
|
+
if (extension.opts.dash) {
|
|
45033
|
+
result = mergeShaders(result, dashShaders);
|
|
45034
|
+
}
|
|
45035
|
+
if (extension.opts.offset) {
|
|
45036
|
+
result = mergeShaders(result, offsetShaders);
|
|
45037
|
+
}
|
|
45038
|
+
return result;
|
|
45039
|
+
}
|
|
45040
|
+
initializeState(context, extension) {
|
|
45041
|
+
const attributeManager = this.getAttributeManager();
|
|
45042
|
+
if (!attributeManager || !extension.isEnabled(this)) {
|
|
45043
|
+
return;
|
|
45044
|
+
}
|
|
45045
|
+
if (extension.opts.dash) {
|
|
45046
|
+
attributeManager.addInstanced({
|
|
45047
|
+
instanceDashArrays: {
|
|
45048
|
+
size: 2,
|
|
45049
|
+
accessor: "getDashArray"
|
|
45050
|
+
}
|
|
45051
|
+
});
|
|
45052
|
+
}
|
|
45053
|
+
if (extension.opts.highPrecisionDash) {
|
|
45054
|
+
attributeManager.addInstanced({
|
|
45055
|
+
instanceDashOffsets: {
|
|
45056
|
+
size: 1,
|
|
45057
|
+
accessor: "getPath",
|
|
45058
|
+
transform: extension.getDashOffsets.bind(this)
|
|
45059
|
+
}
|
|
45060
|
+
});
|
|
45061
|
+
}
|
|
45062
|
+
if (extension.opts.offset) {
|
|
45063
|
+
attributeManager.addInstanced({
|
|
45064
|
+
instanceOffsets: {
|
|
45065
|
+
size: 1,
|
|
45066
|
+
accessor: "getOffset"
|
|
45067
|
+
}
|
|
45068
|
+
});
|
|
45069
|
+
}
|
|
45070
|
+
}
|
|
45071
|
+
updateState(params, extension) {
|
|
45072
|
+
if (!extension.isEnabled(this)) {
|
|
45073
|
+
return;
|
|
45074
|
+
}
|
|
45075
|
+
const uniforms = {};
|
|
45076
|
+
if (extension.opts.dash) {
|
|
45077
|
+
uniforms.dashAlignMode = this.props.dashJustified ? 1 : 0;
|
|
45078
|
+
uniforms.dashGapPickable = Boolean(this.props.dashGapPickable);
|
|
45079
|
+
}
|
|
45080
|
+
this.state.model.setUniforms(uniforms);
|
|
45081
|
+
}
|
|
45082
|
+
getDashOffsets(path) {
|
|
45083
|
+
const result = [0];
|
|
45084
|
+
const positionSize = this.props.positionFormat === "XY" ? 2 : 3;
|
|
45085
|
+
const isNested2 = Array.isArray(path[0]);
|
|
45086
|
+
const geometrySize = isNested2 ? path.length : path.length / positionSize;
|
|
45087
|
+
let p;
|
|
45088
|
+
let prevP;
|
|
45089
|
+
for (let i2 = 0; i2 < geometrySize - 1; i2++) {
|
|
45090
|
+
p = isNested2 ? path[i2] : path.slice(i2 * positionSize, i2 * positionSize + positionSize);
|
|
45091
|
+
p = this.projectPosition(p);
|
|
45092
|
+
if (i2 > 0) {
|
|
45093
|
+
result[i2] = result[i2 - 1] + dist(prevP, p);
|
|
45094
|
+
}
|
|
45095
|
+
prevP = p;
|
|
45096
|
+
}
|
|
45097
|
+
return result;
|
|
45098
|
+
}
|
|
45099
|
+
}
|
|
45100
|
+
_defineProperty(PathStyleExtension, "defaultProps", defaultProps$N);
|
|
45101
|
+
_defineProperty(PathStyleExtension, "extensionName", "PathStyleExtension");
|
|
44809
45102
|
const defaultProps$M = {
|
|
44810
45103
|
clipBounds: [0, 0, 1, 1]
|
|
44811
45104
|
};
|
|
@@ -100853,8 +101146,8 @@ function requireJs$b() {
|
|
|
100853
101146
|
var DeltaPsi = Math.log(Math.tan(phi2 / 2 + Math.PI / 4) / Math.tan(phi12 / 2 + Math.PI / 4));
|
|
100854
101147
|
var q = Math.abs(DeltaPsi) > 1e-11 ? DeltaPhi / DeltaPsi : Math.cos(phi12);
|
|
100855
101148
|
var delta = Math.sqrt(DeltaPhi * DeltaPhi + q * q * DeltaLambda * DeltaLambda);
|
|
100856
|
-
var
|
|
100857
|
-
return
|
|
101149
|
+
var dist2 = delta * R;
|
|
101150
|
+
return dist2;
|
|
100858
101151
|
}
|
|
100859
101152
|
js$a.default = rhumbDistance;
|
|
100860
101153
|
return js$a;
|
|
@@ -101167,7 +101460,7 @@ function requireUtils$2() {
|
|
|
101167
101460
|
var x;
|
|
101168
101461
|
var y;
|
|
101169
101462
|
var segmentIdx;
|
|
101170
|
-
var
|
|
101463
|
+
var dist2;
|
|
101171
101464
|
if (coords.length > 1 && pointCoords.length) {
|
|
101172
101465
|
var lineCoordinates;
|
|
101173
101466
|
var pointCoordinate;
|
|
@@ -101184,17 +101477,17 @@ function requireUtils$2() {
|
|
|
101184
101477
|
if (lineCoordinates[n2][0] !== lineCoordinates[n2 - 1][0]) {
|
|
101185
101478
|
var slope = (lineCoordinates[n2][1] - lineCoordinates[n2 - 1][1]) / (lineCoordinates[n2][0] - lineCoordinates[n2 - 1][0]);
|
|
101186
101479
|
var inverseSlope = lineCoordinates[n2][1] - slope * lineCoordinates[n2][0];
|
|
101187
|
-
|
|
101188
|
-
} else
|
|
101480
|
+
dist2 = Math.abs(slope * pointCoordinate[0] + inverseSlope - pointCoordinate[1]) / Math.sqrt(slope * slope + 1);
|
|
101481
|
+
} else dist2 = Math.abs(pointCoordinate[0] - lineCoordinates[n2][0]);
|
|
101189
101482
|
var rl2 = Math.pow(lineCoordinates[n2][1] - lineCoordinates[n2 - 1][1], 2) + Math.pow(lineCoordinates[n2][0] - lineCoordinates[n2 - 1][0], 2);
|
|
101190
101483
|
var ln2 = Math.pow(lineCoordinates[n2][1] - pointCoordinate[1], 2) + Math.pow(lineCoordinates[n2][0] - pointCoordinate[0], 2);
|
|
101191
101484
|
var lnm12 = Math.pow(lineCoordinates[n2 - 1][1] - pointCoordinate[1], 2) + Math.pow(lineCoordinates[n2 - 1][0] - pointCoordinate[0], 2);
|
|
101192
|
-
var
|
|
101193
|
-
var calcrl2 = ln2 -
|
|
101485
|
+
var dist22 = Math.pow(dist2, 2);
|
|
101486
|
+
var calcrl2 = ln2 - dist22 + lnm12 - dist22;
|
|
101194
101487
|
if (calcrl2 > rl2) {
|
|
101195
|
-
|
|
101488
|
+
dist2 = Math.sqrt(Math.min(ln2, lnm12));
|
|
101196
101489
|
}
|
|
101197
|
-
if (minDist === null || minDist === void 0 || minDist >
|
|
101490
|
+
if (minDist === null || minDist === void 0 || minDist > dist2) {
|
|
101198
101491
|
if (calcrl2 > rl2) {
|
|
101199
101492
|
if (lnm12 < ln2) {
|
|
101200
101493
|
to = 0;
|
|
@@ -101204,10 +101497,10 @@ function requireUtils$2() {
|
|
|
101204
101497
|
to = 1;
|
|
101205
101498
|
}
|
|
101206
101499
|
} else {
|
|
101207
|
-
to = Math.sqrt(lnm12 -
|
|
101208
|
-
from2 = Math.sqrt(ln2 -
|
|
101500
|
+
to = Math.sqrt(lnm12 - dist22) / Math.sqrt(rl2);
|
|
101501
|
+
from2 = Math.sqrt(ln2 - dist22) / Math.sqrt(rl2);
|
|
101209
101502
|
}
|
|
101210
|
-
minDist =
|
|
101503
|
+
minDist = dist2;
|
|
101211
101504
|
segmentIdx = n2;
|
|
101212
101505
|
}
|
|
101213
101506
|
}
|
|
@@ -117538,22 +117831,22 @@ function addDecoder(cases, importFn) {
|
|
|
117538
117831
|
}
|
|
117539
117832
|
cases.forEach((c2) => registry$1.set(c2, importFn));
|
|
117540
117833
|
}
|
|
117541
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
117542
|
-
addDecoder(5, () => import("./lzw-
|
|
117834
|
+
addDecoder([void 0, 1], () => import("./raw-DWdrKuNt.js").then((m2) => m2.default));
|
|
117835
|
+
addDecoder(5, () => import("./lzw-qjsUiTV8.js").then((m2) => m2.default));
|
|
117543
117836
|
addDecoder(6, () => {
|
|
117544
117837
|
throw new Error("old style JPEG compression is not supported.");
|
|
117545
117838
|
});
|
|
117546
|
-
addDecoder(7, () => import("./jpeg-
|
|
117547
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
117548
|
-
addDecoder(32773, () => import("./packbits-
|
|
117839
|
+
addDecoder(7, () => import("./jpeg-DfpY4ESw.js").then((m2) => m2.default));
|
|
117840
|
+
addDecoder([8, 32946], () => import("./deflate-CHWmGKzs.js").then((m2) => m2.default));
|
|
117841
|
+
addDecoder(32773, () => import("./packbits-DpcvKlj_.js").then((m2) => m2.default));
|
|
117549
117842
|
addDecoder(
|
|
117550
117843
|
34887,
|
|
117551
|
-
() => import("./lerc-
|
|
117844
|
+
() => import("./lerc-zU6xDjk2.js").then(async (m2) => {
|
|
117552
117845
|
await m2.zstd.init();
|
|
117553
117846
|
return m2;
|
|
117554
117847
|
}).then((m2) => m2.default)
|
|
117555
117848
|
);
|
|
117556
|
-
addDecoder(50001, () => import("./webimage-
|
|
117849
|
+
addDecoder(50001, () => import("./webimage-DP9dgaA0.js").then((m2) => m2.default));
|
|
117557
117850
|
function decodeRowAcc(row, stride) {
|
|
117558
117851
|
let length2 = row.length - stride;
|
|
117559
117852
|
let offset2 = 0;
|
|
@@ -117968,8 +118261,8 @@ function TreeDesc(dyn_tree, stat_desc) {
|
|
|
117968
118261
|
this.max_code = 0;
|
|
117969
118262
|
this.stat_desc = stat_desc;
|
|
117970
118263
|
}
|
|
117971
|
-
const d_code = (
|
|
117972
|
-
return
|
|
118264
|
+
const d_code = (dist2) => {
|
|
118265
|
+
return dist2 < 256 ? _dist_code[dist2] : _dist_code[256 + (dist2 >>> 7)];
|
|
117973
118266
|
};
|
|
117974
118267
|
const put_short = (s2, w2) => {
|
|
117975
118268
|
s2.pending_buf[s2.pending++] = w2 & 255;
|
|
@@ -118103,7 +118396,7 @@ const tr_static_init = () => {
|
|
|
118103
118396
|
let bits;
|
|
118104
118397
|
let length2;
|
|
118105
118398
|
let code;
|
|
118106
|
-
let
|
|
118399
|
+
let dist2;
|
|
118107
118400
|
const bl_count = new Array(MAX_BITS + 1);
|
|
118108
118401
|
length2 = 0;
|
|
118109
118402
|
for (code = 0; code < LENGTH_CODES - 1; code++) {
|
|
@@ -118113,18 +118406,18 @@ const tr_static_init = () => {
|
|
|
118113
118406
|
}
|
|
118114
118407
|
}
|
|
118115
118408
|
_length_code[length2 - 1] = code;
|
|
118116
|
-
|
|
118409
|
+
dist2 = 0;
|
|
118117
118410
|
for (code = 0; code < 16; code++) {
|
|
118118
|
-
base_dist[code] =
|
|
118411
|
+
base_dist[code] = dist2;
|
|
118119
118412
|
for (n2 = 0; n2 < 1 << extra_dbits[code]; n2++) {
|
|
118120
|
-
_dist_code[
|
|
118413
|
+
_dist_code[dist2++] = code;
|
|
118121
118414
|
}
|
|
118122
118415
|
}
|
|
118123
|
-
|
|
118416
|
+
dist2 >>= 7;
|
|
118124
118417
|
for (; code < D_CODES; code++) {
|
|
118125
|
-
base_dist[code] =
|
|
118418
|
+
base_dist[code] = dist2 << 7;
|
|
118126
118419
|
for (n2 = 0; n2 < 1 << extra_dbits[code] - 7; n2++) {
|
|
118127
|
-
_dist_code[256 +
|
|
118420
|
+
_dist_code[256 + dist2++] = code;
|
|
118128
118421
|
}
|
|
118129
118422
|
}
|
|
118130
118423
|
for (bits = 0; bits <= MAX_BITS; bits++) {
|
|
@@ -118215,17 +118508,17 @@ const pqdownheap = (s2, tree, k) => {
|
|
|
118215
118508
|
s2.heap[k] = v;
|
|
118216
118509
|
};
|
|
118217
118510
|
const compress_block = (s2, ltree, dtree) => {
|
|
118218
|
-
let
|
|
118511
|
+
let dist2;
|
|
118219
118512
|
let lc;
|
|
118220
118513
|
let lx = 0;
|
|
118221
118514
|
let code;
|
|
118222
118515
|
let extra;
|
|
118223
118516
|
if (s2.last_lit !== 0) {
|
|
118224
118517
|
do {
|
|
118225
|
-
|
|
118518
|
+
dist2 = s2.pending_buf[s2.d_buf + lx * 2] << 8 | s2.pending_buf[s2.d_buf + lx * 2 + 1];
|
|
118226
118519
|
lc = s2.pending_buf[s2.l_buf + lx];
|
|
118227
118520
|
lx++;
|
|
118228
|
-
if (
|
|
118521
|
+
if (dist2 === 0) {
|
|
118229
118522
|
send_code(s2, lc, ltree);
|
|
118230
118523
|
} else {
|
|
118231
118524
|
code = _length_code[lc];
|
|
@@ -118235,13 +118528,13 @@ const compress_block = (s2, ltree, dtree) => {
|
|
|
118235
118528
|
lc -= base_length[code];
|
|
118236
118529
|
send_bits(s2, lc, extra);
|
|
118237
118530
|
}
|
|
118238
|
-
|
|
118239
|
-
code = d_code(
|
|
118531
|
+
dist2--;
|
|
118532
|
+
code = d_code(dist2);
|
|
118240
118533
|
send_code(s2, code, dtree);
|
|
118241
118534
|
extra = extra_dbits[code];
|
|
118242
118535
|
if (extra !== 0) {
|
|
118243
|
-
|
|
118244
|
-
send_bits(s2,
|
|
118536
|
+
dist2 -= base_dist[code];
|
|
118537
|
+
send_bits(s2, dist2, extra);
|
|
118245
118538
|
}
|
|
118246
118539
|
}
|
|
118247
118540
|
} while (lx < s2.last_lit);
|
|
@@ -118512,18 +118805,18 @@ const _tr_flush_block = (s2, buf, stored_len, last) => {
|
|
|
118512
118805
|
bi_windup(s2);
|
|
118513
118806
|
}
|
|
118514
118807
|
};
|
|
118515
|
-
const _tr_tally = (s2,
|
|
118516
|
-
s2.pending_buf[s2.d_buf + s2.last_lit * 2] =
|
|
118517
|
-
s2.pending_buf[s2.d_buf + s2.last_lit * 2 + 1] =
|
|
118808
|
+
const _tr_tally = (s2, dist2, lc) => {
|
|
118809
|
+
s2.pending_buf[s2.d_buf + s2.last_lit * 2] = dist2 >>> 8 & 255;
|
|
118810
|
+
s2.pending_buf[s2.d_buf + s2.last_lit * 2 + 1] = dist2 & 255;
|
|
118518
118811
|
s2.pending_buf[s2.l_buf + s2.last_lit] = lc & 255;
|
|
118519
118812
|
s2.last_lit++;
|
|
118520
|
-
if (
|
|
118813
|
+
if (dist2 === 0) {
|
|
118521
118814
|
s2.dyn_ltree[lc * 2]++;
|
|
118522
118815
|
} else {
|
|
118523
118816
|
s2.matches++;
|
|
118524
|
-
|
|
118817
|
+
dist2--;
|
|
118525
118818
|
s2.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]++;
|
|
118526
|
-
s2.dyn_dtree[d_code(
|
|
118819
|
+
s2.dyn_dtree[d_code(dist2) * 2]++;
|
|
118527
118820
|
}
|
|
118528
118821
|
return s2.last_lit === s2.lit_bufsize - 1;
|
|
118529
118822
|
};
|
|
@@ -120028,7 +120321,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120028
120321
|
let here;
|
|
120029
120322
|
let op;
|
|
120030
120323
|
let len2;
|
|
120031
|
-
let
|
|
120324
|
+
let dist2;
|
|
120032
120325
|
let from2;
|
|
120033
120326
|
let from_source;
|
|
120034
120327
|
let input, output;
|
|
@@ -120094,7 +120387,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120094
120387
|
bits -= op;
|
|
120095
120388
|
op = here >>> 16 & 255;
|
|
120096
120389
|
if (op & 16) {
|
|
120097
|
-
|
|
120390
|
+
dist2 = here & 65535;
|
|
120098
120391
|
op &= 15;
|
|
120099
120392
|
if (bits < op) {
|
|
120100
120393
|
hold += input[_in++] << bits;
|
|
@@ -120104,8 +120397,8 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120104
120397
|
bits += 8;
|
|
120105
120398
|
}
|
|
120106
120399
|
}
|
|
120107
|
-
|
|
120108
|
-
if (
|
|
120400
|
+
dist2 += hold & (1 << op) - 1;
|
|
120401
|
+
if (dist2 > dmax) {
|
|
120109
120402
|
strm.msg = "invalid distance too far back";
|
|
120110
120403
|
state.mode = BAD;
|
|
120111
120404
|
break top;
|
|
@@ -120113,8 +120406,8 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120113
120406
|
hold >>>= op;
|
|
120114
120407
|
bits -= op;
|
|
120115
120408
|
op = _out - beg;
|
|
120116
|
-
if (
|
|
120117
|
-
op =
|
|
120409
|
+
if (dist2 > op) {
|
|
120410
|
+
op = dist2 - op;
|
|
120118
120411
|
if (op > whave) {
|
|
120119
120412
|
if (state.sane) {
|
|
120120
120413
|
strm.msg = "invalid distance too far back";
|
|
@@ -120131,7 +120424,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120131
120424
|
do {
|
|
120132
120425
|
output[_out++] = s_window[from2++];
|
|
120133
120426
|
} while (--op);
|
|
120134
|
-
from2 = _out -
|
|
120427
|
+
from2 = _out - dist2;
|
|
120135
120428
|
from_source = output;
|
|
120136
120429
|
}
|
|
120137
120430
|
} else if (wnext < op) {
|
|
@@ -120149,7 +120442,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120149
120442
|
do {
|
|
120150
120443
|
output[_out++] = s_window[from2++];
|
|
120151
120444
|
} while (--op);
|
|
120152
|
-
from2 = _out -
|
|
120445
|
+
from2 = _out - dist2;
|
|
120153
120446
|
from_source = output;
|
|
120154
120447
|
}
|
|
120155
120448
|
}
|
|
@@ -120160,7 +120453,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120160
120453
|
do {
|
|
120161
120454
|
output[_out++] = s_window[from2++];
|
|
120162
120455
|
} while (--op);
|
|
120163
|
-
from2 = _out -
|
|
120456
|
+
from2 = _out - dist2;
|
|
120164
120457
|
from_source = output;
|
|
120165
120458
|
}
|
|
120166
120459
|
}
|
|
@@ -120177,7 +120470,7 @@ var inffast = function inflate_fast(strm, start) {
|
|
|
120177
120470
|
}
|
|
120178
120471
|
}
|
|
120179
120472
|
} else {
|
|
120180
|
-
from2 = _out -
|
|
120473
|
+
from2 = _out - dist2;
|
|
120181
120474
|
do {
|
|
120182
120475
|
output[_out++] = output[from2++];
|
|
120183
120476
|
output[_out++] = output[from2++];
|
|
@@ -120735,7 +121028,7 @@ const fixedtables = (state) => {
|
|
|
120735
121028
|
state.distbits = 5;
|
|
120736
121029
|
};
|
|
120737
121030
|
const updatewindow = (strm, src, end, copy2) => {
|
|
120738
|
-
let
|
|
121031
|
+
let dist2;
|
|
120739
121032
|
const state = strm.state;
|
|
120740
121033
|
if (state.window === null) {
|
|
120741
121034
|
state.wsize = 1 << state.wbits;
|
|
@@ -120748,23 +121041,23 @@ const updatewindow = (strm, src, end, copy2) => {
|
|
|
120748
121041
|
state.wnext = 0;
|
|
120749
121042
|
state.whave = state.wsize;
|
|
120750
121043
|
} else {
|
|
120751
|
-
|
|
120752
|
-
if (
|
|
120753
|
-
|
|
121044
|
+
dist2 = state.wsize - state.wnext;
|
|
121045
|
+
if (dist2 > copy2) {
|
|
121046
|
+
dist2 = copy2;
|
|
120754
121047
|
}
|
|
120755
|
-
state.window.set(src.subarray(end - copy2, end - copy2 +
|
|
120756
|
-
copy2 -=
|
|
121048
|
+
state.window.set(src.subarray(end - copy2, end - copy2 + dist2), state.wnext);
|
|
121049
|
+
copy2 -= dist2;
|
|
120757
121050
|
if (copy2) {
|
|
120758
121051
|
state.window.set(src.subarray(end - copy2, end), 0);
|
|
120759
121052
|
state.wnext = copy2;
|
|
120760
121053
|
state.whave = state.wsize;
|
|
120761
121054
|
} else {
|
|
120762
|
-
state.wnext +=
|
|
121055
|
+
state.wnext += dist2;
|
|
120763
121056
|
if (state.wnext === state.wsize) {
|
|
120764
121057
|
state.wnext = 0;
|
|
120765
121058
|
}
|
|
120766
121059
|
if (state.whave < state.wsize) {
|
|
120767
|
-
state.whave +=
|
|
121060
|
+
state.whave += dist2;
|
|
120768
121061
|
}
|
|
120769
121062
|
}
|
|
120770
121063
|
}
|
|
@@ -124643,14 +124936,14 @@ vec4 colormap(float intensity) {
|
|
|
124643
124936
|
}
|
|
124644
124937
|
};
|
|
124645
124938
|
}
|
|
124646
|
-
const defaultProps$4$
|
|
124939
|
+
const defaultProps$4$2 = {
|
|
124647
124940
|
colormap: { type: "string", value: "viridis", compare: true },
|
|
124648
124941
|
opacity: { type: "number", value: 1, compare: true },
|
|
124649
124942
|
useTransparentColor: { type: "boolean", value: false, compare: true }
|
|
124650
124943
|
};
|
|
124651
124944
|
const AdditiveColormapExtension = class extends LayerExtension {
|
|
124652
124945
|
getShaders() {
|
|
124653
|
-
const name2 = this?.props?.colormap || defaultProps$4$
|
|
124946
|
+
const name2 = this?.props?.colormap || defaultProps$4$2.colormap.value;
|
|
124654
124947
|
const apply_cmap = cmaps[name2];
|
|
124655
124948
|
if (!apply_cmap) {
|
|
124656
124949
|
throw Error(`No colormap named ${name2} found in registry`);
|
|
@@ -124669,8 +124962,8 @@ const AdditiveColormapExtension = class extends LayerExtension {
|
|
|
124669
124962
|
}
|
|
124670
124963
|
draw() {
|
|
124671
124964
|
const {
|
|
124672
|
-
useTransparentColor = defaultProps$4$
|
|
124673
|
-
opacity = defaultProps$4$
|
|
124965
|
+
useTransparentColor = defaultProps$4$2.useTransparentColor.value,
|
|
124966
|
+
opacity = defaultProps$4$2.opacity.value
|
|
124674
124967
|
} = this.props;
|
|
124675
124968
|
const uniforms = {
|
|
124676
124969
|
opacity,
|
|
@@ -124680,7 +124973,7 @@ const AdditiveColormapExtension = class extends LayerExtension {
|
|
|
124680
124973
|
}
|
|
124681
124974
|
};
|
|
124682
124975
|
AdditiveColormapExtension.extensionName = "AdditiveColormapExtension";
|
|
124683
|
-
AdditiveColormapExtension.defaultProps = defaultProps$4$
|
|
124976
|
+
AdditiveColormapExtension.defaultProps = defaultProps$4$2;
|
|
124684
124977
|
const fs$1$2 = `uniform vec3 transparentColor;
|
|
124685
124978
|
uniform bool useTransparentColor;
|
|
124686
124979
|
uniform float opacity;
|
|
@@ -125973,7 +126266,7 @@ const ImageLayer = class extends CompositeLayer {
|
|
|
125973
126266
|
};
|
|
125974
126267
|
ImageLayer.layerName = "ImageLayer";
|
|
125975
126268
|
ImageLayer.defaultProps = defaultProps$5;
|
|
125976
|
-
const defaultProps$4 = {
|
|
126269
|
+
const defaultProps$4$1 = {
|
|
125977
126270
|
pickable: { type: "boolean", value: true, compare: true },
|
|
125978
126271
|
onHover: { type: "function", value: null, compare: false },
|
|
125979
126272
|
contrastLimits: { type: "array", value: [], compare: true },
|
|
@@ -126085,7 +126378,7 @@ const MultiscaleImageLayer = class extends CompositeLayer {
|
|
|
126085
126378
|
}
|
|
126086
126379
|
};
|
|
126087
126380
|
MultiscaleImageLayer.layerName = "MultiscaleImageLayer";
|
|
126088
|
-
MultiscaleImageLayer.defaultProps = defaultProps$4;
|
|
126381
|
+
MultiscaleImageLayer.defaultProps = defaultProps$4$1;
|
|
126089
126382
|
const defaultProps$3$1 = {
|
|
126090
126383
|
pickable: { type: "boolean", value: true, compare: true },
|
|
126091
126384
|
loader: {
|
|
@@ -127161,7 +127454,7 @@ function padWithDefault$1(arr, defaultValue2, padWidth) {
|
|
|
127161
127454
|
}
|
|
127162
127455
|
return newArr;
|
|
127163
127456
|
}
|
|
127164
|
-
const defaultProps$
|
|
127457
|
+
const defaultProps$4 = {
|
|
127165
127458
|
hoveredCell: { type: "number", value: null, compare: true },
|
|
127166
127459
|
// We do not want to deep-compare cellColorData,
|
|
127167
127460
|
// as it is potentially a TypedArray with millions of elements.
|
|
@@ -127278,7 +127571,7 @@ let BitmaskLayer$1 = class BitmaskLayer extends XRLayer {
|
|
|
127278
127571
|
}
|
|
127279
127572
|
};
|
|
127280
127573
|
BitmaskLayer$1.layerName = "BitmaskLayer";
|
|
127281
|
-
BitmaskLayer$1.defaultProps = defaultProps$
|
|
127574
|
+
BitmaskLayer$1.defaultProps = defaultProps$4;
|
|
127282
127575
|
const vs = `
|
|
127283
127576
|
#define SHADER_NAME bitmask-layer-vertex-shader
|
|
127284
127577
|
|
|
@@ -127620,7 +127913,7 @@ function isEqualShallow(prevArr, nextArr) {
|
|
|
127620
127913
|
}
|
|
127621
127914
|
return prevArr === nextArr;
|
|
127622
127915
|
}
|
|
127623
|
-
const defaultProps$
|
|
127916
|
+
const defaultProps$3 = {
|
|
127624
127917
|
channelStrokeWidths: { type: "array", value: null, compare: true },
|
|
127625
127918
|
channelsFilled: { type: "array", value: null, compare: true },
|
|
127626
127919
|
channelOpacities: { type: "array", value: null, compare: true },
|
|
@@ -127884,7 +128177,7 @@ class BitmaskLayer2 extends XRLayer {
|
|
|
127884
128177
|
}
|
|
127885
128178
|
}
|
|
127886
128179
|
BitmaskLayer2.layerName = "BitmaskLayer";
|
|
127887
|
-
BitmaskLayer2.defaultProps = defaultProps$
|
|
128180
|
+
BitmaskLayer2.defaultProps = defaultProps$3;
|
|
127888
128181
|
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;
|
|
127889
128182
|
function clone(configObject) {
|
|
127890
128183
|
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 = {
|
|
@@ -130827,7 +131120,7 @@ function ringArea(coords) {
|
|
|
130827
131120
|
return total * FACTOR;
|
|
130828
131121
|
}
|
|
130829
131122
|
const DEFAULT_THRESHOLD = 1;
|
|
130830
|
-
const defaultProps$
|
|
131123
|
+
const defaultProps$2 = {
|
|
130831
131124
|
// for text
|
|
130832
131125
|
obsSetPath: { type: "object" },
|
|
130833
131126
|
sampleSetPath: { type: "object" },
|
|
@@ -130922,9 +131215,9 @@ class ContourLayerWithText extends ContourLayer {
|
|
|
130922
131215
|
const circlePoint = point(circleCoord);
|
|
130923
131216
|
polygonVertices.forEach((polyCoord) => {
|
|
130924
131217
|
const polyPoint = point(polyCoord);
|
|
130925
|
-
const
|
|
130926
|
-
if (
|
|
130927
|
-
minDist =
|
|
131218
|
+
const dist2 = distance$1(circlePoint, polyPoint);
|
|
131219
|
+
if (dist2 < minDist) {
|
|
131220
|
+
minDist = dist2;
|
|
130928
131221
|
minCirclePoint = circleCoord;
|
|
130929
131222
|
minCirclePointI = circlePointI;
|
|
130930
131223
|
minPolygonPoint = polyCoord;
|
|
@@ -131001,7 +131294,1077 @@ class ContourLayerWithText extends ContourLayer {
|
|
|
131001
131294
|
}
|
|
131002
131295
|
}
|
|
131003
131296
|
ContourLayerWithText.layerName = "ContourLayerWithText";
|
|
131004
|
-
ContourLayerWithText.defaultProps = defaultProps$
|
|
131297
|
+
ContourLayerWithText.defaultProps = defaultProps$2;
|
|
131298
|
+
const ARROW_SCREEN_PX = 14;
|
|
131299
|
+
const LABEL_FONT_FAMILY$1 = '"Roboto", "Helvetica", "Arial", sans-serif';
|
|
131300
|
+
const LABEL_FONT_WEIGHT = "bold";
|
|
131301
|
+
const LABEL_FONT_SIZE = 14;
|
|
131302
|
+
const RATIO_CLUSTER = 0.1;
|
|
131303
|
+
const RATIO_DOT = 0.3;
|
|
131304
|
+
const RATIO_GEO_FADE = 0.55;
|
|
131305
|
+
const RATIO_TIPS = 0.7;
|
|
131306
|
+
const RATIO_LABEL = 0.55;
|
|
131307
|
+
const RATIO_LABEL_FULL = 0.75;
|
|
131308
|
+
function textBgColor(strokeColor) {
|
|
131309
|
+
const [r2, g2, b] = strokeColor;
|
|
131310
|
+
const lum = (0.299 * r2 + 0.587 * g2 + 0.114 * b) / 255;
|
|
131311
|
+
return lum > 0.45 ? [20, 20, 20, 210] : [245, 245, 245, 210];
|
|
131312
|
+
}
|
|
131313
|
+
function parseDashArray(strokeDashArray) {
|
|
131314
|
+
if (!strokeDashArray || strokeDashArray === "none")
|
|
131315
|
+
return null;
|
|
131316
|
+
const nums = strokeDashArray.trim().split(/\s+/).map(Number).filter((n2) => !Number.isNaN(n2) && n2 >= 0);
|
|
131317
|
+
return nums.length >= 2 ? [nums[0], nums[1]] : null;
|
|
131318
|
+
}
|
|
131319
|
+
function computeEllipsePolygon(cx, cy, rx, ry, numSegments = 64) {
|
|
131320
|
+
const pts = [];
|
|
131321
|
+
for (let i2 = 0; i2 < numSegments; i2++) {
|
|
131322
|
+
const angle2 = 2 * Math.PI * i2 / numSegments;
|
|
131323
|
+
pts.push([cx + rx * Math.cos(angle2), cy + ry * Math.sin(angle2)]);
|
|
131324
|
+
}
|
|
131325
|
+
return pts;
|
|
131326
|
+
}
|
|
131327
|
+
function createPreviewLayer(inProgress, hoverCoord, strokeColor = [255, 255, 0]) {
|
|
131328
|
+
if (!inProgress || inProgress.vertices.length === 0)
|
|
131329
|
+
return null;
|
|
131330
|
+
const { type, vertices } = inProgress;
|
|
131331
|
+
const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN };
|
|
131332
|
+
const previewColor = [...strokeColor, 160];
|
|
131333
|
+
const cursor2 = hoverCoord ?? vertices[vertices.length - 1];
|
|
131334
|
+
if (type === "rectangle" && vertices.length === 1) {
|
|
131335
|
+
const [ax, ay] = vertices[0];
|
|
131336
|
+
const [bx, by] = cursor2;
|
|
131337
|
+
const path = [[ax, ay], [bx, ay], [bx, by], [ax, by], [ax, ay]];
|
|
131338
|
+
return new PathLayer({
|
|
131339
|
+
...base,
|
|
131340
|
+
id: "annotation-preview-rectangle",
|
|
131341
|
+
data: [{ path }],
|
|
131342
|
+
getPath: (d) => d.path,
|
|
131343
|
+
getColor: previewColor,
|
|
131344
|
+
getWidth: 1,
|
|
131345
|
+
widthUnits: "pixels",
|
|
131346
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131347
|
+
getDashArray: [8, 4]
|
|
131348
|
+
});
|
|
131349
|
+
}
|
|
131350
|
+
if (type === "line" && vertices.length === 1) {
|
|
131351
|
+
const path = [vertices[0], cursor2];
|
|
131352
|
+
return new PathLayer({
|
|
131353
|
+
...base,
|
|
131354
|
+
id: "annotation-preview-line",
|
|
131355
|
+
data: [{ path }],
|
|
131356
|
+
getPath: (d) => d.path,
|
|
131357
|
+
getColor: previewColor,
|
|
131358
|
+
getWidth: 1,
|
|
131359
|
+
widthUnits: "pixels",
|
|
131360
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131361
|
+
getDashArray: [8, 4]
|
|
131362
|
+
});
|
|
131363
|
+
}
|
|
131364
|
+
if (type === "ellipse" && vertices.length === 1) {
|
|
131365
|
+
const [cx, cy] = vertices[0];
|
|
131366
|
+
const [ex, ey] = cursor2;
|
|
131367
|
+
const rx = Math.abs(ex - cx);
|
|
131368
|
+
const ry = Math.abs(ey - cy);
|
|
131369
|
+
if (rx < 1 && ry < 1)
|
|
131370
|
+
return null;
|
|
131371
|
+
const pts = computeEllipsePolygon(cx, cy, Math.max(rx, 1), Math.max(ry, 1));
|
|
131372
|
+
const path = [...pts, pts[0]];
|
|
131373
|
+
return new PathLayer({
|
|
131374
|
+
...base,
|
|
131375
|
+
id: "annotation-preview-ellipse",
|
|
131376
|
+
data: [{ path }],
|
|
131377
|
+
getPath: (d) => d.path,
|
|
131378
|
+
getColor: previewColor,
|
|
131379
|
+
getWidth: 1,
|
|
131380
|
+
widthUnits: "pixels",
|
|
131381
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131382
|
+
getDashArray: [8, 4]
|
|
131383
|
+
});
|
|
131384
|
+
}
|
|
131385
|
+
if ((type === "polygon" || type === "polyline") && vertices.length >= 1) {
|
|
131386
|
+
const path = [...vertices, cursor2];
|
|
131387
|
+
if (type === "polygon" && vertices.length >= 2)
|
|
131388
|
+
path.push(vertices[0]);
|
|
131389
|
+
return new PathLayer({
|
|
131390
|
+
...base,
|
|
131391
|
+
id: `annotation-preview-${type}`,
|
|
131392
|
+
data: [{ path }],
|
|
131393
|
+
getPath: (d) => d.path,
|
|
131394
|
+
getColor: previewColor,
|
|
131395
|
+
getWidth: 1,
|
|
131396
|
+
widthUnits: "pixels",
|
|
131397
|
+
jointRounded: true,
|
|
131398
|
+
capRounded: true,
|
|
131399
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131400
|
+
getDashArray: [8, 4]
|
|
131401
|
+
});
|
|
131402
|
+
}
|
|
131403
|
+
return null;
|
|
131404
|
+
}
|
|
131405
|
+
function computeTickCap(tipX, tipY, dirX, dirY, dataSize) {
|
|
131406
|
+
const len2 = Math.sqrt(dirX * dirX + dirY * dirY);
|
|
131407
|
+
if (len2 === 0)
|
|
131408
|
+
return null;
|
|
131409
|
+
const ux = dirX / len2;
|
|
131410
|
+
const uy = dirY / len2;
|
|
131411
|
+
const px = -uy;
|
|
131412
|
+
const py = ux;
|
|
131413
|
+
const half = dataSize * 0.55;
|
|
131414
|
+
return [
|
|
131415
|
+
[tipX + px * half, tipY + py * half],
|
|
131416
|
+
[tipX - px * half, tipY - py * half]
|
|
131417
|
+
];
|
|
131418
|
+
}
|
|
131419
|
+
function computeArrowhead(tipX, tipY, dirX, dirY, dataSize) {
|
|
131420
|
+
const len2 = Math.sqrt(dirX * dirX + dirY * dirY);
|
|
131421
|
+
if (len2 === 0)
|
|
131422
|
+
return null;
|
|
131423
|
+
const ux = dirX / len2;
|
|
131424
|
+
const uy = dirY / len2;
|
|
131425
|
+
const px = -uy;
|
|
131426
|
+
const py = ux;
|
|
131427
|
+
const halfBase = dataSize * 0.4;
|
|
131428
|
+
const bx = tipX - ux * dataSize;
|
|
131429
|
+
const by = tipY - uy * dataSize;
|
|
131430
|
+
return [
|
|
131431
|
+
[tipX, tipY],
|
|
131432
|
+
[bx + px * halfBase, by + py * halfBase],
|
|
131433
|
+
[bx - px * halfBase, by - py * halfBase]
|
|
131434
|
+
];
|
|
131435
|
+
}
|
|
131436
|
+
function fmtCommas(n2) {
|
|
131437
|
+
return Math.round(n2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
131438
|
+
}
|
|
131439
|
+
function getMeasurementLabel(shape2, physicalPixelSize, viewType = ViewType$1.SPATIAL) {
|
|
131440
|
+
const pps = physicalPixelSize;
|
|
131441
|
+
const px = pps?.x ?? 1;
|
|
131442
|
+
const py = pps?.y ?? 1;
|
|
131443
|
+
const unit2 = pps ? pps.unit ?? "" : null;
|
|
131444
|
+
const hasPhys = !!pps;
|
|
131445
|
+
const isEmbedding = viewType === ViewType$1.SCATTERPLOT;
|
|
131446
|
+
const fmtDist = (d) => {
|
|
131447
|
+
if (hasPhys)
|
|
131448
|
+
return `${d.toFixed(2)} ${unit2}`;
|
|
131449
|
+
if (isEmbedding)
|
|
131450
|
+
return d.toFixed(2);
|
|
131451
|
+
return `${fmtCommas(d)} px`;
|
|
131452
|
+
};
|
|
131453
|
+
const fmtArea = (a2) => {
|
|
131454
|
+
if (hasPhys)
|
|
131455
|
+
return `${a2.toFixed(2)} ${unit2}²`;
|
|
131456
|
+
if (isEmbedding)
|
|
131457
|
+
return a2.toFixed(2);
|
|
131458
|
+
return `${fmtCommas(a2)} px²`;
|
|
131459
|
+
};
|
|
131460
|
+
if (shape2.type === "line") {
|
|
131461
|
+
const dx = (shape2.x2 ?? 0) - (shape2.x1 ?? 0);
|
|
131462
|
+
const dy = (shape2.y2 ?? 0) - (shape2.y1 ?? 0);
|
|
131463
|
+
const dist2 = hasPhys ? Math.sqrt((dx * px) ** 2 + (dy * py) ** 2) : Math.sqrt(dx * dx + dy * dy);
|
|
131464
|
+
return fmtDist(dist2);
|
|
131465
|
+
}
|
|
131466
|
+
if (shape2.type === "rectangle") {
|
|
131467
|
+
return fmtArea(hasPhys ? Math.abs(shape2.width ?? 0) * px * Math.abs(shape2.height ?? 0) * py : Math.abs((shape2.width ?? 0) * (shape2.height ?? 0)));
|
|
131468
|
+
}
|
|
131469
|
+
if (shape2.type === "ellipse") {
|
|
131470
|
+
const rx = Math.abs(shape2.radiusX ?? 0);
|
|
131471
|
+
const ry = Math.abs(shape2.radiusY ?? 0);
|
|
131472
|
+
return fmtArea(hasPhys ? Math.PI * rx * px * ry * py : Math.PI * rx * ry);
|
|
131473
|
+
}
|
|
131474
|
+
if (shape2.type === "polygon" && shape2.points?.length >= 3) {
|
|
131475
|
+
const pts = shape2.points;
|
|
131476
|
+
let shoelace = 0;
|
|
131477
|
+
for (let i2 = 0; i2 < pts.length; i2++) {
|
|
131478
|
+
const [ax, ay] = pts[i2];
|
|
131479
|
+
const [bx, by] = pts[(i2 + 1) % pts.length];
|
|
131480
|
+
shoelace += (hasPhys ? ax * px : ax) * (hasPhys ? by * py : by) - (hasPhys ? bx * px : bx) * (hasPhys ? ay * py : ay);
|
|
131481
|
+
}
|
|
131482
|
+
return fmtArea(Math.abs(shoelace / 2));
|
|
131483
|
+
}
|
|
131484
|
+
if (shape2.type === "polyline" && shape2.points?.length >= 2) {
|
|
131485
|
+
let total = 0;
|
|
131486
|
+
for (let i2 = 0; i2 < shape2.points.length - 1; i2++) {
|
|
131487
|
+
const [ax, ay] = shape2.points[i2];
|
|
131488
|
+
const [bx, by] = shape2.points[i2 + 1];
|
|
131489
|
+
total += hasPhys ? Math.sqrt(((bx - ax) * px) ** 2 + ((by - ay) * py) ** 2) : Math.sqrt((bx - ax) ** 2 + (by - ay) ** 2);
|
|
131490
|
+
}
|
|
131491
|
+
return fmtDist(total);
|
|
131492
|
+
}
|
|
131493
|
+
return null;
|
|
131494
|
+
}
|
|
131495
|
+
function pickBelowPerp(ux, uy) {
|
|
131496
|
+
const rp = [uy, -ux];
|
|
131497
|
+
const lp = [-uy, ux];
|
|
131498
|
+
return rp[1] > lp[1] || rp[1] === lp[1] && rp[0] > lp[0] ? rp : lp;
|
|
131499
|
+
}
|
|
131500
|
+
function readableAngle(deg) {
|
|
131501
|
+
let a2 = deg;
|
|
131502
|
+
if (a2 > 90)
|
|
131503
|
+
a2 -= 180;
|
|
131504
|
+
if (a2 < -90)
|
|
131505
|
+
a2 += 180;
|
|
131506
|
+
return a2;
|
|
131507
|
+
}
|
|
131508
|
+
function getShapeCentroid(shape2) {
|
|
131509
|
+
if (shape2.type === "rectangle") {
|
|
131510
|
+
return [(shape2.x ?? 0) + (shape2.width ?? 0) / 2, (shape2.y ?? 0) + (shape2.height ?? 0) / 2];
|
|
131511
|
+
}
|
|
131512
|
+
if (shape2.type === "line") {
|
|
131513
|
+
return [((shape2.x1 ?? 0) + (shape2.x2 ?? 0)) / 2, ((shape2.y1 ?? 0) + (shape2.y2 ?? 0)) / 2];
|
|
131514
|
+
}
|
|
131515
|
+
if (shape2.type === "ellipse") {
|
|
131516
|
+
return [shape2.x1 ?? 0, shape2.y1 ?? 0];
|
|
131517
|
+
}
|
|
131518
|
+
if ((shape2.type === "polygon" || shape2.type === "polyline") && shape2.points?.length >= 1) {
|
|
131519
|
+
const mx = shape2.points.reduce((s2, p) => s2 + p[0], 0) / shape2.points.length;
|
|
131520
|
+
const my = shape2.points.reduce((s2, p) => s2 + p[1], 0) / shape2.points.length;
|
|
131521
|
+
return [mx, my];
|
|
131522
|
+
}
|
|
131523
|
+
return [0, 0];
|
|
131524
|
+
}
|
|
131525
|
+
function computeClusters(shapeList, zoom, cellPx = 50) {
|
|
131526
|
+
const cellSize = cellPx / 2 ** Math.floor(zoom);
|
|
131527
|
+
const cells = /* @__PURE__ */ new Map();
|
|
131528
|
+
shapeList.forEach(({ shape: shape2 }) => {
|
|
131529
|
+
const [cx, cy] = getShapeCentroid(shape2);
|
|
131530
|
+
const key = `${Math.floor(cx / cellSize)},${Math.floor(cy / cellSize)}`;
|
|
131531
|
+
if (!cells.has(key)) {
|
|
131532
|
+
cells.set(key, { sumX: 0, sumY: 0, count: 0, color: shape2.strokeColor ?? [255, 255, 255] });
|
|
131533
|
+
}
|
|
131534
|
+
const c2 = cells.get(key);
|
|
131535
|
+
c2.sumX += cx;
|
|
131536
|
+
c2.sumY += cy;
|
|
131537
|
+
c2.count++;
|
|
131538
|
+
});
|
|
131539
|
+
return Array.from(cells.values()).map((c2) => ({
|
|
131540
|
+
position: [c2.sumX / c2.count, c2.sumY / c2.count, 0],
|
|
131541
|
+
count: c2.count,
|
|
131542
|
+
color: c2.color
|
|
131543
|
+
}));
|
|
131544
|
+
}
|
|
131545
|
+
function createAnnotationLayers(shapes = [], zoom = 0, selectedShapeUid = null, physicalPixelSize = null, authoredZoom = null, semanticZoom = true, viewType = ViewType$1.SPATIAL) {
|
|
131546
|
+
const selectionLayers = [];
|
|
131547
|
+
if (selectedShapeUid) {
|
|
131548
|
+
const sel = shapes.find((s2) => s2.uid === selectedShapeUid);
|
|
131549
|
+
if (sel) {
|
|
131550
|
+
const { uid: sUid, type: sType, strokeWidth: sStrokeWidth = 3 } = sel;
|
|
131551
|
+
const haloColor = [255, 220, 50, 70];
|
|
131552
|
+
const haloWidth = Math.max(sStrokeWidth + 8, 10);
|
|
131553
|
+
const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN };
|
|
131554
|
+
if (sType === "rectangle") {
|
|
131555
|
+
const { x, y, width: width2, height: height2 } = sel;
|
|
131556
|
+
selectionLayers.push(new PathLayer({
|
|
131557
|
+
...base,
|
|
131558
|
+
id: `annotation-select-${sUid}`,
|
|
131559
|
+
data: [{
|
|
131560
|
+
path: [
|
|
131561
|
+
[x, y],
|
|
131562
|
+
[x + width2, y],
|
|
131563
|
+
[x + width2, y + height2],
|
|
131564
|
+
[x, y + height2],
|
|
131565
|
+
[x, y]
|
|
131566
|
+
]
|
|
131567
|
+
}],
|
|
131568
|
+
getPath: (d) => d.path,
|
|
131569
|
+
getColor: haloColor,
|
|
131570
|
+
getWidth: haloWidth,
|
|
131571
|
+
widthUnits: "pixels",
|
|
131572
|
+
jointRounded: true,
|
|
131573
|
+
capRounded: true
|
|
131574
|
+
}));
|
|
131575
|
+
}
|
|
131576
|
+
if (sType === "line") {
|
|
131577
|
+
const { x1: x12, y1: y12, x2, y2 } = sel;
|
|
131578
|
+
selectionLayers.push(new PathLayer({
|
|
131579
|
+
...base,
|
|
131580
|
+
id: `annotation-select-${sUid}`,
|
|
131581
|
+
data: [{ path: [[x12, y12], [x2, y2]] }],
|
|
131582
|
+
getPath: (d) => d.path,
|
|
131583
|
+
getColor: haloColor,
|
|
131584
|
+
getWidth: haloWidth,
|
|
131585
|
+
widthUnits: "pixels",
|
|
131586
|
+
capRounded: true
|
|
131587
|
+
}));
|
|
131588
|
+
}
|
|
131589
|
+
if (sType === "ellipse") {
|
|
131590
|
+
const polygon2 = computeEllipsePolygon(sel.x1, sel.y1, sel.radiusX, sel.radiusY);
|
|
131591
|
+
selectionLayers.push(new PathLayer({
|
|
131592
|
+
...base,
|
|
131593
|
+
id: `annotation-select-${sUid}`,
|
|
131594
|
+
data: [{ path: [...polygon2, polygon2[0]] }],
|
|
131595
|
+
getPath: (d) => d.path,
|
|
131596
|
+
getColor: haloColor,
|
|
131597
|
+
getWidth: haloWidth,
|
|
131598
|
+
widthUnits: "pixels",
|
|
131599
|
+
jointRounded: true
|
|
131600
|
+
}));
|
|
131601
|
+
}
|
|
131602
|
+
if (sType === "polygon" && sel.points?.length >= 3) {
|
|
131603
|
+
selectionLayers.push(new PathLayer({
|
|
131604
|
+
...base,
|
|
131605
|
+
id: `annotation-select-${sUid}`,
|
|
131606
|
+
data: [{ path: [...sel.points, sel.points[0]] }],
|
|
131607
|
+
getPath: (d) => d.path,
|
|
131608
|
+
getColor: haloColor,
|
|
131609
|
+
getWidth: haloWidth,
|
|
131610
|
+
widthUnits: "pixels",
|
|
131611
|
+
jointRounded: true
|
|
131612
|
+
}));
|
|
131613
|
+
}
|
|
131614
|
+
if (sType === "polyline" && sel.points?.length >= 2) {
|
|
131615
|
+
selectionLayers.push(new PathLayer({
|
|
131616
|
+
...base,
|
|
131617
|
+
id: `annotation-select-${sUid}`,
|
|
131618
|
+
data: [{ path: sel.points }],
|
|
131619
|
+
getPath: (d) => d.path,
|
|
131620
|
+
getColor: haloColor,
|
|
131621
|
+
getWidth: haloWidth,
|
|
131622
|
+
widthUnits: "pixels",
|
|
131623
|
+
jointRounded: true,
|
|
131624
|
+
capRounded: true
|
|
131625
|
+
}));
|
|
131626
|
+
}
|
|
131627
|
+
}
|
|
131628
|
+
}
|
|
131629
|
+
const layers = [];
|
|
131630
|
+
const dotShapes = [];
|
|
131631
|
+
const clusterDotShapes = [];
|
|
131632
|
+
shapes.forEach((shape2, i2) => {
|
|
131633
|
+
const { uid: uid2, type, strokeColor = [255, 255, 255], strokeWidth = 3, strokeDashArray } = shape2;
|
|
131634
|
+
const isSelected = uid2 === selectedShapeUid;
|
|
131635
|
+
let shapeOpacity = 1;
|
|
131636
|
+
let tipsOpacity = 1;
|
|
131637
|
+
let labelOpacity = 0;
|
|
131638
|
+
if (isSelected || !semanticZoom || authoredZoom === null) {
|
|
131639
|
+
tipsOpacity = 1;
|
|
131640
|
+
labelOpacity = 1;
|
|
131641
|
+
} else {
|
|
131642
|
+
const zoomRatio = 2 ** (zoom - authoredZoom);
|
|
131643
|
+
if (zoomRatio < RATIO_CLUSTER) {
|
|
131644
|
+
clusterDotShapes.push({ shape: shape2 });
|
|
131645
|
+
return;
|
|
131646
|
+
}
|
|
131647
|
+
if (zoomRatio < RATIO_DOT) {
|
|
131648
|
+
dotShapes.push({ shape: shape2, alpha: 200 });
|
|
131649
|
+
return;
|
|
131650
|
+
}
|
|
131651
|
+
if (zoomRatio < RATIO_GEO_FADE) {
|
|
131652
|
+
const t = (zoomRatio - RATIO_DOT) / (RATIO_GEO_FADE - RATIO_DOT);
|
|
131653
|
+
shapeOpacity = t;
|
|
131654
|
+
dotShapes.push({ shape: shape2, alpha: Math.round((1 - t) * 200) });
|
|
131655
|
+
}
|
|
131656
|
+
tipsOpacity = zoomRatio >= RATIO_TIPS ? shapeOpacity : Math.max(0, (zoomRatio - RATIO_GEO_FADE) / (RATIO_TIPS - RATIO_GEO_FADE) * shapeOpacity);
|
|
131657
|
+
if (zoomRatio >= RATIO_LABEL_FULL) {
|
|
131658
|
+
labelOpacity = shapeOpacity;
|
|
131659
|
+
} else if (zoomRatio >= RATIO_LABEL) {
|
|
131660
|
+
labelOpacity = (zoomRatio - RATIO_LABEL) / (RATIO_LABEL_FULL - RATIO_LABEL) * shapeOpacity;
|
|
131661
|
+
}
|
|
131662
|
+
}
|
|
131663
|
+
const arrowDataSize = Math.max(ARROW_SCREEN_PX, strokeWidth * 4) / 2 ** zoom;
|
|
131664
|
+
const base = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: shapeOpacity };
|
|
131665
|
+
const tipsBase = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: tipsOpacity };
|
|
131666
|
+
const labelBase = { coordinateSystem: COORDINATE_SYSTEM.CARTESIAN, opacity: labelOpacity };
|
|
131667
|
+
const labelBgProps = shape2.labelBackground ? {
|
|
131668
|
+
background: true,
|
|
131669
|
+
getBackgroundColor: textBgColor(strokeColor),
|
|
131670
|
+
backgroundPadding: [3, 1, 3, 2]
|
|
131671
|
+
} : {};
|
|
131672
|
+
const labelProps = { ...labelBgProps };
|
|
131673
|
+
const dashArray = parseDashArray(strokeDashArray);
|
|
131674
|
+
const dashExt = [new PathStyleExtension({ dash: true })];
|
|
131675
|
+
const getDash = dashArray ?? [0, 0];
|
|
131676
|
+
if (type === "rectangle") {
|
|
131677
|
+
const { x, y, width: width2, height: height2, fillColor = strokeColor, fillOpacity = 0 } = shape2;
|
|
131678
|
+
const filled = fillOpacity > 0;
|
|
131679
|
+
const rectPolygon = [[x, y], [x + width2, y], [x + width2, y + height2], [x, y + height2]];
|
|
131680
|
+
layers.push(new PolygonLayer({
|
|
131681
|
+
...base,
|
|
131682
|
+
id: `annotation-rect-${uid2}-${i2}`,
|
|
131683
|
+
data: [{ polygon: rectPolygon }],
|
|
131684
|
+
getPolygon: (d) => d.polygon,
|
|
131685
|
+
filled,
|
|
131686
|
+
stroked: true,
|
|
131687
|
+
getFillColor: filled ? [...fillColor, Math.round(fillOpacity * 255)] : [0, 0, 0, 0],
|
|
131688
|
+
getLineColor: strokeColor,
|
|
131689
|
+
getLineWidth: strokeWidth,
|
|
131690
|
+
lineWidthUnits: "pixels",
|
|
131691
|
+
...dashArray ? {
|
|
131692
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131693
|
+
getDashArray: dashArray
|
|
131694
|
+
} : {}
|
|
131695
|
+
}));
|
|
131696
|
+
if (shape2.text && labelOpacity > 0) {
|
|
131697
|
+
layers.push(new TextLayer({
|
|
131698
|
+
...labelBase,
|
|
131699
|
+
...labelProps,
|
|
131700
|
+
id: `annotation-rect-text-${uid2}-${i2}`,
|
|
131701
|
+
data: [{ position: [x, y], text: shape2.text }],
|
|
131702
|
+
getPosition: (d) => d.position,
|
|
131703
|
+
getText: (d) => d.text,
|
|
131704
|
+
getColor: strokeColor,
|
|
131705
|
+
getSize: LABEL_FONT_SIZE,
|
|
131706
|
+
sizeUnits: "pixels",
|
|
131707
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
131708
|
+
fontWeight: LABEL_FONT_WEIGHT,
|
|
131709
|
+
getPixelOffset: [3, -7],
|
|
131710
|
+
getTextAnchor: "start",
|
|
131711
|
+
getAlignmentBaseline: "bottom"
|
|
131712
|
+
}));
|
|
131713
|
+
}
|
|
131714
|
+
}
|
|
131715
|
+
if (type === "line") {
|
|
131716
|
+
const { x1: x12, y1: y12, x2, y2, markerStart, markerEnd } = shape2;
|
|
131717
|
+
const dx = x2 - x12;
|
|
131718
|
+
const dy = y2 - y12;
|
|
131719
|
+
const len2 = Math.sqrt(dx * dx + dy * dy);
|
|
131720
|
+
const ux = len2 > 0 ? dx / len2 : 0;
|
|
131721
|
+
const uy = len2 > 0 ? dy / len2 : 0;
|
|
131722
|
+
const srcX = markerStart === "Arrow" ? x12 + ux * arrowDataSize : x12;
|
|
131723
|
+
const srcY = markerStart === "Arrow" ? y12 + uy * arrowDataSize : y12;
|
|
131724
|
+
const tgtX = markerEnd === "Arrow" ? x2 - ux * arrowDataSize : x2;
|
|
131725
|
+
const tgtY = markerEnd === "Arrow" ? y2 - uy * arrowDataSize : y2;
|
|
131726
|
+
layers.push(new PathLayer({
|
|
131727
|
+
...base,
|
|
131728
|
+
id: `annotation-line-${uid2}-${i2}`,
|
|
131729
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131730
|
+
getDashArray: dashArray ?? [0, 0],
|
|
131731
|
+
data: [{ path: [[srcX, srcY], [tgtX, tgtY]] }],
|
|
131732
|
+
getPath: (d) => d.path,
|
|
131733
|
+
getColor: strokeColor,
|
|
131734
|
+
getWidth: strokeWidth,
|
|
131735
|
+
widthUnits: "pixels",
|
|
131736
|
+
capRounded: true
|
|
131737
|
+
}));
|
|
131738
|
+
if (markerEnd === "Arrow" && tipsOpacity > 0) {
|
|
131739
|
+
const head = computeArrowhead(x2, y2, x2 - x12, y2 - y12, arrowDataSize);
|
|
131740
|
+
if (head) {
|
|
131741
|
+
layers.push(new PolygonLayer({
|
|
131742
|
+
...tipsBase,
|
|
131743
|
+
id: `annotation-end-arrow-${uid2}-${i2}`,
|
|
131744
|
+
data: [{ polygon: head }],
|
|
131745
|
+
getPolygon: (d) => d.polygon,
|
|
131746
|
+
filled: true,
|
|
131747
|
+
stroked: false,
|
|
131748
|
+
getFillColor: strokeColor
|
|
131749
|
+
}));
|
|
131750
|
+
}
|
|
131751
|
+
}
|
|
131752
|
+
if (markerStart === "Arrow" && tipsOpacity > 0) {
|
|
131753
|
+
const head = computeArrowhead(x12, y12, x12 - x2, y12 - y2, arrowDataSize);
|
|
131754
|
+
if (head) {
|
|
131755
|
+
layers.push(new PolygonLayer({
|
|
131756
|
+
...tipsBase,
|
|
131757
|
+
id: `annotation-start-arrow-${uid2}-${i2}`,
|
|
131758
|
+
data: [{ polygon: head }],
|
|
131759
|
+
getPolygon: (d) => d.polygon,
|
|
131760
|
+
filled: true,
|
|
131761
|
+
stroked: false,
|
|
131762
|
+
getFillColor: strokeColor
|
|
131763
|
+
}));
|
|
131764
|
+
}
|
|
131765
|
+
}
|
|
131766
|
+
if (markerEnd === "Tick" && tipsOpacity > 0) {
|
|
131767
|
+
const tick = computeTickCap(x2, y2, x2 - x12, y2 - y12, arrowDataSize);
|
|
131768
|
+
if (tick) {
|
|
131769
|
+
layers.push(new PathLayer({
|
|
131770
|
+
...tipsBase,
|
|
131771
|
+
id: `annotation-end-tick-${uid2}-${i2}`,
|
|
131772
|
+
data: [{ path: tick }],
|
|
131773
|
+
getPath: (d) => d.path,
|
|
131774
|
+
getColor: strokeColor,
|
|
131775
|
+
getWidth: strokeWidth,
|
|
131776
|
+
widthUnits: "pixels",
|
|
131777
|
+
capRounded: true
|
|
131778
|
+
}));
|
|
131779
|
+
}
|
|
131780
|
+
}
|
|
131781
|
+
if (markerStart === "Tick" && tipsOpacity > 0) {
|
|
131782
|
+
const tick = computeTickCap(x12, y12, x12 - x2, y12 - y2, arrowDataSize);
|
|
131783
|
+
if (tick) {
|
|
131784
|
+
layers.push(new PathLayer({
|
|
131785
|
+
...tipsBase,
|
|
131786
|
+
id: `annotation-start-tick-${uid2}-${i2}`,
|
|
131787
|
+
data: [{ path: tick }],
|
|
131788
|
+
getPath: (d) => d.path,
|
|
131789
|
+
getColor: strokeColor,
|
|
131790
|
+
getWidth: strokeWidth,
|
|
131791
|
+
widthUnits: "pixels",
|
|
131792
|
+
capRounded: true
|
|
131793
|
+
}));
|
|
131794
|
+
}
|
|
131795
|
+
}
|
|
131796
|
+
if (shape2.text) {
|
|
131797
|
+
const pos = shape2.textPosition ?? "start";
|
|
131798
|
+
let textX;
|
|
131799
|
+
let textY;
|
|
131800
|
+
if (pos === "start") {
|
|
131801
|
+
textX = x12;
|
|
131802
|
+
textY = y12;
|
|
131803
|
+
} else if (pos === "end") {
|
|
131804
|
+
textX = x2;
|
|
131805
|
+
textY = y2;
|
|
131806
|
+
} else {
|
|
131807
|
+
textX = (x12 + x2) / 2;
|
|
131808
|
+
textY = (y12 + y2) / 2;
|
|
131809
|
+
}
|
|
131810
|
+
let pixelOffset = [0, 0];
|
|
131811
|
+
let textAnchor = "middle";
|
|
131812
|
+
let alignmentBaseline = "center";
|
|
131813
|
+
if (pos !== "middle") {
|
|
131814
|
+
const dxT = x2 - x12;
|
|
131815
|
+
const dyT = y2 - y12;
|
|
131816
|
+
const lenT = Math.sqrt(dxT * dxT + dyT * dyT);
|
|
131817
|
+
if (lenT > 0) {
|
|
131818
|
+
const uxT = dxT / lenT;
|
|
131819
|
+
const uyT = dyT / lenT;
|
|
131820
|
+
const sign2 = pos === "start" ? -1 : 1;
|
|
131821
|
+
const bufferPx = shape2.textBufferPx ?? 8;
|
|
131822
|
+
const offsetX = sign2 * uxT * bufferPx;
|
|
131823
|
+
const offsetY = sign2 * uyT * bufferPx;
|
|
131824
|
+
pixelOffset = [offsetX, offsetY];
|
|
131825
|
+
const absX = Math.abs(offsetX);
|
|
131826
|
+
const absY = Math.abs(offsetY);
|
|
131827
|
+
if (absX >= absY) {
|
|
131828
|
+
textAnchor = offsetX > 0 ? "start" : "end";
|
|
131829
|
+
}
|
|
131830
|
+
if (absY >= absX) {
|
|
131831
|
+
alignmentBaseline = offsetY > 0 ? "top" : "bottom";
|
|
131832
|
+
}
|
|
131833
|
+
}
|
|
131834
|
+
} else if (len2 > 0) {
|
|
131835
|
+
const belowPerp = pickBelowPerp(ux, uy);
|
|
131836
|
+
const bufferPx = shape2.textBufferPx ?? 14;
|
|
131837
|
+
pixelOffset = [-belowPerp[0] * bufferPx, -belowPerp[1] * bufferPx];
|
|
131838
|
+
textAnchor = "middle";
|
|
131839
|
+
alignmentBaseline = "center";
|
|
131840
|
+
}
|
|
131841
|
+
const middleAngle = pos === "middle" && len2 > 0 ? -readableAngle(Math.atan2(dy, dx) * 180 / Math.PI) : null;
|
|
131842
|
+
if (labelOpacity <= 0)
|
|
131843
|
+
return;
|
|
131844
|
+
layers.push(new TextLayer({
|
|
131845
|
+
...labelBase,
|
|
131846
|
+
...labelProps,
|
|
131847
|
+
id: `annotation-line-text-${uid2}-${i2}`,
|
|
131848
|
+
data: [{ position: [textX, textY], text: shape2.text }],
|
|
131849
|
+
getPosition: (d) => d.position,
|
|
131850
|
+
getText: (d) => d.text,
|
|
131851
|
+
getColor: strokeColor,
|
|
131852
|
+
getSize: LABEL_FONT_SIZE,
|
|
131853
|
+
sizeUnits: "pixels",
|
|
131854
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
131855
|
+
fontWeight: LABEL_FONT_WEIGHT,
|
|
131856
|
+
getPixelOffset: pixelOffset,
|
|
131857
|
+
getTextAnchor: textAnchor,
|
|
131858
|
+
getAlignmentBaseline: alignmentBaseline,
|
|
131859
|
+
...middleAngle !== null && { getAngle: middleAngle }
|
|
131860
|
+
}));
|
|
131861
|
+
}
|
|
131862
|
+
}
|
|
131863
|
+
if (type === "ellipse") {
|
|
131864
|
+
const { x1: x12, y1: y12, radiusX, radiusY, fillColor = strokeColor, fillOpacity = 0 } = shape2;
|
|
131865
|
+
const polygon2 = computeEllipsePolygon(x12, y12, radiusX, radiusY);
|
|
131866
|
+
const filled = fillOpacity > 0;
|
|
131867
|
+
layers.push(new PolygonLayer({
|
|
131868
|
+
...base,
|
|
131869
|
+
id: `annotation-ellipse-${uid2}-${i2}`,
|
|
131870
|
+
data: [{ polygon: polygon2 }],
|
|
131871
|
+
getPolygon: (d) => d.polygon,
|
|
131872
|
+
filled,
|
|
131873
|
+
stroked: true,
|
|
131874
|
+
getFillColor: filled ? [...fillColor, Math.round(fillOpacity * 255)] : [0, 0, 0, 0],
|
|
131875
|
+
getLineColor: strokeColor,
|
|
131876
|
+
getLineWidth: strokeWidth,
|
|
131877
|
+
lineWidthUnits: "pixels",
|
|
131878
|
+
...dashArray ? {
|
|
131879
|
+
extensions: [new PathStyleExtension({ dash: true })],
|
|
131880
|
+
getDashArray: dashArray
|
|
131881
|
+
} : {}
|
|
131882
|
+
}));
|
|
131883
|
+
if (shape2.text && labelOpacity > 0) {
|
|
131884
|
+
layers.push(new TextLayer({
|
|
131885
|
+
...labelBase,
|
|
131886
|
+
...labelProps,
|
|
131887
|
+
id: `annotation-ellipse-text-${uid2}-${i2}`,
|
|
131888
|
+
data: [{ position: [x12, y12 - radiusY], text: shape2.text }],
|
|
131889
|
+
getPosition: (d) => d.position,
|
|
131890
|
+
getText: (d) => d.text,
|
|
131891
|
+
getColor: strokeColor,
|
|
131892
|
+
getSize: LABEL_FONT_SIZE,
|
|
131893
|
+
sizeUnits: "pixels",
|
|
131894
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
131895
|
+
fontWeight: LABEL_FONT_WEIGHT,
|
|
131896
|
+
getPixelOffset: [0, -4],
|
|
131897
|
+
getTextAnchor: "middle",
|
|
131898
|
+
getAlignmentBaseline: "bottom"
|
|
131899
|
+
}));
|
|
131900
|
+
}
|
|
131901
|
+
}
|
|
131902
|
+
if (type === "polygon") {
|
|
131903
|
+
const { points, fillColor = strokeColor, fillOpacity = 0 } = shape2;
|
|
131904
|
+
if (!points || points.length < 3)
|
|
131905
|
+
return;
|
|
131906
|
+
const closedPath = [...points, points[0]];
|
|
131907
|
+
if (fillOpacity > 0) {
|
|
131908
|
+
layers.push(new PolygonLayer({
|
|
131909
|
+
...base,
|
|
131910
|
+
id: `annotation-polygon-fill-${uid2}-${i2}`,
|
|
131911
|
+
data: [{ polygon: points }],
|
|
131912
|
+
getPolygon: (d) => d.polygon,
|
|
131913
|
+
stroked: false,
|
|
131914
|
+
filled: true,
|
|
131915
|
+
getFillColor: [...fillColor, Math.round(fillOpacity * 255)]
|
|
131916
|
+
}));
|
|
131917
|
+
}
|
|
131918
|
+
layers.push(new PathLayer({
|
|
131919
|
+
...base,
|
|
131920
|
+
id: `annotation-polygon-${uid2}-${i2}`,
|
|
131921
|
+
extensions: dashExt,
|
|
131922
|
+
getDashArray: getDash,
|
|
131923
|
+
data: [{ path: closedPath }],
|
|
131924
|
+
getPath: (d) => d.path,
|
|
131925
|
+
getColor: strokeColor,
|
|
131926
|
+
getWidth: strokeWidth,
|
|
131927
|
+
widthUnits: "pixels",
|
|
131928
|
+
jointRounded: true
|
|
131929
|
+
}));
|
|
131930
|
+
if (shape2.text && labelOpacity > 0) {
|
|
131931
|
+
const minX = Math.min(...points.map((p) => p[0]));
|
|
131932
|
+
const maxX = Math.max(...points.map((p) => p[0]));
|
|
131933
|
+
const minY = Math.min(...points.map((p) => p[1]));
|
|
131934
|
+
const topCenterX = (minX + maxX) / 2;
|
|
131935
|
+
layers.push(new TextLayer({
|
|
131936
|
+
...labelBase,
|
|
131937
|
+
...labelProps,
|
|
131938
|
+
id: `annotation-polygon-text-${uid2}-${i2}`,
|
|
131939
|
+
data: [{ position: [topCenterX, minY], text: shape2.text }],
|
|
131940
|
+
getPosition: (d) => d.position,
|
|
131941
|
+
getText: (d) => d.text,
|
|
131942
|
+
getColor: strokeColor,
|
|
131943
|
+
getSize: LABEL_FONT_SIZE,
|
|
131944
|
+
sizeUnits: "pixels",
|
|
131945
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
131946
|
+
fontWeight: LABEL_FONT_WEIGHT,
|
|
131947
|
+
getPixelOffset: [0, -4],
|
|
131948
|
+
getTextAnchor: "middle",
|
|
131949
|
+
getAlignmentBaseline: "bottom"
|
|
131950
|
+
}));
|
|
131951
|
+
}
|
|
131952
|
+
}
|
|
131953
|
+
if (type === "polyline") {
|
|
131954
|
+
const { points, markerStart, markerEnd } = shape2;
|
|
131955
|
+
if (!points || points.length < 2)
|
|
131956
|
+
return;
|
|
131957
|
+
let pathPoints = points;
|
|
131958
|
+
if (markerStart === "Arrow") {
|
|
131959
|
+
const [x02, y02] = points[0];
|
|
131960
|
+
const [x12, y12] = points[1];
|
|
131961
|
+
const dx = x02 - x12;
|
|
131962
|
+
const dy = y02 - y12;
|
|
131963
|
+
const len2 = Math.sqrt(dx * dx + dy * dy);
|
|
131964
|
+
if (len2 > 0) {
|
|
131965
|
+
const ux = dx / len2;
|
|
131966
|
+
const uy = dy / len2;
|
|
131967
|
+
pathPoints = [[x02 - ux * arrowDataSize, y02 - uy * arrowDataSize], ...pathPoints.slice(1)];
|
|
131968
|
+
}
|
|
131969
|
+
}
|
|
131970
|
+
if (markerEnd === "Arrow") {
|
|
131971
|
+
const last = pathPoints[pathPoints.length - 1];
|
|
131972
|
+
const prev2 = pathPoints[pathPoints.length - 2];
|
|
131973
|
+
const dx = last[0] - prev2[0];
|
|
131974
|
+
const dy = last[1] - prev2[1];
|
|
131975
|
+
const len2 = Math.sqrt(dx * dx + dy * dy);
|
|
131976
|
+
if (len2 > 0) {
|
|
131977
|
+
const ux = dx / len2;
|
|
131978
|
+
const uy = dy / len2;
|
|
131979
|
+
const shortened = [last[0] - ux * arrowDataSize, last[1] - uy * arrowDataSize];
|
|
131980
|
+
pathPoints = [...pathPoints.slice(0, -1), shortened];
|
|
131981
|
+
}
|
|
131982
|
+
}
|
|
131983
|
+
layers.push(new PathLayer({
|
|
131984
|
+
...base,
|
|
131985
|
+
id: `annotation-polyline-${uid2}-${i2}`,
|
|
131986
|
+
extensions: dashExt,
|
|
131987
|
+
getDashArray: getDash,
|
|
131988
|
+
data: [{ path: pathPoints }],
|
|
131989
|
+
getPath: (d) => d.path,
|
|
131990
|
+
getColor: strokeColor,
|
|
131991
|
+
getWidth: strokeWidth,
|
|
131992
|
+
widthUnits: "pixels",
|
|
131993
|
+
jointRounded: true,
|
|
131994
|
+
capRounded: true
|
|
131995
|
+
}));
|
|
131996
|
+
if (markerStart === "Arrow" && tipsOpacity > 0) {
|
|
131997
|
+
const [x02, y02] = points[0];
|
|
131998
|
+
const [x12, y12] = points[1];
|
|
131999
|
+
const head = computeArrowhead(x02, y02, x02 - x12, y02 - y12, arrowDataSize);
|
|
132000
|
+
if (head) {
|
|
132001
|
+
layers.push(new PolygonLayer({
|
|
132002
|
+
...tipsBase,
|
|
132003
|
+
id: `annotation-polyline-start-arrow-${uid2}-${i2}`,
|
|
132004
|
+
data: [{ polygon: head }],
|
|
132005
|
+
getPolygon: (d) => d.polygon,
|
|
132006
|
+
filled: true,
|
|
132007
|
+
stroked: false,
|
|
132008
|
+
getFillColor: strokeColor
|
|
132009
|
+
}));
|
|
132010
|
+
}
|
|
132011
|
+
}
|
|
132012
|
+
if (markerEnd === "Arrow" && tipsOpacity > 0) {
|
|
132013
|
+
const last = points[points.length - 1];
|
|
132014
|
+
const prev2 = points[points.length - 2];
|
|
132015
|
+
const dxArrow = last[0] - prev2[0];
|
|
132016
|
+
const dyArrow = last[1] - prev2[1];
|
|
132017
|
+
const head = computeArrowhead(last[0], last[1], dxArrow, dyArrow, arrowDataSize);
|
|
132018
|
+
if (head) {
|
|
132019
|
+
layers.push(new PolygonLayer({
|
|
132020
|
+
...tipsBase,
|
|
132021
|
+
id: `annotation-polyline-end-arrow-${uid2}-${i2}`,
|
|
132022
|
+
data: [{ polygon: head }],
|
|
132023
|
+
getPolygon: (d) => d.polygon,
|
|
132024
|
+
filled: true,
|
|
132025
|
+
stroked: false,
|
|
132026
|
+
getFillColor: strokeColor
|
|
132027
|
+
}));
|
|
132028
|
+
}
|
|
132029
|
+
}
|
|
132030
|
+
if (markerStart === "Tick" && tipsOpacity > 0) {
|
|
132031
|
+
const [x02, y02] = points[0];
|
|
132032
|
+
const [x12, y12] = points[1];
|
|
132033
|
+
const tick = computeTickCap(x02, y02, x02 - x12, y02 - y12, arrowDataSize);
|
|
132034
|
+
if (tick) {
|
|
132035
|
+
layers.push(new PathLayer({
|
|
132036
|
+
...tipsBase,
|
|
132037
|
+
id: `annotation-polyline-start-tick-${uid2}-${i2}`,
|
|
132038
|
+
data: [{ path: tick }],
|
|
132039
|
+
getPath: (d) => d.path,
|
|
132040
|
+
getColor: strokeColor,
|
|
132041
|
+
getWidth: strokeWidth,
|
|
132042
|
+
widthUnits: "pixels",
|
|
132043
|
+
capRounded: true
|
|
132044
|
+
}));
|
|
132045
|
+
}
|
|
132046
|
+
}
|
|
132047
|
+
if (markerEnd === "Tick" && tipsOpacity > 0) {
|
|
132048
|
+
const last = points[points.length - 1];
|
|
132049
|
+
const prev2 = points[points.length - 2];
|
|
132050
|
+
const dxTick = last[0] - prev2[0];
|
|
132051
|
+
const dyTick = last[1] - prev2[1];
|
|
132052
|
+
const tick = computeTickCap(last[0], last[1], dxTick, dyTick, arrowDataSize);
|
|
132053
|
+
if (tick) {
|
|
132054
|
+
layers.push(new PathLayer({
|
|
132055
|
+
...tipsBase,
|
|
132056
|
+
id: `annotation-polyline-end-tick-${uid2}-${i2}`,
|
|
132057
|
+
data: [{ path: tick }],
|
|
132058
|
+
getPath: (d) => d.path,
|
|
132059
|
+
getColor: strokeColor,
|
|
132060
|
+
getWidth: strokeWidth,
|
|
132061
|
+
widthUnits: "pixels",
|
|
132062
|
+
capRounded: true
|
|
132063
|
+
}));
|
|
132064
|
+
}
|
|
132065
|
+
}
|
|
132066
|
+
if (shape2.text) {
|
|
132067
|
+
const pos = shape2.textPosition ?? "start";
|
|
132068
|
+
const bufferPx = shape2.textBufferPx ?? 8;
|
|
132069
|
+
let textPt;
|
|
132070
|
+
let dirX;
|
|
132071
|
+
let dirY;
|
|
132072
|
+
if (pos === "end") {
|
|
132073
|
+
const last = points[points.length - 1];
|
|
132074
|
+
const prev2 = points[points.length - 2];
|
|
132075
|
+
textPt = last;
|
|
132076
|
+
dirX = last[0] - prev2[0];
|
|
132077
|
+
dirY = last[1] - prev2[1];
|
|
132078
|
+
} else if (pos === "middle") {
|
|
132079
|
+
const mx = points.reduce((s2, p) => s2 + p[0], 0) / points.length;
|
|
132080
|
+
const my = points.reduce((s2, p) => s2 + p[1], 0) / points.length;
|
|
132081
|
+
textPt = [mx, my];
|
|
132082
|
+
dirX = 0;
|
|
132083
|
+
dirY = 0;
|
|
132084
|
+
} else {
|
|
132085
|
+
[textPt] = points;
|
|
132086
|
+
dirX = points[0][0] - points[1][0];
|
|
132087
|
+
dirY = points[0][1] - points[1][1];
|
|
132088
|
+
}
|
|
132089
|
+
const [textX, textY] = textPt;
|
|
132090
|
+
const lenT = Math.sqrt(dirX * dirX + dirY * dirY);
|
|
132091
|
+
let polylinePixelOffset = [0, 0];
|
|
132092
|
+
let polylineTextAnchor = "middle";
|
|
132093
|
+
let polylineAlignmentBaseline = pos === "middle" ? "center" : "bottom";
|
|
132094
|
+
if (lenT > 0) {
|
|
132095
|
+
const uxT = dirX / lenT;
|
|
132096
|
+
const uyT = dirY / lenT;
|
|
132097
|
+
const offX = uxT * bufferPx;
|
|
132098
|
+
const offY = uyT * bufferPx;
|
|
132099
|
+
polylinePixelOffset = [offX, offY];
|
|
132100
|
+
if (Math.abs(offX) >= Math.abs(offY)) {
|
|
132101
|
+
polylineTextAnchor = offX > 0 ? "start" : "end";
|
|
132102
|
+
}
|
|
132103
|
+
if (Math.abs(offY) >= Math.abs(offX)) {
|
|
132104
|
+
polylineAlignmentBaseline = offY > 0 ? "top" : "bottom";
|
|
132105
|
+
}
|
|
132106
|
+
}
|
|
132107
|
+
if (labelOpacity <= 0)
|
|
132108
|
+
return;
|
|
132109
|
+
layers.push(new TextLayer({
|
|
132110
|
+
...labelBase,
|
|
132111
|
+
...labelProps,
|
|
132112
|
+
id: `annotation-polyline-text-${uid2}-${i2}`,
|
|
132113
|
+
data: [{ position: [textX, textY], text: shape2.text }],
|
|
132114
|
+
getPosition: (d) => d.position,
|
|
132115
|
+
getText: (d) => d.text,
|
|
132116
|
+
getColor: strokeColor,
|
|
132117
|
+
getSize: LABEL_FONT_SIZE,
|
|
132118
|
+
sizeUnits: "pixels",
|
|
132119
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
132120
|
+
fontWeight: LABEL_FONT_WEIGHT,
|
|
132121
|
+
getPixelOffset: polylinePixelOffset,
|
|
132122
|
+
getTextAnchor: polylineTextAnchor,
|
|
132123
|
+
getAlignmentBaseline: polylineAlignmentBaseline
|
|
132124
|
+
}));
|
|
132125
|
+
}
|
|
132126
|
+
}
|
|
132127
|
+
});
|
|
132128
|
+
if (dotShapes.length > 0) {
|
|
132129
|
+
layers.push(new ScatterplotLayer({
|
|
132130
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
132131
|
+
id: "annotation-dots",
|
|
132132
|
+
data: dotShapes.map(({ shape: s2, alpha: alpha2 }) => ({
|
|
132133
|
+
position: getShapeCentroid(s2),
|
|
132134
|
+
color: [...s2.strokeColor ?? [255, 255, 255], alpha2]
|
|
132135
|
+
})),
|
|
132136
|
+
getPosition: (d) => d.position,
|
|
132137
|
+
getFillColor: (d) => d.color,
|
|
132138
|
+
getRadius: 4,
|
|
132139
|
+
radiusUnits: "pixels",
|
|
132140
|
+
filled: true,
|
|
132141
|
+
stroked: false
|
|
132142
|
+
}));
|
|
132143
|
+
}
|
|
132144
|
+
if (clusterDotShapes.length > 0) {
|
|
132145
|
+
const clusters = computeClusters(clusterDotShapes, zoom);
|
|
132146
|
+
layers.push(new ScatterplotLayer({
|
|
132147
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
132148
|
+
id: "annotation-clusters",
|
|
132149
|
+
data: clusters,
|
|
132150
|
+
getPosition: (d) => d.position,
|
|
132151
|
+
getFillColor: (d) => [...d.color, 180],
|
|
132152
|
+
getRadius: (d) => Math.max(6, 4 + Math.sqrt(d.count) * 2),
|
|
132153
|
+
radiusUnits: "pixels",
|
|
132154
|
+
filled: true,
|
|
132155
|
+
stroked: true,
|
|
132156
|
+
getLineColor: (d) => [...d.color, 220],
|
|
132157
|
+
lineWidthMinPixels: 1.5
|
|
132158
|
+
}));
|
|
132159
|
+
const multiClusters = clusters.filter((c2) => c2.count > 1);
|
|
132160
|
+
if (multiClusters.length > 0) {
|
|
132161
|
+
layers.push(new TextLayer({
|
|
132162
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
132163
|
+
id: "annotation-cluster-counts",
|
|
132164
|
+
data: multiClusters,
|
|
132165
|
+
getPosition: (d) => d.position,
|
|
132166
|
+
getText: (d) => String(d.count),
|
|
132167
|
+
getColor: [255, 255, 255],
|
|
132168
|
+
getSize: 10,
|
|
132169
|
+
sizeUnits: "pixels",
|
|
132170
|
+
fontWeight: "bold",
|
|
132171
|
+
getTextAnchor: "middle",
|
|
132172
|
+
getAlignmentBaseline: "center"
|
|
132173
|
+
}));
|
|
132174
|
+
}
|
|
132175
|
+
}
|
|
132176
|
+
const measureLayers = [];
|
|
132177
|
+
shapes.forEach((shape2) => {
|
|
132178
|
+
if (!shape2.showMeasure)
|
|
132179
|
+
return;
|
|
132180
|
+
const mIsSelected = shape2.uid === selectedShapeUid;
|
|
132181
|
+
const label = getMeasurementLabel(shape2, physicalPixelSize, viewType);
|
|
132182
|
+
if (!label)
|
|
132183
|
+
return;
|
|
132184
|
+
const color2 = shape2.strokeColor ?? [255, 255, 255];
|
|
132185
|
+
let mShapeOpacity = 1;
|
|
132186
|
+
let mLabelFactor = 0;
|
|
132187
|
+
if (mIsSelected || !semanticZoom || authoredZoom === null) {
|
|
132188
|
+
mLabelFactor = 1;
|
|
132189
|
+
} else {
|
|
132190
|
+
const mZoomRatio = 2 ** (zoom - authoredZoom);
|
|
132191
|
+
if (mZoomRatio < RATIO_DOT)
|
|
132192
|
+
return;
|
|
132193
|
+
if (mZoomRatio < RATIO_GEO_FADE) {
|
|
132194
|
+
mShapeOpacity = (mZoomRatio - RATIO_DOT) / (RATIO_GEO_FADE - RATIO_DOT);
|
|
132195
|
+
}
|
|
132196
|
+
if (mZoomRatio >= RATIO_LABEL_FULL) {
|
|
132197
|
+
mLabelFactor = 1;
|
|
132198
|
+
} else if (mZoomRatio >= RATIO_LABEL) {
|
|
132199
|
+
mLabelFactor = (mZoomRatio - RATIO_LABEL) / (RATIO_LABEL_FULL - RATIO_LABEL);
|
|
132200
|
+
}
|
|
132201
|
+
}
|
|
132202
|
+
const measureOpacity = mShapeOpacity * mLabelFactor;
|
|
132203
|
+
if (measureOpacity <= 0)
|
|
132204
|
+
return;
|
|
132205
|
+
const base = {
|
|
132206
|
+
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
|
|
132207
|
+
opacity: measureOpacity,
|
|
132208
|
+
getText: (d) => d.text,
|
|
132209
|
+
getPosition: (d) => d.position,
|
|
132210
|
+
getColor: color2,
|
|
132211
|
+
getSize: 13,
|
|
132212
|
+
sizeUnits: "pixels",
|
|
132213
|
+
fontFamily: LABEL_FONT_FAMILY$1,
|
|
132214
|
+
fontWeight: "bold",
|
|
132215
|
+
// 'auto' builds the font atlas from the actual rendered characters (e.g. µ, ²)
|
|
132216
|
+
// instead of deck.gl's default ASCII-only atlas.
|
|
132217
|
+
characterSet: "auto",
|
|
132218
|
+
...shape2.measureBackground ? {
|
|
132219
|
+
background: true,
|
|
132220
|
+
getBackgroundColor: textBgColor(color2),
|
|
132221
|
+
backgroundPadding: [3, 1, 3, 2]
|
|
132222
|
+
} : {}
|
|
132223
|
+
};
|
|
132224
|
+
if (shape2.type === "line") {
|
|
132225
|
+
const mx = ((shape2.x1 ?? 0) + (shape2.x2 ?? 0)) / 2;
|
|
132226
|
+
const my = ((shape2.y1 ?? 0) + (shape2.y2 ?? 0)) / 2;
|
|
132227
|
+
const dx = (shape2.x2 ?? 0) - (shape2.x1 ?? 0);
|
|
132228
|
+
const dy = (shape2.y2 ?? 0) - (shape2.y1 ?? 0);
|
|
132229
|
+
const len2 = Math.sqrt(dx * dx + dy * dy);
|
|
132230
|
+
if (len2 === 0)
|
|
132231
|
+
return;
|
|
132232
|
+
const perp = pickBelowPerp(dx / len2, dy / len2);
|
|
132233
|
+
const angle2 = readableAngle(Math.atan2(dy, dx) * 180 / Math.PI);
|
|
132234
|
+
measureLayers.push(new TextLayer({
|
|
132235
|
+
...base,
|
|
132236
|
+
id: `annotation-measure-${shape2.uid}`,
|
|
132237
|
+
data: [{ position: [mx, my], text: label }],
|
|
132238
|
+
getAngle: -angle2,
|
|
132239
|
+
getTextAnchor: "middle",
|
|
132240
|
+
getAlignmentBaseline: "center",
|
|
132241
|
+
getPixelOffset: [perp[0] * 16, perp[1] * 16]
|
|
132242
|
+
}));
|
|
132243
|
+
} else if (shape2.type === "polyline" && shape2.points?.length >= 2) {
|
|
132244
|
+
const pts = shape2.points;
|
|
132245
|
+
const mi = Math.floor((pts.length - 1) / 2);
|
|
132246
|
+
const [ax, ay] = pts[mi];
|
|
132247
|
+
const [bx, by] = pts[mi + 1];
|
|
132248
|
+
const dx = bx - ax;
|
|
132249
|
+
const dy = by - ay;
|
|
132250
|
+
const len2 = Math.sqrt(dx * dx + dy * dy);
|
|
132251
|
+
if (len2 === 0)
|
|
132252
|
+
return;
|
|
132253
|
+
const perp = pickBelowPerp(dx / len2, dy / len2);
|
|
132254
|
+
const angle2 = readableAngle(Math.atan2(dy, dx) * 180 / Math.PI);
|
|
132255
|
+
measureLayers.push(new TextLayer({
|
|
132256
|
+
...base,
|
|
132257
|
+
id: `annotation-measure-${shape2.uid}`,
|
|
132258
|
+
data: [{ position: [(ax + bx) / 2, (ay + by) / 2], text: label }],
|
|
132259
|
+
getAngle: -angle2,
|
|
132260
|
+
getTextAnchor: "middle",
|
|
132261
|
+
getAlignmentBaseline: "center",
|
|
132262
|
+
getPixelOffset: [perp[0] * 16, perp[1] * 16]
|
|
132263
|
+
}));
|
|
132264
|
+
} else if (shape2.type === "rectangle") {
|
|
132265
|
+
const x02 = shape2.x ?? 0;
|
|
132266
|
+
const y02 = shape2.y ?? 0;
|
|
132267
|
+
const w2 = shape2.width ?? 0;
|
|
132268
|
+
const h = shape2.height ?? 0;
|
|
132269
|
+
const rx = x02 + (w2 >= 0 ? w2 : 0);
|
|
132270
|
+
const ry = y02 + (h >= 0 ? h : 0);
|
|
132271
|
+
measureLayers.push(new TextLayer({
|
|
132272
|
+
...base,
|
|
132273
|
+
id: `annotation-measure-${shape2.uid}`,
|
|
132274
|
+
data: [{ position: [rx, ry], text: label }],
|
|
132275
|
+
getTextAnchor: "end",
|
|
132276
|
+
getAlignmentBaseline: "bottom",
|
|
132277
|
+
getPixelOffset: [-6, -6]
|
|
132278
|
+
}));
|
|
132279
|
+
} else if (shape2.type === "ellipse") {
|
|
132280
|
+
const cx = shape2.x1 ?? 0;
|
|
132281
|
+
const cy = shape2.y1 ?? 0;
|
|
132282
|
+
const ry = Math.abs(shape2.radiusY ?? 0);
|
|
132283
|
+
measureLayers.push(new TextLayer({
|
|
132284
|
+
...base,
|
|
132285
|
+
id: `annotation-measure-${shape2.uid}`,
|
|
132286
|
+
data: [{ position: [cx, cy + ry], text: label }],
|
|
132287
|
+
getTextAnchor: "middle",
|
|
132288
|
+
getAlignmentBaseline: "top",
|
|
132289
|
+
getPixelOffset: [0, 8]
|
|
132290
|
+
}));
|
|
132291
|
+
} else if (shape2.type === "polygon" && shape2.points?.length >= 3) {
|
|
132292
|
+
const xs = shape2.points.map((p) => p[0]);
|
|
132293
|
+
const ys = shape2.points.map((p) => p[1]);
|
|
132294
|
+
const cx = (Math.min(...xs) + Math.max(...xs)) / 2;
|
|
132295
|
+
const maxY = Math.max(...ys);
|
|
132296
|
+
measureLayers.push(new TextLayer({
|
|
132297
|
+
...base,
|
|
132298
|
+
id: `annotation-measure-${shape2.uid}`,
|
|
132299
|
+
data: [{ position: [cx, maxY], text: label }],
|
|
132300
|
+
getTextAnchor: "middle",
|
|
132301
|
+
getAlignmentBaseline: "top",
|
|
132302
|
+
getPixelOffset: [0, 8]
|
|
132303
|
+
}));
|
|
132304
|
+
}
|
|
132305
|
+
});
|
|
132306
|
+
return [...selectionLayers, ...layers, ...measureLayers];
|
|
132307
|
+
}
|
|
132308
|
+
const defaultProps$1 = {
|
|
132309
|
+
// Array of annotation shape objects (see annotationShapeObj in @vitessce/schemas).
|
|
132310
|
+
data: { type: "object", value: [], compare: true },
|
|
132311
|
+
// UID of the shape to highlight with a selection halo.
|
|
132312
|
+
selectedShapeUid: { type: "string", value: null },
|
|
132313
|
+
// { x, y, unit } used to format measurement labels in physical units.
|
|
132314
|
+
physicalPixelSize: { type: "object", value: null, compare: true },
|
|
132315
|
+
// The zoom level at which the shapes were authored (reference for semantic zoom).
|
|
132316
|
+
authoredZoom: { type: "number", value: null },
|
|
132317
|
+
// Whether to apply semantic zoom (level-of-detail) based on authoredZoom.
|
|
132318
|
+
semanticZoom: { type: "boolean", value: true },
|
|
132319
|
+
// The view type in which the layer is rendered (affects measurement label formatting).
|
|
132320
|
+
viewType: { type: "string", value: ViewType$1.SPATIAL },
|
|
132321
|
+
// In-progress shape being drawn, as { type, vertices }.
|
|
132322
|
+
inProgressShape: { type: "object", value: null, compare: true },
|
|
132323
|
+
// Current mouse position (in data coordinates) while drawing.
|
|
132324
|
+
hoverCoord: { type: "array", value: null, compare: true },
|
|
132325
|
+
// Stroke color [r, g, b] of the in-progress shape preview.
|
|
132326
|
+
previewStrokeColor: { type: "color", value: [255, 255, 0] }
|
|
132327
|
+
};
|
|
132328
|
+
class AnnotationLayer extends CompositeLayer {
|
|
132329
|
+
// The semantic zoom and arrowhead sizes depend on the current zoom level,
|
|
132330
|
+
// so the sublayers must also be re-rendered when the viewport changes.
|
|
132331
|
+
// eslint-disable-next-line class-methods-use-this
|
|
132332
|
+
shouldUpdateState({ changeFlags }) {
|
|
132333
|
+
return changeFlags.propsOrDataChanged || changeFlags.viewportChanged;
|
|
132334
|
+
}
|
|
132335
|
+
/**
|
|
132336
|
+
* Prefix the sublayer ID with this layer's ID (so that multiple
|
|
132337
|
+
* AnnotationLayers can co-exist), and combine this layer's
|
|
132338
|
+
* opacity with the per-shape opacity of the sublayer.
|
|
132339
|
+
* Note: we avoid getSubLayerProps here, since it would
|
|
132340
|
+
* overwrite the sublayer extensions (e.g., PathStyleExtension)
|
|
132341
|
+
* and opacity values.
|
|
132342
|
+
* @param {object} layer A DeckGL layer instance.
|
|
132343
|
+
* @returns {object} The cloned layer instance.
|
|
132344
|
+
*/
|
|
132345
|
+
wrapSubLayer(layer) {
|
|
132346
|
+
const { id, opacity, pickable, visible } = this.props;
|
|
132347
|
+
return layer.clone({
|
|
132348
|
+
id: `${id}-${layer.id}`,
|
|
132349
|
+
opacity: layer.props.opacity * opacity,
|
|
132350
|
+
pickable,
|
|
132351
|
+
visible
|
|
132352
|
+
});
|
|
132353
|
+
}
|
|
132354
|
+
renderLayers() {
|
|
132355
|
+
const { data, selectedShapeUid, physicalPixelSize, authoredZoom, semanticZoom, viewType, inProgressShape, hoverCoord, previewStrokeColor } = this.props;
|
|
132356
|
+
const zoom = this.context.viewport?.zoom ?? 0;
|
|
132357
|
+
const visibleShapes = (data ?? []).filter((shape2) => shape2.visible !== false);
|
|
132358
|
+
const annotationLayers = createAnnotationLayers(visibleShapes, zoom, selectedShapeUid, physicalPixelSize, authoredZoom, semanticZoom, viewType);
|
|
132359
|
+
const previewLayer = createPreviewLayer(inProgressShape, hoverCoord, previewStrokeColor.slice(0, 3));
|
|
132360
|
+
return [
|
|
132361
|
+
...annotationLayers,
|
|
132362
|
+
...previewLayer ? [previewLayer] : []
|
|
132363
|
+
].map((layer) => this.wrapSubLayer(layer));
|
|
132364
|
+
}
|
|
132365
|
+
}
|
|
132366
|
+
AnnotationLayer.layerName = "AnnotationLayer";
|
|
132367
|
+
AnnotationLayer.defaultProps = defaultProps$1;
|
|
131005
132368
|
function r$1(e3) {
|
|
131006
132369
|
var t, f2, n2 = "";
|
|
131007
132370
|
if ("string" == typeof e3 || "number" == typeof e3) n2 += e3;
|
|
@@ -145642,11 +147005,13 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
145642
147005
|
this.cellSetsLabelPrevZoom = null;
|
|
145643
147006
|
this.cellSetsLayers = [];
|
|
145644
147007
|
this.contourLayers = [];
|
|
147008
|
+
this.annotationLayer = null;
|
|
145645
147009
|
this.onUpdateCellsData();
|
|
145646
147010
|
this.onUpdateCellsLayer();
|
|
145647
147011
|
this.onUpdateCellSetsLayers();
|
|
145648
147012
|
this.onUpdateStratifiedData();
|
|
145649
147013
|
this.onUpdateContourLayers();
|
|
147014
|
+
this.onUpdateAnnotationLayer();
|
|
145650
147015
|
}
|
|
145651
147016
|
// Want to support multiple types of contour layers
|
|
145652
147017
|
// - One layer for all data points (no filtering)
|
|
@@ -145710,6 +147075,21 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
145710
147075
|
}));
|
|
145711
147076
|
return layers;
|
|
145712
147077
|
}
|
|
147078
|
+
createAnnotationLayer() {
|
|
147079
|
+
const { annotationShapes, annotationOverlayVisible, annotationSemanticZoom, annotationShapeSelection } = this.props;
|
|
147080
|
+
return new AnnotationLayer({
|
|
147081
|
+
data: annotationShapes,
|
|
147082
|
+
visible: annotationOverlayVisible,
|
|
147083
|
+
semanticZoom: annotationSemanticZoom,
|
|
147084
|
+
selectedShapeUid: annotationShapeSelection,
|
|
147085
|
+
viewType: ViewType$1.SCATTERPLOT
|
|
147086
|
+
// TODO: is this needed?
|
|
147087
|
+
// TODO: these are view-level properties, rather than layer-level.
|
|
147088
|
+
// annotationTransitionDuration,
|
|
147089
|
+
// annotationEditable,
|
|
147090
|
+
// Other coordination types related to editing...
|
|
147091
|
+
});
|
|
147092
|
+
}
|
|
145713
147093
|
createCellsLayer() {
|
|
145714
147094
|
const {
|
|
145715
147095
|
obsEmbeddingIndex: obsIndex,
|
|
@@ -145843,12 +147223,13 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
145843
147223
|
], flipYTooltip, this.props.onSelectionBusy);
|
|
145844
147224
|
}
|
|
145845
147225
|
getLayers() {
|
|
145846
|
-
const { cellsLayer, cellSetsLayers, contourLayers } = this;
|
|
147226
|
+
const { cellsLayer, cellSetsLayers, contourLayers, annotationLayer } = this;
|
|
145847
147227
|
return [
|
|
145848
147228
|
cellsLayer,
|
|
145849
147229
|
...contourLayers,
|
|
145850
147230
|
...cellSetsLayers,
|
|
145851
|
-
this.createSelectionLayer()
|
|
147231
|
+
this.createSelectionLayer(),
|
|
147232
|
+
annotationLayer
|
|
145852
147233
|
];
|
|
145853
147234
|
}
|
|
145854
147235
|
/**
|
|
@@ -145885,6 +147266,14 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
145885
147266
|
this.cellsLayer = null;
|
|
145886
147267
|
}
|
|
145887
147268
|
}
|
|
147269
|
+
onUpdateAnnotationLayer() {
|
|
147270
|
+
const { annotationShapes } = this.props;
|
|
147271
|
+
if (annotationShapes) {
|
|
147272
|
+
this.annotationLayer = this.createAnnotationLayer();
|
|
147273
|
+
} else {
|
|
147274
|
+
this.annotationLayer = null;
|
|
147275
|
+
}
|
|
147276
|
+
}
|
|
145888
147277
|
onUpdateStratifiedData() {
|
|
145889
147278
|
const { stratifiedData } = this.props;
|
|
145890
147279
|
if (stratifiedData) {
|
|
@@ -146000,6 +147389,16 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
146000
147389
|
this.onUpdateCellSetsLayers(true);
|
|
146001
147390
|
forceUpdate = true;
|
|
146002
147391
|
}
|
|
147392
|
+
if ([
|
|
147393
|
+
"annotationShapes",
|
|
147394
|
+
"annotationOverlayVisible",
|
|
147395
|
+
"annotationSemanticZoom",
|
|
147396
|
+
"annotationTransitionDuration",
|
|
147397
|
+
"annotationEditable"
|
|
147398
|
+
].some(shallowDiff)) {
|
|
147399
|
+
this.onUpdateAnnotationLayer();
|
|
147400
|
+
forceUpdate = true;
|
|
147401
|
+
}
|
|
146003
147402
|
if (forceUpdate) {
|
|
146004
147403
|
this.forceUpdate();
|
|
146005
147404
|
}
|
|
@@ -148801,7 +150200,6 @@ const DEFAULT_FEATURE_AGGREGATION_STRATEGY = "first";
|
|
|
148801
150200
|
function EmbeddingScatterplotSubscriber(props) {
|
|
148802
150201
|
const {
|
|
148803
150202
|
uuid,
|
|
148804
|
-
coordinationScopes: coordinationScopesRaw,
|
|
148805
150203
|
closeButtonVisible,
|
|
148806
150204
|
downloadButtonVisible,
|
|
148807
150205
|
removeGridComponent,
|
|
@@ -148817,9 +150215,15 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
148817
150215
|
circleScaleFactor = 0.8
|
|
148818
150216
|
} = props;
|
|
148819
150217
|
const loaders = useLoaders();
|
|
148820
|
-
const
|
|
150218
|
+
const [
|
|
150219
|
+
// eslint-disable-next-line no-unused-vars
|
|
150220
|
+
coordinationScopes,
|
|
150221
|
+
_coordinationScopesBy,
|
|
150222
|
+
coordinationValues
|
|
150223
|
+
] = useViewMapping(uuid);
|
|
148821
150224
|
const setComponentHover = useSetComponentHover();
|
|
148822
150225
|
const setComponentViewInfo = useSetComponentViewInfo(uuid);
|
|
150226
|
+
useAnnotationFrameCoordination(uuid, coordinationScopes, coordinationValues);
|
|
148823
150227
|
const [{
|
|
148824
150228
|
dataset,
|
|
148825
150229
|
obsType,
|
|
@@ -148856,7 +150260,13 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
148856
150260
|
embeddingContourPercentiles: contourPercentiles,
|
|
148857
150261
|
contourColorEncoding,
|
|
148858
150262
|
contourColor,
|
|
148859
|
-
featureAggregationStrategy
|
|
150263
|
+
featureAggregationStrategy,
|
|
150264
|
+
annotationStory,
|
|
150265
|
+
annotationShapes,
|
|
150266
|
+
annotationOverlayVisible,
|
|
150267
|
+
annotationSemanticZoom,
|
|
150268
|
+
annotationTransitionDuration,
|
|
150269
|
+
annotationEditable
|
|
148860
150270
|
}, {
|
|
148861
150271
|
setEmbeddingZoom: setZoom,
|
|
148862
150272
|
setEmbeddingTargetX: setTargetX,
|
|
@@ -148883,21 +150293,41 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
148883
150293
|
setEmbeddingContoursFilled,
|
|
148884
150294
|
setEmbeddingContourPercentiles: setContourPercentiles,
|
|
148885
150295
|
setContourColorEncoding,
|
|
148886
|
-
setFeatureAggregationStrategy
|
|
148887
|
-
|
|
150296
|
+
setFeatureAggregationStrategy,
|
|
150297
|
+
setAnnotationStory
|
|
150298
|
+
}] = useCoordination(
|
|
150299
|
+
COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT],
|
|
150300
|
+
coordinationScopes,
|
|
150301
|
+
coordinationValues,
|
|
150302
|
+
uuid
|
|
150303
|
+
);
|
|
148888
150304
|
const {
|
|
148889
150305
|
embeddingZoom: initialZoom,
|
|
148890
150306
|
embeddingTargetX: initialTargetX,
|
|
148891
150307
|
embeddingTargetY: initialTargetY
|
|
148892
150308
|
} = useInitialCoordination(
|
|
148893
150309
|
COMPONENT_COORDINATION_TYPES[ViewType$1.SCATTERPLOT],
|
|
148894
|
-
coordinationScopes
|
|
150310
|
+
coordinationScopes,
|
|
150311
|
+
coordinationValues
|
|
148895
150312
|
);
|
|
148896
150313
|
const observationsLabel = observationsLabelOverride || obsType;
|
|
148897
150314
|
const sampleSetSelection = sampleSetSelectionFromProps || sampleSetSelectionFromCoordination;
|
|
148898
150315
|
const featureAggregationStrategyToUse = featureAggregationStrategy ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY;
|
|
148899
150316
|
const [width2, height2, deckRef] = useDeckCanvasSize();
|
|
148900
150317
|
const title = titleOverride || `Scatterplot (${mapping})`;
|
|
150318
|
+
const [
|
|
150319
|
+
,
|
|
150320
|
+
annotationStoryStatus,
|
|
150321
|
+
annotationStoryUrls,
|
|
150322
|
+
annotationStoryError
|
|
150323
|
+
] = useAnnotationStoryData(
|
|
150324
|
+
loaders,
|
|
150325
|
+
dataset,
|
|
150326
|
+
false,
|
|
150327
|
+
{ setAnnotationStory },
|
|
150328
|
+
{ annotationStory },
|
|
150329
|
+
{}
|
|
150330
|
+
);
|
|
148901
150331
|
const [
|
|
148902
150332
|
// eslint-disable-next-line no-unused-vars
|
|
148903
150333
|
obsLabelsTypes,
|
|
@@ -149004,11 +150434,13 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
149004
150434
|
matrixIndicesError,
|
|
149005
150435
|
featureLabelsError,
|
|
149006
150436
|
sampleSetsError,
|
|
149007
|
-
sampleEdgesError
|
|
150437
|
+
sampleEdgesError,
|
|
150438
|
+
annotationStoryError
|
|
149008
150439
|
];
|
|
149009
150440
|
const isReady = useReady([
|
|
149010
150441
|
obsEmbeddingStatus,
|
|
149011
150442
|
obsSetsStatus,
|
|
150443
|
+
annotationStoryStatus,
|
|
149012
150444
|
featureSelectionStatus,
|
|
149013
150445
|
featureLabelsStatus,
|
|
149014
150446
|
expandedFeatureLabelsStatus,
|
|
@@ -149022,7 +150454,8 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
149022
150454
|
matrixIndicesUrls,
|
|
149023
150455
|
featureLabelsUrls,
|
|
149024
150456
|
sampleSetsUrl,
|
|
149025
|
-
sampleEdgesUrl
|
|
150457
|
+
sampleEdgesUrl,
|
|
150458
|
+
annotationStoryUrls
|
|
149026
150459
|
]);
|
|
149027
150460
|
const [dynamicCellRadius, setDynamicCellRadius] = useState(cellRadiusFixed);
|
|
149028
150461
|
const [isSelectionPending, setIsSelectionPending] = useState(false);
|
|
@@ -149398,7 +150831,12 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
149398
150831
|
embeddingPointsVisible,
|
|
149399
150832
|
embeddingContoursVisible,
|
|
149400
150833
|
circleInfo,
|
|
149401
|
-
featureSelection: geneSelection
|
|
150834
|
+
featureSelection: geneSelection,
|
|
150835
|
+
annotationShapes,
|
|
150836
|
+
annotationOverlayVisible,
|
|
150837
|
+
annotationSemanticZoom,
|
|
150838
|
+
annotationTransitionDuration,
|
|
150839
|
+
annotationEditable
|
|
149402
150840
|
}
|
|
149403
150841
|
),
|
|
149404
150842
|
tooltipsVisible && width2 && height2 ? /* @__PURE__ */ React__default.createElement(
|