mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.37k stars 1.32k forks source link

Programmatically generated raster sources #7471

Closed 1ec5 closed 4 years ago

1ec5 commented 7 years ago

https://github.com/mapbox/mapbox-gl/issues/27#issuecomment-267752292 demonstrates a use case for programmatically generated raster tile sources similar to what MapKit enables through -[MKTileOverlay loadTileAtPath:result:] and the Google Maps SDK enables through -[GMSTileLayer requestTileForX:y:zoom:receiver:].

In contrast to #6940, which would expose a separate source type for vector content, the SDK would make it possible for developers subclass MGLRasterSource and override a -loadTileAtPath:result: method that returns an image for a particular tile coordinate. mbgl::style::RasterSource’s initializer would accept an optional lambda that passes premultiplied image data into an asynchronous callback. mbgl::style::RasterSource would call this lambda for each tile, falling back on the current code path when none is provided. MGLRasterSource would pass in a lambda that calls -loadTileAtPath:result:.

This would require MGLStyle to own all MGLSource objects, as proposed in https://github.com/mapbox/mapbox-gl-native/issues/7375#issuecomment-266528289. Allowing an SDK source object to control the tile loading process would allow us to avoid a proliferation of source types and make the source customization hooks more intuitive for developers.

/cc @kkaefer @johndpope @JesseCrocker

1ec5 commented 7 years ago

We’d have to circumvent ambient and offline tile caching for programmatically defined raster sources.

1ec5 commented 7 years ago

At the same time as we add an API for providing images, we should also add a parallel API for providing tile URLs on a per-tile or per-request basis. Callback or block-based APIs are very common for this feature:

1ec5 commented 7 years ago

mapbox/mapbox-gl-style-spec#656 added a canvas source type to the style specification, conceptually allowing the developer to generate a raster source using imperative code. The proposal here accomplishes essentially the same goal, allowing the developer to draw a raster source using Core Graphics or Core Animation (on iOS and macOS) or a Canvas (on Android) without the OpenGL learning curve required by MGLOpenGLStyleLayer (iOS/macOS) or CustomLayer (Android), yet without adding a new source type.

/cc @lbud @lucaswoj

lucaswoj commented 7 years ago

Glad to hear there's a route to get parity on this feature @1ec5! 🎉

Would the syntax for canvas sources in GL JS work with a Core Graphics / Core Animation / Canvas implementation? Is there anything you'd change?

This design strikes me as a middle ground between MGLOpenGLStyleLayer and saying "no" to custom layers.

1ec5 commented 7 years ago

The -loadTileAtPath:result: method proposed here has a major drawback: we’d only call it whenever we currently try to load a tile. So as you zoom in smoothly, the programmatically generated raster layer would appear to jump between zoom levels at the .5 mark. So on second thought, this feature, while necessary, isn’t quite an answer to the canvas source type. #7823 comes a lot closer in terms of satisfying the same use case as canvas.

I can’t speak to how Android developers would expect Canvas to work, but from an iOS developer’s perspective, the biggest oddity in mapbox/mapbox-gl-style-spec#656 is that it requires an ID, whereas views and Core Animation layers are never identified by IDs on iOS. As for things I’d change: is it strictly necessary for the style file format specification to define a source type for a source that should never be defined in a style JSON file? (The style JSON file shouldn’t make assumptions about the environment in which it’s displayed, right?)

lucaswoj commented 7 years ago

These are good questions and open questions. When designing this API, I envisioned GL Native adding an API along the lines of Map#addCanvas(id, canvasInstance).

1ec5 commented 7 years ago

It has to be lower-level than that, because there’s no single “canvas” concept that makes sense for all the platforms mbgl sits below.

stale[bot] commented 5 years ago

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

1ec5 commented 5 years ago

This would complement computed shape sources.

davenquinn commented 5 years ago

This seems to be the path to allow locally-hosted MBTiles or similar overlays for offline use, and it is standard functionality within other mapping frameworks, as @1ec5 pointed out.

I am building an application for field geologic research, so offline access and custom raster image types are paramount. I have support for MBTiles layers currently with MapKit, and this seems to be a blocker for porting things over to the Mapbox platform. Given that Mapbox's differentiator is customizability and that MBTiles is a format invented by you guys, I am really surprised that this isn't already available. I would urge you to implement this, unless you see any other avenues to this functionality.

davenquinn commented 5 years ago

To update on progress, I managed to get a MBTiles dataset to display using a workaround developed by @namannik. This works but involves setting up a local in-app webserver, which adds dependencies and, potentially, security issues. It'd be far more straightforward to simply be able to provide image tiles on demand within the application, from an arbitrary backend.

stale[bot] commented 4 years ago

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

halset commented 4 years ago

It is possible to work around this limitation on iOS by adding a custom NSURLProtocol with a custom URL scheme and add it to MGLNetworkConfiguration.sharedManager.sessionConfiguration.protocolClasses.

stale[bot] commented 4 years ago

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.