From 0c4c026f6eb950af4ab587bde45b951d2702bcce Mon Sep 17 00:00:00 2001 From: Piyush Chauhan <42397980+pyshx@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:21:46 +0530 Subject: [PATCH] chore(web): add support for heatMap in beta (#835) Co-authored-by: Piyush Chauhan Co-authored-by: keiya01 --- web/package.json | 2 + .../Cesium/Feature/HeatMap/HeatmapMesh.tsx | 187 +++++++ .../Feature/HeatMap/HeatmapMeshMaterial.ts | 81 +++ .../Cesium/Feature/HeatMap/colorMap.ts | 47 ++ .../Cesium/Feature/HeatMap/constants.ts | 521 ++++++++++++++++++ .../Feature/HeatMap/createMeshImageData.ts | 108 ++++ .../engines/Cesium/Feature/HeatMap/index.tsx | 149 +++++ .../HeatMap/shaders/heatmapMeshMaterial.glsl | 78 +++ .../Feature/HeatMap/shaders/makeContour.glsl | 13 + .../HeatMap/shaders/sampleBicubic.glsl | 57 ++ .../engines/Cesium/Feature/HeatMap/utils.ts | 30 + .../lib/core/engines/Cesium/Feature/index.tsx | 3 + .../lib/core/engines/Cesium/Feature/utils.tsx | 12 + web/src/beta/lib/core/engines/Cesium/hooks.ts | 8 +- .../lib/core/engines/Cesium/useEngineRef.ts | 18 +- web/src/beta/lib/core/engines/Cesium/utils.ts | 19 +- .../beta/lib/core/mantle/types/appearance.ts | 20 + web/src/beta/lib/core/mantle/types/index.ts | 3 +- web/src/beta/lib/core/mantle/types/value.ts | 10 + web/src/beta/utils/util.ts | 10 + web/yarn.lock | 483 +++++++++++++++- yarn.lock | 4 - 22 files changed, 1848 insertions(+), 15 deletions(-) create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMesh.tsx create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMeshMaterial.ts create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/colorMap.ts create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/constants.ts create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/createMeshImageData.ts create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/index.tsx create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/heatmapMeshMaterial.glsl create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/makeContour.glsl create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/sampleBicubic.glsl create mode 100644 web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/utils.ts delete mode 100644 yarn.lock diff --git a/web/package.json b/web/package.json index 8e7bb46c3..61191a969 100644 --- a/web/package.json +++ b/web/package.json @@ -117,6 +117,7 @@ "@sentry/browser": "7.77.0", "@seznam/compose-react-refs": "1.0.6", "@turf/turf": "6.5.0", + "@types/d3": "^7.4.3", "@types/escape-string-regexp": "2.0.1", "@ungap/event-target": "0.2.4", "apollo-link-sentry": "3.2.3", @@ -130,6 +131,7 @@ "core-js": "3.33.2", "crypto-js": "4.2.0", "csv-parse": "5.5.2", + "d3": "^7.8.5", "date-fns": "2.30.0", "dayjs": "1.11.10", "detect-browser": "5.3.0", diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMesh.tsx b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMesh.tsx new file mode 100644 index 000000000..6224cc35f --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMesh.tsx @@ -0,0 +1,187 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/heatmap/src/HeatmapMesh.tsx + +import { + ArcType, + BoundingSphere, + EllipsoidSurfaceAppearance, + GeometryInstance, + GroundPrimitive, + PolygonGeometry, +} from "cesium"; +import { type MultiPolygon, type Polygon } from "geojson"; +import { pick } from "lodash-es"; +import { + forwardRef, + useEffect, + useImperativeHandle, + useRef, + useMemo, + useLayoutEffect, + memo, +} from "react"; +import { useCesium } from "resium"; + +import { ComputedFeature, ComputedLayer } from "@reearth/beta/lib/core/mantle"; +import { useConstant } from "@reearth/beta/utils/util"; + +import { attachTag } from "../utils"; + +import { createColorMapImage } from "./colorMap"; +import { viridisColorMapLUT } from "./constants"; +import { type MeshImageData } from "./createMeshImageData"; +import { createHeatmapMeshMaterial, type HeatmapMeshMaterialOptions } from "./HeatmapMeshMaterial"; +import { convertPolygonToHierarchyArray } from "./utils"; + +export type HeatmapMeshHandle = { + bringToFront: () => void; + sendToBack: () => void; +}; + +export type HeatmapMeshProps = Omit & { + layer?: ComputedLayer; + feature?: ComputedFeature; + boundingSphere: BoundingSphere; + meshImageData: MeshImageData; + geometry: Polygon | MultiPolygon; +}; + +export const HeatmapMesh = memo( + forwardRef( + ( + { + layer, + feature, + boundingSphere, + meshImageData, + geometry, + colorMapLUT, + bound, + cropBound, + ...props + }, + ref, + ) => { + const { scene } = useCesium(); + const groundPrimitives = scene?.primitives; + const primitiveRef = useRef(); + + const material = useConstant(() => + createHeatmapMeshMaterial({ + image: meshImageData.image, + width: meshImageData.width, + height: meshImageData.height, + bound, + cropBound, + }), + ); + + const geometryInstances = useMemo(() => { + return convertPolygonToHierarchyArray(geometry).map(polygonHierarchy => { + const instance = new GeometryInstance({ + geometry: new PolygonGeometry({ + polygonHierarchy, + arcType: ArcType.GEODESIC, + vertexFormat: EllipsoidSurfaceAppearance.VERTEX_FORMAT, + }), + id: layer?.id, + }); + + return instance; + }); + }, [geometry, layer?.id]); + + // Since we expect a single feature, we directly access the first one + const geometryInstance = geometryInstances[0]; + + useEffect(() => { + if (groundPrimitives?.isDestroyed()) { + return; + } + const primitive = + // TODO: Needs trapezoidal texture projection to accurately map the + // data. See also: https://github.com/CesiumGS/cesium/issues/4164 + new GroundPrimitive({ + geometryInstances: geometryInstance, + appearance: new EllipsoidSurfaceAppearance({ + material, + }), + }); + groundPrimitives?.add(primitive); + primitiveRef.current = primitive; + + return () => { + if (!groundPrimitives?.isDestroyed()) { + groundPrimitives?.remove(primitive); + } + primitiveRef.current = undefined; + }; + }, [geometryInstance, groundPrimitives, material]); + + useLayoutEffect(() => { + // Code for attaching tag + if (!primitiveRef.current || primitiveRef.current?.isDestroyed()) return; + attachTag(primitiveRef.current, { + layerId: layer?.id, + featureId: feature?.id, + originalProperties: boundingSphere, + }); + }, [layer?.id, feature?.id, boundingSphere]); + + useEffect(() => { + material.uniforms.image = meshImageData.image; + }, [meshImageData.image, material]); + + Object.assign(material.uniforms, pick(meshImageData, ["width", "height"])); + + useEffect(() => { + material.uniforms.colorMap = + colorMapLUT != null + ? createColorMapImage(colorMapLUT) + : createColorMapImage(viridisColorMapLUT); + }, [colorMapLUT, material]); + + Object.assign( + material.uniforms, + pick(props, [ + "minValue", + "maxValue", + "opacity", + "contourSpacing", + "contourThickness", + "contourAlpha", + "logarithmic", + ]), + ); + + useImperativeHandle( + ref, + () => ({ + bringToFront: () => { + if (groundPrimitives?.isDestroyed()) { + return; + } + + if (groundPrimitives?.contains(primitiveRef)) { + groundPrimitives?.raiseToTop(primitiveRef); + } + }, + sendToBack: () => { + if (groundPrimitives?.isDestroyed()) { + return; + } + + if (groundPrimitives?.contains(primitiveRef)) { + groundPrimitives?.lowerToBottom(primitiveRef); + } + }, + }), + [groundPrimitives], + ); + + scene?.requestRender(); + return null; + }, + ), +); + +HeatmapMesh.displayName = "HeatmapMesh"; diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMeshMaterial.ts b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMeshMaterial.ts new file mode 100644 index 000000000..a6039f082 --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/HeatmapMeshMaterial.ts @@ -0,0 +1,81 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/heatmap/src/HeatmapMeshMaterial.ts + +import { Cartesian2, Material, Rectangle } from "cesium"; + +import { Bound, LUT } from "@reearth/beta/lib/core/mantle"; + +import { createColorMapImage } from "./colorMap"; +import { viridisColorMapLUT } from "./constants"; +import heatmapMeshMaterial from "./shaders/heatmapMeshMaterial.glsl?raw"; +import makeContour from "./shaders/makeContour.glsl?raw"; +import sampleBicubic from "./shaders/sampleBicubic.glsl?raw"; + +export type HeatmapMeshMaterialOptions = { + image: string | HTMLCanvasElement; + width: number; + height: number; + minValue?: number; + maxValue?: number; + bound?: Bound; + cropBound?: Bound; + colorMapLUT?: LUT; + opacity?: number; + contourSpacing?: number; + contourThickness?: number; + contourAlpha?: number; + logarithmic?: boolean; +}; + +export function createHeatmapMeshMaterial({ + image, + width, + height, + minValue = 0, + maxValue = 100, + bound, + cropBound, + colorMapLUT = viridisColorMapLUT, + opacity = 1, + contourSpacing = 10, + contourThickness = 1, + contourAlpha = 0.2, + logarithmic = false, +}: HeatmapMeshMaterialOptions): Material { + const imageScale = new Cartesian2(1, 1); + const imageOffset = new Cartesian2(); + const cropRectangle = new Rectangle( + cropBound?.west, + cropBound?.south, + cropBound?.east, + cropBound?.north, + ); + const rectangle = new Rectangle(bound?.west, bound?.south, bound?.east, bound?.north); + if (cropBound != null && rectangle != null && cropRectangle != null) { + imageScale.x = cropRectangle.width / rectangle.width; + imageScale.y = cropRectangle.height / rectangle.height; + imageOffset.x = (cropRectangle.west - rectangle.west) / rectangle.width; + imageOffset.y = (cropRectangle.south - rectangle.south) / rectangle.height; + } + + return new Material({ + fabric: { + type: "HeatmapMesh", + uniforms: { + colorMap: createColorMapImage(colorMapLUT), + image, + imageScale, + imageOffset, + width, + height, + minValue, + maxValue, + opacity, + contourSpacing, + contourThickness, + contourAlpha, + logarithmic, + }, + source: [sampleBicubic, makeContour, heatmapMeshMaterial].join("\n"), + }, + }); +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/colorMap.ts b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/colorMap.ts new file mode 100644 index 000000000..e8237b167 --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/colorMap.ts @@ -0,0 +1,47 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/color-maps/src/ColorMap.ts + +import { interpolate, quantize, rgb, scaleLinear, type ScaleLinear } from "d3"; +import invariant from "tiny-invariant"; + +import type { ColorTuple, LUT } from "@reearth/beta/lib/core/mantle"; + +export type ColorMapType = "sequential" | "diverging"; + +function createScaleLinear(lut: LUT): ScaleLinear { + invariant(lut.length > 1); + return scaleLinear() + .domain(quantize(interpolate(0, 1), lut.length)) + .range(lut) + .clamp(true); +} + +export function linearColorMap(lut: LUT, value: number): ColorTuple { + const scaleLinear = createScaleLinear(lut); + const result = scaleLinear(value); + invariant(result != null); + return result; +} + +export function countColorMap(lut: LUT): number { + return lut.length; +} + +export function quantizeColorMap(lut: LUT, count: number): ColorTuple[] { + invariant(count > 1); + return [...Array(count)].map((_, index) => { + return linearColorMap(lut, index / (count - 1)); + }); +} + +export function createColorMapImage(lut: LUT): HTMLCanvasElement { + const canvas = document.createElement("canvas"); + canvas.width = lut.length; + canvas.height = 1; + const context = canvas.getContext("2d"); + invariant(context != null); + lut.forEach(([r, g, b], index) => { + context.fillStyle = rgb(r * 255, g * 255, b * 255).toString(); + context.fillRect(index, 0, 1, 1); + }); + return canvas; +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/constants.ts b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/constants.ts new file mode 100644 index 000000000..55a1a774a --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/constants.ts @@ -0,0 +1,521 @@ +import { LUT } from "@reearth/beta/lib/core/mantle"; + +// Reference: https://github.com/matplotlib/matplotlib/blob/main/lib/matplotlib/_cm_listed.py +export const viridisColorMapLUT: LUT = [ + [0.267004, 0.004874, 0.329415], + [0.26851, 0.009605, 0.335427], + [0.269944, 0.014625, 0.341379], + [0.271305, 0.019942, 0.347269], + [0.272594, 0.025563, 0.353093], + [0.273809, 0.031497, 0.358853], + [0.274952, 0.037752, 0.364543], + [0.276022, 0.044167, 0.370164], + [0.277018, 0.050344, 0.375715], + [0.277941, 0.056324, 0.381191], + [0.278791, 0.062145, 0.386592], + [0.279566, 0.067836, 0.391917], + [0.280267, 0.073417, 0.397163], + [0.280894, 0.078907, 0.402329], + [0.281446, 0.08432, 0.407414], + [0.281924, 0.089666, 0.412415], + [0.282327, 0.094955, 0.417331], + [0.282656, 0.100196, 0.42216], + [0.28291, 0.105393, 0.426902], + [0.283091, 0.110553, 0.431554], + [0.283197, 0.11568, 0.436115], + [0.283229, 0.120777, 0.440584], + [0.283187, 0.125848, 0.44496], + [0.283072, 0.130895, 0.449241], + [0.282884, 0.13592, 0.453427], + [0.282623, 0.140926, 0.457517], + [0.28229, 0.145912, 0.46151], + [0.281887, 0.150881, 0.465405], + [0.281412, 0.155834, 0.469201], + [0.280868, 0.160771, 0.472899], + [0.280255, 0.165693, 0.476498], + [0.279574, 0.170599, 0.479997], + [0.278826, 0.17549, 0.483397], + [0.278012, 0.180367, 0.486697], + [0.277134, 0.185228, 0.489898], + [0.276194, 0.190074, 0.493001], + [0.275191, 0.194905, 0.496005], + [0.274128, 0.199721, 0.498911], + [0.273006, 0.20452, 0.501721], + [0.271828, 0.209303, 0.504434], + [0.270595, 0.214069, 0.507052], + [0.269308, 0.218818, 0.509577], + [0.267968, 0.223549, 0.512008], + [0.26658, 0.228262, 0.514349], + [0.265145, 0.232956, 0.516599], + [0.263663, 0.237631, 0.518762], + [0.262138, 0.242286, 0.520837], + [0.260571, 0.246922, 0.522828], + [0.258965, 0.251537, 0.524736], + [0.257322, 0.25613, 0.526563], + [0.255645, 0.260703, 0.528312], + [0.253935, 0.265254, 0.529983], + [0.252194, 0.269783, 0.531579], + [0.250425, 0.27429, 0.533103], + [0.248629, 0.278775, 0.534556], + [0.246811, 0.283237, 0.535941], + [0.244972, 0.287675, 0.53726], + [0.243113, 0.292092, 0.538516], + [0.241237, 0.296485, 0.539709], + [0.239346, 0.300855, 0.540844], + [0.237441, 0.305202, 0.541921], + [0.235526, 0.309527, 0.542944], + [0.233603, 0.313828, 0.543914], + [0.231674, 0.318106, 0.544834], + [0.229739, 0.322361, 0.545706], + [0.227802, 0.326594, 0.546532], + [0.225863, 0.330805, 0.547314], + [0.223925, 0.334994, 0.548053], + [0.221989, 0.339161, 0.548752], + [0.220057, 0.343307, 0.549413], + [0.21813, 0.347432, 0.550038], + [0.21621, 0.351535, 0.550627], + [0.214298, 0.355619, 0.551184], + [0.212395, 0.359683, 0.55171], + [0.210503, 0.363727, 0.552206], + [0.208623, 0.367752, 0.552675], + [0.206756, 0.371758, 0.553117], + [0.204903, 0.375746, 0.553533], + [0.203063, 0.379716, 0.553925], + [0.201239, 0.38367, 0.554294], + [0.19943, 0.387607, 0.554642], + [0.197636, 0.391528, 0.554969], + [0.19586, 0.395433, 0.555276], + [0.1941, 0.399323, 0.555565], + [0.192357, 0.403199, 0.555836], + [0.190631, 0.407061, 0.556089], + [0.188923, 0.41091, 0.556326], + [0.187231, 0.414746, 0.556547], + [0.185556, 0.41857, 0.556753], + [0.183898, 0.422383, 0.556944], + [0.182256, 0.426184, 0.55712], + [0.180629, 0.429975, 0.557282], + [0.179019, 0.433756, 0.55743], + [0.177423, 0.437527, 0.557565], + [0.175841, 0.44129, 0.557685], + [0.174274, 0.445044, 0.557792], + [0.172719, 0.448791, 0.557885], + [0.171176, 0.45253, 0.557965], + [0.169646, 0.456262, 0.55803], + [0.168126, 0.459988, 0.558082], + [0.166617, 0.463708, 0.558119], + [0.165117, 0.467423, 0.558141], + [0.163625, 0.471133, 0.558148], + [0.162142, 0.474838, 0.55814], + [0.160665, 0.47854, 0.558115], + [0.159194, 0.482237, 0.558073], + [0.157729, 0.485932, 0.558013], + [0.15627, 0.489624, 0.557936], + [0.154815, 0.493313, 0.55784], + [0.153364, 0.497, 0.557724], + [0.151918, 0.500685, 0.557587], + [0.150476, 0.504369, 0.55743], + [0.149039, 0.508051, 0.55725], + [0.147607, 0.511733, 0.557049], + [0.14618, 0.515413, 0.556823], + [0.144759, 0.519093, 0.556572], + [0.143343, 0.522773, 0.556295], + [0.141935, 0.526453, 0.555991], + [0.140536, 0.530132, 0.555659], + [0.139147, 0.533812, 0.555298], + [0.13777, 0.537492, 0.554906], + [0.136408, 0.541173, 0.554483], + [0.135066, 0.544853, 0.554029], + [0.133743, 0.548535, 0.553541], + [0.132444, 0.552216, 0.553018], + [0.131172, 0.555899, 0.552459], + [0.129933, 0.559582, 0.551864], + [0.128729, 0.563265, 0.551229], + [0.127568, 0.566949, 0.550556], + [0.126453, 0.570633, 0.549841], + [0.125394, 0.574318, 0.549086], + [0.124395, 0.578002, 0.548287], + [0.123463, 0.581687, 0.547445], + [0.122606, 0.585371, 0.546557], + [0.121831, 0.589055, 0.545623], + [0.121148, 0.592739, 0.544641], + [0.120565, 0.596422, 0.543611], + [0.120092, 0.600104, 0.54253], + [0.119738, 0.603785, 0.5414], + [0.119512, 0.607464, 0.540218], + [0.119423, 0.611141, 0.538982], + [0.119483, 0.614817, 0.537692], + [0.119699, 0.61849, 0.536347], + [0.120081, 0.622161, 0.534946], + [0.120638, 0.625828, 0.533488], + [0.12138, 0.629492, 0.531973], + [0.122312, 0.633153, 0.530398], + [0.123444, 0.636809, 0.528763], + [0.12478, 0.640461, 0.527068], + [0.126326, 0.644107, 0.525311], + [0.128087, 0.647749, 0.523491], + [0.130067, 0.651384, 0.521608], + [0.132268, 0.655014, 0.519661], + [0.134692, 0.658636, 0.517649], + [0.137339, 0.662252, 0.515571], + [0.14021, 0.665859, 0.513427], + [0.143303, 0.669459, 0.511215], + [0.146616, 0.67305, 0.508936], + [0.150148, 0.676631, 0.506589], + [0.153894, 0.680203, 0.504172], + [0.157851, 0.683765, 0.501686], + [0.162016, 0.687316, 0.499129], + [0.166383, 0.690856, 0.496502], + [0.170948, 0.694384, 0.493803], + [0.175707, 0.6979, 0.491033], + [0.180653, 0.701402, 0.488189], + [0.185783, 0.704891, 0.485273], + [0.19109, 0.708366, 0.482284], + [0.196571, 0.711827, 0.479221], + [0.202219, 0.715272, 0.476084], + [0.20803, 0.718701, 0.472873], + [0.214, 0.722114, 0.469588], + [0.220124, 0.725509, 0.466226], + [0.226397, 0.728888, 0.462789], + [0.232815, 0.732247, 0.459277], + [0.239374, 0.735588, 0.455688], + [0.24607, 0.73891, 0.452024], + [0.252899, 0.742211, 0.448284], + [0.259857, 0.745492, 0.444467], + [0.266941, 0.748751, 0.440573], + [0.274149, 0.751988, 0.436601], + [0.281477, 0.755203, 0.432552], + [0.288921, 0.758394, 0.428426], + [0.296479, 0.761561, 0.424223], + [0.304148, 0.764704, 0.419943], + [0.311925, 0.767822, 0.415586], + [0.319809, 0.770914, 0.411152], + [0.327796, 0.77398, 0.40664], + [0.335885, 0.777018, 0.402049], + [0.344074, 0.780029, 0.397381], + [0.35236, 0.783011, 0.392636], + [0.360741, 0.785964, 0.387814], + [0.369214, 0.788888, 0.382914], + [0.377779, 0.791781, 0.377939], + [0.386433, 0.794644, 0.372886], + [0.395174, 0.797475, 0.367757], + [0.404001, 0.800275, 0.362552], + [0.412913, 0.803041, 0.357269], + [0.421908, 0.805774, 0.35191], + [0.430983, 0.808473, 0.346476], + [0.440137, 0.811138, 0.340967], + [0.449368, 0.813768, 0.335384], + [0.458674, 0.816363, 0.329727], + [0.468053, 0.818921, 0.323998], + [0.477504, 0.821444, 0.318195], + [0.487026, 0.823929, 0.312321], + [0.496615, 0.826376, 0.306377], + [0.506271, 0.828786, 0.300362], + [0.515992, 0.831158, 0.294279], + [0.525776, 0.833491, 0.288127], + [0.535621, 0.835785, 0.281908], + [0.545524, 0.838039, 0.275626], + [0.555484, 0.840254, 0.269281], + [0.565498, 0.84243, 0.262877], + [0.575563, 0.844566, 0.256415], + [0.585678, 0.846661, 0.249897], + [0.595839, 0.848717, 0.243329], + [0.606045, 0.850733, 0.236712], + [0.616293, 0.852709, 0.230052], + [0.626579, 0.854645, 0.223353], + [0.636902, 0.856542, 0.21662], + [0.647257, 0.8584, 0.209861], + [0.657642, 0.860219, 0.203082], + [0.668054, 0.861999, 0.196293], + [0.678489, 0.863742, 0.189503], + [0.688944, 0.865448, 0.182725], + [0.699415, 0.867117, 0.175971], + [0.709898, 0.868751, 0.169257], + [0.720391, 0.87035, 0.162603], + [0.730889, 0.871916, 0.156029], + [0.741388, 0.873449, 0.149561], + [0.751884, 0.874951, 0.143228], + [0.762373, 0.876424, 0.137064], + [0.772852, 0.877868, 0.131109], + [0.783315, 0.879285, 0.125405], + [0.79376, 0.880678, 0.120005], + [0.804182, 0.882046, 0.114965], + [0.814576, 0.883393, 0.110347], + [0.82494, 0.88472, 0.106217], + [0.83527, 0.886029, 0.102646], + [0.845561, 0.887322, 0.099702], + [0.85581, 0.888601, 0.097452], + [0.866013, 0.889868, 0.095953], + [0.876168, 0.891125, 0.09525], + [0.886271, 0.892374, 0.095374], + [0.89632, 0.893616, 0.096335], + [0.906311, 0.894855, 0.098125], + [0.916242, 0.896091, 0.100717], + [0.926106, 0.89733, 0.104071], + [0.935904, 0.89857, 0.108131], + [0.945636, 0.899815, 0.112838], + [0.9553, 0.901065, 0.118128], + [0.964894, 0.902323, 0.123941], + [0.974417, 0.90359, 0.130215], + [0.983868, 0.904867, 0.136897], + [0.993248, 0.906157, 0.143936], +]; + +// Reference: https://github.com/mwaskom/seaborn/blob/master/seaborn/cm.py +export const flareColorMapLUT: LUT = [ + [0.92907237, 0.68878959, 0.50411509], + [0.92891402, 0.68494686, 0.50173994], + [0.92864754, 0.68116207, 0.4993754], + [0.92836112, 0.67738527, 0.49701572], + [0.9280599, 0.67361354, 0.49466044], + [0.92775569, 0.66983999, 0.49230866], + [0.9274375, 0.66607098, 0.48996097], + [0.927111, 0.66230315, 0.48761688], + [0.92677996, 0.6585342, 0.485276], + [0.92644317, 0.65476476, 0.48293832], + [0.92609759, 0.65099658, 0.48060392], + [0.925747, 0.64722729, 0.47827244], + [0.92539502, 0.64345456, 0.47594352], + [0.92503106, 0.6396848, 0.47361782], + [0.92466877, 0.6359095, 0.47129427], + [0.92429828, 0.63213463, 0.46897349], + [0.92392172, 0.62835879, 0.46665526], + [0.92354597, 0.62457749, 0.46433898], + [0.9231622, 0.6207962, 0.46202524], + [0.92277222, 0.61701365, 0.45971384], + [0.92237978, 0.61322733, 0.45740444], + [0.92198615, 0.60943622, 0.45509686], + [0.92158735, 0.60564276, 0.45279137], + [0.92118373, 0.60184659, 0.45048789], + [0.92077582, 0.59804722, 0.44818634], + [0.92036413, 0.59424414, 0.44588663], + [0.91994924, 0.5904368, 0.44358868], + [0.91952943, 0.58662619, 0.4412926], + [0.91910675, 0.58281075, 0.43899817], + [0.91868096, 0.57899046, 0.4367054], + [0.91825103, 0.57516584, 0.43441436], + [0.91781857, 0.57133556, 0.43212486], + [0.9173814, 0.56750099, 0.4298371], + [0.91694139, 0.56366058, 0.42755089], + [0.91649756, 0.55981483, 0.42526631], + [0.91604942, 0.55596387, 0.42298339], + [0.9155979, 0.55210684, 0.42070204], + [0.9151409, 0.54824485, 0.4184247], + [0.91466138, 0.54438817, 0.41617858], + [0.91416896, 0.54052962, 0.41396347], + [0.91366559, 0.53666778, 0.41177769], + [0.91315173, 0.53280208, 0.40962196], + [0.91262605, 0.52893336, 0.40749715], + [0.91208866, 0.52506133, 0.40540404], + [0.91153952, 0.52118582, 0.40334346], + [0.91097732, 0.51730767, 0.4013163], + [0.910403, 0.51342591, 0.39932342], + [0.90981494, 0.50954168, 0.39736571], + [0.90921368, 0.5056543, 0.39544411], + [0.90859797, 0.50176463, 0.39355952], + [0.90796841, 0.49787195, 0.39171297], + [0.90732341, 0.4939774, 0.38990532], + [0.90666382, 0.49008006, 0.38813773], + [0.90598815, 0.486181, 0.38641107], + [0.90529624, 0.48228017, 0.38472641], + [0.90458808, 0.47837738, 0.38308489], + [0.90386248, 0.47447348, 0.38148746], + [0.90311921, 0.4705685, 0.37993524], + [0.90235809, 0.46666239, 0.37842943], + [0.90157824, 0.46275577, 0.37697105], + [0.90077904, 0.45884905, 0.37556121], + [0.89995995, 0.45494253, 0.37420106], + [0.89912041, 0.4510366, 0.37289175], + [0.8982602, 0.44713126, 0.37163458], + [0.89737819, 0.44322747, 0.37043052], + [0.89647387, 0.43932557, 0.36928078], + [0.89554477, 0.43542759, 0.36818855], + [0.89458871, 0.4315354, 0.36715654], + [0.89360794, 0.42764714, 0.36618273], + [0.89260152, 0.42376366, 0.36526813], + [0.8915687, 0.41988565, 0.36441384], + [0.89050882, 0.41601371, 0.36362102], + [0.8894159, 0.41215334, 0.36289639], + [0.888292, 0.40830288, 0.36223756], + [0.88713784, 0.40446193, 0.36164328], + [0.88595253, 0.40063149, 0.36111438], + [0.88473115, 0.39681635, 0.3606566], + [0.88347246, 0.39301805, 0.36027074], + [0.88217931, 0.38923439, 0.35995244], + [0.880851, 0.38546632, 0.35970244], + [0.87947728, 0.38172422, 0.35953127], + [0.87806542, 0.37800172, 0.35942941], + [0.87661509, 0.37429964, 0.35939659], + [0.87511668, 0.37062819, 0.35944178], + [0.87357554, 0.36698279, 0.35955811], + [0.87199254, 0.3633634, 0.35974223], + [0.87035691, 0.35978174, 0.36000516], + [0.86867647, 0.35623087, 0.36033559], + [0.86694949, 0.35271349, 0.36073358], + [0.86516775, 0.34923921, 0.36120624], + [0.86333996, 0.34580008, 0.36174113], + [0.86145909, 0.3424046, 0.36234402], + [0.85952586, 0.33905327, 0.36301129], + [0.85754536, 0.33574168, 0.36373567], + [0.855514, 0.33247568, 0.36451271], + [0.85344392, 0.32924217, 0.36533344], + [0.8513284, 0.32604977, 0.36620106], + [0.84916723, 0.32289973, 0.36711424], + [0.84696243, 0.31979068, 0.36806976], + [0.84470627, 0.31673295, 0.36907066], + [0.84240761, 0.31371695, 0.37010969], + [0.84005337, 0.31075974, 0.37119284], + [0.83765537, 0.30784814, 0.3723105], + [0.83520234, 0.30499724, 0.37346726], + [0.83270291, 0.30219766, 0.37465552], + [0.83014895, 0.29946081, 0.37587769], + [0.82754694, 0.29677989, 0.37712733], + [0.82489111, 0.29416352, 0.37840532], + [0.82218644, 0.29160665, 0.37970606], + [0.81942908, 0.28911553, 0.38102921], + [0.81662276, 0.28668665, 0.38236999], + [0.81376555, 0.28432371, 0.383727], + [0.81085964, 0.28202508, 0.38509649], + [0.8079055, 0.27979128, 0.38647583], + [0.80490309, 0.27762348, 0.3878626], + [0.80185613, 0.2755178, 0.38925253], + [0.79876118, 0.27347974, 0.39064559], + [0.79562644, 0.27149928, 0.39203532], + [0.79244362, 0.2695883, 0.39342447], + [0.78922456, 0.26773176, 0.3948046], + [0.78596161, 0.26594053, 0.39617873], + [0.7826624, 0.26420493, 0.39754146], + [0.77932717, 0.26252522, 0.39889102], + [0.77595363, 0.2609049, 0.4002279], + [0.77254999, 0.25933319, 0.40154704], + [0.76911107, 0.25781758, 0.40284959], + [0.76564158, 0.25635173, 0.40413341], + [0.76214598, 0.25492998, 0.40539471], + [0.75861834, 0.25356035, 0.40663694], + [0.75506533, 0.25223402, 0.40785559], + [0.75148963, 0.2509473, 0.40904966], + [0.74788835, 0.24970413, 0.41022028], + [0.74426345, 0.24850191, 0.41136599], + [0.74061927, 0.24733457, 0.41248516], + [0.73695678, 0.24620072, 0.41357737], + [0.73327278, 0.24510469, 0.41464364], + [0.72957096, 0.24404127, 0.4156828], + [0.72585394, 0.24300672, 0.41669383], + [0.7221226, 0.24199971, 0.41767651], + [0.71837612, 0.24102046, 0.41863486], + [0.71463236, 0.24004289, 0.41956983], + [0.7108932, 0.23906316, 0.42048681], + [0.70715842, 0.23808142, 0.42138647], + [0.70342811, 0.2370976, 0.42226844], + [0.69970218, 0.23611179, 0.42313282], + [0.69598055, 0.2351247, 0.42397678], + [0.69226314, 0.23413578, 0.42480327], + [0.68854988, 0.23314511, 0.42561234], + [0.68484064, 0.23215279, 0.42640419], + [0.68113541, 0.23115942, 0.42717615], + [0.67743412, 0.23016472, 0.42792989], + [0.67373662, 0.22916861, 0.42866642], + [0.67004287, 0.22817117, 0.42938576], + [0.66635279, 0.22717328, 0.43008427], + [0.66266621, 0.22617435, 0.43076552], + [0.65898313, 0.22517434, 0.43142956], + [0.65530349, 0.22417381, 0.43207427], + [0.65162696, 0.22317307, 0.4327001], + [0.64795375, 0.22217149, 0.43330852], + [0.64428351, 0.22116972, 0.43389854], + [0.64061624, 0.22016818, 0.43446845], + [0.63695183, 0.21916625, 0.43502123], + [0.63329016, 0.21816454, 0.43555493], + [0.62963102, 0.2171635, 0.43606881], + [0.62597451, 0.21616235, 0.43656529], + [0.62232019, 0.21516239, 0.43704153], + [0.61866821, 0.21416307, 0.43749868], + [0.61501835, 0.21316435, 0.43793808], + [0.61137029, 0.21216761, 0.4383556], + [0.60772426, 0.2111715, 0.43875552], + [0.60407977, 0.21017746, 0.43913439], + [0.60043678, 0.20918503, 0.43949412], + [0.59679524, 0.20819447, 0.43983393], + [0.59315487, 0.20720639, 0.44015254], + [0.58951566, 0.20622027, 0.44045213], + [0.58587715, 0.20523751, 0.44072926], + [0.5822395, 0.20425693, 0.44098758], + [0.57860222, 0.20328034, 0.44122241], + [0.57496549, 0.20230637, 0.44143805], + [0.57132875, 0.20133689, 0.4416298], + [0.56769215, 0.20037071, 0.44180142], + [0.5640552, 0.19940936, 0.44194923], + [0.56041794, 0.19845221, 0.44207535], + [0.55678004, 0.1975, 0.44217824], + [0.55314129, 0.19655316, 0.44225723], + [0.54950166, 0.19561118, 0.44231412], + [0.54585987, 0.19467771, 0.44234111], + [0.54221157, 0.19375869, 0.44233698], + [0.5385549, 0.19285696, 0.44229959], + [0.5348913, 0.19197036, 0.44222958], + [0.53122177, 0.1910974, 0.44212735], + [0.52754464, 0.19024042, 0.44199159], + [0.52386353, 0.18939409, 0.44182449], + [0.52017476, 0.18856368, 0.44162345], + [0.51648277, 0.18774266, 0.44139128], + [0.51278481, 0.18693492, 0.44112605], + [0.50908361, 0.18613639, 0.4408295], + [0.50537784, 0.18534893, 0.44050064], + [0.50166912, 0.18457008, 0.44014054], + [0.49795686, 0.18380056, 0.43974881], + [0.49424218, 0.18303865, 0.43932623], + [0.49052472, 0.18228477, 0.43887255], + [0.48680565, 0.1815371, 0.43838867], + [0.48308419, 0.18079663, 0.43787408], + [0.47936222, 0.18006056, 0.43733022], + [0.47563799, 0.17933127, 0.43675585], + [0.47191466, 0.17860416, 0.43615337], + [0.46818879, 0.17788392, 0.43552047], + [0.46446454, 0.17716458, 0.43486036], + [0.46073893, 0.17645017, 0.43417097], + [0.45701462, 0.17573691, 0.43345429], + [0.45329097, 0.17502549, 0.43271025], + [0.44956744, 0.17431649, 0.4319386], + [0.44584668, 0.17360625, 0.43114133], + [0.44212538, 0.17289906, 0.43031642], + [0.43840678, 0.17219041, 0.42946642], + [0.43469046, 0.17148074, 0.42859124], + [0.4309749, 0.17077192, 0.42769008], + [0.42726297, 0.17006003, 0.42676519], + [0.42355299, 0.16934709, 0.42581586], + [0.41984535, 0.16863258, 0.42484219], + [0.41614149, 0.16791429, 0.42384614], + [0.41244029, 0.16719372, 0.42282661], + [0.40874177, 0.16647061, 0.42178429], + [0.40504765, 0.16574261, 0.42072062], + [0.401357, 0.16501079, 0.41963528], + [0.397669, 0.16427607, 0.418528], + [0.39398585, 0.16353554, 0.41740053], + [0.39030735, 0.16278924, 0.41625344], + [0.3866314, 0.16203977, 0.41508517], + [0.38295904, 0.16128519, 0.41389849], + [0.37928736, 0.16052483, 0.41270599], + [0.37562649, 0.15974704, 0.41151182], + [0.37197803, 0.15895049, 0.41031532], + [0.36833779, 0.15813871, 0.40911916], + [0.36470944, 0.15730861, 0.40792149], + [0.36109117, 0.15646169, 0.40672362], + [0.35748213, 0.15559861, 0.40552633], + [0.353885, 0.15471714, 0.40432831], + [0.35029682, 0.15381967, 0.4031316], + [0.34671861, 0.1529053, 0.40193587], + [0.34315191, 0.15197275, 0.40074049], + [0.33959331, 0.15102466, 0.3995478], + [0.33604378, 0.15006017, 0.39835754], + [0.33250529, 0.14907766, 0.39716879], + [0.32897621, 0.14807831, 0.39598285], + [0.3254559, 0.14706248, 0.39480044], + [0.32194567, 0.14602909, 0.39362106], + [0.31844477, 0.14497857, 0.39244549], + [0.31494974, 0.14391333, 0.39127626], + [0.31146605, 0.14282918, 0.39011024], + [0.30798857, 0.1417297, 0.38895105], + [0.30451661, 0.14061515, 0.38779953], + [0.30105136, 0.13948445, 0.38665531], + [0.2975886, 0.1383403, 0.38552159], + [0.29408557, 0.13721193, 0.38442775], +]; diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/createMeshImageData.ts b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/createMeshImageData.ts new file mode 100644 index 000000000..d853d2a98 --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/createMeshImageData.ts @@ -0,0 +1,108 @@ +import { quantile } from "d3"; + +export type MeshImageData = { + image: HTMLCanvasElement; + width: number; + height: number; + maxValue?: number; + minValue?: number; + outlierThreshold?: number; +}; + +export async function fetchImageAndCreateMeshImageData( + url: string, + reversingImageNeeded?: boolean, +): Promise { + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + if (!ctx) { + return Promise.reject("Failed to create canvas context"); + } + + return new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => { + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0); + + const imageData = ctx.getImageData(0, 0, img.width, img.height).data; + const { minValue, maxValue, outlierThreshold } = reversingImageNeeded + ? reverseMeshDataAndComputeValues(imageData, img.width, img.height) + : { + minValue: 0, + maxValue: 100, + outlierThreshold: 100, + }; + + resolve({ + image: canvas, + width: img.width, + height: img.height, + minValue, + maxValue, + outlierThreshold, + }); + }; + img.onerror = reject; + + if (url.startsWith("data:image")) { + img.src = url; + } else { + fetch(url) + .then(response => response.blob()) + .then(blob => { + img.src = URL.createObjectURL(blob); + }) + .catch(reject); + } + }); +} + +function computeOutlierThreshold(values: number[]): number { + return ( + quantile( + values.filter(value => value > 0), + 0.999, + ) ?? 0 + ); +} + +function reverseMeshDataAndComputeValues( + data: Uint8ClampedArray, + width: number, + height: number, + scale = 1, +): Omit { + let minValue = Infinity; + let maxValue = -Infinity; + const valuesForOutlierCalculation = []; + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const i = (y * width + x) * 4; + const r = data[i]; + const g = data[i + 1]; + const b = data[i + 2]; + + let originalValue = ((((r << 16) >>> 0) + ((g << 8) >>> 0) + b) >>> 0) - 0x800000; + + if (scale !== 1) { + originalValue /= scale; + } + + minValue = Math.min(minValue, originalValue); + maxValue = Math.max(maxValue, originalValue); + + valuesForOutlierCalculation.push(Math.abs(originalValue)); + } + } + + const outlierThreshold = computeOutlierThreshold(valuesForOutlierCalculation); + + return { + minValue, + maxValue, + outlierThreshold, + }; +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/index.tsx b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/index.tsx new file mode 100644 index 000000000..6e7a38cb3 --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/index.tsx @@ -0,0 +1,149 @@ +import * as turf from "@turf/turf"; +import { BoundingSphere, Intersect, PerspectiveFrustum, Rectangle, Cartesian3 } from "cesium"; +import { memo, useEffect, useMemo, useState } from "react"; +import { useCesium } from "resium"; +import invariant from "tiny-invariant"; + +import { HeatMapAppearance } from "@reearth/beta/lib/core/mantle"; + +import { FeatureComponentConfig, FeatureProps } from "../utils"; + +import { flareColorMapLUT } from "./constants"; +import { fetchImageAndCreateMeshImageData, MeshImageData } from "./createMeshImageData"; +import { HeatmapMesh } from "./HeatmapMesh"; + +export type Props = FeatureProps; + +export type Property = HeatMapAppearance; + +export default memo(function HeatMap({ property, isVisible, layer, feature }: Props) { + const { + valueMap, + colorMap = flareColorMapLUT, + width, + height, + bounds, + cropBounds, + minValue, + maxValue, + opacity = 0.8, + contourThickness = 1, + contourAlpha = 0.2, + logarithmic = false, + } = property ?? {}; + const { scene } = useCesium(); + + // Bounds is nested object, and this cause unnecessary render frequently, so wrap with useMemo. + const boudsRef = useMemo( + () => [bounds?.west ?? 0, bounds?.south ?? 0, bounds?.east ?? 0, bounds?.north ?? 0] as const, + [bounds?.west, bounds?.south, bounds?.east, bounds?.north], + ); + + const boundingSphere = useMemo( + () => BoundingSphere.fromRectangle3D(Rectangle.fromDegrees(...boudsRef)), + [boudsRef], + ); + + const [visible, setVisible] = useState(false); + useEffect(() => { + const isVisible = (): boolean => { + const camera = scene?.camera; + const frustum = camera?.frustum; + invariant(frustum instanceof PerspectiveFrustum); + const cullingVolume = frustum.computeCullingVolume( + camera?.position || Cartesian3.ONE, + camera?.direction || Cartesian3.ONE, + camera?.up || Cartesian3.ONE, + ); + return cullingVolume.computeVisibility(boundingSphere) !== Intersect.OUTSIDE; + }; + if (isVisible()) { + setVisible(true); + return; + } + const callback = (): void => { + if (isVisible()) { + setVisible(true); + scene?.camera?.changed.removeEventListener(callback); + } + }; + scene?.camera?.changed.addEventListener(callback); + return () => { + scene?.camera?.changed.removeEventListener(callback); + }; + }, [boundingSphere, scene]); + + useEffect(() => { + return () => { + if (!scene?.isDestroyed()) { + scene?.requestRender(); + } + }; + }, [scene]); + + const [meshImageData, setMeshImageData] = useState(); + const reversingImageNeeded = property?.maxValue == null && property?.minValue == null; + useEffect(() => { + if (!visible || !valueMap) return; + fetchImageAndCreateMeshImageData(valueMap, reversingImageNeeded) + .then(meshImageData => { + setMeshImageData(meshImageData); + }) + .catch(() => {}); + }, [reversingImageNeeded, valueMap, visible]); + + const { + contourSpacing = maxValue != null + ? Math.max(10, maxValue / 20) + : Math.max(10, (meshImageData?.outlierThreshold || 0) / 20), + } = property ?? {}; + + const colorRange = + minValue != null && maxValue != null + ? [minValue, maxValue] + : extendRange([0, 100], [0, meshImageData?.outlierThreshold || 0]); + + const hasBounds = !!bounds; + const geometry = useMemo( + () => + meshImageData != null && hasBounds + ? turf.bboxPolygon([boudsRef[0], boudsRef[1], boudsRef[2], boudsRef[3]]).geometry + : undefined, + [hasBounds, boudsRef, meshImageData], + ); + + if (!isVisible || meshImageData == null || geometry == null) { + return null; + } + return ( + + ); +}); + +function extendRange(a: number[], b: number[]): [number, number] { + invariant(a.length === 2); + invariant(b.length === 2); + return [Math.min(a[0], b[0]), Math.max(a[1], b[1])]; +} + +export const config: FeatureComponentConfig = { + noFeature: true, +}; diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/heatmapMeshMaterial.glsl b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/heatmapMeshMaterial.glsl new file mode 100644 index 000000000..a56d9e15e --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/heatmapMeshMaterial.glsl @@ -0,0 +1,78 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/heatmap/src/shaders/heatmapMeshMaterial.glsl + +uniform sampler2D colorMap; +uniform sampler2D image; +uniform vec2 imageScale; +uniform vec2 imageOffset; +uniform float width; +uniform float height; +uniform float opacity; +uniform float contourSpacing; +uniform float contourThickness; +uniform float contourAlpha; +uniform bool logarithmic; + +#define LOG_10 (2.302585092994046) + +float pseudoLog(float value) { + return value > 10.0 + ? log(value) / LOG_10 + : value < -10.0 + ? -log(-value) / LOG_10 + : value / 10.0; +} + +czm_material czm_getMaterial(czm_materialInput materialInput) { + vec2 texSize = vec2(width, height); + vec2 texelSize = 1.0 / texSize; + vec2 pair = sampleBicubic( + image, + // TODO: Derive geographic coordinates from UV and unproject them to find + // non-linear sampling coordinates. + materialInput.st * imageScale + imageOffset, + texSize, + texelSize + ); + float value = pair.x; + float alpha = pair.y; + + float scaledMinValue = czm_branchFreeTernary( + logarithmic, + pseudoLog(minValue), + minValue + ); + float scaledMaxValue = czm_branchFreeTernary( + logarithmic, + pseudoLog(maxValue), + maxValue + ); + float scaledValue = czm_branchFreeTernary( + logarithmic, + pseudoLog(value), + value + ); + + float normalizedValue = clamp( + (scaledValue - scaledMinValue) / (scaledMaxValue - scaledMinValue), + 0.0, + 1.0 + ); + vec3 color = texture(colorMap, vec2(normalizedValue, 0.5)).rgb; + color = czm_gammaCorrect(color); + + float contour = makeContour( + value - minValue, + contourSpacing, + contourThickness + ); + color = mix( + color, + vec3(step(dot(color, vec3(0.299, 0.587, 0.114)), 0.5)), + contour * contourAlpha + ); + + czm_material material = czm_getDefaultMaterial(materialInput); + material.diffuse = color; + material.alpha = opacity * alpha; + return material; +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/makeContour.glsl b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/makeContour.glsl new file mode 100644 index 000000000..363ee8fca --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/makeContour.glsl @@ -0,0 +1,13 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/heatmap/src/shaders/makeContour.glsl +// Reference: https://github.com/CesiumGS/cesium/blob/main/packages/engine/Source/Shaders/Materials/ElevationContourMaterial.glsl + +float makeContour(float value, float spacing, float width) { + if (value < spacing) { + return 0.0; + } + float distanceToContour = mod(value + 0.5, spacing); + float dx = abs(dFdx(value)); + float dy = abs(dFdy(value)); + float f = max(dx, dy) * czm_pixelRatio * width; + return step(distanceToContour, f); +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/sampleBicubic.glsl b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/sampleBicubic.glsl new file mode 100644 index 000000000..69262229a --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/shaders/sampleBicubic.glsl @@ -0,0 +1,57 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/heatmap/src/shaders/sampleBicubic.glsl + +vec2 unpack(vec4 value) { + return vec2( + dot(value.rgb, vec3(16711680.0, 65280.0, 255.0)) - 8388608.0, + (value.a - 0.5) * 2.0 + ); +} + +vec2 sampleBilinear( + sampler2D image, + vec2 texCoord, + vec2 texSize, + vec2 texelSize +) { + vec2 unnormTexCoord = texCoord * texSize - 0.5; + vec2 uv = (floor(unnormTexCoord) + 0.5) / texSize; + vec2 f = fract(unnormTexCoord); + vec2 s1 = unpack(texture(image, uv)); + vec2 s2 = unpack(texture(image, uv + vec2(texelSize.x, 0.0))); + vec2 s3 = unpack(texture(image, uv + vec2(0.0, texelSize.y))); + vec2 s4 = unpack(texture(image, uv + texelSize)); + return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y); +} + +// Reference: https://jvm-gaming.org/t/glsl-simple-fast-bicubic-filtering-shader-function/52549 +vec4 cubic(float v) { + vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v; + vec4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return vec4(x, y, z, w) * (1.0 / 6.0); +} + +vec2 sampleBicubic( + sampler2D image, + vec2 texCoord, + vec2 texSize, + vec2 texelSize +) { + vec2 unnormTexCoord = texCoord * texSize - 0.5; + vec2 f = fract(unnormTexCoord); + vec4 cubicX = cubic(f.x); + vec4 cubicY = cubic(f.y); + vec4 c = (unnormTexCoord - f).xxyy + vec2(-0.5, 1.5).xyxy; + vec4 s = vec4(cubicX.xz + cubicX.yw, cubicY.xz + cubicY.yw); + vec4 offset = (c + vec4(cubicX.yw, cubicY.yw) / s) * texelSize.xxyy; + vec2 s1 = sampleBilinear(image, offset.xz, texSize, texelSize); + vec2 s2 = sampleBilinear(image, offset.yz, texSize, texelSize); + vec2 s3 = sampleBilinear(image, offset.xw, texSize, texelSize); + vec2 s4 = sampleBilinear(image, offset.yw, texSize, texelSize); + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + return mix(mix(s4, s3, sx), mix(s2, s1, sx), sy); +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/utils.ts b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/utils.ts new file mode 100644 index 000000000..6f88ba9eb --- /dev/null +++ b/web/src/beta/lib/core/engines/Cesium/Feature/HeatMap/utils.ts @@ -0,0 +1,30 @@ +// ref: https://github.com/takram-design-engineering/plateau-view/blob/main/libs/cesium-helpers/src/convertPolygonToHierarchyArray.ts + +import { Cartesian3, type PolygonHierarchy } from "@cesium/engine"; +import unkinkPolygon from "@turf/unkink-polygon"; +import { type MultiPolygon, type Polygon, type Position } from "geojson"; + +function coordinatesToHierarchy(coordinates: readonly Position[][]): PolygonHierarchy | undefined { + return coordinates.length > 0 + ? { + positions: coordinates[0].map(([x, y]) => Cartesian3.fromDegrees(x, y, 0)), + holes: coordinates.slice(1).map(coordinates => ({ + positions: coordinates.map(([x, y]) => Cartesian3.fromDegrees(x, y, 0)), + holes: [], + })), + } + : undefined; +} + +export function convertPolygonToHierarchyArray( + polygon: Polygon | MultiPolygon, +): PolygonHierarchy[] { + const polygons = unkinkPolygon(polygon).features; + return polygons + .map(polygon => coordinatesToHierarchy(polygon.geometry.coordinates)) + .filter(isNotNullish); +} + +export function isNotNullish(value: T | null | undefined): value is T { + return value != null; +} diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/index.tsx b/web/src/beta/lib/core/engines/Cesium/Feature/index.tsx index 2524c2ea5..2cc9f78d4 100644 --- a/web/src/beta/lib/core/engines/Cesium/Feature/index.tsx +++ b/web/src/beta/lib/core/engines/Cesium/Feature/index.tsx @@ -9,6 +9,7 @@ import Box, { config as boxConfig } from "./Box"; import Ellipse, { config as ellipseConfig } from "./Ellipse"; import Ellipsoid, { config as ellipsoidConfig } from "./Ellipsoid"; import Frustum, { config as frustumConfig } from "./Frustum"; +import HeatMap, { config as heatMapConfig } from "./HeatMap"; import Marker, { config as markerConfig } from "./Marker"; import Model, { config as modelConfig } from "./Model"; import PhotoOverlay, { config as photoOverlayConfig } from "./PhotoOverlay"; @@ -49,6 +50,7 @@ const components: Record< photooverlay: [PhotoOverlay, photoOverlayConfig], resource: [Resource, resourceConfig], raster: [Raster, rasterConfig], + heatMap: [HeatMap, heatMapConfig], frustum: [Frustum, frustumConfig], }; @@ -71,6 +73,7 @@ const displayConfig: Record = { gml: [], gltf: ["model"], tiles: ["raster"], + heatMap: ["heatMap"], }; // Some layer that is delegated data is not computed when layer is updated. diff --git a/web/src/beta/lib/core/engines/Cesium/Feature/utils.tsx b/web/src/beta/lib/core/engines/Cesium/Feature/utils.tsx index 17d3c1092..84942e290 100644 --- a/web/src/beta/lib/core/engines/Cesium/Feature/utils.tsx +++ b/web/src/beta/lib/core/engines/Cesium/Feature/utils.tsx @@ -14,6 +14,7 @@ import { Cesium3DTilePointFeature, ImageryLayer, Primitive, + GroundPrimitive, } from "cesium"; import md5 from "js-md5"; import { pick } from "lodash-es"; @@ -102,6 +103,7 @@ export function attachTag( | InternalCesium3DTileFeature | ImageryLayer | Primitive + | GroundPrimitive | null | undefined, tag: Tag, @@ -128,6 +130,11 @@ export function attachTag( return; } + if (entity instanceof GroundPrimitive) { + (entity as any)[tagKey] = tag; + return; + } + if (!entity.properties) { entity.properties = new PropertyBag(); } @@ -145,6 +152,7 @@ export function getTag( | Cesium3DTileFeature | Cesium3DTilePointFeature | Primitive + | GroundPrimitive | Model | ImageryLayer | null @@ -169,6 +177,10 @@ export function getTag( return (entity as any)[tagKey]; } + if (entity instanceof GroundPrimitive) { + return (entity as any)[tagKey]; + } + if (!entity.properties) return; return Object.fromEntries( diff --git a/web/src/beta/lib/core/engines/Cesium/hooks.ts b/web/src/beta/lib/core/engines/Cesium/hooks.ts index ba8a15960..f32938d18 100644 --- a/web/src/beta/lib/core/engines/Cesium/hooks.ts +++ b/web/src/beta/lib/core/engines/Cesium/hooks.ts @@ -13,6 +13,7 @@ import { DirectionalLight, Viewer as CesiumViewer, Primitive, + GroundPrimitive, ShadowMap, } from "cesium"; import CesiumDnD, { Context } from "cesium-dnd"; @@ -321,7 +322,7 @@ export default ({ }, [camera, engineAPI]); const prevSelectedEntity = useRef< - Entity | Cesium3DTileset | InternalCesium3DTileFeature | Primitive + Entity | Cesium3DTileset | InternalCesium3DTileFeature | Primitive | GroundPrimitive >(); // manage layer selection useEffect(() => { @@ -594,7 +595,10 @@ export default ({ return; } - if (target?.primitive && target.primitive instanceof Primitive) { + if ( + target?.primitive && + (target.primitive instanceof Primitive || target.primitive instanceof GroundPrimitive) + ) { const primitive = target.primitive; const tag = getTag(primitive); if (tag) { diff --git a/web/src/beta/lib/core/engines/Cesium/useEngineRef.ts b/web/src/beta/lib/core/engines/Cesium/useEngineRef.ts index 48f3ebf5f..2ab3e23ca 100644 --- a/web/src/beta/lib/core/engines/Cesium/useEngineRef.ts +++ b/web/src/beta/lib/core/engines/Cesium/useEngineRef.ts @@ -261,8 +261,8 @@ export default function useEngineRef( if (!viewer || viewer.isDestroyed()) return; const layerOrFeatureId = target; - const entityFromFeatureId = findEntity(viewer, undefined, layerOrFeatureId, true); - + const entityFromFeatureId = findEntity(viewer, layerOrFeatureId, layerOrFeatureId, true); + const tag = getTag(entityFromFeatureId); if (entityFromFeatureId instanceof Cesium.Primitive) { viewer.scene.camera.flyToBoundingSphere( Cesium.BoundingSphere.fromTransformation(entityFromFeatureId.modelMatrix), @@ -270,6 +270,14 @@ export default function useEngineRef( return; } + // specifically added for HeatMap, consult @pyshx before making changes here + if (entityFromFeatureId instanceof Cesium.GroundPrimitive) { + viewer.scene.camera.flyToBoundingSphere( + tag?.originalProperties as Cesium.BoundingSphere, + ); + return; + } + // `viewer.flyTo` doesn't support Cesium3DTileFeature. if ( entityFromFeatureId && @@ -277,7 +285,8 @@ export default function useEngineRef( entityFromFeatureId instanceof Cesium.Cesium3DTileFeature || entityFromFeatureId instanceof Cesium.Cesium3DTilePointFeature || entityFromFeatureId instanceof Cesium.Model || - entityFromFeatureId instanceof Cesium.Primitive + entityFromFeatureId instanceof Cesium.Primitive || + entityFromFeatureId instanceof Cesium.GroundPrimitive ) ) { viewer.flyTo(entityFromFeatureId, options); @@ -320,7 +329,8 @@ export default function useEngineRef( entityFromLayerId instanceof Cesium.Cesium3DTileFeature || entityFromLayerId instanceof Cesium.Cesium3DTilePointFeature || entityFromLayerId instanceof Cesium.Model || - entityFromLayerId instanceof Cesium.Primitive + entityFromLayerId instanceof Cesium.Primitive || + entityFromLayerId instanceof Cesium.GroundPrimitive ) ) { viewer.flyTo(entityFromLayerId, options); diff --git a/web/src/beta/lib/core/engines/Cesium/utils.ts b/web/src/beta/lib/core/engines/Cesium/utils.ts index 359049e31..1d892cc12 100644 --- a/web/src/beta/lib/core/engines/Cesium/utils.ts +++ b/web/src/beta/lib/core/engines/Cesium/utils.ts @@ -16,6 +16,7 @@ import { Viewer, Cesium3DTilePointFeature, Primitive, + GroundPrimitive, } from "cesium"; import { InfoboxProperty } from "@reearth/beta/lib/core/Crust/Infobox"; @@ -141,7 +142,13 @@ export function findEntity( layerId?: string, featureId?: string, withoutTileFeature?: boolean, -): Entity | Cesium3DTileset | InternalCesium3DTileFeature | Primitive | undefined { +): + | Entity + | Cesium3DTileset + | InternalCesium3DTileFeature + | Primitive + | GroundPrimitive + | undefined { const id = featureId ?? layerId; const keyName = featureId ? "featureId" : "layerId"; if (!id) return; @@ -149,6 +156,8 @@ export function findEntity( let entity = viewer.entities.getById(id); if (entity) return entity; + // we can store groundPrimitives as a state as aren't saved as unique entities in the viewer, i.e Workaround for making FlyTo for HeatMaps: @pyshx + entity = viewer.entities.values.find(e => getTag(e)?.[keyName] === id); if (entity) return entity; @@ -162,10 +171,14 @@ export function findEntity( } } - // Find Cesium3DTileset or Primitive + // Find Cesium3DTileset or Primitive or GroundPrimitive for (let i = 0; i < viewer.scene.primitives.length; i++) { const prim = viewer.scene.primitives.get(i); - if (!(prim instanceof Cesium3DTileset) && !(prim instanceof Primitive)) { + if ( + !(prim instanceof Cesium3DTileset) && + !(prim instanceof Primitive) && + !(prim instanceof GroundPrimitive) + ) { continue; } diff --git a/web/src/beta/lib/core/mantle/types/appearance.ts b/web/src/beta/lib/core/mantle/types/appearance.ts index 7dfeace70..f5618af97 100644 --- a/web/src/beta/lib/core/mantle/types/appearance.ts +++ b/web/src/beta/lib/core/mantle/types/appearance.ts @@ -2,6 +2,8 @@ import { objKeys } from "../utils"; import type { ExpressionContainer } from "./expression"; import type { + LUT, + Bound, Camera, ClassificationType, EXPERIMENTAL_clipping, @@ -29,6 +31,7 @@ export type AppearanceTypes = { photooverlay: LegacyPhotooverlayAppearance; resource: ResourceAppearance; raster: RasterAppearance; + heatMap: HeatMapAppearance; frustum: FrustumAppearance; transition: TransitionAppearance; }; @@ -104,6 +107,22 @@ export type PolygonAppearance = { classificationType?: ClassificationType; }; +export type HeatMapAppearance = { + valueMap: string; + bounds: Bound; + colorMap?: LUT; + cropBounds?: Bound; + width?: number; + height?: number; + minValue?: number; + maxValue?: number; + opacity?: number; + contourSpacing?: number; + contourThickness?: number; + contourAlpha?: number; + logarithmic?: boolean; +}; + export type EllipsoidAppearance = { show?: boolean; heightReference?: "none" | "clamp" | "relative"; @@ -277,6 +296,7 @@ export const appearanceKeyObj: { [k in keyof AppearanceTypes]: 1 } = { photooverlay: 1, resource: 1, raster: 1, + heatMap: 1, frustum: 1, transition: 1, }; diff --git a/web/src/beta/lib/core/mantle/types/index.ts b/web/src/beta/lib/core/mantle/types/index.ts index 271da06b3..ee63994e7 100644 --- a/web/src/beta/lib/core/mantle/types/index.ts +++ b/web/src/beta/lib/core/mantle/types/index.ts @@ -112,7 +112,8 @@ export type DataType = | "georss" | "gltf" | "tiles" - | "tms"; + | "tms" + | "heatMap"; export type TimeInterval = [start: Date, end?: Date]; diff --git a/web/src/beta/lib/core/mantle/types/value.ts b/web/src/beta/lib/core/mantle/types/value.ts index 35885b75f..d047dc831 100644 --- a/web/src/beta/lib/core/mantle/types/value.ts +++ b/web/src/beta/lib/core/mantle/types/value.ts @@ -38,6 +38,16 @@ export type Spacing = { top: number; }; +export type Bound = { + east: number; + north: number; + south: number; + west: number; +}; + +export type ColorTuple = [number, number, number]; +export type LUT = readonly ColorTuple[]; + export type Coordinates = LatLngHeight[]; export type Polygon = LatLngHeight[][]; diff --git a/web/src/beta/utils/util.ts b/web/src/beta/utils/util.ts index e67345ae9..4a20a0a59 100644 --- a/web/src/beta/utils/util.ts +++ b/web/src/beta/utils/util.ts @@ -1,3 +1,5 @@ +import { useRef } from "react"; + import { Args, Args3, Args2 } from "@reearth/types"; /** @@ -69,3 +71,11 @@ export function checkIfFileType(url: string, fileTypes: string) { export const isEmptyString = function (text: string): boolean { return text === null || /^ *$/.test(text); }; + +export function useConstant(callback: () => T): T { + const ref = useRef<{ value: T }>(); + if (ref.current == null) { + ref.current = { value: callback() }; + } + return ref.current.value; +} diff --git a/web/yarn.lock b/web/yarn.lock index bbe04c68d..b82ebaa4c 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -8376,6 +8376,216 @@ dependencies: "@types/node" "*" +"@types/d3-array@*": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" + integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + +"@types/d3-drag@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.9.tgz#dd96ccefba4386fe4ff36b8e4ee4e120c21fcf29" + integrity sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.6.tgz#8d3638df273ec90da34b3ac89d8784c59708cb0d" + integrity sha512-qlmD/8aMk5xGorUvTUWHCiumvgaUXYldYjNVOWtYoTYY/L+WwIEAmJxUmTgr9LoGNG0PPAOmqMDJVDPc7DOpPw== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.2.tgz#4327f4a05d475cf9be46a93fc2e0f8d23380805a" + integrity sha512-WAIEVlOCdd/NKRYTsqCpOMHQHemKBEINf8YXMYOtXH0GA7SY0dqMB78P3Uhgfy+4X+/Mlw2wDtlETkN6kQUCMA== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" + integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== + +"@types/d3-scale@*": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe" + integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg== + +"@types/d3-shape@*": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72" + integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f" + integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.3": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + "@types/debug@^4.0.0": version "4.1.8" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.8.tgz#cef723a5d0a90990313faec2d1e22aee5eecb317" @@ -10434,6 +10644,11 @@ commander@2: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@7: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" @@ -10746,6 +10961,103 @@ d3-array@1: resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + d3-geo@1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.7.1.tgz#44bbc7a218b1fd859f3d8fd7c443ca836569ce99" @@ -10753,11 +11065,158 @@ d3-geo@1.7.1: dependencies: d3-array "1" +d3-geo@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" + integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-scale-chromatic@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" + integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + d3-voronoi@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c" integrity sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw== +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.8.5: + version "7.8.5" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.8.5.tgz#fde4b760d4486cdb6f0cc8e2cbff318af844635c" + integrity sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + data-uri-to-buffer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" @@ -10982,6 +11441,13 @@ del@^7.1.0: rimraf "^3.0.2" slash "^4.0.0" +delaunator@5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -12989,7 +13455,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.6.3, iconv-lite@^0.6.3: +iconv-lite@0.6, iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -13115,6 +13581,11 @@ internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -16963,6 +17434,11 @@ robust-predicates@^2.0.4: resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-2.0.4.tgz#0a2367a93abd99676d075981707f29cfb402248b" integrity sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg== +robust-predicates@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + rollup-plugin-external-globals@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/rollup-plugin-external-globals/-/rollup-plugin-external-globals-0.6.1.tgz#861c260b5727144e0fd1b424b103f9f0282fc365" @@ -17063,6 +17539,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@^7.5.5, rxjs@^7.8.0: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index fb57ccd13..000000000 --- a/yarn.lock +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -