Skip to content

Commit 289a1fb

Browse files
docs & format
1 parent 0ff0ee8 commit 289a1fb

File tree

13 files changed

+108
-108
lines changed

13 files changed

+108
-108
lines changed

dataframe-geo/build.gradle.kts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
alias(kotlin.jvm)
77
alias(publisher)
88
alias(jupyter.api)
9-
//alias(ktlint)
9+
alias(ktlint)
1010
}
1111
}
1212

@@ -67,6 +67,3 @@ tasks.processJupyterApiResources {
6767
tasks.test {
6868
useJUnitPlatform()
6969
}
70-
kotlin {
71-
jvmToolchain(11)
72-
}

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/GeoDataFrame.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@ import org.jetbrains.kotlinx.dataframe.api.with
1717
*/
1818
class GeoDataFrame<T : WithGeometry>(val df: DataFrame<T>, val crs: CoordinateReferenceSystem?) {
1919
/**
20-
* Updates the `GeoDataFrame` using a specified transformation block on the underlying DataFrame.
20+
* Creates a new `GeoDataFrame` using a specified transformation block on the underlying DataFrame.
2121
*
2222
* @param updateBlock The block defining the transformations to be applied to the DataFrame.
2323
* @return A new `GeoDataFrame` instance with updated data and the same CRS.
2424
*/
25-
fun update(updateBlock: DataFrame<T>.() -> DataFrame<T>): GeoDataFrame<T> {
26-
return GeoDataFrame(df.updateBlock(), crs)
27-
}
25+
fun update(updateBlock: DataFrame<T>.() -> DataFrame<T>): GeoDataFrame<T> = GeoDataFrame(df.updateBlock(), crs)
2826

2927
/**
3028
* Transforms the geometries to a specified Coordinate Reference System (CRS).
@@ -41,25 +39,30 @@ class GeoDataFrame<T : WithGeometry>(val df: DataFrame<T>, val crs: CoordinateRe
4139
}
4240
if (targetCrs == this.crs) return this
4341
// Use WGS 84 by default TODO
44-
val sourceCRS: CoordinateReferenceSystem = this.crs ?: DEFAULT_CRS
42+
val sourceCRS: CoordinateReferenceSystem = this.crs
4543
val transform = CRS.findMathTransform(sourceCRS, targetCrs, true)
4644
return GeoDataFrame(
4745
df.update { geometry }.with { JTS.transform(it, transform) },
48-
targetCrs
46+
targetCrs,
4947
)
5048
}
5149

5250
override fun equals(other: Any?): Boolean {
5351
if (this === other) return true
5452
if (other !is GeoDataFrame<*>) return false
5553

56-
return df == other.df && when {
57-
crs == null && other.crs == null -> true
58-
crs == null || other.crs == null -> false
59-
else -> CRS.equalsIgnoreMetadata(crs, other.crs)
60-
}
54+
return df == other.df &&
55+
when {
56+
crs == null && other.crs == null -> true
57+
crs == null || other.crs == null -> false
58+
else -> CRS.equalsIgnoreMetadata(crs, other.crs)
59+
}
6160
}
6261

62+
override fun toString(): String = super.toString()
63+
64+
override fun hashCode(): Int = super.hashCode()
65+
6366
companion object {
6467
val DEFAULT_CRS = CRS.decode("EPSG:4326", true)
6568
}

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/WithGeometry.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ interface WithMultiPolygon : WithGeometry {
2222
override val geometry: MultiPolygon
2323
}
2424

25+
@Suppress("UNCHECKED_CAST")
2526
@get:JvmName("geometry")
26-
val <T : WithGeometry> ColumnsContainer<T>.geometry: DataColumn<Geometry>
27+
val ColumnsContainer<WithGeometry>.geometry: DataColumn<Geometry>
2728
get() = get("geometry") as DataColumn<Geometry>
2829

30+
@Suppress("UNCHECKED_CAST")
2931
@get:JvmName("geometryPolygon")
30-
val <T : WithPolygon> ColumnsContainer<T>.geometry: DataColumn<Polygon>
32+
val ColumnsContainer<WithPolygon>.geometry: DataColumn<Polygon>
3133
get() = get("geometry") as DataColumn<Polygon>
3234

35+
@Suppress("UNCHECKED_CAST")
3336
@get:JvmName("geometryMultiPolygon")
34-
val <T : WithMultiPolygon> ColumnsContainer<T>.geometry: DataColumn<MultiPolygon>
37+
val ColumnsContainer<WithMultiPolygon>.geometry: DataColumn<MultiPolygon>
3538
get() = get("geometry") as DataColumn<MultiPolygon>

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/bounds.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,4 @@ import org.jetbrains.kotlinx.dataframe.geo.jts.computeBounds
1212
* @return The bounding envelope that includes all geometries,
1313
* associated with the CRS of the `GeoDataFrame`.
1414
*/
15-
fun GeoDataFrame<*>.bounds(): ReferencedEnvelope {
16-
return ReferencedEnvelope(df.geometry.asIterable().computeBounds(), crs)
17-
}
15+
fun GeoDataFrame<*>.bounds(): ReferencedEnvelope = ReferencedEnvelope(df.geometry.asIterable().computeBounds(), crs)

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/geocode/Geocoder.kt

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,27 @@ import org.locationtech.jts.geom.Geometry
2121
import org.locationtech.jts.geom.GeometryFactory
2222
import org.locationtech.jts.io.geojson.GeoJsonReader
2323

24-
2524
object Geocoder {
2625

2726
private val url = "https://geo2.datalore.jetbrains.com/map_data/geocoding"
2827

29-
private fun countryQuery(country: String) = """ {
30-
"region_query_names" : [ "$country" ],
31-
"region_query_countries" : null,
32-
"region_query_states" : null,
33-
"region_query_counties" : null,
34-
"ambiguity_resolver" : {
35-
"ambiguity_resolver_ignoring_strategy" : null,
36-
"ambiguity_resolver_box" : null,
37-
"ambiguity_resolver_closest_coord" : null
38-
}
39-
}
40-
""".trimIndent()
28+
private fun countryQuery(country: String) =
29+
"""
30+
{
31+
"region_query_names" : [ "$country" ],
32+
"region_query_countries" : null,
33+
"region_query_states" : null,
34+
"region_query_counties" : null,
35+
"ambiguity_resolver" : {
36+
"ambiguity_resolver_ignoring_strategy" : null,
37+
"ambiguity_resolver_box" : null,
38+
"ambiguity_resolver_closest_coord" : null
39+
}
40+
}
41+
""".trimIndent()
4142

42-
private fun geocodeQuery(countries: List<String>) = """
43+
private fun geocodeQuery(countries: List<String>) =
44+
"""
4345
{
4446
"version" : 3,
4547
"mode" : "by_geocoding",
@@ -55,29 +57,31 @@ object Geocoder {
5557
"namesake_example_limit" : 10,
5658
"allow_ambiguous" : false
5759
}
58-
""".trimIndent()
60+
""".trimIndent()
5961

60-
private fun idsQuery(ids: List<String>) = """
61-
{"version": 3,
62-
"mode": "by_id",
63-
"feature_options": ["boundary"],
64-
"resolution": 5,
65-
"view_box": null,
66-
"fetched_ids": null,
67-
"ids": [${ids.joinToString(", ") { "\"" + it + "\"" }}]}
68-
""".trimIndent()
62+
private fun idsQuery(ids: List<String>) =
63+
"""
64+
{"version": 3,
65+
"mode": "by_id",
66+
"feature_options": ["boundary"],
67+
"resolution": 5,
68+
"view_box": null,
69+
"fetched_ids": null,
70+
"ids": [${ids.joinToString(", ") { "\"" + it + "\"" }}]}
71+
""".trimIndent()
6972

7073
private val client = HttpClient(CIO) {
7174
install(ContentNegotiation) {
72-
json(Json {
73-
prettyPrint = true
74-
isLenient = true
75-
})
75+
json(
76+
Json {
77+
prettyPrint = true
78+
isLenient = true
79+
},
80+
)
7681
}
7782
}
7883

7984
fun geocodeCountries(countries: List<String>): GeoDataFrame<*> {
80-
8185
val query = geocodeQuery(countries)
8286
val foundNames = mutableListOf<String>()
8387
val geometries = mutableListOf<Geometry>()
@@ -104,13 +108,14 @@ object Geocoder {
104108
}.bodyAsText()
105109

106110
val geoJsonReader = GeoJsonReader(GeometryFactory())
107-
Json.parseToJsonElement(responseStringGeometries).jsonObject["data"]!!.jsonObject["answers"]!!.jsonArray.forEach {
111+
Json.parseToJsonElement(
112+
responseStringGeometries,
113+
).jsonObject["data"]!!.jsonObject["answers"]!!.jsonArray.forEach {
108114
it.jsonObject["features"]!!.jsonArray.single().jsonObject.also {
109115
val boundary = it["boundary"]!!.jsonPrimitive.content
110116
geometries.add(geoJsonReader.read(boundary))
111117
}
112118
}
113-
114119
}
115120
return dataFrameOf(
116121
"country" to countries,

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/geotools/toGeoDataFrame.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,17 @@ import org.jetbrains.kotlinx.dataframe.geo.GeoDataFrame
1313
import org.jetbrains.kotlinx.dataframe.geo.WithGeometry
1414
import org.locationtech.jts.geom.Geometry
1515

16+
/**
17+
* Converts this SimpleFeatureCollection to a GeoDataFrame.
18+
*
19+
* This method transforms the SimpleFeatureCollection into a GeoDataFrame, extracting both
20+
* spatial (geometry) and non-spatial attributes, and associates them with an optional
21+
* Coordinate Reference System (CRS) if available.
22+
*
23+
* @return a GeoDataFrame containing the data from this SimpleFeatureCollection, including
24+
* geometries and other attributes, and an associated CRS if present.
25+
*/
1626
fun SimpleFeatureCollection.toGeoDataFrame(): GeoDataFrame<*> {
17-
1827
require(schema is SimpleFeatureType) {
1928
"GeoTools: SimpleFeatureType expected but was: ${schema::class.simpleName}"
2029
}
@@ -52,5 +61,6 @@ fun SimpleFeatureCollection.toGeoDataFrame(): GeoDataFrame<*> {
5261

5362
val geometryColumn = DataColumn.create("geometry", geometries, Infer.Type)
5463

64+
@Suppress("UNCHECKED_CAST")
5565
return GeoDataFrame((data.toDataFrame() + geometryColumn) as DataFrame<WithGeometry>, crs)
5666
}

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/geotools/toSimpleFeatureCollection.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,26 @@ import org.jetbrains.kotlinx.dataframe.api.single
1111
import org.jetbrains.kotlinx.dataframe.geo.GeoDataFrame
1212
import org.locationtech.jts.geom.Geometry
1313

14+
/**
15+
* Converts the `GeoDataFrame` to a `SimpleFeatureCollection`.
16+
*
17+
* @param name Optional name for the `SimpleFeatureCollection`. Defaults to "geodata" if not specified.
18+
* @param singleGeometryType Whether to enforce a single geometry type within the collection. Defaults to false.
19+
* @return A `SimpleFeatureCollection` representing the `GeoDataFrame`.
20+
*/
1421
fun GeoDataFrame<*>.toSimpleFeatureCollection(
1522
name: String? = null,
16-
singleGeometryType: Boolean = false
23+
singleGeometryType: Boolean = false,
1724
): SimpleFeatureCollection {
1825
val typeBuilder = SimpleFeatureTypeBuilder()
1926
typeBuilder.name = name ?: "geodata"
2027
typeBuilder.setCRS(crs)
2128
val geometryClass = if (singleGeometryType) {
2229
// todo singleOrNull() ?: error()
2330
df["geometry"].map { it!!::class.java }.distinct().single()
24-
} else Geometry::class.java
31+
} else {
32+
Geometry::class.java
33+
}
2534
typeBuilder.add("the_geom", geometryClass)
2635
df.columnNames().filter { it != "geometry" }.forEach { colName ->
2736
typeBuilder.add(colName, String::class.java)

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/io/read.kt

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,20 @@ import org.jetbrains.kotlinx.dataframe.geo.geotools.toGeoDataFrame
99
import org.jetbrains.kotlinx.dataframe.io.asURL
1010
import java.net.URL
1111

12+
fun GeoDataFrame.Companion.readGeoJson(path: String): GeoDataFrame<*> = readGeoJson(asURL(path))
1213

13-
fun GeoDataFrame.Companion.readGeoJson(path: String): GeoDataFrame<*> {
14-
return readGeoJson(asURL(path))
15-
}
14+
fun GeoDataFrame.Companion.readGeoJson(url: URL): GeoDataFrame<*> =
15+
(FeatureJSON().readFeatureCollection(url.openStream()) as SimpleFeatureCollection).toGeoDataFrame()
1616

17-
fun GeoDataFrame.Companion.readGeoJson(url: URL): GeoDataFrame<*> {
18-
return (FeatureJSON().readFeatureCollection(url.openStream()) as SimpleFeatureCollection).toGeoDataFrame()
19-
}
17+
fun DataFrame.Companion.readGeoJson(path: String): GeoDataFrame<*> = GeoDataFrame.readGeoJson(path)
2018

21-
fun DataFrame.Companion.readGeoJson(path: String): GeoDataFrame<*> {
22-
return GeoDataFrame.readGeoJson(path)
23-
}
19+
fun DataFrame.Companion.readGeoJson(url: URL): GeoDataFrame<*> = GeoDataFrame.readGeoJson(url)
2420

25-
fun DataFrame.Companion.readGeoJson(url: URL): GeoDataFrame<*> {
26-
return GeoDataFrame.readGeoJson(url)
27-
}
21+
fun GeoDataFrame.Companion.readShapefile(path: String): GeoDataFrame<*> = readShapefile(asURL(path))
2822

29-
fun GeoDataFrame.Companion.readShapefile(path: String): GeoDataFrame<*> {
30-
return readShapefile(asURL(path))
31-
}
23+
fun GeoDataFrame.Companion.readShapefile(url: URL): GeoDataFrame<*> =
24+
ShapefileDataStoreFactory().createDataStore(url).featureSource.features.toGeoDataFrame()
3225

33-
fun GeoDataFrame.Companion.readShapefile(url: URL): GeoDataFrame<*> {
34-
return ShapefileDataStoreFactory().createDataStore(url).featureSource.features.toGeoDataFrame()
35-
}
26+
fun DataFrame.Companion.readShapefile(path: String): GeoDataFrame<*> = GeoDataFrame.readShapefile(path)
3627

37-
fun DataFrame.Companion.readShapefile(path: String): GeoDataFrame<*> {
38-
return GeoDataFrame.readShapefile(path)
39-
}
40-
41-
fun DataFrame.Companion.readShapefile(url: URL): GeoDataFrame<*> {
42-
return GeoDataFrame.readShapefile(url)
43-
}
28+
fun DataFrame.Companion.readShapefile(url: URL): GeoDataFrame<*> = GeoDataFrame.readShapefile(url)

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/io/write.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ import org.jetbrains.kotlinx.dataframe.geo.GeoDataFrame
99
import org.jetbrains.kotlinx.dataframe.geo.geotools.toSimpleFeatureCollection
1010
import java.io.File
1111

12-
1312
fun GeoDataFrame<*>.writeGeoJson(path: String): Unit = writeGeoJson(File(path))
1413

1514
fun GeoDataFrame<*>.writeGeoJson(file: File) {
16-
1715
// TODO: adds ids that breaks order of reading
1816
val featureJSON = FeatureJSON()
1917
file.outputStream().use { outputStream ->
@@ -24,7 +22,6 @@ fun GeoDataFrame<*>.writeGeoJson(file: File) {
2422
fun GeoDataFrame<*>.writeShapefile(directoryPath: String): Unit = writeShapefile(File(directoryPath))
2523

2624
fun GeoDataFrame<*>.writeShapefile(directory: File) {
27-
2825
if (!directory.exists()) {
2926
directory.mkdirs()
3027
}
@@ -35,7 +32,6 @@ fun GeoDataFrame<*>.writeShapefile(directory: File) {
3532
val creationParams = mutableMapOf<String, java.io.Serializable>()
3633
creationParams["url"] = file.toURI().toURL()
3734

38-
3935
val factory = FileDataStoreFinder.getDataStoreFactory("shp")
4036
val dataStore = factory.createNewDataStore(creationParams)
4137

@@ -58,5 +54,4 @@ fun GeoDataFrame<*>.writeShapefile(directory: File) {
5854
} finally {
5955
transaction.close()
6056
}
61-
6257
}

dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/jts/geometryExtenstions.kt renamed to dataframe-geo/src/main/kotlin/org/jetbrains/kotlinx/dataframe/geo/jts/geometryExtensions.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ import org.locationtech.jts.geom.util.AffineTransformation
99
* @param factor The scaling factor for both the X and Y axes.
1010
* @return A new geometry scaled around its center.
1111
*/
12-
fun Geometry.scaleAroundCenter(factor: Double): Geometry {
13-
return scaleAroundCenter(factor, factor)
14-
}
12+
fun Geometry.scaleAroundCenter(factor: Double): Geometry = scaleAroundCenter(factor, factor)
1513

1614
/**
1715
* Scales the geometry around its center using different scaling factors for the X and Y axes.
@@ -39,9 +37,8 @@ fun Geometry.scaleAroundCenter(xFactor: Double, yFactor: Double): Geometry {
3937
* @param valueY The translation distance along the Y axis.
4038
* @return A new geometry translated by the specified distances.
4139
*/
42-
fun Geometry.translate(valueX: Double, valueY: Double): Geometry {
43-
return AffineTransformation().translate(valueX, valueY).transform(this)
44-
}
40+
fun Geometry.translate(valueX: Double, valueY: Double): Geometry =
41+
AffineTransformation().translate(valueX, valueY).transform(this)
4542

4643
/**
4744
* Rotates the geometry around its center by the specified angle in radians.
@@ -65,15 +62,11 @@ fun Geometry.rotate(angleRadians: Double): Geometry {
6562
*
6663
* @return A new geometry reflected across the X axis.
6764
*/
68-
fun Geometry.reflectX(): Geometry {
69-
return scaleAroundCenter(-1.0, 1.0)
70-
}
65+
fun Geometry.reflectX(): Geometry = scaleAroundCenter(-1.0, 1.0)
7166

7267
/**
7368
* Reflects the geometry across the Y axis, inverting its vertical position.
7469
*
7570
* @return A new geometry reflected across the Y axis.
7671
*/
77-
fun Geometry.reflectY(): Geometry {
78-
return scaleAroundCenter(1.0, -1.0)
79-
}
72+
fun Geometry.reflectY(): Geometry = scaleAroundCenter(1.0, -1.0)

0 commit comments

Comments
 (0)