Add geojson demo

This commit is contained in:
Alexander Nozik 2022-12-27 11:51:14 +03:00
parent 5da23b83c1
commit 8969b2b094
6 changed files with 61 additions and 26 deletions

View File

@ -1,4 +1,3 @@
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins { plugins {
@ -19,6 +18,7 @@ kotlin {
val jvmMain by getting { val jvmMain by getting {
dependencies { dependencies {
implementation(projects.mapsKtCompose) implementation(projects.mapsKtCompose)
implementation(projects.mapsKtGeojson)
implementation(compose.desktop.currentOs) implementation(compose.desktop.currentOs)
implementation("io.ktor:ktor-client-cio") implementation("io.ktor:ktor-client-cio")
implementation("ch.qos.logback:logback-classic:1.2.11") implementation("ch.qos.logback:logback-classic:1.2.11")

View File

@ -13,9 +13,11 @@ import androidx.compose.ui.window.application
import center.sciprog.maps.compose.* import center.sciprog.maps.compose.*
import center.sciprog.maps.coordinates.* import center.sciprog.maps.coordinates.*
import center.sciprog.maps.features.* import center.sciprog.maps.features.*
import center.sciprog.maps.geojson.geoJson
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO import io.ktor.client.engine.cio.CIO
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import java.net.URL
import java.nio.file.Path import java.nio.file.Path
import kotlin.math.PI import kotlin.math.PI
import kotlin.random.Random import kotlin.random.Random
@ -44,8 +46,6 @@ fun App() {
val pointTwo = 55.929444 to 37.518434 val pointTwo = 55.929444 to 37.518434
val pointThree = 60.929444 to 37.518434 val pointThree = 60.929444 to 37.518434
val dragPoint = 55.744 to 37.614
MapView( MapView(
mapTileProvider = mapTileProvider, mapTileProvider = mapTileProvider,
// initialViewPoint = MapViewPoint( // initialViewPoint = MapViewPoint(
@ -62,6 +62,8 @@ fun App() {
) )
) { ) {
geoJson(URL("https://raw.githubusercontent.com/ggolikov/cities-comparison/master/src/moscow.geo.json"))
image(pointOne, Icons.Filled.Home) image(pointOne, Icons.Filled.Home)
val marker1 = rectangle(55.744 to 37.614, size = DpSize(10.dp, 10.dp), color = Color.Magenta) val marker1 = rectangle(55.744 to 37.614, size = DpSize(10.dp, 10.dp), color = Color.Magenta)

View File

@ -29,11 +29,7 @@ public value class GeoJsonFeature(override val json: JsonObject) : GeoJson {
public val geometry: GeoJsonGeometry? get() = json[GEOMETRY_KEY]?.jsonObject?.let { GeoJsonGeometry(it) } public val geometry: GeoJsonGeometry? get() = json[GEOMETRY_KEY]?.jsonObject?.let { GeoJsonGeometry(it) }
public fun getProperty(propertyName: String): JsonElement? = properties?.get(propertyName) public companion object {
public fun getString(propertyName: String): String? = getProperty(propertyName)?.jsonPrimitive?.contentOrNull
public companion object{
public const val GEOMETRY_KEY: String = "geometry" public const val GEOMETRY_KEY: String = "geometry"
} }
} }
@ -62,6 +58,13 @@ public value class GeoJsonFeatureCollection(override val json: JsonObject) : Geo
} }
} }
public fun GeoJson(json: JsonObject): GeoJson =
when (json[TYPE_KEY]?.jsonPrimitive?.contentOrNull ?: error("Not a GeoJson")) {
"Feature" -> GeoJsonFeature(json)
"FeatureCollection" -> GeoJsonFeatureCollection(json)
else -> GeoJsonGeometry(json)
}
/** /**
* Combine a collection of features to a new [GeoJsonFeatureCollection] * Combine a collection of features to a new [GeoJsonFeatureCollection]
*/ */

View File

@ -83,10 +83,12 @@ public value class GeoJsonPolygon(override val json: JsonObject) : GeoJsonGeomet
require(type == "Polygon") { "Not a GeoJson Polygon geometry" } require(type == "Polygon") { "Not a GeoJson Polygon geometry" }
} }
public val coordinates: List<Gmc> public val coordinates: List<List<Gmc>>
get() = json[COORDINATES_KEY]?.jsonArray get() = json[COORDINATES_KEY]?.jsonArray?.map { polygon ->
?.map { it.toGmc() } polygon.jsonArray.map { point ->
?: error("Coordinates are not provided") point.toGmc()
}
} ?: error("Coordinates are not provided")
} }
@JvmInline @JvmInline
@ -95,10 +97,12 @@ public value class GeoJsonMultiPolygon(override val json: JsonObject) : GeoJsonG
require(type == "MultiPolygon") { "Not a GeoJson MultiPolygon geometry" } require(type == "MultiPolygon") { "Not a GeoJson MultiPolygon geometry" }
} }
public val coordinates: List<List<Gmc>> public val coordinates: List<List<List<Gmc>>>
get() = json[COORDINATES_KEY]?.jsonArray?.map { lineJson -> get() = json[COORDINATES_KEY]?.jsonArray?.map { allPolygons ->
lineJson.jsonArray.map { allPolygons.jsonArray.map { polygon ->
it.toGmc() polygon.jsonArray.map { point ->
point.toGmc()
}
} }
} ?: error("Coordinates are not provided") } ?: error("Coordinates are not provided")
} }

