Conversation
…load functionality
…mproved iframe rendering
…ce pixel calculations
…tions for width and height based on device pixel ratio
…improving canvas handling for accurate output
… GeoTIFF output and resetting map size post-capture
… and update snapshot function to ensure proper data URL format for GeoTIFF conversion
…rchive. support kml, kmz, and worldfile generation
…urate GeoTIFF output
…-vector-tile-snapshot
…ent calculations, and dynamic EPSG code handling
…orldview into WV-3018-vector-tile-snapshot
…orldview into WV-3018-vector-tile-snapshot
…tions and optimizing high-res tile grid updates
There was a problem hiding this comment.
Pull Request Overview
This PR implements front-end rendering for snapshot generation, replacing the WVS API approach. This enables snapshot generation for any imagery renderable in Worldview, improves ground resolution accuracy by ~9.5%, and moves the resource-intensive processing to the edge.
- Frontend snapshot generation using html2canvas and GDAL for georeferencing
- Updated resolution handling with meters-per-pixel values instead of symbolic strings
- Support for multiple output formats (JPEG, PNG, GeoTIFF, KMZ) with client-side georeferencing
Reviewed Changes
Copilot reviewed 128 out of 129 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| webpack.config.js | Added GDAL.js dependencies and build configuration |
| web/js/modules/image-download/util.js | Core snapshot functionality with canvas capture and georeferencing |
| web/js/modules/image-download/util.test.js | Comprehensive test suite for new snapshot functions |
| web/js/components/image-download/image-download-panel.js | Updated UI to use new snapshot system with progress indicators |
| web/js/modules/image-download/constants.js | Updated resolution constants with meter-based values and tile matrix IDs |
| package.json | Added required dependencies for canvas rendering and GDAL processing |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| function getMetersPerUnit(projection, center = [0, 0]) { | ||
| const units = projection.getUnits(); | ||
| let metersPerUnit = projection.getMetersPerUnit(); | ||
|
|
||
| if (units === 'degrees') metersPerUnit *= evaluate(`cos((${center[1]} * pi) / ${180})`); | ||
|
|
||
| return metersPerUnit; | ||
| } |
There was a problem hiding this comment.
Using mathjs evaluate() for simple mathematical operations is inefficient. Replace with native JavaScript: metersPerUnit *= Math.cos((center[1] * Math.PI) / 180).
| function convertResolutionToMetersPerPixel(resolution, projection, center = [0, 0]) { | ||
| const metersPerUnit = getMetersPerUnit(projection, center); | ||
|
|
||
| return evaluate(`${resolution} * ${metersPerUnit}`); |
There was a problem hiding this comment.
Using mathjs evaluate() for simple multiplication is unnecessary overhead. Replace with native JavaScript: return resolution * metersPerUnit.
| return evaluate(`${resolution} * ${metersPerUnit}`); | |
| return resolution * metersPerUnit; |
| ); | ||
| }; | ||
|
|
||
| const timeout = setTimeout(onCancelSnapshot, 180_000); |
There was a problem hiding this comment.
The 3-minute timeout value (180_000ms) should be extracted to a named constant for better maintainability and clarity.
| const matrixIds = originalTileGrid.getMatrixIds?.(); | ||
| const maxResolutions = new Array(resolutions.length) | ||
| .fill(resolutions.at(tileMatrixID) || resolutions.at(-1)) | ||
| .map((res, i) => evaluate(`${res} - (${i} * (${res} * 0.000000000001))`)); // Ensure unique resolutions see: openlayers/src/ol/tilegrid/TileGrid.js line 90 |
There was a problem hiding this comment.
Using mathjs evaluate() in a map operation is inefficient. Replace with native JavaScript: .map((res, i) => res - (i * (res * 0.000000000001))).
| const aoiPixelWidth = Math.abs(evaluate(`${aoiPixelTopRight[0]} - ${aoiPixelTopLeft[0]}`)); | ||
| const aoiPixelHeight = Math.abs(evaluate(`${aoiPixelBottomLeft[1]} - ${aoiPixelTopLeft[1]}`)); |
There was a problem hiding this comment.
Using mathjs evaluate() for simple arithmetic is inefficient. Replace with native JavaScript: Math.abs(aoiPixelTopRight[0] - aoiPixelTopLeft[0]) and Math.abs(aoiPixelBottomLeft[1] - aoiPixelTopLeft[1]).
| const outputWidth = evaluate(`${aoiPixelWidth} * ${dpr}`); | ||
| const outputHeight = evaluate(`${aoiPixelHeight} * ${dpr}`); |
There was a problem hiding this comment.
Using mathjs evaluate() for simple multiplication is unnecessary. Replace with native JavaScript: aoiPixelWidth * dpr and aoiPixelHeight * dpr.
| const outputWidth = evaluate(`${aoiPixelWidth} * ${dpr}`); | |
| const outputHeight = evaluate(`${aoiPixelHeight} * ${dpr}`); | |
| const outputWidth = aoiPixelWidth * dpr; | |
| const outputHeight = aoiPixelHeight * dpr; |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Design round one * loading spinner style tweak
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Refactor snapshot function to improve readability * lint fix * move comment to correct location * Removed unneeded rejectIfAborted --------- Co-authored-by: christof-wittreich <christof.wittreich@nasa.gov>
* Added check when setting tile loading state * Storm tracks fixed for snapshots
Description
Uses front-end rendering to generate snapshots instead of the WVS API. This allows us to generate snapshots of any imagery that can be rendered in Worldview, easily add other map elements (legend, scale-bar, etc.), moves the resource intensive part of the process to the edge, and makes the ground resolution of the output image more accurate (improved by ~9.5%).
How To Test
git checkout WV-3018-vector-tile-snapshotnpm i && npm run dev && npm run watchPR Submission Checklist
This is simply a reminder of what we are going to look for before merging your code.
Merging
Please use the
squash and mergecommit method unless each commit in your branch is vital to the commit history of main.@nasa-gibs/worldview