mirror of
https://github.com/Pygmalion69/OpenTopoMapViewer.git
synced 2025-10-06 00:02:42 +02:00
Add elevation endpoints
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package org.nitri.ors
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.nitri.ors.client.OpenRouteServiceClient
|
||||
import org.nitri.ors.repository.ElevationRepository
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ElevationInstrumentedTest {
|
||||
|
||||
private fun createRepository(context: Context): ElevationRepository {
|
||||
val apiKey = context.getString(R.string.ors_api_key)
|
||||
val api = OpenRouteServiceClient.create(apiKey, context)
|
||||
return ElevationRepository(api)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testElevation_point_successful() = runBlocking {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
val repository = createRepository(context)
|
||||
|
||||
// A point near Heidelberg, Germany
|
||||
val lon = 8.681495
|
||||
val lat = 49.41461
|
||||
|
||||
val response = repository.getElevationPoint(lon = lon, lat = lat)
|
||||
|
||||
assertNotNull("Elevation point response should not be null", response)
|
||||
assertNotNull("Geometry should not be null", response.geometry)
|
||||
assertEquals("Geometry type should be Point", "Point", response.geometry.type)
|
||||
|
||||
val coords = response.geometry.coordinates
|
||||
assertTrue("Point coordinates should contain at least [lon, lat]", coords.size >= 2)
|
||||
// Typically API returns elevation as third value
|
||||
if (coords.size >= 3) {
|
||||
// elevation could be any double, just ensure it's a number
|
||||
val elevation = coords[2]
|
||||
assertTrue("Elevation should be a finite number", elevation.isFinite())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testElevation_line_successful() = runBlocking {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
val repository = createRepository(context)
|
||||
|
||||
// A short line segment around Heidelberg
|
||||
val coordinates = listOf(
|
||||
listOf(8.681495, 49.41461),
|
||||
listOf(8.687872, 49.420318)
|
||||
)
|
||||
|
||||
val response = repository.getElevationLine(coordinates = coordinates)
|
||||
|
||||
assertNotNull("Elevation line response should not be null", response)
|
||||
assertEquals("Geometry type should be LineString", "LineString", response.geometry.type)
|
||||
val lineCoords = response.geometry.coordinates
|
||||
assertTrue("LineString should have at least 2 points", lineCoords.size >= 2)
|
||||
|
||||
val first = lineCoords.first()
|
||||
assertTrue("Each coordinate should have at least [lon, lat]", first.size >= 2)
|
||||
if (first.size >= 3) {
|
||||
val elevation = first[2]
|
||||
assertTrue("Elevation should be a finite number", elevation.isFinite())
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package org.nitri.ors.model.elevation
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
|
||||
|
||||
@Serializable
|
||||
data class ElevationLineRequest(
|
||||
/** One of: "geojson", "polyline", "encodedpolyline5", "encodedpolyline6" */
|
||||
@SerialName("format_in") val formatIn: String,
|
||||
|
||||
/** One of: "geojson", "polyline", "encodedpolyline5", "encodedpolyline6" */
|
||||
@SerialName("format_out") val formatOut: String,
|
||||
|
||||
/**
|
||||
* Geometry payload. The API accepts different shapes depending on format:
|
||||
* - format_in = "geojson" -> a GeoJSON LineString object
|
||||
* - format_in = "polyline" -> [[lon,lat], [lon,lat], ...]
|
||||
* - format_in = "encodedpolyline5/6"-> a single encoded polyline string
|
||||
*
|
||||
* Using JsonElement keeps this field flexible for all variants.
|
||||
*/
|
||||
val geometry: JsonElement,
|
||||
|
||||
/** Optional: pick a specific elevation dataset (e.g., "SRTM", "COP90", …) */
|
||||
val dataset: String? = null
|
||||
)
|
||||
|
||||
object ElevationFormats {
|
||||
const val GEOJSON = "geojson"
|
||||
const val POLYLINE = "polyline"
|
||||
const val ENCODED_5 = "encodedpolyline5"
|
||||
const val ENCODED_6 = "encodedpolyline6"
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package org.nitri.ors.model.elevation
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ElevationLineResponse(
|
||||
val attribution: String? = null,
|
||||
val geometry: ElevationLineGeometry,
|
||||
val timestamp: Long? = null,
|
||||
val version: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ElevationLineGeometry(
|
||||
val type: String, // "LineString"
|
||||
/** Coordinates with elevation: [lon, lat, ele] (API may return [lon,lat] if ele missing) */
|
||||
val coordinates: List<List<Double>>
|
||||
)
|
@@ -0,0 +1,17 @@
|
||||
package org.nitri.ors.model.elevation
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ElevationPointRequest(
|
||||
@SerialName("format_in")
|
||||
val formatIn: String, // Input format, must be provided (e.g., "point")
|
||||
|
||||
@SerialName("format_out")
|
||||
val formatOut: String = "geojson", // "geojson" or "point"
|
||||
|
||||
val dataset: String? = null, // Optional dataset, e.g. "srtm"
|
||||
|
||||
val geometry: List<Double> // [lon, lat]
|
||||
)
|
@@ -0,0 +1,17 @@
|
||||
package org.nitri.ors.model.elevation
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ElevationPointResponse(
|
||||
val attribution: String,
|
||||
val geometry: ElevationPointGeometry,
|
||||
val timestamp: Long,
|
||||
val version: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ElevationPointGeometry(
|
||||
val coordinates: List<Double>, // [lon, lat, elevation]
|
||||
val type: String // "Point"
|
||||
)
|
@@ -0,0 +1,72 @@
|
||||
package org.nitri.ors.repository
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import org.nitri.ors.api.OpenRouteServiceApi
|
||||
import org.nitri.ors.model.elevation.ElevationLineRequest
|
||||
import org.nitri.ors.model.elevation.ElevationLineResponse
|
||||
import org.nitri.ors.model.elevation.ElevationPointRequest
|
||||
import org.nitri.ors.model.elevation.ElevationPointResponse
|
||||
|
||||
class ElevationRepository(private val api: OpenRouteServiceApi) {
|
||||
|
||||
/**
|
||||
* Calls the ORS elevation/line POST endpoint with a prepared request.
|
||||
*/
|
||||
suspend fun getElevationLine(request: ElevationLineRequest): ElevationLineResponse =
|
||||
api.getElevationLine(request)
|
||||
|
||||
/**
|
||||
* Convenience helper to request elevation for a LineString provided as list of [lon, lat] pairs.
|
||||
* Builds a GeoJSON LineString payload and requests GeoJSON output.
|
||||
*/
|
||||
suspend fun getElevationLine(
|
||||
coordinates: List<List<Double>>, // [[lon,lat], [lon,lat], ...]
|
||||
dataset: String? = null,
|
||||
formatOut: String = "geojson",
|
||||
): ElevationLineResponse {
|
||||
val geometry: JsonElement = JsonObject(
|
||||
mapOf(
|
||||
"type" to JsonPrimitive("LineString"),
|
||||
"coordinates" to JsonArray(
|
||||
coordinates.map { pair ->
|
||||
JsonArray(pair.map { JsonPrimitive(it) })
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
val request = ElevationLineRequest(
|
||||
formatIn = "geojson",
|
||||
formatOut = formatOut,
|
||||
geometry = geometry,
|
||||
dataset = dataset
|
||||
)
|
||||
return api.getElevationLine(request)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the ORS elevation/point POST endpoint for a single coordinate.
|
||||
*
|
||||
* @param lon longitude
|
||||
* @param lat latitude
|
||||
* @param formatOut either "geojson" or "point"
|
||||
* @param dataset optional dataset (e.g., "srtm")
|
||||
*/
|
||||
suspend fun getElevationPoint(
|
||||
lon: Double,
|
||||
lat: Double,
|
||||
formatOut: String = "geojson",
|
||||
dataset: String? = null,
|
||||
): ElevationPointResponse {
|
||||
val request = ElevationPointRequest(
|
||||
formatIn = "point",
|
||||
formatOut = formatOut,
|
||||
dataset = dataset,
|
||||
geometry = listOf(lon, lat)
|
||||
)
|
||||
return api.getElevationPoint(request)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user