Skip to content

Commit 03c02c5

Browse files
RD-1252: Add raster sources (#94)
1 parent 5720a13 commit 03c02c5

File tree

4 files changed

+316
-0
lines changed

4 files changed

+316
-0
lines changed

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ override fun onDestroy() {
203203
## ktlint Compliance (MANDATORY)
204204
- ALWAYS follow the rules enforced by the `org.jlleitschuh.gradle.ktlint` plugin.
205205
- Key rules: spacing, imports order, trailing newline, indentation, annotation/kdoc formatting, no wildcard imports.
206+
- Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end.
206207
- Pre-commit: a Git hook runs `./gradlew ktlintCheck`. Ensure zero violations before committing by running ./gradlew ktlintFormat
207208
- CI/Local requirement: run `./gradlew ktlintCheck` and ensure zero warnings/errors. PRs must be lint-clean.
208209

MapTilerSDK/src/main/java/com/maptiler/maptilersdk/commands/style/AddSource.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.maptiler.maptilersdk.bridge.MTCommand
1212
import com.maptiler.maptilersdk.helpers.JsonConfig
1313
import com.maptiler.maptilersdk.helpers.formatUrlForJs
1414
import com.maptiler.maptilersdk.map.style.source.MTGeoJSONSource
15+
import com.maptiler.maptilersdk.map.style.source.MTRasterDEMSource
16+
import com.maptiler.maptilersdk.map.style.source.MTRasterTileSource
1517
import com.maptiler.maptilersdk.map.style.source.MTSource
1618
import com.maptiler.maptilersdk.map.style.source.MTVectorTileSource
1719
import kotlinx.serialization.json.Json
@@ -28,8 +30,12 @@ internal data class AddSource(
2830
override fun toJS(): String =
2931
if (source is MTVectorTileSource) {
3032
handleMTVectorTileSource(source)
33+
} else if (source is MTRasterTileSource) {
34+
handleMTRasterTileSource(source)
3135
} else if (source is MTGeoJSONSource) {
3236
handleGeoJSONSource(source)
37+
} else if (source is MTRasterDEMSource) {
38+
handleMTRasterDEMSource(source)
3339
} else {
3440
""
3541
}
@@ -96,4 +102,63 @@ internal data class AddSource(
96102
}
97103

98104
// shared helper in helpers package
105+
106+
private fun handleMTRasterTileSource(source: MTRasterTileSource): JSString {
107+
val props = mutableListOf<String>()
108+
109+
// Use serialized enum value (lowercase, per style spec)
110+
props += "type: '${source.type}'"
111+
props += "minzoom: ${source.minZoom}"
112+
props += "maxzoom: ${source.maxZoom}"
113+
props += "scheme: '${source.scheme}'"
114+
props += "tileSize: ${source.tileSize}"
115+
props += "bounds: ${source.bounds.contentToString()}"
116+
117+
if (source.url != null) {
118+
props += "url: '${source.url!!}'"
119+
} else if (source.tiles != null) {
120+
val urls: List<String> = source.tiles!!.map { it.toString() }
121+
val tilesString: JSString = JsonConfig.json.encodeToString(urls)
122+
props += "tiles: $tilesString"
123+
}
124+
125+
source.attribution?.let { props += "attribution: '$it'" }
126+
127+
val propsString = props.joinToString(",\n ")
128+
129+
return """
130+
${MTBridge.MAP_OBJECT}.addSource('${source.identifier}', {
131+
$propsString
132+
});
133+
"""
134+
}
135+
136+
private fun handleMTRasterDEMSource(source: MTRasterDEMSource): JSString {
137+
val props = mutableListOf<String>()
138+
139+
props += "type: '${source.type}'"
140+
props += "minzoom: ${source.minZoom}"
141+
props += "maxzoom: ${source.maxZoom}"
142+
props += "tileSize: ${source.tileSize}"
143+
props += "bounds: ${source.bounds.contentToString()}"
144+
props += "encoding: '${source.encoding}'"
145+
146+
if (source.url != null) {
147+
props += "url: '${source.url!!}'"
148+
} else if (source.tiles != null) {
149+
val urls: List<String> = source.tiles!!.map { it.toString() }
150+
val tilesString: JSString = JsonConfig.json.encodeToString(urls)
151+
props += "tiles: $tilesString"
152+
}
153+
154+
source.attribution?.let { props += "attribution: '$it'" }
155+
156+
val propsString = props.joinToString(",\n ")
157+
158+
return """
159+
${MTBridge.MAP_OBJECT}.addSource('${source.identifier}', {
160+
$propsString
161+
});
162+
"""
163+
}
99164
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2025, MapTiler
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD 3-Clause
5+
*/
6+
7+
package com.maptiler.maptilersdk.map.style.source
8+
9+
import com.maptiler.maptilersdk.map.MTMapViewController
10+
import kotlinx.serialization.SerialName
11+
import kotlinx.serialization.Serializable
12+
import java.net.URL
13+
14+
/**
15+
* A raster DEM source. Only supports Terrain RGB encodings.
16+
*
17+
* For MapTiler Terrain RGB, the URL should typically point to a TileJSON resource.
18+
*/
19+
class MTRasterDEMSource : MTTileSource {
20+
/** Unique identifier of a source. */
21+
override var identifier: String
22+
23+
/** Attribution to be displayed when the map is shown to a user. */
24+
override var attribution: String? = null
25+
26+
/**
27+
* An array containing the longitude and latitude of the southwest and northeast corners of the source’s
28+
* bounding box in the following order: [sw.lng, sw.lat, ne.lng, ne.lat].
29+
* Defaults to [-180, -85.051129, 180, 85.051129].
30+
*/
31+
override var bounds: DoubleArray = doubleArrayOf(-180.0, -85.051129, 180.0, 85.051129)
32+
33+
/** Maximum zoom level for which tiles are available. Defaults to 22. */
34+
override var maxZoom: Double = 22.0
35+
36+
/** Minimum zoom level for which tiles are available. Defaults to 0. */
37+
override var minZoom: Double = 0.0
38+
39+
/** An array of one or more tile source URLs. */
40+
override var tiles: Array<URL>? = null
41+
42+
/** A URL to a TileJSON resource. Supported protocols are http, https. */
43+
override var url: URL? = null
44+
45+
/** Type of the source. */
46+
override var type: MTSourceType = MTSourceType.RASTER_DEM
47+
private set
48+
49+
/**
50+
* Tile size in pixels. Defaults to 512.
51+
*/
52+
var tileSize: Int = 512
53+
54+
/**
55+
* The encoding used by this source.
56+
* One of "terrarium" or "mapbox" (Terrain RGB). Defaults to MAPBOX.
57+
*/
58+
var encoding: MTRasterDEMEncoding = MTRasterDEMEncoding.MAPBOX
59+
60+
constructor(
61+
identifier: String,
62+
attribution: String?,
63+
bounds: DoubleArray,
64+
maxZoom: Double,
65+
minZoom: Double,
66+
tiles: Array<URL>?,
67+
url: URL?,
68+
type: MTSourceType,
69+
tileSize: Int,
70+
encoding: MTRasterDEMEncoding,
71+
) {
72+
this.identifier = identifier
73+
this.attribution = attribution
74+
this.bounds = bounds
75+
this.maxZoom = maxZoom
76+
this.minZoom = minZoom
77+
this.tiles = tiles
78+
this.url = url
79+
this.type = type
80+
this.tileSize = tileSize
81+
this.encoding = encoding
82+
}
83+
84+
constructor(
85+
identifier: String,
86+
url: URL,
87+
) {
88+
this.identifier = identifier
89+
this.url = url
90+
}
91+
92+
/**
93+
* Sets the url of the source. Used for updating the source data.
94+
*
95+
* @param url URL to raster DEM TileJSON resource.
96+
* @param mapViewController MTMapViewController which holds the source.
97+
*/
98+
fun setURL(
99+
url: URL,
100+
mapViewController: MTMapViewController,
101+
) {
102+
mapViewController.style?.setUrlToSource(url, this)
103+
}
104+
105+
/**
106+
* Sets the tiles of the source. Used for updating the source data.
107+
*
108+
* @param tiles list of URLs with tile resources.
109+
* @param mapViewController MTMapViewController which holds the source.
110+
*/
111+
fun setTiles(
112+
tiles: Array<URL>,
113+
mapViewController: MTMapViewController,
114+
) {
115+
mapViewController.style?.setTilesToSource(tiles, this)
116+
}
117+
}
118+
119+
/**
120+
* Encoding types for Raster DEM sources.
121+
*/
122+
@Serializable
123+
enum class MTRasterDEMEncoding {
124+
/** Terrarium format PNG tiles. */
125+
@SerialName("terrarium")
126+
TERRARIUM,
127+
128+
/** Terrain RGB tiles (Mapbox/MapTiler RGB Terrain). */
129+
@SerialName("mapbox")
130+
MAPBOX,
131+
;
132+
133+
override fun toString() = serializer().descriptor.getElementName(ordinal)
134+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2025, MapTiler
3+
* All rights reserved.
4+
* SPDX-License-Identifier: BSD 3-Clause
5+
*/
6+
7+
package com.maptiler.maptilersdk.map.style.source
8+
9+
import com.maptiler.maptilersdk.map.MTMapViewController
10+
import com.maptiler.maptilersdk.map.style.MTTileScheme
11+
import java.net.URL
12+
13+
/**
14+
* A raster tile source. Tiles must be in ZXY or TMS tile format.
15+
* For raster tiles hosted by MapTiler, the URL should be of the form:
16+
* https://api.maptiler.com/tiles/[tilesetid]/tiles.json?key=<YOUR_MAPTILER_API_KEY>
17+
*/
18+
class MTRasterTileSource : MTTileSource {
19+
/** Unique identifier of a source. */
20+
override var identifier: String
21+
22+
/** Attribution to be displayed when the map is shown to a user. */
23+
override var attribution: String? = null
24+
25+
/**
26+
* An array containing the longitude and latitude of the southwest and northeast corners
27+
* of the source’s bounding box in the following order: [sw.lng, sw.lat, ne.lng, ne.lat].
28+
* Defaults to [-180, -85.051129, 180, 85.051129].
29+
*/
30+
override var bounds: DoubleArray = doubleArrayOf(-180.0, -85.051129, 180.0, 85.051129)
31+
32+
/** Maximum zoom level for which tiles are available. Defaults to 22. */
33+
override var maxZoom: Double = 22.0
34+
35+
/** Minimum zoom level for which tiles are available. Defaults to 0. */
36+
override var minZoom: Double = 0.0
37+
38+
/** An array of one or more tile source URLs. */
39+
override var tiles: Array<URL>? = null
40+
41+
/** A URL to a TileJSON resource. Supported protocols are http, https. */
42+
override var url: URL? = null
43+
44+
/** Type of the source. */
45+
override var type: MTSourceType = MTSourceType.RASTER
46+
private set
47+
48+
/**
49+
* Scheme used for tiles. Influences the y direction of the tile coordinates.
50+
* Defaults to XYZ.
51+
*/
52+
var scheme: MTTileScheme = MTTileScheme.XYZ
53+
54+
/**
55+
* Tile size in pixels. Only configurable for raster sources. Defaults to 512.
56+
*/
57+
var tileSize: Int = 512
58+
59+
constructor(
60+
identifier: String,
61+
attribution: String?,
62+
bounds: DoubleArray,
63+
maxZoom: Double,
64+
minZoom: Double,
65+
tiles: Array<URL>?,
66+
url: URL?,
67+
type: MTSourceType,
68+
scheme: MTTileScheme,
69+
tileSize: Int,
70+
) {
71+
this.identifier = identifier
72+
this.attribution = attribution
73+
this.bounds = bounds
74+
this.maxZoom = maxZoom
75+
this.minZoom = minZoom
76+
this.tiles = tiles
77+
this.url = url
78+
this.type = type
79+
this.scheme = scheme
80+
this.tileSize = tileSize
81+
}
82+
83+
constructor(
84+
identifier: String,
85+
url: URL,
86+
) {
87+
this.identifier = identifier
88+
this.url = url
89+
}
90+
91+
/**
92+
* Sets the url of the source. Used for updating the source data.
93+
*
94+
* @param url URL to raster TileJSON resource.
95+
* @param mapViewController MTMapViewController which holds the source.
96+
*/
97+
fun setURL(
98+
url: URL,
99+
mapViewController: MTMapViewController,
100+
) {
101+
mapViewController.style?.setUrlToSource(url, this)
102+
}
103+
104+
/**
105+
* Sets the tiles of the source. Used for updating the source data.
106+
*
107+
* @param tiles list of URLs with tile resources.
108+
* @param mapViewController MTMapViewController which holds the source.
109+
*/
110+
fun setTiles(
111+
tiles: Array<URL>,
112+
mapViewController: MTMapViewController,
113+
) {
114+
mapViewController.style?.setTilesToSource(tiles, this)
115+
}
116+
}

0 commit comments

Comments
 (0)