Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import sandboxedEval from '../../utils/sandbox';
import { GetLayerType, createDeckGLComponent } from '../../factory';
import { ColorType } from '../../types';
import TooltipRow from '../../TooltipRow';
import { getSafeCellSize } from './getSafeCellSize';
import {
createTooltipContent,
CommonTooltipRows,
Expand Down Expand Up @@ -159,11 +160,23 @@ export const getLayer: GetLayerType<ContourLayer> = function ({
return baseTooltipContent(o);
};

const safeCellSize = getSafeCellSize({
cellSize,
viewport: fd.viewport,
onAutoAdjust: ({ original, adjusted, estimatedCells }) => {
console.warn(
`[DeckGL Contour] cellSize=${original} would create ~${Math.round(
estimatedCells,
)} cells. Auto-adjusted to ${adjusted} to prevent WebGL crash.`,
);
},
});

return new ContourLayer({
id: `contourLayer-${fd.slice_id}`,
data,
contours,
cellSize: Number(cellSize || '200'),
cellSize: safeCellSize,
aggregation: aggregation.toUpperCase(),
getPosition: (d: { position: number[]; weight: number }) =>
d.position as Position,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {
getSafeCellSize,
MIN_CELL_SIZE,
MAX_CELL_SIZE,
} from './getSafeCellSize';

describe('getSafeCellSize', () => {
it('defaults to 200 when value is not finite', () => {
expect(getSafeCellSize({ cellSize: 'nope' })).toBe(200);
});

it('clamps below minimum', () => {
expect(getSafeCellSize({ cellSize: 1 })).toBe(MIN_CELL_SIZE);
});

it('clamps above maximum', () => {
expect(getSafeCellSize({ cellSize: 999999 })).toBe(MAX_CELL_SIZE);
});

it('auto-scales when estimated grid is too large', () => {
const size = getSafeCellSize({
cellSize: 1,
viewport: { width: 11000, height: 11000 },
});

expect(size).toBeGreaterThan(MIN_CELL_SIZE);
});

it('never exceeds MAX_CELL_SIZE', () => {
const size = getSafeCellSize({
cellSize: 1,
viewport: { width: 100000, height: 100000 },
});

expect(size).toBeLessThanOrEqual(MAX_CELL_SIZE);
});

it('calls onAutoAdjust when scaling happens', () => {
const spy = jest.fn();

getSafeCellSize({
cellSize: 1,
viewport: { width: 11000, height: 11000 },
onAutoAdjust: spy,
});

expect(spy).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export const MIN_CELL_SIZE = 10;
export const MAX_CELL_SIZE = 5000;
export const MAX_GRID_CELLS = 1_000_000;

export function getSafeCellSize({
cellSize,
viewport,
onAutoAdjust,
}: {
cellSize?: string | number;
viewport?: { width?: number; height?: number };
onAutoAdjust?: (info: {
original: number;
adjusted: number;
estimatedCells: number;
}) => void;
}) {
let parsedCellSize = Number(cellSize ?? 200);
if (!Number.isFinite(parsedCellSize)) {
parsedCellSize = 200;
}

let safeCellSize = Math.min(
MAX_CELL_SIZE,
Math.max(MIN_CELL_SIZE, parsedCellSize),
);

if (
viewport &&
typeof viewport.width === 'number' &&
typeof viewport.height === 'number' &&
viewport.width > 0 &&
viewport.height > 0
) {
const estimatedCells =
(viewport.width / safeCellSize) * (viewport.height / safeCellSize);

if (estimatedCells > MAX_GRID_CELLS) {
const scaleFactor = Math.sqrt(estimatedCells / MAX_GRID_CELLS);
const adjustedCellSize = Math.ceil(safeCellSize * scaleFactor);

const finalSize = Math.min(MAX_CELL_SIZE, adjustedCellSize);

onAutoAdjust?.({
original: safeCellSize,
adjusted: finalSize,
estimatedCells,
});

safeCellSize = finalSize;
}
}

return safeCellSize;
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ export default class ContourChartPlugin extends ChartPlugin {
});
}
}

export { getSafeCellSize } from './getSafeCellSize';
Loading