diff --git a/demo/maps/build.gradle.kts b/demo/maps/build.gradle.kts index 719078c..5e8d8dc 100644 --- a/demo/maps/build.gradle.kts +++ b/demo/maps/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.dsl.TargetFormat plugins { @@ -19,6 +18,7 @@ kotlin { val jvmMain by getting { dependencies { implementation(projects.mapsKtCompose) + implementation(projects.mapsKtGeojson) implementation(compose.desktop.currentOs) implementation("io.ktor:ktor-client-cio") implementation("ch.qos.logback:logback-classic:1.2.11") diff --git a/demo/maps/src/jvmMain/kotlin/Main.kt b/demo/maps/src/jvmMain/kotlin/Main.kt index 8146799..ebd4f8d 100644 --- a/demo/maps/src/jvmMain/kotlin/Main.kt +++ b/demo/maps/src/jvmMain/kotlin/Main.kt @@ -13,9 +13,11 @@ import androidx.compose.ui.window.application import center.sciprog.maps.compose.* import center.sciprog.maps.coordinates.* import center.sciprog.maps.features.* +import center.sciprog.maps.geojson.geoJson import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO import kotlinx.coroutines.delay +import java.net.URL import java.nio.file.Path import kotlin.math.PI import kotlin.random.Random @@ -44,8 +46,6 @@ fun App() { val pointTwo = 55.929444 to 37.518434 val pointThree = 60.929444 to 37.518434 - val dragPoint = 55.744 to 37.614 - MapView( mapTileProvider = mapTileProvider, // 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) val marker1 = rectangle(55.744 to 37.614, size = DpSize(10.dp, 10.dp), color = Color.Magenta) diff --git a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJson.kt b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJson.kt index 989f40c..471ab40 100644 --- a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJson.kt +++ b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJson.kt @@ -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 fun getProperty(propertyName: String): JsonElement? = properties?.get(propertyName) - - public fun getString(propertyName: String): String? = getProperty(propertyName)?.jsonPrimitive?.contentOrNull - - public companion object{ + public companion object { 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] */ diff --git a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJsonGeometry.kt b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJsonGeometry.kt index 99009c1..39e26b3 100644 --- a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJsonGeometry.kt +++ b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/GeoJsonGeometry.kt @@ -83,10 +83,12 @@ public value class GeoJsonPolygon(override val json: JsonObject) : GeoJsonGeomet require(type == "Polygon") { "Not a GeoJson Polygon geometry" } } - public val coordinates: List - get() = json[COORDINATES_KEY]?.jsonArray - ?.map { it.toGmc() } - ?: error("Coordinates are not provided") + public val coordinates: List> + get() = json[COORDINATES_KEY]?.jsonArray?.map { polygon -> + polygon.jsonArray.map { point -> + point.toGmc() + } + } ?: error("Coordinates are not provided") } @JvmInline @@ -95,10 +97,12 @@ public value class GeoJsonMultiPolygon(override val json: JsonObject) : GeoJsonG require(type == "MultiPolygon") { "Not a GeoJson MultiPolygon geometry" } } - public val coordinates: List> - get() = json[COORDINATES_KEY]?.jsonArray?.map { lineJson -> - lineJson.jsonArray.map { - it.toGmc() + public val coordinates: List>> + get() = json[COORDINATES_KEY]?.jsonArray?.map { allPolygons -> + allPolygons.jsonArray.map { polygon -> + polygon.jsonArray.map { point -> + point.toGmc() + } } } ?: error("Coordinates are not provided") } diff --git a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonFeature.kt b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonFeature.kt index 8557478..29243a5 100644 --- a/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonFeature.kt +++ b/maps-kt-geojson/src/commonMain/kotlin/center/sciprog/maps/geojson/geoJsonFeature.kt @@ -16,7 +16,7 @@ public fun FeatureBuilder.geoJsonGeometry( geometry: GeoJsonGeometry, color: Color = defaultColor, id: String? = null, -): FeatureId<*> = when (geometry) { +): FeatureId> = when (geometry) { is GeoJsonLineString -> points( geometry.coordinates, color = color, @@ -42,7 +42,7 @@ public fun FeatureBuilder.geoJsonGeometry( is GeoJsonMultiPolygon -> group(id = id) { geometry.coordinates.forEach { points( - it, + it.first(), color = color, pointMode = PointMode.Polygon ) @@ -51,7 +51,7 @@ public fun FeatureBuilder.geoJsonGeometry( is GeoJsonPoint -> circle(geometry.coordinates, color = color, id = id) is GeoJsonPolygon -> points( - geometry.coordinates, + geometry.coordinates.first(), color = color, pointMode = PointMode.Polygon ) @@ -67,18 +67,23 @@ public fun FeatureBuilder.geoJsonFeature( geoJson: GeoJsonFeature, color: Color = defaultColor, id: String? = null, -) { - val geometry = geoJson.geometry ?: return +): FeatureId>? { + val geometry = geoJson.geometry ?: return null val idOverride = geoJson.properties?.get("id")?.jsonPrimitive?.contentOrNull ?: id val colorOverride = geoJson.properties?.get("color")?.jsonPrimitive?.intOrNull?.let { Color(it) } ?: color - geoJsonGeometry(geometry, colorOverride, idOverride) + return geoJsonGeometry(geometry, colorOverride, idOverride) } public fun FeatureBuilder.geoJson( - geoJson: GeoJsonFeatureCollection, + geoJson: GeoJson, id: String? = null, -): FeatureId> = group(id = id) { - geoJson.features.forEach { - geoJsonFeature(it) +): FeatureId>? = when (geoJson) { + is GeoJsonFeature -> geoJsonFeature(geoJson, id = id) + is GeoJsonFeatureCollection -> group(id = id) { + geoJson.features.forEach { + geoJsonFeature(it) + } } + + is GeoJsonGeometry -> geoJsonGeometry(geoJson, id = id) } \ No newline at end of file diff --git a/maps-kt-geojson/src/jvmMain/kotlin/center/sciprog/maps/geojson/geoJsonFeatureJvm.kt b/maps-kt-geojson/src/jvmMain/kotlin/center/sciprog/maps/geojson/geoJsonFeatureJvm.kt new file mode 100644 index 0000000..9436911 --- /dev/null +++ b/maps-kt-geojson/src/jvmMain/kotlin/center/sciprog/maps/geojson/geoJsonFeatureJvm.kt @@ -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.geoJson( + geoJsonUrl: URL, + id: String? = null, +) { + val jsonString = geoJsonUrl.readText() + val json = Json.parseToJsonElement(jsonString).jsonObject + val geoJson = GeoJson(json) + + geoJson(geoJson, id) +} \ No newline at end of file