View File

@ -16,7 +16,7 @@ public fun FeatureBuilder<Gmc>.geoJsonGeometry(
geometry: GeoJsonGeometry, geometry: GeoJsonGeometry,
color: Color = defaultColor, color: Color = defaultColor,
id: String? = null, id: String? = null,
): FeatureId<*> = when (geometry) { ): FeatureId<Feature<Gmc>> = when (geometry) {
is GeoJsonLineString -> points( is GeoJsonLineString -> points(
geometry.coordinates, geometry.coordinates,
color = color, color = color,
@ -42,7 +42,7 @@ public fun FeatureBuilder<Gmc>.geoJsonGeometry(
is GeoJsonMultiPolygon -> group(id = id) { is GeoJsonMultiPolygon -> group(id = id) {
geometry.coordinates.forEach { geometry.coordinates.forEach {
points( points(
it, it.first(),
color = color, color = color,
pointMode = PointMode.Polygon pointMode = PointMode.Polygon
) )
@ -51,7 +51,7 @@ public fun FeatureBuilder<Gmc>.geoJsonGeometry(
is GeoJsonPoint -> circle(geometry.coordinates, color = color, id = id) is GeoJsonPoint -> circle(geometry.coordinates, color = color, id = id)
is GeoJsonPolygon -> points( is GeoJsonPolygon -> points(
geometry.coordinates, geometry.coordinates.first(),
color = color, color = color,
pointMode = PointMode.Polygon pointMode = PointMode.Polygon
) )
@ -67,18 +67,23 @@ public fun FeatureBuilder<Gmc>.geoJsonFeature(
geoJson: GeoJsonFeature, geoJson: GeoJsonFeature,
color: Color = defaultColor, color: Color = defaultColor,
id: String? = null, id: String? = null,
) { ): FeatureId<Feature<Gmc>>? {
val geometry = geoJson.geometry ?: return val geometry = geoJson.geometry ?: return null
val idOverride = geoJson.properties?.get("id")?.jsonPrimitive?.contentOrNull ?: id val idOverride = geoJson.properties?.get("id")?.jsonPrimitive?.contentOrNull ?: id
val colorOverride = geoJson.properties?.get("color")?.jsonPrimitive?.intOrNull?.let { Color(it) } ?: color val colorOverride = geoJson.properties?.get("color")?.jsonPrimitive?.intOrNull?.let { Color(it) } ?: color
geoJsonGeometry(geometry, colorOverride, idOverride) return geoJsonGeometry(geometry, colorOverride, idOverride)
} }
public fun FeatureBuilder<Gmc>.geoJson( public fun FeatureBuilder<Gmc>.geoJson(
geoJson: GeoJsonFeatureCollection, geoJson: GeoJson,
id: String? = null, id: String? = null,
): FeatureId<FeatureGroup<Gmc>> = group(id = id) { ): FeatureId<Feature<Gmc>>? = when (geoJson) {
geoJson.features.forEach { is GeoJsonFeature -> geoJsonFeature(geoJson, id = id)
geoJsonFeature(it) is GeoJsonFeatureCollection -> group(id = id) {
geoJson.features.forEach {
geoJsonFeature(it)
}
} }
is GeoJsonGeometry -> geoJsonGeometry(geoJson, id = id)
} }

View File

@ -0,0 +1,21 @@
package center.sciprog.maps.geojson
import center.sciprog.maps.coordinates.Gmc
import center.sciprog.maps.features.FeatureBuilder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import java.net.URL
/**
* Add geojson features from url
*/
public fun FeatureBuilder<Gmc>.geoJson(
geoJsonUrl: URL,
id: String? = null,
) {
val jsonString = geoJsonUrl.readText()
val json = Json.parseToJsonElement(jsonString).jsonObject
val geoJson = GeoJson(json)
geoJson(geoJson, id)
}