Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STAC support (a STAC layer group) #14927

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

m-mohr
Copy link
Contributor

@m-mohr m-mohr commented Jul 20, 2023

This PR proposes to add STAC capabilities to OpenLayers. It adds a STAC LayerGroup.

The layer group creates various layers depending on the given options and what the STAC entity offers, e.g. footprints, COGs and thumbnails. What usually is the source is the stac-js library here.

Examples: https://deploy-preview-14927--ol-site.netlify.app/en/latest/examples/?q=stac

The work is based on PR #14101 from @tschaub (he's aware of this work).
The interface is mostly aligned with the stac-layer library for Leaflet (https://github.com/stac-utils/stac-layer), which is also based on stac-js and offers pretty much the same functionality.

An important question is whether this is something for OL core or whether I should publish this as an extension.

The functionality implemented here includes:

  • Bounding box / geometry rendering with custom styles
  • COG rendering (client-side or server-side)
    • it reads various information from the STAC metadata to find a good default rendering
    • if the client-side rendering errors (e.g. due to CORS), it can fallback to a XYZ tile-server
  • Rendering of thumbnails if no COG is available
  • Several options to customize the behavior, e.g. specific bands, which assets to display, tile-server, styles, ...
  • Supports STAC Items, Collections, API Collections, and API Items
  • Supports older STAC versions (via stac-migrate)
  • Supports several events: assetsready, sourceready, error
  • Multiple examples showing various ways of usage
  • The async method getSourceOptions (implemented by @tschaub) to provide a function that returns options for the source given item metadata. The Planetary Computer example uses this option to sign the asset URLs before the source is created.
  • Adds a projection option to the GeoTiff source to allow overriding the auto-detected projection with what STAC provides Moved to Allow to set GeoTiff projection #15036

Todos:

Curious to get thoughts from others and maybe point me to things that can be improved.

PS: The work on this was funded by Planet and EOX.

@m-mohr m-mohr changed the title Stac js STAC support (a STAC source and layer group) Jul 20, 2023
@github-actions
Copy link

📦 Preview the website for this branch here: https://deploy-preview-14927--ol-site.netlify.app/.

@jahow
Copy link
Contributor

jahow commented Jul 21, 2023

Impressive work @m-mohr, thanks!! since you're asking for feedback here are a few things that came to my mind when reading your PR. Note that some aspects of the PR may have already been discussed and agreed on so this is just my opinion!

  • The fact that the STAC layer can create other layers (e.g. in case of a collection of items) is uncommon for layers in the library; this might make things awkward for users e.g. for specifying layer options (should layer options be applied to all created layer?) or getting back these layers without searching through the layer tree
  • More generally, it feels like the STAC layer is doing too much magic: using a XYZ or Geotiff source depending of where tiles are computed, using a vector source for the footprint and a static source for the preview... I think the API would be more explicit and straightforward with utilities like readStacItem and readStacCollection (naming probably dumb) that would then allow the user to explicitly create the type of layer and source they want according to the assets found; it might be significantly more verbose though
  • I would externalize STAC-related utilities to make the STAC layer file lighter (see for example https://github.com/openlayers/openlayers/blob/main/src/ol/source/ogcTileUtil.js)
  • Some examples have logic for reading layer titles as well, but this doesn't show up visually (it looks like it's expecting a layer tree ?)

Again, this is just my opinion and not a definitive review. And it's great to see first-class STAC support coming in OpenLayers!

@m-mohr
Copy link
Contributor Author

m-mohr commented Jul 21, 2023

Thank you for your feedback @jahow, I appeciate it!

The fact that the STAC layer can create other layers (e.g. in case of a collection of items) is uncommon for layers in the library; this might make things awkward for users e.g. for specifying layer options (should layer options be applied to all created layer?) or getting back these layers without searching through the layer tree

This is something we could improve, of course, e.g. by having options like geotiffOptions, xyzOptions that are passed through. We could also specify a property for each layer for identification purposes.

More generally, it feels like the STAC layer is doing too much magic: using a XYZ or Geotiff source depending of where tiles are computed, using a vector source for the footprint and a static source for the preview... I think the API would be more explicit and straightforward with utilities like readStacItem and readStacCollection (naming probably dumb) that would then allow the user to explicitly create the type of layer and source they want according to the assets found; it might be significantly more verbose though

That's why it is a LayerGroup, of course. If you just want XYZ or GeoTiff or VectorLayer, stac-js makes it very simple to just use those separately, but then you don't need any STAC integration at all in OL, I think. The LayerGroup is meant to make life very easy and give a consistent rendering behavior for STAC. But I can understand that this might be too much magic for the core OL library. In that case an option could also be to just include the change to the GeoTiff in this PR, and then keep the magic/LayerGroup as extension outside of this repo. Also fine with me. Just let me know what the maintainers think about it.

I would externalize STAC-related utilities to make the STAC layer file lighter (see for example https://github.com/openlayers/openlayers/blob/main/src/ol/source/ogcTileUtil.js)

Sure, I've created a stacUtil.js to externalize some of the code. Other than that, I'd need to dig a bit deeper to see what makes sense. If you have something obvious in mind, please let me know.

Some examples have logic for reading layer titles as well, but this doesn't show up visually (it looks like it's expecting a layer tree ?)

Yeah, I think it was for debugging purposes at some point. I could add a layer switcher there, which could help visualize the layer tree structure. Not sure whether that's something you would want in an example though?

@m-mohr m-mohr changed the title STAC support (a STAC source and layer group) STAC support (a STAC layer group) Jul 21, 2023
@m-mohr m-mohr force-pushed the stac-js branch 4 times, most recently from a98ec25 to d183dee Compare July 25, 2023 19:48
@m-mohr m-mohr force-pushed the stac-js branch 3 times, most recently from 7e01122 to f9a1f7b Compare August 2, 2023 14:41
src/ol/layer/STAC.js Outdated Show resolved Hide resolved
src/ol/layer/stacUtil.js Outdated Show resolved Hide resolved
@m-mohr m-mohr marked this pull request as ready for review August 2, 2023 16:43
Comment on lines 513 to 522
const features = new GeoJSON().readFeatures(geojson, {
featureProjection: 'EPSG:3857', // TODO: revisit this
});
const source = new VectorSource({features});
const vectorLayer = new VectorLayer({
source,
style: getBoundsStyle(this.boundsStyle_, this),
});
vectorLayer.set('bounds', true);
features.forEach((feature) => feature.set('stac', data));
Copy link
Member

Choose a reason for hiding this comment

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

A few thoughts here:

  • If you configure the source with a loader instead of features, you can use the view projection, which is passed to the loader as 3rd argument. Then you do not need to hard-code the projection.
  • Instead of spreading metadata across assets that the STAC layer group creates, I'd suggest making them available through the STAC instance (e.g. getBoundsLayer() instead of setting a bounds boolean on the layer. Same for the stac data, which should not be set on each feature.

Copy link
Contributor Author

@m-mohr m-mohr Aug 2, 2023

Choose a reason for hiding this comment

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

Thanks, good pointers!

  1. Switched to use a loader, which seems to work perfectly.
  2. I removed the stac metadata for the features, this is not needed anymore (due to the change for STAC support (a STAC layer group) #14927 (comment)). I added a getBoundsLayer() method, but the metadata on the assets is still valuable due to the nesting of the LayerGroups, I think. In case you go through all layers, it is helpful to be able to retrieve the relevant STAC entities. Using that for example for customized LayerSwitcher or for the "click detection" in stacUtils / the STAC Item Collection example.

@m-mohr m-mohr force-pushed the stac-js branch 4 times, most recently from dd3bcb8 to ddc2698 Compare August 3, 2023 13:35
m-mohr added a commit to tschaub/openlayers that referenced this pull request Aug 21, 2023
@@ -382,7 +384,7 @@ class GeoTIFFSource extends DataTile {
super({
state: 'loading',
tileGrid: null,
projection: null,
projection: options.projection || null,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've extracted the changes in this file to #15036 so that we could also release this PR separately, if required.

@@ -0,0 +1,25 @@
/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a shared event between MapboxVector and STAC, but now that MapboxVector was removed I could also keep it outside of the events folder and copy it into stacUtils.js or STAC.js. Whatever you prefer.

@m-mohr
Copy link
Contributor Author

m-mohr commented Aug 22, 2023

Hey there,
to be able to get this into our projects via npm etc, I (temporarily?) released this in a separate repo: https://m-mohr.github.io/ol-stac/
I used the OL repo as a template with all the nice boilerplate for website, examples, docs etc. I'm wondering if this is fine with you/the OL maintainers? Shall I change the design more to make it look too less like an "official" openlayers thing?

@ahocevar
Copy link
Member

Thanks @m-mohr for your effort on this, and having this as a separate library makes perfect sense! No objections from me on how the website looks.

Would you mind creating a pull request that adds your library to the list of 3rd party libraries in site/src/3rd-party/index.hbs?

Also, to make this more prominent in OpenLayers, I think it would be nice to have an example here that uses your library.

This was referenced Aug 22, 2023
@m-mohr
Copy link
Contributor Author

m-mohr commented Aug 22, 2023

Thanks, @ahocevar. If you still want STAC be part of OL, I'm also happy to also have it live in OpenLayers directly. Up to the maintainers :-) But I wanted to get this out so people can start using it and give feedback.

Would you mind creating a pull request that adds your library to the list of 3rd party libraries in site/src/3rd-party/index.hbs?

Sure, see #15041

Also, to make this more prominent in OpenLayers, I think it would be nice to have an example here that uses your library.

I tried this, but couldn't figure out how it works with the dependencies. How can I reference external dependencies? If I just add the ol-stac import, it can't resolve it. Any hints? devDependencies? See #15042

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.

None yet

3 participants