@vitessce/scatterplot 3.5.8 → 3.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{deflate-485af92e.js → deflate-c5f0776b.js} +1 -1
- package/dist/{index-6f1ecd35.js → index-d522aebb.js} +12668 -8189
- package/dist/index.js +1 -1
- package/dist/{jpeg-6a951bc6.js → jpeg-59437681.js} +1 -1
- package/dist/{lerc-36211a81.js → lerc-124acb2f.js} +1 -1
- package/dist/{lzw-cdee9c4e.js → lzw-723527e2.js} +1 -1
- package/dist/{packbits-7bc2030b.js → packbits-74a934fa.js} +1 -1
- package/dist/{raw-8e26cce5.js → raw-8fb6d135.js} +1 -1
- package/dist/{webimage-d457d41a.js → webimage-cdc82395.js} +1 -1
- package/dist-tsc/Scatterplot.d.ts.map +1 -1
- package/dist-tsc/Scatterplot.js +54 -28
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.d.ts.map +1 -1
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.js +14 -5
- package/package.json +7 -7
- package/src/Scatterplot.js +66 -34
- package/src/shared-spatial-scatterplot/dynamic-opacity.js +11 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as inflate_1 } from "./pako.esm-68f84e2a.js";
|
|
2
|
-
import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-
|
|
2
|
+
import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-d522aebb.js";
|
|
3
3
|
import "react";
|
|
4
4
|
import "@vitessce/vit-s";
|
|
5
5
|
import "react-dom";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Scatterplot.d.ts","sourceRoot":"","sources":["../src/Scatterplot.js"],"names":[],"mappings":";AA+
|
|
1
|
+
{"version":3,"file":"Scatterplot.d.ts","sourceRoot":"","sources":["../src/Scatterplot.js"],"names":[],"mappings":";AA+jBA;;;;;;GAMG;AACH,sCAKG"}
|
package/dist-tsc/Scatterplot.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import React, { forwardRef } from 'react';
|
|
4
4
|
import { forceSimulation } from 'd3-force';
|
|
5
5
|
import { isEqual } from 'lodash-es';
|
|
6
|
-
import { deck, getSelectionLayer, ScaledExpressionExtension, SelectionExtension, } from '@vitessce/gl';
|
|
6
|
+
import { deck, getSelectionLayer, ScaledExpressionExtension, SelectionExtension, ContourLayerWithText, } from '@vitessce/gl';
|
|
7
7
|
import { getDefaultColor } from '@vitessce/utils';
|
|
8
8
|
import { AbstractSpatialOrScatterplot, createQuadTree, forceCollideRects, getOnHoverCallback, } from './shared-spatial-scatterplot/index.js';
|
|
9
9
|
const CELLS_LAYER_ID = 'scatterplot';
|
|
@@ -108,7 +108,11 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
108
108
|
// - Array of per-selected-sampleSet layers (filter to sampleSet members)
|
|
109
109
|
// - Array of per-sampleSet, per-obsSet layers (filter to sampleSet and obsSet members)
|
|
110
110
|
createContourLayers() {
|
|
111
|
-
const { theme, obsSetColor, sampleSetColor, contourColorEncoding, contourThresholds, contoursFilled, contourColor: contourColorProp, } = this.props;
|
|
111
|
+
const { theme, obsSetColor, sampleSetColor, contourColorEncoding, contourThresholds, contoursFilled, contourColor: contourColorProp, circleInfo, cellSetLabelsVisible, cellSetLabelSize, featureSelection, } = this.props;
|
|
112
|
+
const circlePointSet = new Set();
|
|
113
|
+
const [getWeight, aggregation] = Array.isArray(featureSelection) && featureSelection.length > 0
|
|
114
|
+
? ([contourGetWeight, 'MEAN'])
|
|
115
|
+
: ([1, 'COUNT']);
|
|
112
116
|
const layers = Array.from(this.stratifiedData.entries())
|
|
113
117
|
.flatMap(([obsSetKey, sampleSetMap]) => Array.from(sampleSetMap.entries())
|
|
114
118
|
.map(([sampleSetKey, arrs]) => {
|
|
@@ -127,30 +131,34 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
127
131
|
contourColor = (sampleSetColor?.find(d => isEqual(sampleSetKey, d.path))?.color
|
|
128
132
|
|| contourColor);
|
|
129
133
|
}
|
|
130
|
-
|
|
134
|
+
const contours = contourThresholds.map((threshold, i) => ({
|
|
135
|
+
i,
|
|
136
|
+
threshold: (contoursFilled ? [threshold, threshold[i + 1] || Infinity] : threshold),
|
|
137
|
+
// TODO: should the opacity steps be uniform? Should align with human perception.
|
|
138
|
+
// TODO: support usage of static colors.
|
|
139
|
+
color: [
|
|
140
|
+
// r, g, b
|
|
141
|
+
...contourColor,
|
|
142
|
+
// a
|
|
143
|
+
(contoursFilled
|
|
144
|
+
? ((i + 0.5) / contourThresholds.length * 255)
|
|
145
|
+
: ((i + 1) / (contourThresholds.length)) * 255),
|
|
146
|
+
],
|
|
147
|
+
strokeWidth: 2,
|
|
148
|
+
// We need to specify a greater z-index so that the contour layers
|
|
149
|
+
// will render on top of the point layer.
|
|
150
|
+
zIndex: POINT_LAYER_Z_INDEX + 1 + i,
|
|
151
|
+
}));
|
|
152
|
+
return new ContourLayerWithText({
|
|
131
153
|
id: `contour-${JSON.stringify(obsSetKey)}-${JSON.stringify(sampleSetKey)}`,
|
|
132
154
|
coordinateSystem: deck.COORDINATE_SYSTEM.CARTESIAN,
|
|
133
155
|
data: deckData,
|
|
134
|
-
getWeight
|
|
156
|
+
getWeight,
|
|
135
157
|
getPosition: contourGetPosition,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
color: [
|
|
141
|
-
// r, g, b
|
|
142
|
-
...contourColor,
|
|
143
|
-
// a
|
|
144
|
-
(contoursFilled
|
|
145
|
-
? ((i + 0.5) / contourThresholds.length * 255)
|
|
146
|
-
: ((i + 1) / (contourThresholds.length)) * 255),
|
|
147
|
-
],
|
|
148
|
-
strokeWidth: 2,
|
|
149
|
-
// We need to specify a greater z-index so that the contour layers
|
|
150
|
-
// will render on top of the point layer.
|
|
151
|
-
zIndex: POINT_LAYER_Z_INDEX + 1 + i,
|
|
152
|
-
})),
|
|
153
|
-
aggregation: 'MEAN',
|
|
158
|
+
obsSetPath: obsSetKey,
|
|
159
|
+
sampleSetPath: sampleSetKey,
|
|
160
|
+
contours,
|
|
161
|
+
aggregation,
|
|
154
162
|
gpuAggregation: true,
|
|
155
163
|
visible: true,
|
|
156
164
|
pickable: false,
|
|
@@ -158,6 +166,14 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
158
166
|
filled: contoursFilled,
|
|
159
167
|
cellSize: 0.25,
|
|
160
168
|
zOffset: 0.005,
|
|
169
|
+
// Info for text/line rendering
|
|
170
|
+
circleInfo,
|
|
171
|
+
circlePointSet,
|
|
172
|
+
obsSetLabelsVisible: cellSetLabelsVisible,
|
|
173
|
+
obsSetLabelSize: cellSetLabelSize,
|
|
174
|
+
updateTriggers: {
|
|
175
|
+
getWeight: [getWeight],
|
|
176
|
+
},
|
|
161
177
|
});
|
|
162
178
|
}));
|
|
163
179
|
return layers;
|
|
@@ -349,11 +365,16 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
349
365
|
}
|
|
350
366
|
}
|
|
351
367
|
onUpdateCellSetsLayers(onlyViewStateChange) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
368
|
+
const { viewState, cellSetLabelsVisible, embeddingContoursVisible } = this.props;
|
|
369
|
+
if (embeddingContoursVisible) {
|
|
370
|
+
// If rendering contours, we do not want to render text labels using this method,
|
|
371
|
+
// as the ContourLayerWithText implements its own text labeling internally.
|
|
372
|
+
this.cellSetsLayers = [];
|
|
373
|
+
}
|
|
374
|
+
else if (onlyViewStateChange) {
|
|
375
|
+
// Because the label sizes for the force simulation depend on the zoom level,
|
|
376
|
+
// we _could_ run the simulation every time the zoom level changes.
|
|
377
|
+
// However, this has a performance impact in firefox.
|
|
357
378
|
const { zoom } = viewState;
|
|
358
379
|
const { cellSetsLabelPrevZoom } = this;
|
|
359
380
|
// Instead, we can just check if the zoom level has changed
|
|
@@ -412,7 +433,11 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
412
433
|
this.onUpdateCellsLayer();
|
|
413
434
|
forceUpdate = true;
|
|
414
435
|
}
|
|
415
|
-
if ([
|
|
436
|
+
if ([
|
|
437
|
+
'stratifiedData', 'contourColorEncoding', 'contoursFilled',
|
|
438
|
+
'contourThresholds', 'embeddingContoursVisible',
|
|
439
|
+
'cellSetLabelsVisible', 'cellSetLabelSize',
|
|
440
|
+
].some(shallowDiff)) {
|
|
416
441
|
// Cells data changed.
|
|
417
442
|
this.onUpdateContourLayers();
|
|
418
443
|
forceUpdate = true;
|
|
@@ -420,6 +445,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
420
445
|
if ([
|
|
421
446
|
'cellSetPolygons', 'cellSetPolygonsVisible',
|
|
422
447
|
'cellSetLabelsVisible', 'cellSetLabelSize',
|
|
448
|
+
'embeddingContoursVisible',
|
|
423
449
|
].some(shallowDiff)) {
|
|
424
450
|
// Cell sets layer props changed.
|
|
425
451
|
this.onUpdateCellSetsLayers(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-opacity.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/dynamic-opacity.js"],"names":[],"mappings":"AAKA,mIA0BC;AAGD,
|
|
1
|
+
{"version":3,"file":"dynamic-opacity.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/dynamic-opacity.js"],"names":[],"mappings":"AAKA,mIA0BC;AAGD,uIA6BC"}
|
|
@@ -24,11 +24,20 @@ export function getPointSizeDevicePixels(devicePixelRatio, zoom, xRange, yRange,
|
|
|
24
24
|
// Reference: https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds
|
|
25
25
|
export function getPointOpacity(zoom, xRange, yRange, width, height, numCells, avgFillDensity) {
|
|
26
26
|
const N = numCells;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
let minX;
|
|
28
|
+
let minY;
|
|
29
|
+
let maxX;
|
|
30
|
+
let maxY;
|
|
31
|
+
try {
|
|
32
|
+
[minX, minY, maxX, maxY] = new deck.OrthographicView({ zoom }).makeViewport({
|
|
33
|
+
height,
|
|
34
|
+
width,
|
|
35
|
+
viewState: { zoom, target: [0, 0, 0] },
|
|
36
|
+
}).getBounds();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return 1.0;
|
|
40
|
+
}
|
|
32
41
|
const X = maxY - minY;
|
|
33
42
|
const Y = maxX - minX;
|
|
34
43
|
const X0 = xRange;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/scatterplot",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.10",
|
|
4
4
|
"author": "HIDIVE Lab at HMS",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"d3-quadtree": "^1.0.7",
|
|
24
24
|
"lodash-es": "^4.17.21",
|
|
25
25
|
"react-aria": "^3.28.0",
|
|
26
|
-
"@vitessce/constants-internal": "3.5.
|
|
27
|
-
"@vitessce/gl": "3.5.
|
|
28
|
-
"@vitessce/icons": "3.5.
|
|
29
|
-
"@vitessce/tooltip": "3.5.
|
|
30
|
-
"@vitessce/utils": "3.5.
|
|
31
|
-
"@vitessce/vit-s": "3.5.
|
|
26
|
+
"@vitessce/constants-internal": "3.5.10",
|
|
27
|
+
"@vitessce/gl": "3.5.10",
|
|
28
|
+
"@vitessce/icons": "3.5.10",
|
|
29
|
+
"@vitessce/tooltip": "3.5.10",
|
|
30
|
+
"@vitessce/utils": "3.5.10",
|
|
31
|
+
"@vitessce/vit-s": "3.5.10"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@testing-library/jest-dom": "^5.16.4",
|
package/src/Scatterplot.js
CHANGED
|
@@ -4,6 +4,7 @@ import { forceSimulation } from 'd3-force';
|
|
|
4
4
|
import { isEqual } from 'lodash-es';
|
|
5
5
|
import {
|
|
6
6
|
deck, getSelectionLayer, ScaledExpressionExtension, SelectionExtension,
|
|
7
|
+
ContourLayerWithText,
|
|
7
8
|
} from '@vitessce/gl';
|
|
8
9
|
import { getDefaultColor } from '@vitessce/utils';
|
|
9
10
|
import {
|
|
@@ -130,8 +131,17 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
130
131
|
contourThresholds,
|
|
131
132
|
contoursFilled,
|
|
132
133
|
contourColor: contourColorProp,
|
|
134
|
+
circleInfo,
|
|
135
|
+
cellSetLabelsVisible,
|
|
136
|
+
cellSetLabelSize,
|
|
137
|
+
featureSelection,
|
|
133
138
|
} = this.props;
|
|
134
139
|
|
|
140
|
+
const circlePointSet = new Set();
|
|
141
|
+
const [getWeight, aggregation] = Array.isArray(featureSelection) && featureSelection.length > 0
|
|
142
|
+
? ([contourGetWeight, 'MEAN'])
|
|
143
|
+
: ([1, 'COUNT']);
|
|
144
|
+
|
|
135
145
|
const layers = Array.from(this.stratifiedData.entries())
|
|
136
146
|
.flatMap(([obsSetKey, sampleSetMap]) => Array.from(sampleSetMap.entries())
|
|
137
147
|
.map(([sampleSetKey, arrs]) => {
|
|
@@ -155,30 +165,35 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
155
165
|
|| contourColor
|
|
156
166
|
);
|
|
157
167
|
}
|
|
158
|
-
|
|
168
|
+
const contours = contourThresholds.map((threshold, i) => ({
|
|
169
|
+
i,
|
|
170
|
+
threshold: (contoursFilled ? [threshold, threshold[i + 1] || Infinity] : threshold),
|
|
171
|
+
// TODO: should the opacity steps be uniform? Should align with human perception.
|
|
172
|
+
// TODO: support usage of static colors.
|
|
173
|
+
color: [
|
|
174
|
+
// r, g, b
|
|
175
|
+
...contourColor,
|
|
176
|
+
// a
|
|
177
|
+
(contoursFilled
|
|
178
|
+
? ((i + 0.5) / contourThresholds.length * 255)
|
|
179
|
+
: ((i + 1) / (contourThresholds.length)) * 255),
|
|
180
|
+
],
|
|
181
|
+
strokeWidth: 2,
|
|
182
|
+
// We need to specify a greater z-index so that the contour layers
|
|
183
|
+
// will render on top of the point layer.
|
|
184
|
+
zIndex: POINT_LAYER_Z_INDEX + 1 + i,
|
|
185
|
+
}));
|
|
186
|
+
|
|
187
|
+
return new ContourLayerWithText({
|
|
159
188
|
id: `contour-${JSON.stringify(obsSetKey)}-${JSON.stringify(sampleSetKey)}`,
|
|
160
189
|
coordinateSystem: deck.COORDINATE_SYSTEM.CARTESIAN,
|
|
161
190
|
data: deckData,
|
|
162
|
-
getWeight
|
|
191
|
+
getWeight,
|
|
163
192
|
getPosition: contourGetPosition,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
color: [
|
|
169
|
-
// r, g, b
|
|
170
|
-
...contourColor,
|
|
171
|
-
// a
|
|
172
|
-
(contoursFilled
|
|
173
|
-
? ((i + 0.5) / contourThresholds.length * 255)
|
|
174
|
-
: ((i + 1) / (contourThresholds.length)) * 255),
|
|
175
|
-
],
|
|
176
|
-
strokeWidth: 2,
|
|
177
|
-
// We need to specify a greater z-index so that the contour layers
|
|
178
|
-
// will render on top of the point layer.
|
|
179
|
-
zIndex: POINT_LAYER_Z_INDEX + 1 + i,
|
|
180
|
-
})),
|
|
181
|
-
aggregation: 'MEAN',
|
|
193
|
+
obsSetPath: obsSetKey,
|
|
194
|
+
sampleSetPath: sampleSetKey,
|
|
195
|
+
contours,
|
|
196
|
+
aggregation,
|
|
182
197
|
gpuAggregation: true,
|
|
183
198
|
visible: true,
|
|
184
199
|
pickable: false,
|
|
@@ -186,6 +201,14 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
186
201
|
filled: contoursFilled,
|
|
187
202
|
cellSize: 0.25,
|
|
188
203
|
zOffset: 0.005,
|
|
204
|
+
// Info for text/line rendering
|
|
205
|
+
circleInfo,
|
|
206
|
+
circlePointSet,
|
|
207
|
+
obsSetLabelsVisible: cellSetLabelsVisible,
|
|
208
|
+
obsSetLabelSize: cellSetLabelSize,
|
|
209
|
+
updateTriggers: {
|
|
210
|
+
getWeight: [getWeight],
|
|
211
|
+
},
|
|
189
212
|
});
|
|
190
213
|
}));
|
|
191
214
|
return layers;
|
|
@@ -429,30 +452,34 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
429
452
|
}
|
|
430
453
|
|
|
431
454
|
onUpdateCellSetsLayers(onlyViewStateChange) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
455
|
+
const { viewState, cellSetLabelsVisible, embeddingContoursVisible } = this.props;
|
|
456
|
+
if (embeddingContoursVisible) {
|
|
457
|
+
// If rendering contours, we do not want to render text labels using this method,
|
|
458
|
+
// as the ContourLayerWithText implements its own text labeling internally.
|
|
459
|
+
this.cellSetsLayers = [];
|
|
460
|
+
} else if (onlyViewStateChange) {
|
|
461
|
+
// Because the label sizes for the force simulation depend on the zoom level,
|
|
462
|
+
// we _could_ run the simulation every time the zoom level changes.
|
|
463
|
+
// However, this has a performance impact in firefox.
|
|
437
464
|
const { zoom } = viewState;
|
|
438
465
|
const { cellSetsLabelPrevZoom } = this;
|
|
439
466
|
// Instead, we can just check if the zoom level has changed
|
|
440
467
|
// by some relatively large delta, to be more conservative
|
|
441
468
|
// about re-running the force simulation.
|
|
442
469
|
if (cellSetLabelsVisible
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
470
|
+
&& (
|
|
471
|
+
cellSetsLabelPrevZoom === null
|
|
472
|
+
|| Math.abs(cellSetsLabelPrevZoom - zoom) > LABEL_UPDATE_ZOOM_DELTA
|
|
473
|
+
)
|
|
447
474
|
) {
|
|
448
475
|
this.cellSetsLayers = this.createCellSetsLayers();
|
|
449
476
|
this.cellSetsLabelPrevZoom = zoom;
|
|
450
477
|
}
|
|
451
478
|
} else {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
479
|
+
// Otherwise, something more substantial than just
|
|
480
|
+
// the viewState has changed, such as the label array
|
|
481
|
+
// itself, so we always want to update the layer
|
|
482
|
+
// in this case.
|
|
456
483
|
this.cellSetsLayers = this.createCellSetsLayers();
|
|
457
484
|
}
|
|
458
485
|
}
|
|
@@ -507,7 +534,11 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
507
534
|
forceUpdate = true;
|
|
508
535
|
}
|
|
509
536
|
|
|
510
|
-
if ([
|
|
537
|
+
if ([
|
|
538
|
+
'stratifiedData', 'contourColorEncoding', 'contoursFilled',
|
|
539
|
+
'contourThresholds', 'embeddingContoursVisible',
|
|
540
|
+
'cellSetLabelsVisible', 'cellSetLabelSize',
|
|
541
|
+
].some(shallowDiff)) {
|
|
511
542
|
// Cells data changed.
|
|
512
543
|
this.onUpdateContourLayers();
|
|
513
544
|
forceUpdate = true;
|
|
@@ -516,6 +547,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
516
547
|
if ([
|
|
517
548
|
'cellSetPolygons', 'cellSetPolygonsVisible',
|
|
518
549
|
'cellSetLabelsVisible', 'cellSetLabelSize',
|
|
550
|
+
'embeddingContoursVisible',
|
|
519
551
|
].some(shallowDiff)) {
|
|
520
552
|
// Cell sets layer props changed.
|
|
521
553
|
this.onUpdateCellSetsLayers(false);
|
|
@@ -34,11 +34,17 @@ export function getPointSizeDevicePixels(devicePixelRatio, zoom, xRange, yRange,
|
|
|
34
34
|
// Reference: https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds
|
|
35
35
|
export function getPointOpacity(zoom, xRange, yRange, width, height, numCells, avgFillDensity) {
|
|
36
36
|
const N = numCells;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
let minX; let minY; let maxX; let
|
|
38
|
+
maxY;
|
|
39
|
+
try {
|
|
40
|
+
[minX, minY, maxX, maxY] = new deck.OrthographicView({ zoom }).makeViewport({
|
|
41
|
+
height,
|
|
42
|
+
width,
|
|
43
|
+
viewState: { zoom, target: [0, 0, 0] },
|
|
44
|
+
}).getBounds();
|
|
45
|
+
} catch {
|
|
46
|
+
return 1.0;
|
|
47
|
+
}
|
|
42
48
|
const X = maxY - minY;
|
|
43
49
|
const Y = maxX - minX;
|
|
44
50
|
const X0 = xRange;
|