GpuBasemap¶
Namespace: ThinkGeo.UI.Wpf
The GPU-rendered basemap: a MapStyle rendered by the perspective-capable GL engine. The style is the single input - load one from a document with MapStyle.LoadAsync, compose one with its Add* methods, or build one in code - and JSON ends at the style, never reaching the map. Deliberately NOT an Overlay - the basemap is the ground every overlay sits on, not one of the things sitting on it. Assign it to MapView.Basemap; the map composites it beneath the whole Overlays collection and drives its lifecycle. The camera - TiltAngle, tilt gestures, rotation - lives on the MapView.
Zoom, wherever the style speaks of it - a layer's minzoom, a zoom stop - is the MapView's own: MapUtil.GetZoom(scale, ZoomScales) over the map's ZoomScales ladder, the number MapView.CurrentZoom reports. The default ladder of a metre-unit map is the MapLibre one, so a style document reads as it would in MapLibre; replacing ZoomScales with a 256-pixel ladder shifts the whole style by a zoom. See StyleLayer.MinZoom.
public sealed class GpuBasemap : System.IDisposable
Inheritance object → GpuBasemap
Implements IDisposable
Properties¶
AutoRequestHighPerformanceGpu¶
On hybrid-GPU machines whose GL context starts on the power-saving adapter, the engine arms the per-application Windows GPU preference (the same setting as Settings > Display > Graphics) so the NEXT launch uses the high-performance adapter. Default true; set false before the first map is created to leave the preference untouched.
public static bool AutoRequestHighPerformanceGpu { get; set; }
Property Value¶
DisplayProjection¶
The projection this map DISPLAYS in - Robinson, Albers, a UTM zone by EPSG code, any of the natively supported families (see ). Every coordinate the API speaks - CenterPoint, CurrentExtent, feature geometry - stays web mercator; the projection reshapes only how that plane reaches the screen, so switching it re-renders the same tiles without refetching. Set it before the map view loads; changing it afterwards throws (a running map's shaders carry the projection baked in - live switching arrives with the projection morph phase, see GpuBasemap.AnimateDisplayProjectionAsync(DisplayProjection, TimeSpan, CancellationToken)).
public DisplayProjection DisplayProjection { get; set; }
Property Value¶
DisplayProjection
TileSources¶
Vector tile sources supplied in code, keyed by the "source" id the style's layers name. A source here is used instead of one the style declares under the same id, so a style document can name data it cannot reach itself - a shapefile through a FeatureSourceVectorTileSource, a local MBTiles archive.
public GeoCollection<IVectorTileSource> TileSources { get; }
Property Value¶
GeoCollection<IVectorTileSource>
Remarks:
Read when the basemap opens. Add the sources before the map draws the basemap the first time; a source added afterwards is not drawn.
RasterTileSources¶
Raster tile sources supplied in code, keyed by the source id the style's raster layers name; a source here is used instead of one the style declares under the same id. To draw a raster the style does not mention, add it to the style with MapStyle.AddRaster(RasterTileSource, Nullable<RasterPaint>, string, StyleLayerSlot).
public GeoCollection<RasterTileSource> RasterTileSources { get; }
Property Value¶
GeoCollection<RasterTileSource>
Remarks:
Add the sources before the map draws the basemap the first time, as with GpuBasemap.TileSources.
LocalFontsDirectory¶
Gets or sets a directory of extra font files, for scripts the embedded Noto Sans does not cover. Process-wide, like the glyph cache it feeds: every GPU map in the process uses it, and a map reads it when it opens, so set it before the first map is shown.
public static string LocalFontsDirectory { get; set; }
Property Value¶
IsBackgroundTransparent¶
Gets or sets whether the basemap draws onto a transparent surface: beyond the world, and wherever the style paints nothing, what is beneath the map shows through. A style without a background layer leaves the surface empty behind itself either way. Set it before the map first draws the basemap.
public bool IsBackgroundTransparent { get; set; }
Property Value¶
RenderWorldCopies¶
Whether the world repeats horizontally when the viewport is wider than one world (web mercator, far zoomed out). On by default; off draws a single world with the background beside it.
public bool RenderWorldCopies { get; set; }
Property Value¶
IsSceneStableForCapture¶
Gets whether everything the current view needs is drawn: no zoom animation running, no tile loading or uploading, no label placement pending. A screenshot or export taken while it is false can miss tiles or labels.
public bool IsSceneStableForCapture { get; }
Property Value¶
IsExtrusionDrawingEnabled¶
Draws or skips the style's fill-extrusion layers - the cheap "3D buildings" switch. A renderer flag, not a restyle: nothing is rebuilt.
public bool IsExtrusionDrawingEnabled { get; set; }
Property Value¶
IsLabelDrawingEnabled¶
Draws or skips every label. A renderer flag, not a restyle.
public bool IsLabelDrawingEnabled { get; set; }
Property Value¶
LabelFadeDurationInMilliseconds¶
How long labels fade in and out over, in milliseconds; 0 disables the fade. 300 by default. A renderer setting, not a restyle.
public float LabelFadeDurationInMilliseconds { get; set; }
Property Value¶
IsGlobeActive¶
True while the map is drawn as a globe, which changes what a screen pixel means.
public bool IsGlobeActive { get; }
Property Value¶
GlobeHandoverFactor¶
How far through the globe-to-mercator handover the current view stands: 0 a ball, 1 flat, in between a blend - so an app can say which it is showing rather than guessing from the zoom. 1 until the basemap is on a map.
public double GlobeHandoverFactor { get; }
Property Value¶
Constructors¶
GpuBasemap(MapStyle)¶
The usual construction path: a MapStyle, whatever built it - a document (MapStyle.LoadAsync(string, CancellationToken)), composition (AddStyleAsync/AddRaster/AddVectorTiles on the style), or pure code (new MapStyle() + AddLayers). The style's own source declarations supply the tiles; a style with none needs GpuBasemap.TileSources filled before the map is shown. Compilation happens at this display's actual scale, so sprite@2x arrives on a hi-dpi screen by itself.
public GpuBasemap(MapStyle style)
Parameters¶
style MapStyle
GpuBasemap(IVectorTileSource, MapStyle)¶
Imperative construction with explicit tile sources: the style is used exactly as compiled - hand it a style from MapStyle.LoadAsync or one built with AddLayers.
public GpuBasemap(IVectorTileSource tileSource, MapStyle style)
Parameters¶
tileSource IVectorTileSource
style MapStyle
GpuBasemap(IReadOnlyList<IVectorTileSource>, MapStyle)¶
The several-source form of imperative construction: each source keeps its own tile pipeline, so a slow one cannot hold the others off the screen.
public GpuBasemap(IReadOnlyList<IVectorTileSource> tileSources, MapStyle style)
Parameters¶
tileSources IReadOnlyList<IVectorTileSource>
style MapStyle
Methods¶
AnimateDisplayProjectionAsync(DisplayProjection, TimeSpan, CancellationToken)¶
Animates the map from its current display projection to - the morph the drawing-time architecture exists to make possible. Every coordinate the API speaks stays web mercator throughout; what moves is only how that plane reaches the screen, so the camera, the tiles and the styles are untouched by it.
public Task AnimateDisplayProjectionAsync(DisplayProjection target, TimeSpan duration, CancellationToken cancellationToken)
Parameters¶
target DisplayProjection
The projection to end on.
duration TimeSpan
How long the walk takes. Zero or less switches outright, exactly as assigning does.
cancellationToken CancellationToken
Stops the walk at the blend it reached.
Returns¶
Exceptions¶
Thrown if the walk is canceled, either through
or because a newer morph superseded it.
Remarks:
Awaitable to the end of the animation. A second morph started while one is running supersedes it: the earlier one stops at the blend it reached, its task is canceled, and the new one walks on from there. A walk stopped by also stays at its blend until the next morph. While the walk runs, GpuBasemap.DisplayProjection keeps reading the projection it left - the property names settled states, and the in-between is a blend that is not any named projection; GpuBasemap.GlobeHandoverFactor is how the in-between is asked about.
A(IReadOnlyList<ExternalRasterLayer>)¶
internal void A(IReadOnlyList<ExternalRasterLayer> )
Parameters¶
`` IReadOnlyList<ExternalRasterLayer>
Returns¶
a(IReadOnlyList<ExternalRasterLayer>)¶
internal void a(IReadOnlyList<ExternalRasterLayer> )
Parameters¶
`` IReadOnlyList<ExternalRasterLayer>
Returns¶
SetStyleAsync(MapStyle)¶
Swaps the style on a running map - the equivalent of MapLibre setStyle. The map keeps drawing what it has while the new style's tiles are built beside them, and swaps when they are ready: no new overlay, no new GL scene, and no re-fetch, because the decoded tiles are style-independent and stay in memory. What is rebuilt is what the style decides - geometry buckets, labels - over features the map already holds.
Recompiles only what changed: a composition edit since the last compile, or a display-scale difference. A style that fails to compile throws before anything is applied, so the map keeps the picture it had - hand it the style, catch the exception, keep the last good frame.
For a single property on a single layer there are cheaper calls - and change one value without rebuilding anything. This is for changing the style.
Sources. A style carries its data as well as its cartography, and the map reconciles the two lists. Vector sources are told apart by object: a source the map already draws keeps its open connection and its decoded tiles at whatever position the new style puts it - so hold the same instance across restyles, and a source that leaves the middle of the list costs the ones after it nothing; a source the map has not seen is opened; one the style stops naming is dropped, its tiles with it. A style that names no vector source is drawn over an empty one - raster only, or nothing but overlays. Raster sources are told apart by id: a new object under a known id replaces the old one and its tiles; an id the style stops declaring is unbound, its tiles and textures released; ids the application registered on GpuBasemap.RasterTileSources itself are never touched by a restyle. To make the map re-read a source whose data changed in place, hand it a new source object under the same id (raster) or a new instance (vector); a raster source can also raise its own Refreshed event.
Ownership. The map disposes nothing a restyle drops - the sources are yours, and one you will not use again is yours to dispose. What the map still holds when it closes, it disposes then. A call that throws - the style would not compile, or a vector source arrives on another tile grid than the map's - has changed nothing: the map keeps its sources and its picture. Fetches still running for a source that left are allowed to finish and their answers are discarded. To cancel a restyle - closing a project while a style compiles - use GpuBasemap.SetStyleAsync(MapStyle, CancellationToken). https://community.thinkgeo.com/t/v15-beta160-follow-up-remaining-gpu-style-parity-source-lifecycle-wfs-v2-and-wms-gaps/12468
public Task SetStyleAsync(MapStyle style)
Parameters¶
style MapStyle
The style to draw from now on.
Returns¶
SetStyleAsync(MapStyle, CancellationToken)¶
GpuBasemap.SetStyleAsync(MapStyle), cancellable while the style compiles.
public Task SetStyleAsync(MapStyle style, CancellationToken cancellationToken)
Parameters¶
style MapStyle
The style to draw from now on.
cancellationToken CancellationToken
Cancels the restyle while the style compiles.
Returns¶
Remarks:
Compiling the style - resolving it and fetching its sprite and glyphs - is the slow part of a restyle and where the token is honoured. Cancelled then, the call throws OperationCanceledException and the map keeps the style, the sources and the picture it had, as a call that fails to compile does; closing a project or switching away no longer has to wait for it. Once the new style is being bound the hand-over completes, so a call that returns has applied its style.
RefreshVectorTiles(IVectorTileSource, RectangleShape)¶
Tells the map the data inside a vector source changed: what it decoded from that source - every tile, or only the tiles meeting - is forgotten and fetched again, and the scene is rebuilt around it while the picture on screen is held, the way a restyle is. The other sources keep their decoded tiles; a FeatureSourceVectorTileSource with a VectorTileCache drops the cached files of the same tiles. The counterpart of a raster source's Refreshed event; without it the only way to re-read a vector source was a new source object under the same layers. False when this map is not drawing . https://community.thinkgeo.com/t/v15-beta160-follow-up-remaining-gpu-style-parity-source-lifecycle-wfs-v2-and-wms-gaps/12468
public bool RefreshVectorTiles(IVectorTileSource source, RectangleShape extent)
Parameters¶
source IVectorTileSource
The source, the same object the style names.
extent RectangleShape
The area whose data changed, in the map's projection; null for all of it.
Returns¶
GetElevationAsync(double, double, CancellationToken)¶
Reads the elevation under a point given in decimal degrees, fetching the DEM tile when it is not yet held.
public Task<Nullable<double>> GetElevationAsync(double longitude, double latitude, CancellationToken cancellationToken)
Parameters¶
longitude double
The longitude in decimal degrees.
latitude double
The latitude in decimal degrees.
cancellationToken CancellationToken
A cancellation token.
Returns¶
Task<Nullable<double>>
The elevation in meters, unscaled by exaggeration; or null when the style has no raster-dem source, the point is outside its coverage, or no tile over it could be fetched.
Remarks:
Terrain need not be on: with terrain off, the style's only raster-dem source answers. For a point in map coordinates use the overload that takes an SRID - a mercator coordinate passed here is refused with an ArgumentOutOfRangeException.
GetElevationAsync(PointShape, int, CancellationToken)¶
Reads the elevation under a point given in any projection, fetching the DEM tile when it is not yet held.
public Task<Nullable<double>> GetElevationAsync(PointShape point, int srid, CancellationToken cancellationToken)
Parameters¶
point PointShape
The point, in the projection names.
srid int
The SRID of the point's coordinates - 3857 for a map in Spherical Mercator meters.
cancellationToken CancellationToken
A cancellation token.
Returns¶
Task<Nullable<double>>
The elevation in meters, unscaled by exaggeration; or null when the style has no raster-dem source, the point is outside its coverage, or no tile over it could be fetched.
GetElevationProfileAsync(LineBaseShape, int, double, string, Nullable<int>, CancellationToken)¶
Samples the elevation along a line, evenly spaced on the ground, from the same raster-dem tiles the map renders, and returns the profile a chart draws.
public Task<ElevationProfile> GetElevationProfileAsync(LineBaseShape line, int srid, double intervalInMeters, string demSourceId, Nullable<int> zoom, CancellationToken cancellationToken)
Parameters¶
line LineBaseShape
The line to profile, in the projection names.
srid int
The SRID of the line's coordinates - 3857 for a map in Spherical Mercator meters.
intervalInMeters double
The ground distance between samples; the line's endpoints are always included.
demSourceId string
The raster-dem source to read, by the id the style declares it under. Null reads the terrain's source, or the style's only raster-dem source when terrain is off.
zoom Nullable<int>
The tile zoom to sample at, clamped into the source's range; null for the deepest the source publishes. It sets the profile's vertical resolution.
cancellationToken CancellationToken
A cancellation token.
Returns¶
Exceptions¶
ArgumentException
No raster-dem source answers to , or none was named and the style declares none or several.
D()¶
internal void D()
Returns¶
GetIsolineFieldAsync(CancellationToken)¶
Reads back the interpolated field the isoline pass produced, as numbers in the data's own units - see IsolineFieldSnapshot. Only the GL thread can read the texture, so the snapshot arrives once the next frame has a current field. The result is null when the next frame has no isoline field.
public Task<IsolineFieldSnapshot> GetIsolineFieldAsync(CancellationToken cancellationToken)
Parameters¶
cancellationToken CancellationToken
Cancels the wait for the next frame.
Returns¶
Exceptions¶
Thrown if the request is canceled through , by a
newer call, or by disposing the basemap.
Remarks:
One request is pending at a time: a newer call cancels the one still waiting, and disposing the basemap cancels it too.
Dispose()¶
Releases the basemap's sources, caches and GPU resources. The map does this itself when MapView.Basemap is given another basemap or the map is disposed.
public void Dispose()
Returns¶
Events¶
DisplayProjectionChanged¶
Raised when GpuBasemap.DisplayProjection changes.
public event EventHandler DisplayProjectionChanged;
TileLoadFailed¶
Raised on the UI thread when a tile of one of this map's sources could not be loaded: the request failed, timed out or returned an error, the feature source threw while the tile was cut, or the bytes would not decode. The tile is left out and what lies underneath it shows; the map does not throw, and a handler that wants an exception raises its own. TileLoadFailedEventArgs.Retry says whether the tile is asked for again - by default it is, by the next draw that still needs it, 3 seconds after the failure at the soonest - and the handler may change it. Every failure is also written to the GPU trace (ThinkGeoDebugger.LogType). The counterpart of the classic overlay's ThrowingException. https://community.thinkgeo.com/t/wmsrastertilesource-wmtsrastertilesource-and-authentication/12470
public event EventHandler<TileLoadFailedEventArgs> TileLoadFailed;