1
1
mirror of https://github.com/Pygmalion69/OpenTopoMapViewer.git synced 2025-10-06 00:02:42 +02:00

docs: improve ORS client documentation (#37)

This commit is contained in:
Serge Helfrich
2025-08-30 12:34:53 +02:00
committed by GitHub
parent aff7527f9c
commit df4d38ba12
31 changed files with 244 additions and 74 deletions

View File

@@ -25,9 +25,14 @@ import org.nitri.ors.domain.snap.SnapRequest
import org.nitri.ors.domain.snap.SnapResponse
import org.nitri.ors.restclient.OpenRouteServiceRestClient
/**
* Default implementation of [OrsClient] using the Retrofit based
* [OpenRouteServiceRestClient].
*/
class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
private val api = OpenRouteServiceRestClient.create(apiKey, context)
/** @inheritDoc */
override suspend fun getRoute(
profile: Profile,
routeRequest: RouteRequest
@@ -35,6 +40,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getRoute(profile.key, routeRequest)
}
/** @inheritDoc */
override suspend fun getRouteGpx(
profile: Profile,
routeRequest: RouteRequest
@@ -42,6 +48,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getRouteGpx(profile.key, routeRequest).body()?.string() ?: ""
}
/** @inheritDoc */
override suspend fun getRouteGeoJson(
profile: Profile,
routeRequest: RouteRequest
@@ -49,6 +56,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getRouteGeoJson(profile.key, routeRequest)
}
/** @inheritDoc */
override suspend fun export(
profile: Profile,
exportRequest: ExportRequest
@@ -56,6 +64,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.export(profile.key, exportRequest)
}
/** @inheritDoc */
override suspend fun exportJson(
profile: Profile,
exportRequest: ExportRequest
@@ -63,6 +72,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.exportJson(profile.key, exportRequest)
}
/** @inheritDoc */
override suspend fun exportTopoJson(
profile: Profile,
exportRequest: ExportRequest
@@ -70,6 +80,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.exportTopoJson(profile.key, exportRequest)
}
/** @inheritDoc */
override suspend fun getIsochrones(
profile: Profile,
isochronesRequest: IsochronesRequest
@@ -77,6 +88,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getIsochrones(profile.key, isochronesRequest)
}
/** @inheritDoc */
override suspend fun getMatrix(
profile: Profile,
matrixRequest: MatrixRequest
@@ -84,6 +96,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getMatrix(profile.key, matrixRequest)
}
/** @inheritDoc */
override suspend fun getSnap(
profile: Profile,
snapRequest: SnapRequest
@@ -91,6 +104,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getSnap(profile.key, snapRequest)
}
/** @inheritDoc */
override suspend fun getSnapJson(
profile: Profile,
snapRequest: SnapRequest
@@ -98,6 +112,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getSnapJson(profile.key, snapRequest)
}
/** @inheritDoc */
override suspend fun getSnapGeoJson(
profile: Profile,
snapRequest: SnapRequest
@@ -105,6 +120,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return api.getSnapGeoJson(profile.key, snapRequest)
}
/** @inheritDoc */
override suspend fun getPois(poisRequest: PoisRequest): PoisGeoJsonResponse {
val raw = api.getPois(poisRequest)
fun PoisGeoJsonResponse.sanitized(): PoisGeoJsonResponse =
@@ -112,22 +128,26 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
return raw.sanitized()
}
/** @inheritDoc */
override suspend fun getOptimization(optimizationRequest: OptimizationRequest): OptimizationResponse {
return api.getOptimization(optimizationRequest)
}
/** @inheritDoc */
override suspend fun getElevationLine(
elevationLineRequest: ElevationLineRequest
): ElevationLineResponse {
return api.getElevationLine(elevationLineRequest)
}
/** @inheritDoc */
override suspend fun getElevationPoint(
elevationPointRequest: ElevationPointRequest
): ElevationPointResponse {
return api.getElevationPoint(elevationPointRequest)
}
/** @inheritDoc */
override suspend fun geocodeSearch(
text: String,
apiKey: String,
@@ -166,6 +186,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
)
}
/** @inheritDoc */
override suspend fun geocodeAutocomplete(
apiKey: String,
text: String,
@@ -202,6 +223,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
)
}
/** @inheritDoc */
override suspend fun geocodeStructured(
apiKey: String,
address: String?,
@@ -252,6 +274,7 @@ class DefaultOrsClient(apiKey: String, context: Context) : OrsClient {
)
}
/** @inheritDoc */
override suspend fun geocodeReverse(
apiKey: String,
lon: Double,

View File

@@ -2,8 +2,16 @@ package org.nitri.ors
import android.content.Context
/**
* Factory for obtaining [OrsClient] instances.
*/
object Ors {
/** If you already construct the Retrofit API elsewhere, inject it here. */
/**
* Creates a default [OrsClient] backed by Retrofit.
*
* @param apiKey API key obtained from openrouteservice.org
* @param context Android context used for HTTP client construction
*/
@JvmStatic
fun create(apiKey: String, context: Context): OrsClient = DefaultOrsClient(apiKey, context)
}

View File

@@ -23,6 +23,11 @@ import org.nitri.ors.domain.snap.SnapGeoJsonResponse
import org.nitri.ors.domain.snap.SnapRequest
import org.nitri.ors.domain.snap.SnapResponse
/**
* Supported routing profiles used across the OpenRouteService endpoints.
*
* The [key] corresponds to the profile identifier expected by the HTTP API.
*/
enum class Profile(val key: String) {
DRIVING_CAR("driving-car"),
DRIVING_HGV("driving-hgv"),
@@ -35,44 +40,84 @@ enum class Profile(val key: String) {
WHEELCHAIR("wheelchair")
}
@JvmInline value class Lon(val v: Double)
@JvmInline value class Lat(val v: Double)
/** Longitude value wrapper used by the DSL builders. */
@JvmInline
value class Lon(val v: Double)
/** Latitude value wrapper used by the DSL builders. */
@JvmInline
value class Lat(val v: Double)
/** Convenience pair for longitude/latitude coordinates. */
data class LonLat(val lon: Double, val lat: Double)
/**
* Abstraction over the OpenRouteService HTTP API.
*
* Implementations map these suspending functions to the respective REST
* endpoints as documented in the
* [OpenRouteService API reference](https://openrouteservice.org/dev/#/api-docs).
*/
interface OrsClient {
// Directions
/**
* Requests a route using the Directions endpoint.
* `GET /v2/directions/{profile}`
*/
suspend fun getRoute(profile: Profile, routeRequest: RouteRequest): RouteResponse
/** Retrieves the route as GPX. */
suspend fun getRouteGpx(profile: Profile, routeRequest: RouteRequest): String
/** Retrieves the route as GeoJSON feature collection. */
suspend fun getRouteGeoJson(profile: Profile, routeRequest: RouteRequest): GeoJsonRouteResponse
// Export
/** Calls the export endpoint returning plain JSON. */
suspend fun export(profile: Profile, exportRequest: ExportRequest): ExportResponse
/** Same as [export] but explicitly requesting JSON output. */
suspend fun exportJson(profile: Profile, exportRequest: ExportRequest): ExportResponse
/** Requests TopoJSON output from the export endpoint. */
suspend fun exportTopoJson(profile: Profile, exportRequest: ExportRequest): TopoJsonExportResponse
// Isochrones
/** Accesses the isochrones endpoint. */
suspend fun getIsochrones(profile: Profile, isochronesRequest: IsochronesRequest): IsochronesResponse
// Matrix
/** Calls the matrix endpoint and returns distance/duration matrices. */
suspend fun getMatrix(profile: Profile, matrixRequest: MatrixRequest): MatrixResponse
// Snapping
/** Snaps coordinates to the road network. */
suspend fun getSnap(profile: Profile, snapRequest: SnapRequest): SnapResponse
/** Snaps coordinates and returns the JSON variant of the response. */
suspend fun getSnapJson(profile: Profile, snapRequest: SnapRequest): SnapResponse
/** Snaps coordinates and returns a GeoJSON response. */
suspend fun getSnapGeoJson(profile: Profile, snapRequest: SnapRequest): SnapGeoJsonResponse
// POIs
/** Queries points of interest and returns a GeoJSON feature collection. */
suspend fun getPois(poisRequest: PoisRequest): PoisGeoJsonResponse
// Optimization
/** Delegates to the VROOM based optimization service. */
suspend fun getOptimization(optimizationRequest: OptimizationRequest): OptimizationResponse
// Elevation
/** Calls the elevation/line endpoint. */
suspend fun getElevationLine(elevationLineRequest: ElevationLineRequest): ElevationLineResponse
/** Calls the elevation/point endpoint. */
suspend fun getElevationPoint(elevationPointRequest: ElevationPointRequest): ElevationPointResponse
// Geocode
/** Forward geocoding search endpoint. */
suspend fun geocodeSearch(
text: String,
apiKey: String,
@@ -92,6 +137,7 @@ interface OrsClient {
size: Int? = 10,
): GeocodeSearchResponse
/** Autocomplete endpoint returning suggestions for a partial query. */
suspend fun geocodeAutocomplete(
apiKey: String,
text: String,
@@ -110,6 +156,7 @@ interface OrsClient {
size: Int? = null,
): GeocodeSearchResponse
/** Structured forward geocoding using discrete address fields. */
suspend fun geocodeStructured(
apiKey: String,
address: String? = null,
@@ -135,6 +182,7 @@ interface OrsClient {
size: Int? = null,
): GeocodeSearchResponse
/** Reverse geocoding for a single coordinate. */
suspend fun geocodeReverse(
apiKey: String,
lon: Double,

View File

@@ -5,10 +5,11 @@ import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonArray
// Kotlin DSL for ElevationLineRequest
/** DSL for building [ElevationLineRequest] instances. */
inline fun elevationLineRequest(build: ElevationLineRequestBuilder.() -> Unit): ElevationLineRequest =
ElevationLineRequestBuilder().apply(build).build()
/** Builder used by [elevationLineRequest]. */
class ElevationLineRequestBuilder {
var formatIn: String = ElevationFormats.POLYLINE
var formatOut: String = ElevationFormats.GEOJSON
@@ -40,10 +41,11 @@ class ElevationLineRequestBuilder {
}
}
// Kotlin DSL for ElevationPointRequest
/** DSL for constructing [ElevationPointRequest] objects. */
inline fun elevationPointRequest(build: ElevationPointRequestBuilder.() -> Unit): ElevationPointRequest =
ElevationPointRequestBuilder().apply(build).build()
/** Builder used by [elevationPointRequest]. */
class ElevationPointRequestBuilder {
var formatIn: String = "point"
var formatOut: String = "geojson"
@@ -92,4 +94,4 @@ class ElevationPointRequestBuilderJ {
fun dataset(v: String?) = apply { dsl.dataset = v }
fun point(lon: Double, lat: Double) = apply { dsl.point(lon, lat) }
fun build(): ElevationPointRequest = dsl.build()
}
}

View File

@@ -3,15 +3,20 @@ package org.nitri.ors.domain.elevation
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** Request for the `elevation/point` endpoint. */
@Serializable
data class ElevationPointRequest(
@SerialName("format_in")
val formatIn: String, // Input format, must be provided (e.g., "point")
/** Input format, e.g. `point`. */
val formatIn: String,
@SerialName("format_out")
val formatOut: String = "geojson", // "geojson" or "point"
/** Output format: `geojson` or `point`. */
val formatOut: String = "geojson",
val dataset: String? = null, // Optional dataset, e.g. "srtm"
/** Optional elevation dataset name, e.g. `srtm`. */
val dataset: String? = null,
val geometry: List<Double> // [lon, lat]
/** Coordinate as `[lon, lat]`. */
val geometry: List<Double>
)

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.export
// Kotlin DSL for ExportRequest
/** DSL for creating [ExportRequest] objects. */
inline fun exportRequest(build: ExportRequestBuilder.() -> Unit): ExportRequest =
ExportRequestBuilder().apply(build).build()
/** Builder used by [exportRequest]. */
class ExportRequestBuilder {
private var bbox: List<List<Double>>? = null
private var id: String? = null
@@ -23,7 +24,7 @@ class ExportRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class ExportRequestBuilderJ {
private var bbox: List<List<Double>>? = null
private var id: String? = null
@@ -41,4 +42,4 @@ class ExportRequestBuilderJ {
val i = id ?: "export_request"
return ExportRequest(bbox = b, id = i, geometry = geometry)
}
}
}

View File

@@ -2,9 +2,13 @@ package org.nitri.ors.domain.export
import kotlinx.serialization.Serializable
/** Request payload for the export endpoint. */
@Serializable
data class ExportRequest(
val bbox: List<List<Double>>, // [minLon, minLat, maxLon, maxLat]
/** Bounding box specified as `[[minLon,minLat],[maxLon,maxLat]]`. */
val bbox: List<List<Double>>,
/** Client-specified identifier. */
val id: String,
/** Whether to include full geometry in the response. */
val geometry: Boolean? = null
)

View File

@@ -12,23 +12,26 @@ import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.doubleOrNull
/** Graph export response containing nodes and edges. */
@Serializable
data class ExportResponse(
val nodes: List<Node> = emptyList(),
val edges: List<GraphEdge> = emptyList()
)
/** Node entry in an [ExportResponse]. */
@Serializable
data class Node(
@SerialName("nodeId") val nodeId: Long,
/** [lon, lat] */
/** `[lon, lat]` coordinate. */
val location: List<Double>
)
/** Graph edge entry in an [ExportResponse]. */
@Serializable
data class GraphEdge(
@SerialName("fromId") val fromId: Long,
@SerialName("toId") val toId: Long,
@SerialName("toId") val toId: Long,
@Serializable(with = StringAsDoubleSerializer::class)
val weight: Double
)

View File

@@ -3,13 +3,14 @@ package org.nitri.ors.domain.export
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** TopoJSON variant of the export response. */
@Serializable
data class TopoJsonExportResponse(
val type: String, // "Topology"
val type: String,
val objects: TopoObjects,
/** Top-level arcs are arrays of [lon, lat] Double coordinates */
/** Top-level arcs represented as `[lon, lat]` coordinate pairs. */
val arcs: List<List<List<Double>>>,
val bbox: List<Double> // [minLon, minLat, maxLon, maxLat]
val bbox: List<Double>
)
@Serializable
@@ -19,23 +20,23 @@ data class TopoObjects(
@Serializable
data class GeometryCollection(
val type: String, // "GeometryCollection"
val type: String,
val geometries: List<TopoGeometry>
)
@Serializable
data class TopoGeometry(
val type: String, // "LineString" (currently)
/** These are indices into the top-level arcs array (can be negative to indicate reversal) */
val type: String,
/** Indices into the top-level [TopoJsonExportResponse.arcs] array. */
val arcs: List<Int>,
val properties: GeometryProps? = null // be lenient; fields can vary
val properties: GeometryProps? = null
)
@Serializable
data class GeometryProps(
// weight often arrives as a string in this endpoint
/** Edge weight often supplied as a string. */
val weight: String? = null,
@SerialName("node_from") val nodeFrom: Long? = null,
@SerialName("node_to") val nodeTo: Long? = null
@SerialName("node_to") val nodeTo: Long? = null
)

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.isochrones
// Kotlin DSL for IsochronesRequest
/** DSL for constructing [IsochronesRequest] objects. */
inline fun isochronesRequest(build: IsochronesRequestBuilder.() -> Unit): IsochronesRequest =
IsochronesRequestBuilder().apply(build).build()
/** Builder used by [isochronesRequest]. */
class IsochronesRequestBuilder {
private val locations = mutableListOf<List<Double>>()
private var range: MutableList<Int> = mutableListOf()
@@ -38,7 +39,7 @@ class IsochronesRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class IsochronesRequestBuilderJ {
private val locations = mutableListOf<List<Double>>()
private val range: MutableList<Int> = mutableListOf()
@@ -80,4 +81,4 @@ class IsochronesRequestBuilderJ {
options = options
)
}
}
}

View File

@@ -3,6 +3,7 @@ package org.nitri.ors.domain.isochrones
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** GeoJSON response returned by the isochrones endpoint. */
@Serializable
data class IsochronesResponse(
val type: String,
@@ -11,6 +12,7 @@ data class IsochronesResponse(
val metadata: IsochronesMetadata
)
/** Individual isochrone feature. */
@Serializable
data class IsochroneFeature(
val type: String,
@@ -25,12 +27,11 @@ data class IsochroneProperties(
val center: List<Double>
)
/** Geometry of an isochrone feature. */
@Serializable
data class IsochroneGeometry(
val type: String, // "Polygon" (sometimes "MultiPolygon")
// ORS is returning Polygon for your case:
val type: String,
val coordinates: List<List<List<Double>>>
// If you later see MultiPolygon, change to List<List<List<List<Double>>>> or make it polymorphic.
)
@Serializable

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.matrix
// Kotlin DSL for MatrixRequest
/** DSL for building [MatrixRequest] instances. */
inline fun matrixRequest(build: MatrixRequestBuilder.() -> Unit): MatrixRequest =
MatrixRequestBuilder().apply(build).build()
/** Builder used by [matrixRequest]. */
class MatrixRequestBuilder {
private val locations = mutableListOf<List<Double>>()
var destinations: List<Int>? = null
@@ -27,7 +28,7 @@ class MatrixRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class MatrixRequestBuilderJ {
private val locations = mutableListOf<List<Double>>()
private var destinations: List<Int>? = null
@@ -54,4 +55,4 @@ class MatrixRequestBuilderJ {
sources = sources
)
}
}
}

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.optimization
// Kotlin DSL for OptimizationRequest (minimal and pragmatic)
/** DSL for building [OptimizationRequest] payloads. */
inline fun optimizationRequest(build: OptimizationRequestBuilder.() -> Unit): OptimizationRequest =
OptimizationRequestBuilder().apply(build).build()
/** Builder used by [optimizationRequest]. */
class OptimizationRequestBuilder {
private val jobs = mutableListOf<Job>()
private val shipments = mutableListOf<Shipment>()
@@ -62,7 +63,7 @@ class OptimizationRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class OptimizationRequestBuilderJ {
private val dsl = OptimizationRequestBuilder()
@@ -82,4 +83,4 @@ class OptimizationRequestBuilderJ {
fun options(o: Map<String, kotlinx.serialization.json.JsonElement>?) = apply { dsl.options(o) }
fun build(): OptimizationRequest = dsl.build()
}
}

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.pois
// Kotlin DSL for PoisRequest
/** DSL for constructing [PoisRequest] objects. */
inline fun poisRequest(build: PoisRequestBuilder.() -> Unit): PoisRequest =
PoisRequestBuilder().apply(build).build()
/** Builder used by [poisRequest]. */
class PoisRequestBuilder {
private var bbox: List<List<Double>>? = null
private var geojson: GeoJsonGeometry? = null
@@ -38,7 +39,7 @@ class PoisRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class PoisRequestBuilderJ {
private var bbox: List<List<Double>>? = null
private var geojson: GeoJsonGeometry? = null
@@ -75,4 +76,4 @@ class PoisRequestBuilderJ {
sortby = sortby
)
}
}
}

View File

@@ -3,6 +3,7 @@ package org.nitri.ors.domain.pois
import kotlinx.serialization.Required
import kotlinx.serialization.Serializable
/** Request for the POIs endpoint. */
@Serializable
data class PoisRequest(
@Required val request: String = "pois",
@@ -14,13 +15,17 @@ data class PoisRequest(
@Serializable
data class Geometry(
val bbox: List<List<Double>>? = null, // [[minLon,minLat],[maxLon,maxLat]]
val geojson: GeoJsonGeometry? = null, // optional: GeoJSON geometry
val buffer: Int? = null // optional: buffer in meters
/** Bounding box `[[minLon,minLat],[maxLon,maxLat]]` if set. */
val bbox: List<List<Double>>? = null,
/** Optional GeoJSON geometry. */
val geojson: GeoJsonGeometry? = null,
/** Optional buffer in meters applied to the geometry. */
val buffer: Int? = null
)
@Serializable
data class GeoJsonGeometry(
val type: String, // e.g., "Point"
val coordinates: List<Double> // [lon, lat]
val type: String,
/** `[lon, lat]` pair defining the point location. */
val coordinates: List<Double>
)

View File

@@ -2,21 +2,22 @@ package org.nitri.ors.domain.route
import org.nitri.ors.LonLat
// Kotlin DSL
/** DSL for constructing [RouteRequest] instances. */
inline fun routeRequest(build: RouteRequestBuilder.() -> Unit): RouteRequest =
RouteRequestBuilder().apply(build).build()
/** Builder used by [routeRequest]. */
class RouteRequestBuilder {
private val coords = mutableListOf<LonLat>()
var language: String? = null
fun start(lon: Double, lat: Double) = apply { coords.add(LonLat(lon, lat)) }
fun end(lon: Double, lat: Double) = apply { coords.add(LonLat(lon, lat)) }
fun end(lon: Double, lat: Double) = apply { coords.add(LonLat(lon, lat)) }
fun coordinate(lon: Double, lat: Double) = apply { coords.add(LonLat(lon, lat)) }
fun build(): RouteRequest {
require(coords.size >= 2) { "At least start and end coordinates required" }
val coordinates = coords.map { listOf(it.lon, it.lat) }
return RouteRequest(coordinates, language = language)
return RouteRequest(coordinates, language = language)
}
}

View File

@@ -3,6 +3,7 @@ package org.nitri.ors.domain.route
import kotlinx.serialization.Serializable
import org.nitri.ors.domain.meta.Metadata
/** GeoJSON response for the directions endpoint. */
@Serializable
data class GeoJsonRouteResponse(
val type: String,
@@ -11,6 +12,7 @@ data class GeoJsonRouteResponse(
val metadata: Metadata
)
/** A single GeoJSON feature within the route response. */
@Serializable
data class Feature(
val type: String,
@@ -18,6 +20,7 @@ data class Feature(
val properties: Map<String, kotlinx.serialization.json.JsonElement> = emptyMap()
)
/** Geometry of a route feature. */
@Serializable
data class Geometry(
val type: String,

View File

@@ -3,6 +3,7 @@ package org.nitri.ors.domain.route
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
/** GPX response returned by the directions endpoint when requesting GPX. */
@Serializable
data class GpxResponse(
val metadata: GpxMetadata,

View File

@@ -3,39 +3,65 @@ package org.nitri.ors.domain.route
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Payload for the directions `v2/directions/{profile}` endpoint.
*
* All parameters map to the official ORS API; nullable properties are omitted
* from the serialized JSON when not provided.
*/
@Serializable
data class RouteRequest(
/** List of `[lon, lat]` coordinate pairs in order of travel. */
val coordinates: List<List<Double>>,
/** Search radiuses around each coordinate in meters. */
val radiuses: List<Double>? = null,
/** List of `[bearing, range]` constraints for each coordinate. */
val bearings: List<List<Double>>? = null,
/** Include elevation data in response. */
val elevation: Boolean? = null,
@SerialName("extra_info")
/** Additional information to include, e.g., `waytype`. */
val extraInfo: List<String>? = null,
/** Whether to return turn-by-turn instructions. */
val instructions: Boolean? = null,
@SerialName("instructions_format")
/** Format of instructions such as `html` or `text`. */
val instructionsFormat: String? = null,
/** Preferred language for textual parts of the response. */
val language: String? = null,
/** Routing preference such as `fastest` or `shortest`. */
val preference: String? = null,
/** Unit system for distances. */
val units: String? = null,
/** Whether to include geometry. */
val geometry: Boolean? = null,
@SerialName("geometry_simplify")
/** Simplify the returned geometry. */
val geometrySimplify: Boolean? = null,
@SerialName("roundabout_exits")
/** Return `exit` indices for roundabouts. */
val roundaboutExits: Boolean? = null,
/** Additional attributes to include for each segment. */
val attributes: List<String>? = null,
/** Include a list of maneuvers. */
val maneuvers: Boolean? = null,
@SerialName("continue_straight")
/** Force continue straight at waypoints? */
val continueStraight: Boolean? = null,
/** Optional advanced options. */
val options: RouteOptions? = null
)
@Serializable
data class RouteOptions(
@SerialName("avoid_features")
/** Features to avoid, e.g., `ferries` or `tollways`. */
val avoidFeatures: List<String>? = null,
@SerialName("avoid_polygons")
/** Optional polygon geometry to avoid. */
val avoidPolygons: AvoidPolygons? = null,
@SerialName("profile_params")
/** Profile specific parameters such as restrictions. */
val profileParams: ProfileParams? = null
)

View File

@@ -4,6 +4,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.nitri.ors.domain.meta.Metadata
/** Response from the directions endpoint. */
@Serializable
data class RouteResponse(
val routes: List<Route>,
@@ -11,6 +12,7 @@ data class RouteResponse(
val metadata: Metadata? = null
)
/** Single route variant returned by the API. */
@Serializable
data class Route(
val summary: RouteSummary,
@@ -20,6 +22,7 @@ data class Route(
val wayPoints: List<Int>? = null
)
/** Aggregated summary of a route. */
@Serializable
data class RouteSummary(
val distance: Double,
@@ -28,6 +31,7 @@ data class RouteSummary(
val descent: Double? = null
)
/** One segment between intermediate waypoints. */
@Serializable
data class Segment(
val distance: Double,
@@ -40,6 +44,7 @@ data class Segment(
val percentage: Double? = null
)
/** Turn instruction within a segment. */
@Serializable
data class Step(
val distance: Double,

View File

@@ -1,9 +1,10 @@
package org.nitri.ors.domain.snap
// Kotlin DSL for SnapRequest
/** DSL for constructing [SnapRequest] objects. */
inline fun snapRequest(build: SnapRequestBuilder.() -> Unit): SnapRequest =
SnapRequestBuilder().apply(build).build()
/** Builder used by [snapRequest]. */
class SnapRequestBuilder {
private val locations = mutableListOf<List<Double>>()
private var radius: Int? = null
@@ -19,7 +20,7 @@ class SnapRequestBuilder {
}
}
// Java-friendly builder
/** Java-friendly builder counterpart. */
class SnapRequestBuilderJ {
private val locations = mutableListOf<List<Double>>()
private var radius: Int? = null
@@ -34,4 +35,4 @@ class SnapRequestBuilderJ {
val r = requireNotNull(radius) { "radius is required" }
return SnapRequest(locations = locations.toList(), radius = r, id = id)
}
}
}

View File

@@ -10,7 +10,8 @@ import org.nitri.ors.domain.elevation.ElevationLineResponse
import org.nitri.ors.domain.elevation.ElevationPointRequest
import org.nitri.ors.domain.elevation.ElevationPointResponse
class ElevationHelper() {
/** Helper functions for the ORS elevation endpoints. */
class ElevationHelper {
/**
* Convenience helper to request elevation for a LineString provided as list of [lon, lat] pairs.

View File

@@ -6,8 +6,10 @@ import org.nitri.ors.domain.export.ExportRequest
import org.nitri.ors.domain.export.ExportResponse
import org.nitri.ors.domain.export.TopoJsonExportResponse
class ExportHelper() {
/** Helpers for the export endpoints. */
class ExportHelper {
/** Requests the export endpoint with bounding box [bbox]. */
suspend fun OrsClient.export(bbox: List<List<Double>>, geometry: Boolean? = null, profile: Profile): ExportResponse {
val request = ExportRequest(
bbox = bbox,
@@ -17,6 +19,7 @@ class ExportHelper() {
return export(profile, request)
}
/** Requests the export endpoint asking explicitly for JSON output. */
suspend fun OrsClient.exportJson(bbox: List<List<Double>>, geometry: Boolean? = null, profile: Profile): ExportResponse {
val request = ExportRequest(
bbox = bbox,
@@ -26,6 +29,7 @@ class ExportHelper() {
return exportJson(profile, request)
}
/** Requests the export endpoint with TopoJSON output. */
suspend fun OrsClient.exportTopoJson(bbox: List<List<Double>>, geometry: Boolean? = null, profile: Profile): TopoJsonExportResponse {
val request = ExportRequest(
bbox = bbox,

View File

@@ -6,9 +6,9 @@ import org.nitri.ors.domain.geocode.GeocodeSearchResponse
/**
* Repository for ORS Geocoding endpoints using GET requests only.
*
* Methods are member extensions on OrsClient and delegate to OrsClient.
* Methods are member extensions on [OrsClient] and delegate to it.
*/
class GeocodeHelper() {
class GeocodeHelper {
/**
* Forward geocoding search.

View File

@@ -5,8 +5,10 @@ import org.nitri.ors.Profile
import org.nitri.ors.domain.isochrones.IsochronesRequest
import org.nitri.ors.domain.isochrones.IsochronesResponse
class IsochronesHelper() {
/** Helpers for requesting isochrones. */
class IsochronesHelper {
/** Calls the isochrones endpoint with the given parameters. */
suspend fun OrsClient.getIsochrones(
locations: List<List<Double>>,
range: List<Int>,

View File

@@ -5,11 +5,10 @@ import org.nitri.ors.Profile
import org.nitri.ors.domain.matrix.MatrixRequest
import org.nitri.ors.domain.matrix.MatrixResponse
class MatrixHelper() {
/** Helpers for the matrix endpoint. */
class MatrixHelper {
/**
* Calls the ORS Matrix endpoint for the given profile.
*/
/** Calls the ORS Matrix endpoint for the given [profile]. */
suspend fun OrsClient.getMatrix(
locations: List<List<Double>>,
profile: Profile,

View File

@@ -10,9 +10,9 @@ import org.nitri.ors.domain.optimization.Shipment
import org.nitri.ors.domain.optimization.Vehicle
/**
* Repository for the OpenRouteService Optimization endpoint using OrsClient.
* Repository for the OpenRouteService Optimization endpoint using [OrsClient].
*/
class OptimizationHelper() {
class OptimizationHelper {
/**
* Calls the ORS Optimization endpoint with provided arguments and builds the request.

View File

@@ -6,7 +6,8 @@ import org.nitri.ors.domain.pois.Geometry
import org.nitri.ors.domain.pois.PoisGeoJsonResponse
import org.nitri.ors.domain.pois.PoisRequest
class PoisHelper() {
/** Convenience extensions for the POIs endpoints. */
class PoisHelper {
/**
* Query POIs within a bounding box.

View File

@@ -6,12 +6,19 @@ import org.nitri.ors.domain.route.GeoJsonRouteResponse
import org.nitri.ors.domain.route.RouteRequest
import org.nitri.ors.domain.route.RouteResponse
class RouteHelper() {
/**
* Convenience extensions for invoking the directions endpoints.
*/
class RouteHelper {
/** Converts a profile key string to the corresponding [Profile] enum. */
private fun profileFromKey(key: String): Profile =
Profile.entries.firstOrNull { it.key == key }
?: throw IllegalArgumentException("Unknown profile key: $key")
/**
* Retrieves a route between two coordinates.
*/
suspend fun OrsClient.getRoute(
start: Pair<Double, Double>,
end: Pair<Double, Double>,
@@ -26,6 +33,9 @@ class RouteHelper() {
return getRoute(profileFromKey(profile), request)
}
/**
* Retrieves a route as GPX between two coordinates.
*/
suspend fun OrsClient.getRouteGpx(
start: Pair<Double, Double>,
end: Pair<Double, Double>,
@@ -40,6 +50,9 @@ class RouteHelper() {
return getRouteGpx(profileFromKey(profile), request)
}
/**
* Retrieves a route as GPX for an arbitrary coordinate list.
*/
suspend fun OrsClient.getRouteGpx(
coordinates: List<List<Double>>,
language: String,
@@ -49,6 +62,9 @@ class RouteHelper() {
return getRouteGpx(profileFromKey(profile), request)
}
/**
* Retrieves a route as GeoJSON feature collection.
*/
suspend fun OrsClient.getRouteGeoJson(
start: Pair<Double, Double>,
end: Pair<Double, Double>,

View File

@@ -6,11 +6,10 @@ import org.nitri.ors.domain.snap.SnapGeoJsonResponse
import org.nitri.ors.domain.snap.SnapRequest
import org.nitri.ors.domain.snap.SnapResponse
class SnapHelper() {
/** Helpers for the snap endpoints. */
class SnapHelper {
/**
* Calls the ORS Snap endpoint for the given profile.
*/
/** Calls the ORS Snap endpoint for the given [profile]. */
suspend fun OrsClient.getSnap(
locations: List<List<Double>>,
radius: Int,
@@ -25,9 +24,7 @@ class SnapHelper() {
return getSnap(profile, request)
}
/**
* Calls the ORS Snap JSON endpoint.
*/
/** Calls the ORS Snap JSON endpoint. */
suspend fun OrsClient.getSnapJson(
locations: List<List<Double>>,
radius: Int,
@@ -42,9 +39,7 @@ class SnapHelper() {
return getSnapJson(profile, request)
}
/**
* Calls the ORS Snap GeoJSON endpoint.
*/
/** Calls the ORS Snap GeoJSON endpoint. */
suspend fun OrsClient.getSnapGeoJson(
locations: List<List<Double>>,
radius: Int,

View File

@@ -11,7 +11,17 @@ import org.nitri.ors.api.OpenRouteServiceApi
import okhttp3.MediaType.Companion.toMediaType
import java.util.concurrent.TimeUnit
/**
* Builds a Retrofit HTTP client configured for the public
* [OpenRouteService](https://openrouteservice.org/) API.
*/
object OpenRouteServiceRestClient {
/**
* Creates an [OpenRouteServiceApi] with authorization and sensible defaults.
*
* @param apiKey ORS API key used in the Authorization header
* @param context Android context used for user-agent construction
*/
fun create(apiKey: String, context: Context): OpenRouteServiceApi {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)