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

feat: add collections option to OGCVectorTile source #15792

Merged
merged 4 commits into from May 7, 2024

Conversation

jansule
Copy link
Contributor

@jansule jansule commented May 3, 2024

This adds support for the OGC API Tiles Part 1 - Core "Collections Selection" conformance class for the OGCVectorTile source.

This solves #15791

Copy link

github-actions bot commented May 3, 2024

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

src/ol/source/ogcTileUtil.js Outdated Show resolved Hide resolved
src/ol/source/ogcTileUtil.js Outdated Show resolved Hide resolved
Co-authored-by: Andreas Hocevar <andreas.hocevar@gmail.com>
@jansule
Copy link
Contributor Author

jansule commented May 7, 2024

Good points @ahocevar. Applied the suggestions.

@jansule
Copy link
Contributor Author

jansule commented May 7, 2024

While having another look at it, it looks like the suggested approach does change the semantics a little in the sense that previously we did not add a domain for the case that link.href did not provide one. A href without domain should be prepended by the domain name of the service and not window.location. The service domain will also already be prepended by https://github.com/openlayers/openlayers/blob/main/src/ol/source/ogcTileUtil.js#L341.

So I think the initial approach should be used instead.

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

@jansule Can you elaborate on what the difference would be? If link.href is a href without an origin, the resulting requests would be exactly the same as new URL(link.href, window.location.href).

The reason for the failing test is that Node does not have a window object. So you would have to move that test to the browser tests.

@jansule
Copy link
Contributor Author

jansule commented May 7, 2024

@jansule Can you elaborate on what the difference would be? If link.href is a href without an origin, the resulting requests would be exactly the same as new URL(link.href, window.location.href).

If link.href is without an origin, it relates to the document it belongs to (the service) and not to the document our JavaScript code is running. E.g. when my OL application is running on https://my-app.com and I want to include a OGCVectorTile from https://maps.gnosis.earth/ogcapi/collections/Daraa/tiles/WebMercatorQuad?f=json , which provides following link item:

{
  rel: "item",
  type: "application/vnd.mapbox-vector-tile",
  title: "WebMercatorQuad multi-layer vector tiles for Daraa (as Mapbox Vector Tiles)",
  href: "/ogcapi/collections/Daraa/tiles/WebMercatorQuad/{tileMatrix}/{tileRow}/{tileCol}.mvt",
  templated: true
}

The url should always be resolved to https://maps.gnosis.earth/ogcapi/collections/Daraa/tiles/WebMercatorQuad/{tileMatrix}/{tileRow}/{tileCol}.mvt and not to https://my-app.com/ogcapi/collections/Daraa/tiles/WebMercatorQuad/{tileMatrix}/{tileRow}/{tileCol}.mvt.

Resolving urls without a domain in relation to its service will already be done by https://github.com/openlayers/openlayers/blob/main/src/ol/source/ogcTileUtil.js#L341.

So using window.location.href does not make sense here, as it points to the wrong reference (the application, not the service).

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

Got it, thanks for the explanation. Then instead of window.location.href, you just have to use the document url (sourceInfo.url) as second argument to the URL constructor.

One more thing: isn't the collections option also specified for OGCMapTile?

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

But you're right, @jansule. Looking at the rest of the OGC API code, this should also work with local files, so using the URL constructor like in my suggestion indeed isn't the best thing to do.

@jansule
Copy link
Contributor Author

jansule commented May 7, 2024

One more thing: isn't the collections option also specified for OGCMapTile?

Yes it is. I thought it would be better to do separate PRs for that.

Looking at the rest of the OGC API code, this should also work with local files, so using the URL constructor like in my suggestion indeed isn't the best thing to do.

So should I just revert the last commit, or should I check again to see if I can simplify the code a little?

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

So should I just revert the last commit, or should I check again to see if I can simplify the code a little?

I think you should at least get rid of the try/catch. Maybe not using the URL constructor at all would yield simpler code.

Regarding OGCMapTile: since it's the same code, you might add that in this pull request, and create a common function instead of duplicating the code there.

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

@jansule I think something like this might be a good solution:

  if (collections && collections.length) {
    // According to conformance class
    // http://www.opengis.net/spec/ogcapi-tiles-1/1.0/conf/collections-selection
    // commata in the identifiers of the `collections` query parameter
    // need to be URLEncoded, while the commata separating the identifiers
    // should not.
    const url = new URL(tileUrlTemplate, 'file:/');
    if (url.pathname.split('/').includes('collections')) {
      logError(
        'The "collections" query parameter cannot be added to collection endpoints',
      );
      return tileUrlTemplate;
    }
    const encodedCollections = collections
      .map((c) => encodeURIComponent(c))
      .join(',');

    url.searchParams.append('collections', encodedCollections);
    const baseUrl = tileUrlTemplate.split('?')[0];
    const queryParams = decodeURIComponent(url.searchParams.toString());
    return `${baseUrl}?${queryParams}`;
  }

It does use the URL constructor, but takes the baseUrl directly from the original template URL.

@jansule
Copy link
Contributor Author

jansule commented May 7, 2024

Yes, came to the same solution 😀 Do you know any example service that provides dataset tilesets (/map/tiles) that I can use for the OGCMapTile tests? The example services on https://tiles.developer.ogc.org/ only provide geoData tilesets (/collections/{collectionId}/map/tiles).

@ahocevar
Copy link
Member

ahocevar commented May 7, 2024

Thanks for your continued effort, @jansule. Unfortunately I don't have an example for an OGCMapTile data set with collections.

Copy link
Member

@ahocevar ahocevar left a comment

Choose a reason for hiding this comment

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

Thanks, @jansule !

}

// making sure we can always construct a URL instance.
const url = new URL(tileUrlTemplate, 'file://');
Copy link
Member

Choose a reason for hiding this comment

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

Minor but one slash is enough:

Suggested change
const url = new URL(tileUrlTemplate, 'file://');
const url = new URL(tileUrlTemplate, 'file:/');

Copy link
Member

Choose a reason for hiding this comment

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

Oops. I forgot to wait for this. Maybe something for a quick follow-up fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created a follow up PR: #15809

@ahocevar ahocevar merged commit 5c3529a into openlayers:main May 7, 2024
8 checks passed
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

2 participants