Skip to content

WV-3018 vector tile snapshot#5758

Draft
PatchesMaps wants to merge 81 commits intodevelopfrom
WV-3018-vector-tile-snapshot
Draft

WV-3018 vector tile snapshot#5758
PatchesMaps wants to merge 81 commits intodevelopfrom
WV-3018-vector-tile-snapshot

Conversation

@PatchesMaps
Copy link
Collaborator

@PatchesMaps PatchesMaps commented Mar 17, 2025

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

  1. git checkout WV-3018-vector-tile-snapshot
  2. npm i && npm run dev && npm run watch
  3. Open
  4. Experiment with generating snapshots and compare to ones generated by WVS.

PR Submission Checklist

This is simply a reminder of what we are going to look for before merging your code.

  • I have read the CONTRIBUTING doc
  • I have added necessary documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)
  • Any dependent changes have been merged and published in downstream modules (if applicable)

Merging

Please use the squash and merge commit method unless each commit in your branch is vital to the commit history of main.

@nasa-gibs/worldview

…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
@PatchesMaps PatchesMaps self-assigned this Mar 17, 2025
@PatchesMaps PatchesMaps marked this pull request as draft March 17, 2025 14:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +114 to +121
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;
}
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using mathjs evaluate() for simple mathematical operations is inefficient. Replace with native JavaScript: metersPerUnit *= Math.cos((center[1] * Math.PI) / 180).

Copilot uses AI. Check for mistakes.
function convertResolutionToMetersPerPixel(resolution, projection, center = [0, 0]) {
const metersPerUnit = getMetersPerUnit(projection, center);

return evaluate(`${resolution} * ${metersPerUnit}`);
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using mathjs evaluate() for simple multiplication is unnecessary overhead. Replace with native JavaScript: return resolution * metersPerUnit.

Suggested change
return evaluate(`${resolution} * ${metersPerUnit}`);
return resolution * metersPerUnit;

Copilot uses AI. Check for mistakes.
);
};

const timeout = setTimeout(onCancelSnapshot, 180_000);
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 3-minute timeout value (180_000ms) should be extracted to a named constant for better maintainability and clarity.

Copilot uses AI. Check for mistakes.
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
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using mathjs evaluate() in a map operation is inefficient. Replace with native JavaScript: .map((res, i) => res - (i * (res * 0.000000000001))).

Copilot uses AI. Check for mistakes.
Comment on lines +776 to +777
const aoiPixelWidth = Math.abs(evaluate(`${aoiPixelTopRight[0]} - ${aoiPixelTopLeft[0]}`));
const aoiPixelHeight = Math.abs(evaluate(`${aoiPixelBottomLeft[1]} - ${aoiPixelTopLeft[1]}`));
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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]).

Copilot uses AI. Check for mistakes.
Comment on lines +785 to +786
const outputWidth = evaluate(`${aoiPixelWidth} * ${dpr}`);
const outputHeight = evaluate(`${aoiPixelHeight} * ${dpr}`);
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using mathjs evaluate() for simple multiplication is unnecessary. Replace with native JavaScript: aoiPixelWidth * dpr and aoiPixelHeight * dpr.

Suggested change
const outputWidth = evaluate(`${aoiPixelWidth} * ${dpr}`);
const outputHeight = evaluate(`${aoiPixelHeight} * ${dpr}`);
const outputWidth = aoiPixelWidth * dpr;
const outputHeight = aoiPixelHeight * dpr;

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@rboller rboller removed their request for review October 1, 2025 19:12
PatchesMaps and others added 12 commits October 14, 2025 16:25
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants