From d0a07e13159344d4500dfdef9c8763919d77450e Mon Sep 17 00:00:00 2001 From: Dimitris Date: Wed, 24 Dec 2025 07:24:12 +0100 Subject: [PATCH] Umbau --- .../com/kouros/navigation/ui/MainActivity.kt | 19 ++- .../kouros/navigation/car/SurfaceRenderer.kt | 2 +- .../com/kouros/navigation/car/map/MapView.kt | 2 +- .../car/screen/RoutePreviewScreen.kt | 6 +- .../navigation/data/NavigationRepository.kt | 2 +- .../java/com/kouros/navigation/data/Route.kt | 150 +++++++---------- .../com/kouros/navigation/data/route/Leg.kt | 5 + .../kouros/navigation/data/route/Maneuver.kt | 8 + .../com/kouros/navigation/data/route/Step.kt | 10 ++ .../kouros/navigation/data/route/Summary.kt | 6 + .../kouros/navigation/data/valhalla/Legs.kt | 3 +- .../{Summary.kt => SummaryValhalla.kt} | 3 +- .../kouros/navigation/data/valhalla/Trip.kt | 5 +- .../data/valhalla/ValhallaResponse.kt | 20 +++ .../navigation/data/valhalla/ValhallaRoute.kt | 43 +++++ .../com/kouros/navigation/model/RouteModel.kt | 154 +++++++----------- .../src/main/res/drawable/navigation_48px.xml | 2 +- 17 files changed, 234 insertions(+), 206 deletions(-) create mode 100644 common/data/src/main/java/com/kouros/navigation/data/route/Leg.kt create mode 100644 common/data/src/main/java/com/kouros/navigation/data/route/Maneuver.kt create mode 100644 common/data/src/main/java/com/kouros/navigation/data/route/Step.kt create mode 100644 common/data/src/main/java/com/kouros/navigation/data/route/Summary.kt rename common/data/src/main/java/com/kouros/navigation/data/valhalla/{Summary.kt => SummaryValhalla.kt} (95%) create mode 100644 common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaResponse.kt create mode 100644 common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaRoute.kt diff --git a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt index f01eea1..fd3d16e 100644 --- a/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt +++ b/app/src/main/java/com/kouros/navigation/ui/MainActivity.kt @@ -236,7 +236,7 @@ class MainActivity : ComponentActivity() { if (isNavigating()) { updateLocation(currentLocation, navigationViewModel) stepData.value = currentStep() - if (route.currentManeuverIndex + 1 <= route.maneuvers.size) { + if (route.currentStep + 1 <= legs.steps.size) { nextStepData.value = nextStep() } if (routeState.maneuverType == 39 @@ -302,20 +302,21 @@ class MainActivity : ComponentActivity() { @OptIn(DelicateCoroutinesApi::class) fun simulate() = GlobalScope.async { - for ((_, loc) in routeModel.route.waypoints.withIndex()) { - if (routeModel.isNavigating()) { - mock.setMockLocation(loc[1], loc[0]) - delay(500L) // + for ((index, step) in routeModel.legs.steps.withIndex()) { + for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) { + mock.setMockLocation(waypoint[1], waypoint[0]) + delay(1000L) // } } } fun test() { - for ((index, loc) in routeModel.route.waypoints.withIndex()) { - if (index > 300) { - routeModel.updateLocation(location(loc[0], loc[1]), navigationViewModel) + for ((index, step) in routeModel.legs.steps.withIndex()) { + println("${step.maneuver.waypoints.size}") + for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) { + routeModel.updateLocation(location(waypoint[0], waypoint[1]), navigationViewModel) routeModel.currentStep() - if (routeModel.route.currentManeuverIndex + 1 <= routeModel.route.maneuvers.size) { + if (index + 1 <= routeModel.legs.steps.size) { nextStepData.value = routeModel.nextStep() } println(routeModel.routeState.maneuverType) diff --git a/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt b/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt index 4f11a5d..50f1aba 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/SurfaceRenderer.kt @@ -300,7 +300,7 @@ class SurfaceRenderer( with(routeModel) { routeData.value = route.routeGeoJson centerLocation = route.centerLocation - previewDistance = route.distance + previewDistance = route.summary!!.distance } updateCameraPosition( 0.0, diff --git a/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt b/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt index ac630ec..10f67c3 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/map/MapView.kt @@ -196,7 +196,7 @@ fun DrawNavigationImages( @Composable fun NavigationImage(padding: PaddingValues, width: Int, height: Int) { - val imageSize = (height / 6) + val imageSize = (height / 8) val color = remember { NavigationColor } Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) { Canvas( diff --git a/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt b/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt index 9b3d1b3..6e7261e 100644 --- a/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt +++ b/common/car/src/main/java/com/kouros/navigation/car/screen/RoutePreviewScreen.kt @@ -89,7 +89,7 @@ class RoutePreviewScreen( ) .build() - val message = if (routeModel.isNavigating() && routeModel.route.waypoints.isNotEmpty()) { + val message = if (routeModel.isNavigating() && routeModel.route.waypoints!!.isNotEmpty()) { createRouteText() } else { CarText.Builder("Wait") @@ -173,8 +173,8 @@ class RoutePreviewScreen( .build() private fun createRouteText(): CarText { - val time = routeModel.route.summary.time - val length = BigDecimal(routeModel.route.distance).setScale(1, RoundingMode.HALF_EVEN) + val time = routeModel.route.summary!!.duration + val length = BigDecimal(routeModel.route.summary!!.distance).setScale(1, RoundingMode.HALF_EVEN) val firstRoute = SpannableString(" \u00b7 $length km") firstRoute.setSpan( DurationSpan.create(time.toLong()), 0, 1, 0 diff --git a/common/data/src/main/java/com/kouros/navigation/data/NavigationRepository.kt b/common/data/src/main/java/com/kouros/navigation/data/NavigationRepository.kt index af01e26..462ab13 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/NavigationRepository.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/NavigationRepository.kt @@ -40,7 +40,7 @@ abstract class NavigationRepository { val route = getRoute(currentLocation, location, searchFilter) val routeModel = RouteModel() routeModel.startNavigation(route) - return routeModel.route.distance + return routeModel.route.summary!!.distance } fun searchPlaces(search: String, location: Location) : String { diff --git a/common/data/src/main/java/com/kouros/navigation/data/Route.kt b/common/data/src/main/java/com/kouros/navigation/data/Route.kt index 1d31742..6621fce 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/Route.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/Route.kt @@ -2,125 +2,91 @@ package com.kouros.navigation.data import android.location.Location import com.google.gson.GsonBuilder -import com.kouros.navigation.data.valhalla.Maneuvers -import com.kouros.navigation.data.valhalla.Summary -import com.kouros.navigation.data.valhalla.Trip -import com.kouros.navigation.data.valhalla.ValhallaJson +import com.kouros.navigation.data.route.Leg +import com.kouros.navigation.data.route.Step +import com.kouros.navigation.data.route.Summary +import com.kouros.navigation.data.valhalla.ValhallaResponse +import com.kouros.navigation.data.valhalla.ValhallaRoute import com.kouros.navigation.utils.GeoUtils.createCenterLocation -import com.kouros.navigation.utils.GeoUtils.createLineStringCollection -import com.kouros.navigation.utils.GeoUtils.decodePolyline import com.kouros.navigation.utils.location +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.jsonObject import org.maplibre.geojson.Point data class Route( - /** - * A Leg is a route between only two waypoints. - * - * @since 1.0.0 - */ - val maneuvers: List, - /** - * The distance traveled from origin to destination. - * - * @return a double number with unit meters - * @since 1.0.0 - */ - val distance: Double, + val routeEngine: Int, + val summary: Summary?, + val legs: List?, + val routeGeoJson: String = "", + val centerLocation : Location = location(0.0, 0.0), + var currentStep : Int = 0, + val waypoints: List>?, + ) { - /** - * List of [List] objects. Each `waypoint` is an input coordinate - * snapped to the road and path network. The `waypoint` appear in the list in the order of - * the input coordinates. - * - * @since 1.0.0 - */ - val waypoints: List>, + data class Builder ( - /** - * List of [List] objects. Each `Point` is an input coordinate - * snapped to the road and path network. The `waypoint` appear in the list in the order of - * the input coordinates. - * - * @since 1.0.0 - */ - val pointLocations: List, - - val summary: Summary, - - val trip: Trip, - - val time: Double, - - val routeGeoJson: String, - - val currentManeuverIndex : Int, - - val centerLocation: Location - -) { - - class Builder { - private lateinit var maneuvers: List - private var distance: Double = 0.0 - private var time: Double = 0.0 - private lateinit var waypoints: List> - private lateinit var pointLocations: List - private lateinit var summary: Summary - private lateinit var trip: Trip - private var routeGeoJson = "" - private var centerLocation = location(0.0, 0.0) + var routeEngine : Int = 0, + var summary: Summary? = null, + var legs: List? = null, + var routeGeoJson: String = "", + var centerLocation: Location = location(0.0, 0.0), + var waypoints : List>? = null,) { + fun routeType (routeEngine: Int) = apply {this.routeEngine = routeEngine } + fun summary(summary: Summary) = apply { this.summary = summary } + fun legs(legs: List) = apply { this.legs = legs } + fun routeGeoJson(routeGeoJson: String) = apply { + this.routeGeoJson = routeGeoJson + centerLocation = createCenterLocation(routeGeoJson) + } + fun waypoints(waypoints: List>) = apply { this.waypoints = waypoints } fun route(route: String) = apply { if (route.isNotEmpty() && route != "[]") { val gson = GsonBuilder().serializeNulls().create() - val routeJson = gson.fromJson(route, ValhallaJson::class.java) - trip = routeJson.trip + val jsonObject: Map = Json.parseToJsonElement(route).jsonObject + val routeJson = + gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java) + ValhallaRoute().mapJsonToValhalla(routeJson, this) } } fun build(): Route { - maneuvers = trip.legs[0].maneuvers - summary = trip.summary - distance = summary.length - time = summary.time - waypoints = decodePolyline(trip.legs[0].shape) - val points = mutableListOf() - for (loc in waypoints) { - val point = Point.fromLngLat(loc[0], loc[1]) - points.add(point) - } - pointLocations = points - routeGeoJson = createLineStringCollection( waypoints) - centerLocation = createCenterLocation(routeGeoJson) return Route( - maneuvers, - distance, - waypoints, - pointLocations, - summary, - trip, - time, - routeGeoJson, - 0, - centerLocation + routeEngine = this.routeEngine, + summary = this.summary, + legs = this.legs, + waypoints = this.waypoints, + routeGeoJson = this.routeGeoJson, ) } } fun maneuverLocations(): List { - return pointLocations + val step = currentStep() + val waypoints = step.maneuver.waypoints + val points = mutableListOf() + for (loc in waypoints) { + val point = Point.fromLngLat(loc[0], loc[1]) + points.add(point) + } + return points } - fun currentManeuver(): Maneuvers { - return maneuvers[currentManeuverIndex] + fun currentStep(): Step { + if (legs != null) { + return legs.first().steps[currentStep] + } else { + throw IndexOutOfBoundsException("No legs available.") + } } - fun nextManeuver(): Maneuvers { - val nextIndex = currentManeuverIndex + 1 - return if (nextIndex < maneuvers.size) { - maneuvers[nextIndex] + fun nextStep(): Step { + val nextIndex = currentStep + 1 + return if (nextIndex < legs!!.first().steps.size) { + legs.first().steps[currentStep + 1] } else { throw IndexOutOfBoundsException("No next maneuver available.") } diff --git a/common/data/src/main/java/com/kouros/navigation/data/route/Leg.kt b/common/data/src/main/java/com/kouros/navigation/data/route/Leg.kt new file mode 100644 index 0000000..80d5283 --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/route/Leg.kt @@ -0,0 +1,5 @@ +package com.kouros.navigation.data.route + +data class Leg( + var steps : List = arrayListOf() +) diff --git a/common/data/src/main/java/com/kouros/navigation/data/route/Maneuver.kt b/common/data/src/main/java/com/kouros/navigation/data/route/Maneuver.kt new file mode 100644 index 0000000..1f1ba33 --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/route/Maneuver.kt @@ -0,0 +1,8 @@ +package com.kouros.navigation.data.route + +data class Maneuver( + val bearingBefore : Int = 0, + val bearingAfter : Int = 0, + val type: Int = 0, + val waypoints: List>, +) diff --git a/common/data/src/main/java/com/kouros/navigation/data/route/Step.kt b/common/data/src/main/java/com/kouros/navigation/data/route/Step.kt new file mode 100644 index 0000000..75b491e --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/route/Step.kt @@ -0,0 +1,10 @@ +package com.kouros.navigation.data.route + +class Step( + var index : Int = 0, + var waypointIndex : Int = 0, + val maneuver: Maneuver, + val duration: Double = 0.0, + val distance: Double = 0.0, + val name : String = "", +) diff --git a/common/data/src/main/java/com/kouros/navigation/data/route/Summary.kt b/common/data/src/main/java/com/kouros/navigation/data/route/Summary.kt new file mode 100644 index 0000000..c8c5a1b --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/route/Summary.kt @@ -0,0 +1,6 @@ +package com.kouros.navigation.data.route + +data class Summary( + var duration : Double = 0.0, + var distance : Double = 0.0, +) \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Legs.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Legs.kt index dd3ffcf..ec405fc 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Legs.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Legs.kt @@ -2,7 +2,6 @@ package com.kouros.navigation.data.valhalla import com.google.gson.annotations.SerializedName import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonIgnoreUnknownKeys @@ -11,7 +10,7 @@ import kotlinx.serialization.json.JsonIgnoreUnknownKeys data class Legs ( @SerializedName("maneuvers" ) var maneuvers : ArrayList = arrayListOf(), - @SerializedName("summary" ) var summary : Summary = Summary(), + @SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(), @SerializedName("shape" ) var shape : String = "" ) \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Summary.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/SummaryValhalla.kt similarity index 95% rename from common/data/src/main/java/com/kouros/navigation/data/valhalla/Summary.kt rename to common/data/src/main/java/com/kouros/navigation/data/valhalla/SummaryValhalla.kt index 0f83d4a..285990e 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Summary.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/SummaryValhalla.kt @@ -2,13 +2,12 @@ package com.kouros.navigation.data.valhalla import com.google.gson.annotations.SerializedName import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonIgnoreUnknownKeys @OptIn(ExperimentalSerializationApi::class) @JsonIgnoreUnknownKeys -data class Summary ( +data class SummaryValhalla ( @SerializedName("has_time_restrictions" ) var hasTimeRestrictions : Boolean = false, @SerializedName("has_toll" ) var hasToll : Boolean = false, diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Trip.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Trip.kt index 0709a7c..22b5412 100644 --- a/common/data/src/main/java/com/kouros/navigation/data/valhalla/Trip.kt +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/Trip.kt @@ -2,7 +2,6 @@ package com.kouros.navigation.data.valhalla import com.google.gson.annotations.SerializedName import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonIgnoreUnknownKeys @@ -12,10 +11,10 @@ data class Trip ( @SerializedName("locations" ) var locations : ArrayList = arrayListOf(), @SerializedName("legs" ) var legs : ArrayList = arrayListOf(), - @SerializedName("summary" ) var summary : Summary = Summary(), + @SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(), @SerializedName("status_message" ) var statusMessage : String = "", @SerializedName("status" ) var status : Int = 0, @SerializedName("units" ) var units : String = "", @SerializedName("language" ) var language : String = "", -) \ No newline at end of file + ) \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaResponse.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaResponse.kt new file mode 100644 index 0000000..1e1d359 --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaResponse.kt @@ -0,0 +1,20 @@ +package com.kouros.navigation.data.valhalla + +import com.google.gson.annotations.SerializedName +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.JsonIgnoreUnknownKeys + + +@OptIn(ExperimentalSerializationApi::class) +@JsonIgnoreUnknownKeys +data class ValhallaResponse( + + @SerializedName("locations") var locations: ArrayList = arrayListOf(), + @SerializedName("legs") var legs: ArrayList = arrayListOf(), + @SerializedName("summary") var summaryValhalla: SummaryValhalla = SummaryValhalla(), + @SerializedName("status_message") var statusMessage: String = "", + @SerializedName("status") var status: Int = 0, + @SerializedName("units") var units: String = "", + @SerializedName("language") var language: String = "", + + ) diff --git a/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaRoute.kt b/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaRoute.kt new file mode 100644 index 0000000..438ffdd --- /dev/null +++ b/common/data/src/main/java/com/kouros/navigation/data/valhalla/ValhallaRoute.kt @@ -0,0 +1,43 @@ +package com.kouros.navigation.data.valhalla + +import com.kouros.navigation.data.Route +import com.kouros.navigation.data.route.Leg +import com.kouros.navigation.data.route.Maneuver +import com.kouros.navigation.data.route.Step +import com.kouros.navigation.data.route.Summary +import com.kouros.navigation.utils.GeoUtils.createLineStringCollection +import com.kouros.navigation.utils.GeoUtils.decodePolyline + +class ValhallaRoute { + + fun mapJsonToValhalla(routeJson: ValhallaResponse, builder: Route.Builder) { + val waypoints = decodePolyline(routeJson.legs[0].shape) + val summary = Summary() + summary.distance = routeJson.summaryValhalla.length + summary.duration = routeJson.summaryValhalla.time + val steps = mutableListOf() + var stepIndex = 0 + routeJson.legs[0].maneuvers.forEach { + val maneuver = Maneuver( + bearingBefore = 0, + bearingAfter = it.bearingAfter, + type = it.type, + waypoints =waypoints.subList(it.beginShapeIndex, it.endShapeIndex+1) + ) + var name = "" + if (it.streetNames != null && it.streetNames.isNotEmpty()) { + name = it.streetNames[0] + } + val step = Step( index = stepIndex, name = name, distance = it.length, duration = it.time, maneuver = maneuver) + steps.add(step) + stepIndex += 1 + } + val leg = Leg(steps) + builder + .routeType(1) + .summary(summary) + .routeGeoJson(createLineStringCollection(waypoints)) + .legs(listOf(leg)) + .waypoints(waypoints) + } +} \ No newline at end of file diff --git a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt index edaa0ae..4d602f0 100644 --- a/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt +++ b/common/data/src/main/java/com/kouros/navigation/model/RouteModel.kt @@ -9,6 +9,7 @@ import com.kouros.navigation.data.ManeuverType import com.kouros.navigation.data.Place import com.kouros.navigation.data.Route import com.kouros.navigation.data.StepData +import com.kouros.navigation.data.route.Leg import com.kouros.navigation.utils.location import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers @@ -24,16 +25,11 @@ open class RouteModel() { val destination: Place = Place(), val arrived: Boolean = false, val maneuverType: Int = 0, - var currentShapeIndex: Int = 0, - var distanceToStepEnd: Float = 0F, - var beginIndex: Int = 0, - var endIndex: Int = 0, val travelMessage: String = "", // max speed for street (maneuver) val lastSpeedIndex: Int = 0, val maxSpeed: Int = 0, - - ) + ) var routeState = RouteState() @@ -43,6 +39,10 @@ open class RouteModel() { routeState = routeState.copy(route = value) } + + val legs: Leg + get() = routeState.route!!.legs!!.first() + fun startNavigation(routeString: String) { val newRoute = Route.Builder() .route(routeString) @@ -59,40 +59,39 @@ open class RouteModel() { isNavigating = false, arrived = false, maneuverType = 0, - currentShapeIndex = 0, - distanceToStepEnd = 0F, - beginIndex = 0, - endIndex = 0 ) } @OptIn(DelicateCoroutinesApi::class) fun updateLocation(location: Location, viewModel: ViewModel) { - var nearestDistance = 100000.0f - var newShapeIndex = -1 - // find nearest waypoint and current shape index - // start search at last shape index - for (i in routeState.currentShapeIndex..= route.currentStep && nearestDistance > 0) { + for ((wayIndex, waypoint) in step.maneuver.waypoints.withIndex()) { + if (wayIndex >= step.waypointIndex) { + val distance = location.distanceTo(location(waypoint[0], waypoint[1])) + if (distance < nearestDistance) { + nearestDistance = distance + route.currentStep = step.index + step.waypointIndex = wayIndex + } + } + } + } + } + } + fun updateSpeedLimit(location: Location, viewModel: ViewModel) { // speed limit for each maneuver index - if (routeState.lastSpeedIndex < route.currentManeuverIndex) { - routeState = routeState.copy(lastSpeedIndex = route.currentManeuverIndex) + if (routeState.lastSpeedIndex < route.currentStep) { + routeState = routeState.copy(lastSpeedIndex = route.currentStep) val elements = viewModel.getMaxSpeed(location) elements.forEach { if (it.tags.name != null && it.tags.maxspeed != null) { @@ -103,52 +102,30 @@ open class RouteModel() { } } - private fun findManeuver(newShapeIndex: Int) { - for (i in route.currentManeuverIndex..= newShapeIndex) { - route = route.copy(currentManeuverIndex = i) - routeState.apply { - currentShapeIndex = newShapeIndex - beginIndex = maneuver.beginShapeIndex - endIndex = maneuver.endShapeIndex - distanceToStepEnd = 0F - // calculate shape distance to step end - for (j in newShapeIndex + 1..maneuver.endShapeIndex) { - val loc1 = location(route!!.waypoints[j - 1][0], route.waypoints[j - 1][1]) - val loc2 = location(route.waypoints[j][0], route.waypoints[j][1]) - distanceToStepEnd += loc1.distanceTo(loc2) - } - break - } - } - } - } - fun currentStep(): StepData { - val currentManeuver = route.currentManeuver() + val currentStep = route.currentStep() // Determine if we should display the current or the next maneuver val distanceToNextStep = leftStepDistance() val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD val shouldAdvance = - isNearNextManeuver && route.currentManeuverIndex < (route.maneuvers.size) + isNearNextManeuver && route.currentStep < (route.legs!!.first().steps.size) // Determine the maneuver type and corresponding icon - var maneuverType = if (hasArrived(currentManeuver.type)) { - currentManeuver.type + var maneuverType = if (hasArrived(currentStep.maneuver.type)) { + currentStep.maneuver.type } else { ManeuverType.None.value } // Get the single, correct maneuver for this state val relevantManeuver = if (shouldAdvance) { - route.nextManeuver() // This advances the route's state + route.nextStep() // This advances the route's state } else { - route.currentManeuver() + route.currentStep() } // Safely get the street name from the maneuver - val streetName = relevantManeuver.streetNames?.firstOrNull() ?: "" + val streetName = relevantManeuver.name if (shouldAdvance) { - maneuverType = relevantManeuver.type + maneuverType = relevantManeuver.maneuver.type } val maneuverIconPair = maneuverIcon(maneuverType) routeState = routeState.copy(maneuverType = maneuverIconPair.first) @@ -165,8 +142,8 @@ open class RouteModel() { fun nextStep(): StepData { - val maneuver = route.nextManeuver() - val maneuverType = maneuver.type + val step = route.nextStep() + val maneuverType = step.maneuver.type val distanceLeft = leftStepDistance() var text = "" @@ -175,8 +152,8 @@ open class RouteModel() { } else -> { - if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { - text = maneuver.streetNames[0] + if (step.name.isNotEmpty()) { + text = step.name } } } @@ -195,18 +172,16 @@ open class RouteModel() { fun travelLeftTime(): Double { var timeLeft = 0.0 - for (i in route.currentManeuverIndex + 1.. 0) { - val maneuver = route.currentManeuver() - val curTime = maneuver.time - val percent = - 100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex) - val time = curTime * percent / 100 - timeLeft += time + for (i in route.currentStep + 1.. 0) { - leftDistance = (routeState.distanceToStepEnd / 1000).toDouble() - } + val step = route.currentStep() + var leftDistance = step.distance + val percent = + 100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size) + leftDistance = leftDistance * percent / 100 // The remaining distance to the step, rounded to the nearest 10 units. return (leftDistance * 1000 / 10.0).roundToInt() * 10.0 @@ -234,18 +209,17 @@ open class RouteModel() { /** Returns the left distance in km. */ fun travelLeftDistance(): Double { var leftDistance = 0.0 - for (i in route.currentManeuverIndex + 1.. 0) { - val maneuver = route.currentManeuver() - val curDistance = maneuver.length - val percent = - 100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex) - val time = curDistance * percent / 100 - leftDistance += time + for (i in route.currentStep + 1.. + android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840ZM258,742L480,644L702,742L480,228L258,742ZM480,644L480,644L480,644L480,644Z"/>