Class LocalTileSource
A local, per-tile-addressed raster tile source: a folder of individual
tile image files on disk, addressed the same way a URL template would
be ({z}/{x}/{y} substitution into a file path
pattern instead of a URL).
public sealed class LocalTileSource : ITileDataSource
- Inheritance
-
objectLocalTileSource
- Implements
Remarks
Not a TileSource variant, for the same class of reason
LansMap.Core.Vector.VectorTileSource is not one either: several
of TileSource's members would lie for a local construction -
ApiKey/{key} (a local read has no key to substitute),
Subdomains/{s} (meaningless without HTTP host sharding),
and MaxConcurrentRequests (today that number is politeness
toward a remote provider; a local read has no provider to be polite
to).
Scoped to per-tile-addressed local data only. Archive-addressed
formats - MBTiles (single SQLite file, z/x/y SQL query) and PMTiles
(single file, byte-range) - are explicitly out of scope, the same
exclusion VectorTileSource applies to PMTiles: neither has a
per-tile path PathTemplate could honestly represent.
Each gets its own type(s) of its own, if and when that work
starts.
Constructors
LocalTileSource(string, string, string, int, string, int, int, int, string, TileTextureFormat, int)
Creates a validated local tile source.
public LocalTileSource(string name, string pathTemplate, string datasetId, int tileSizePx, string attribution, int maxConcurrentRequests = 16, int minZoom = 0, int maxNativeZoom = 22, string attributionUrl = null, TileTextureFormat textureFormat = TileTextureFormat.RGBA32, int prefetchReserveSlots = 2)
Parameters
namestringDataset name for display. Required.
pathTemplatestringFile path template. Must contain
{z},{x}and{y}.datasetIdstringDeveloper-supplied dataset identity fed into CacheTag. Required, never derived automatically. See DatasetId.
tileSizePxintTile edge length in px; 256 or 512.
attributionstringCredit text. Required.
maxConcurrentRequestsintLocal reads in flight at once, 1 to 32. Omit it for DefaultMaxConcurrentRequests.
minZoomintShallowest level in the dataset, 0 to 24.
maxNativeZoomintDeepest level in the dataset, from
minZoomto 24.attributionUrlstringLink target for the credit; null for no link.
textureFormatTileTextureFormatGPU residency format for this source's tiles. Omit for RGBA32.
prefetchReserveSlotsint
Exceptions
- ArgumentException
The name, template, dataset id or attribution is missing; the template lacks a required placeholder; the tile size is not 256 or 512; or a zoom or concurrency value is out of range.
Fields
DefaultMaxConcurrentRequests
Concurrency used when a source does not name one: 16.
public const int DefaultMaxConcurrentRequests = 16
Field Value
Remarks
DefaultMaxConcurrentRequests (8) is HTTP provider politeness and has no local meaning. The number that matters for local reads is disk I/O / worker-thread contention. A local SSD read this small is dominated by per-request async overhead rather than by how many are in flight, so slot count barely matters on this hardware; 16 is picked as the midpoint of that flat band - enough parallelism to exceed DefaultMaxConcurrentRequests (8, which is HTTP politeness and has no local meaning here) without the extra file-handle/thread overhead of 32 buying anything measured. This was measured on one desktop SSD, not the reference iPhone 14 Pro device or a mobile flash/StreamingAssets read path, which can behave differently under sandboxed I/O; re-measure there before relying on this number for a mobile-bundled dataset (not yet done).
Properties
Attribution
Credit text, rendered verbatim by the attribution overlay. Never empty; the constructor rejects a source without it. A bundled offline basemap still needs its provider's licence honoured - local origin does not exempt a dataset from attribution: what matters is whether a user sees credit, not whether the tiles came over the network.
public string Attribution { get; }
Property Value
AttributionUrl
Where the attribution text links to. Empty string, never null.
public string AttributionUrl { get; }
Property Value
CacheTag
Dataset identity for the disk cache: an FNV-1a 64 hash of a
"local:"-tagged DatasetId.
public ulong CacheTag { get; }
Property Value
Remarks
Hashes DatasetId, not PathTemplate - see DatasetId's remarks for why a path is a poor cache-identity input. Also folds in TextureFormat, same scheme as CacheTag: only a non-default format adds a suffix, so two default-format sources on the identical dataset id still tag identically.
The leading "local:" tag means this type's tag can never
equal a TileSource's ("raster:"-tagged) or a
VectorTileSource's ("vector:"-tagged) tag, so no two
source kinds can ever collide in the shared disk cache regardless
of what template/dataset-id text they happen to share.
ConcurrencyLoweredForPoliteness
Always false: a local read has no remote provider to be polite to, so MaxConcurrentRequests here is disk I/O tuning (see its remarks), never provider politeness. Unlike ConcurrencyLoweredForPoliteness, this is not derived from the concurrency value - deriving it the same way would misread a low local value (tuned for a slow disk) as a politeness signal, and a high one as impolite, neither of which means anything for a source with no provider terms to respect.
public bool ConcurrencyLoweredForPoliteness { get; }
Property Value
DatasetId
Developer-supplied dataset identity, fed into CacheTag.
Not derived from the path or file bytes: a raw absolute path is
unstable across machines/devices (desktop vs. an iOS app sandbox
vs. an Android persistentDataPath), and a
StreamingAssets-relative path is app-build-relative rather than
content-relative, so it cannot see a re-tiled dataset shipped
under the identical relative path. Required; the constructor
rejects an empty one. Set it the way Name
is developer-supplied rather than derived - e.g. a name+version
string such as "city-basemap-2026-08". A developer who
wants content-addressing can pass a hash of their dataset as this
id.
public string DatasetId { get; }
Property Value
MaxConcurrentRequests
How many local reads to keep in flight against this dataset at once, 1 to 32.
public int MaxConcurrentRequests { get; }
Property Value
MaxNativeZoom
Deepest zoom level in this dataset.
public int MaxNativeZoom { get; }
Property Value
MinZoom
Shallowest zoom level in this dataset, 0 for a world-wide one.
public int MinZoom { get; }
Property Value
Name
Human-readable dataset name, used in the inspector and in logs. Never empty.
public string Name { get; }
Property Value
PathTemplate
The file path template, with {z}, {x} and
{y} left unexpanded (e.g.
"tiles/{z}/{x}/{y}.png"). No {key} or {s}
concept - see the type remarks.
public string PathTemplate { get; }
Property Value
PixelRatio
Always 1: a local pyramid is stored at its scheme resolution, with no high-DPI variant to choose between.
public int PixelRatio { get; }
Property Value
PrefetchReserveSlots
How many transport slots the idle-time background trickle (parent-tile prefetch, the world-floor trickle) may use at once, 0 to 16. Same additive-reserve shape as PrefetchReserveSlots: always additive here, since ConcurrencyLoweredForPoliteness is always false for a local read (no remote provider to be polite to, see that member's remarks).
public int PrefetchReserveSlots { get; }
Property Value
TextureFormat
The GPU residency format this source's tiles should be uploaded as. Defaults to RGBA32; folded into CacheTag, same as TileSource.
public TileTextureFormat TextureFormat { get; }
Property Value
TexturePx
Decoded image edge length in px, equal to TileSizePx.
public int TexturePx { get; }
Property Value
TileSizePx
Tile edge length in px, 256 or 512. Both the zoom scheme and the image size: a local pyramid stores one texel per scheme pixel.
public int TileSizePx { get; }
Property Value
Methods
ClampZoom(int)
Clamps a desired zoom level into the range this dataset covers.
public int ClampZoom(int desiredZoom)
Parameters
desiredZoomint
Returns
DiskCacheKey(TileCoord)
The disk cache key for one tile from this source.
public ulong DiskCacheKey(TileCoord tile)
Parameters
tileTileCoord
Returns
IsServable(int)
Whether this dataset covers the given zoom level directly.
public bool IsServable(int zoom)
Parameters
zoomint