This commit is contained in:
Dimitris
2025-12-24 07:24:12 +01:00
parent ddae6f2189
commit d0a07e1315
17 changed files with 234 additions and 206 deletions

View File

@@ -236,7 +236,7 @@ class MainActivity : ComponentActivity() {
if (isNavigating()) { if (isNavigating()) {
updateLocation(currentLocation, navigationViewModel) updateLocation(currentLocation, navigationViewModel)
stepData.value = currentStep() stepData.value = currentStep()
if (route.currentManeuverIndex + 1 <= route.maneuvers.size) { if (route.currentStep + 1 <= legs.steps.size) {
nextStepData.value = nextStep() nextStepData.value = nextStep()
} }
if (routeState.maneuverType == 39 if (routeState.maneuverType == 39
@@ -302,20 +302,21 @@ class MainActivity : ComponentActivity() {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
fun simulate() = GlobalScope.async { fun simulate() = GlobalScope.async {
for ((_, loc) in routeModel.route.waypoints.withIndex()) { for ((index, step) in routeModel.legs.steps.withIndex()) {
if (routeModel.isNavigating()) { for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) {
mock.setMockLocation(loc[1], loc[0]) mock.setMockLocation(waypoint[1], waypoint[0])
delay(500L) // delay(1000L) //
} }
} }
} }
fun test() { fun test() {
for ((index, loc) in routeModel.route.waypoints.withIndex()) { for ((index, step) in routeModel.legs.steps.withIndex()) {
if (index > 300) { println("${step.maneuver.waypoints.size}")
routeModel.updateLocation(location(loc[0], loc[1]), navigationViewModel) for ((windex, waypoint) in step.maneuver.waypoints.withIndex()) {
routeModel.updateLocation(location(waypoint[0], waypoint[1]), navigationViewModel)
routeModel.currentStep() routeModel.currentStep()
if (routeModel.route.currentManeuverIndex + 1 <= routeModel.route.maneuvers.size) { if (index + 1 <= routeModel.legs.steps.size) {
nextStepData.value = routeModel.nextStep() nextStepData.value = routeModel.nextStep()
} }
println(routeModel.routeState.maneuverType) println(routeModel.routeState.maneuverType)

View File

@@ -300,7 +300,7 @@ class SurfaceRenderer(
with(routeModel) { with(routeModel) {
routeData.value = route.routeGeoJson routeData.value = route.routeGeoJson
centerLocation = route.centerLocation centerLocation = route.centerLocation
previewDistance = route.distance previewDistance = route.summary!!.distance
} }
updateCameraPosition( updateCameraPosition(
0.0, 0.0,

View File

@@ -196,7 +196,7 @@ fun DrawNavigationImages(
@Composable @Composable
fun NavigationImage(padding: PaddingValues, width: Int, height: Int) { fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
val imageSize = (height / 6) val imageSize = (height / 8)
val color = remember { NavigationColor } val color = remember { NavigationColor }
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) { Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) {
Canvas( Canvas(

View File

@@ -89,7 +89,7 @@ class RoutePreviewScreen(
) )
.build() .build()
val message = if (routeModel.isNavigating() && routeModel.route.waypoints.isNotEmpty()) { val message = if (routeModel.isNavigating() && routeModel.route.waypoints!!.isNotEmpty()) {
createRouteText() createRouteText()
} else { } else {
CarText.Builder("Wait") CarText.Builder("Wait")
@@ -173,8 +173,8 @@ class RoutePreviewScreen(
.build() .build()
private fun createRouteText(): CarText { private fun createRouteText(): CarText {
val time = routeModel.route.summary.time val time = routeModel.route.summary!!.duration
val length = BigDecimal(routeModel.route.distance).setScale(1, RoundingMode.HALF_EVEN) val length = BigDecimal(routeModel.route.summary!!.distance).setScale(1, RoundingMode.HALF_EVEN)
val firstRoute = SpannableString(" \u00b7 $length km") val firstRoute = SpannableString(" \u00b7 $length km")
firstRoute.setSpan( firstRoute.setSpan(
DurationSpan.create(time.toLong()), 0, 1, 0 DurationSpan.create(time.toLong()), 0, 1, 0

View File

@@ -40,7 +40,7 @@ abstract class NavigationRepository {
val route = getRoute(currentLocation, location, searchFilter) val route = getRoute(currentLocation, location, searchFilter)
val routeModel = RouteModel() val routeModel = RouteModel()
routeModel.startNavigation(route) routeModel.startNavigation(route)
return routeModel.route.distance return routeModel.route.summary!!.distance
} }
fun searchPlaces(search: String, location: Location) : String { fun searchPlaces(search: String, location: Location) : String {

View File

@@ -2,125 +2,91 @@ package com.kouros.navigation.data
import android.location.Location import android.location.Location
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.kouros.navigation.data.valhalla.Maneuvers import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.data.valhalla.Summary import com.kouros.navigation.data.route.Step
import com.kouros.navigation.data.valhalla.Trip import com.kouros.navigation.data.route.Summary
import com.kouros.navigation.data.valhalla.ValhallaJson 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.createCenterLocation
import com.kouros.navigation.utils.GeoUtils.createLineStringCollection
import com.kouros.navigation.utils.GeoUtils.decodePolyline
import com.kouros.navigation.utils.location 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 import org.maplibre.geojson.Point
data class Route( data class Route(
/**
* A Leg is a route between only two waypoints.
*
* @since 1.0.0
*/
val maneuvers: List<Maneuvers>,
/**
* The distance traveled from origin to destination.
*
* @return a double number with unit meters
* @since 1.0.0
*/
val distance: Double,
/**
* List of [List<Double>] 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<List<Double>>,
/**
* List of [List<Point>] 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<Point>,
val summary: Summary,
val trip: Trip,
val time: Double,
val routeGeoJson: String,
val currentManeuverIndex : Int,
val centerLocation: Location
val routeEngine: Int,
val summary: Summary?,
val legs: List<Leg>?,
val routeGeoJson: String = "",
val centerLocation : Location = location(0.0, 0.0),
var currentStep : Int = 0,
val waypoints: List<List<Double>>?,
) { ) {
class Builder { data class Builder (
private lateinit var maneuvers: List<Maneuvers>
private var distance: Double = 0.0
private var time: Double = 0.0
private lateinit var waypoints: List<List<Double>>
private lateinit var pointLocations: List<Point>
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<Leg>? = null,
var routeGeoJson: String = "",
var centerLocation: Location = location(0.0, 0.0),
var waypoints : List<List<Double>>? = null,) {
fun routeType (routeEngine: Int) = apply {this.routeEngine = routeEngine }
fun summary(summary: Summary) = apply { this.summary = summary }
fun legs(legs: List<Leg>) = apply { this.legs = legs }
fun routeGeoJson(routeGeoJson: String) = apply {
this.routeGeoJson = routeGeoJson
centerLocation = createCenterLocation(routeGeoJson)
}
fun waypoints(waypoints: List<List<Double>>) = apply { this.waypoints = waypoints }
fun route(route: String) = apply { fun route(route: String) = apply {
if (route.isNotEmpty() && route != "[]") { if (route.isNotEmpty() && route != "[]") {
val gson = GsonBuilder().serializeNulls().create() val gson = GsonBuilder().serializeNulls().create()
val routeJson = gson.fromJson(route, ValhallaJson::class.java) val jsonObject: Map<String, JsonElement> = Json.parseToJsonElement(route).jsonObject
trip = routeJson.trip val routeJson =
gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java)
ValhallaRoute().mapJsonToValhalla(routeJson, this)
} }
} }
fun build(): Route { 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<Point>()
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( return Route(
maneuvers, routeEngine = this.routeEngine,
distance, summary = this.summary,
waypoints, legs = this.legs,
pointLocations, waypoints = this.waypoints,
summary, routeGeoJson = this.routeGeoJson,
trip,
time,
routeGeoJson,
0,
centerLocation
) )
} }
} }
fun maneuverLocations(): List<Point> { fun maneuverLocations(): List<Point> {
return pointLocations val step = currentStep()
val waypoints = step.maneuver.waypoints
val points = mutableListOf<Point>()
for (loc in waypoints) {
val point = Point.fromLngLat(loc[0], loc[1])
points.add(point)
}
return points
} }
fun currentManeuver(): Maneuvers { fun currentStep(): Step {
return maneuvers[currentManeuverIndex] if (legs != null) {
return legs.first().steps[currentStep]
} else {
throw IndexOutOfBoundsException("No legs available.")
}
} }
fun nextManeuver(): Maneuvers { fun nextStep(): Step {
val nextIndex = currentManeuverIndex + 1 val nextIndex = currentStep + 1
return if (nextIndex < maneuvers.size) { return if (nextIndex < legs!!.first().steps.size) {
maneuvers[nextIndex] legs.first().steps[currentStep + 1]
} else { } else {
throw IndexOutOfBoundsException("No next maneuver available.") throw IndexOutOfBoundsException("No next maneuver available.")
} }

View File

@@ -0,0 +1,5 @@
package com.kouros.navigation.data.route
data class Leg(
var steps : List<Step> = arrayListOf()
)

View File

@@ -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<List<Double>>,
)

View File

@@ -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 = "",
)

View File

@@ -0,0 +1,6 @@
package com.kouros.navigation.data.route
data class Summary(
var duration : Double = 0.0,
var distance : Double = 0.0,
)

View File

@@ -2,7 +2,6 @@ package com.kouros.navigation.data.valhalla
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonIgnoreUnknownKeys import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@@ -11,7 +10,7 @@ import kotlinx.serialization.json.JsonIgnoreUnknownKeys
data class Legs ( data class Legs (
@SerializedName("maneuvers" ) var maneuvers : ArrayList<Maneuvers> = arrayListOf(), @SerializedName("maneuvers" ) var maneuvers : ArrayList<Maneuvers> = arrayListOf(),
@SerializedName("summary" ) var summary : Summary = Summary(), @SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(),
@SerializedName("shape" ) var shape : String = "" @SerializedName("shape" ) var shape : String = ""
) )

View File

@@ -2,13 +2,12 @@ package com.kouros.navigation.data.valhalla
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonIgnoreUnknownKeys import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@JsonIgnoreUnknownKeys @JsonIgnoreUnknownKeys
data class Summary ( data class SummaryValhalla (
@SerializedName("has_time_restrictions" ) var hasTimeRestrictions : Boolean = false, @SerializedName("has_time_restrictions" ) var hasTimeRestrictions : Boolean = false,
@SerializedName("has_toll" ) var hasToll : Boolean = false, @SerializedName("has_toll" ) var hasToll : Boolean = false,

View File

@@ -2,7 +2,6 @@ package com.kouros.navigation.data.valhalla
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonIgnoreUnknownKeys import kotlinx.serialization.json.JsonIgnoreUnknownKeys
@@ -12,7 +11,7 @@ data class Trip (
@SerializedName("locations" ) var locations : ArrayList<Locations> = arrayListOf(), @SerializedName("locations" ) var locations : ArrayList<Locations> = arrayListOf(),
@SerializedName("legs" ) var legs : ArrayList<Legs> = arrayListOf(), @SerializedName("legs" ) var legs : ArrayList<Legs> = arrayListOf(),
@SerializedName("summary" ) var summary : Summary = Summary(), @SerializedName("summary" ) var summaryValhalla : SummaryValhalla = SummaryValhalla(),
@SerializedName("status_message" ) var statusMessage : String = "", @SerializedName("status_message" ) var statusMessage : String = "",
@SerializedName("status" ) var status : Int = 0, @SerializedName("status" ) var status : Int = 0,
@SerializedName("units" ) var units : String = "", @SerializedName("units" ) var units : String = "",

View File

@@ -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<Locations> = arrayListOf(),
@SerializedName("legs") var legs: ArrayList<Legs> = 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 = "",
)

View File

@@ -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<Step>()
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)
}
}

View File

@@ -9,6 +9,7 @@ import com.kouros.navigation.data.ManeuverType
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.Route import com.kouros.navigation.data.Route
import com.kouros.navigation.data.StepData import com.kouros.navigation.data.StepData
import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -24,15 +25,10 @@ open class RouteModel() {
val destination: Place = Place(), val destination: Place = Place(),
val arrived: Boolean = false, val arrived: Boolean = false,
val maneuverType: Int = 0, val maneuverType: Int = 0,
var currentShapeIndex: Int = 0,
var distanceToStepEnd: Float = 0F,
var beginIndex: Int = 0,
var endIndex: Int = 0,
val travelMessage: String = "", val travelMessage: String = "",
// max speed for street (maneuver) // max speed for street (maneuver)
val lastSpeedIndex: Int = 0, val lastSpeedIndex: Int = 0,
val maxSpeed: Int = 0, val maxSpeed: Int = 0,
) )
var routeState = RouteState() var routeState = RouteState()
@@ -43,6 +39,10 @@ open class RouteModel() {
routeState = routeState.copy(route = value) routeState = routeState.copy(route = value)
} }
val legs: Leg
get() = routeState.route!!.legs!!.first()
fun startNavigation(routeString: String) { fun startNavigation(routeString: String) {
val newRoute = Route.Builder() val newRoute = Route.Builder()
.route(routeString) .route(routeString)
@@ -59,40 +59,39 @@ open class RouteModel() {
isNavigating = false, isNavigating = false,
arrived = false, arrived = false,
maneuverType = 0, maneuverType = 0,
currentShapeIndex = 0,
distanceToStepEnd = 0F,
beginIndex = 0,
endIndex = 0
) )
} }
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
fun updateLocation(location: Location, viewModel: ViewModel) { fun updateLocation(location: Location, viewModel: ViewModel) {
var nearestDistance = 100000.0f findStep(location)
var newShapeIndex = -1
// find nearest waypoint and current shape index
// start search at last shape index
for (i in routeState.currentShapeIndex..<route.waypoints.size) {
val waypoint = route.waypoints[i]
val distance = location.distanceTo(location(waypoint[0], waypoint[1]))
if (distance < nearestDistance) {
nearestDistance = distance
newShapeIndex = i
}
}
// find maneuver
// calculate distance to step end
findManeuver(newShapeIndex)
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
updateSpeedLimit(location, viewModel) updateSpeedLimit(location, viewModel)
} }
} }
private fun findStep(location: Location) {
var nearestDistance = 100000.0f
for ((index, step) in legs.steps.withIndex()) {
if (index >= 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) { fun updateSpeedLimit(location: Location, viewModel: ViewModel) {
// speed limit for each maneuver index // speed limit for each maneuver index
if (routeState.lastSpeedIndex < route.currentManeuverIndex) { if (routeState.lastSpeedIndex < route.currentStep) {
routeState = routeState.copy(lastSpeedIndex = route.currentManeuverIndex) routeState = routeState.copy(lastSpeedIndex = route.currentStep)
val elements = viewModel.getMaxSpeed(location) val elements = viewModel.getMaxSpeed(location)
elements.forEach { elements.forEach {
if (it.tags.name != null && it.tags.maxspeed != null) { 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..<route.maneuvers.size) {
val maneuver = route.maneuvers[i]
if (maneuver.beginShapeIndex <= newShapeIndex && maneuver.endShapeIndex >= 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 { fun currentStep(): StepData {
val currentManeuver = route.currentManeuver() val currentStep = route.currentStep()
// Determine if we should display the current or the next maneuver // Determine if we should display the current or the next maneuver
val distanceToNextStep = leftStepDistance() val distanceToNextStep = leftStepDistance()
val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD val isNearNextManeuver = distanceToNextStep in 0.0..NEXT_STEP_THRESHOLD
val shouldAdvance = val shouldAdvance =
isNearNextManeuver && route.currentManeuverIndex < (route.maneuvers.size) isNearNextManeuver && route.currentStep < (route.legs!!.first().steps.size)
// Determine the maneuver type and corresponding icon // Determine the maneuver type and corresponding icon
var maneuverType = if (hasArrived(currentManeuver.type)) { var maneuverType = if (hasArrived(currentStep.maneuver.type)) {
currentManeuver.type currentStep.maneuver.type
} else { } else {
ManeuverType.None.value ManeuverType.None.value
} }
// Get the single, correct maneuver for this state // Get the single, correct maneuver for this state
val relevantManeuver = if (shouldAdvance) { val relevantManeuver = if (shouldAdvance) {
route.nextManeuver() // This advances the route's state route.nextStep() // This advances the route's state
} else { } else {
route.currentManeuver() route.currentStep()
} }
// Safely get the street name from the maneuver // Safely get the street name from the maneuver
val streetName = relevantManeuver.streetNames?.firstOrNull() ?: "" val streetName = relevantManeuver.name
if (shouldAdvance) { if (shouldAdvance) {
maneuverType = relevantManeuver.type maneuverType = relevantManeuver.maneuver.type
} }
val maneuverIconPair = maneuverIcon(maneuverType) val maneuverIconPair = maneuverIcon(maneuverType)
routeState = routeState.copy(maneuverType = maneuverIconPair.first) routeState = routeState.copy(maneuverType = maneuverIconPair.first)
@@ -165,8 +142,8 @@ open class RouteModel() {
fun nextStep(): StepData { fun nextStep(): StepData {
val maneuver = route.nextManeuver() val step = route.nextStep()
val maneuverType = maneuver.type val maneuverType = step.maneuver.type
val distanceLeft = leftStepDistance() val distanceLeft = leftStepDistance()
var text = "" var text = ""
@@ -175,8 +152,8 @@ open class RouteModel() {
} }
else -> { else -> {
if (maneuver.streetNames != null && maneuver.streetNames.isNotEmpty()) { if (step.name.isNotEmpty()) {
text = maneuver.streetNames[0] text = step.name
} }
} }
} }
@@ -195,18 +172,16 @@ open class RouteModel() {
fun travelLeftTime(): Double { fun travelLeftTime(): Double {
var timeLeft = 0.0 var timeLeft = 0.0
for (i in route.currentManeuverIndex + 1..<route.maneuvers.size) { for (i in route.currentStep + 1..<legs.steps.size) {
val maneuver = route.maneuvers[i] val step = legs.steps[i]
timeLeft += maneuver.time timeLeft += step.duration
} }
if (routeState.endIndex > 0) { val step = route.nextStep()
val maneuver = route.currentManeuver() val curTime = step.duration
val curTime = maneuver.time
val percent = val percent =
100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex) 100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size)
val time = curTime * percent / 100 val time = curTime * percent / 100
timeLeft += time timeLeft += time
}
return timeLeft return timeLeft
} }
@@ -221,11 +196,11 @@ open class RouteModel() {
/** Returns the current [Step] left distance in m. */ /** Returns the current [Step] left distance in m. */
fun leftStepDistance(): Double { fun leftStepDistance(): Double {
val maneuver = route.currentManeuver() val step = route.currentStep()
var leftDistance = maneuver.length var leftDistance = step.distance
if (routeState.endIndex > 0) { val percent =
leftDistance = (routeState.distanceToStepEnd / 1000).toDouble() 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. // The remaining distance to the step, rounded to the nearest 10 units.
return (leftDistance * 1000 / 10.0).roundToInt() * 10.0 return (leftDistance * 1000 / 10.0).roundToInt() * 10.0
@@ -234,18 +209,17 @@ open class RouteModel() {
/** Returns the left distance in km. */ /** Returns the left distance in km. */
fun travelLeftDistance(): Double { fun travelLeftDistance(): Double {
var leftDistance = 0.0 var leftDistance = 0.0
for (i in route.currentManeuverIndex + 1..<route.maneuvers.size) { for (i in route.currentStep + 1..<legs.steps.size) {
val maneuver = route.maneuvers[i] val step = route.legs!![0].steps[i]
leftDistance += maneuver.length leftDistance += step.distance
} }
if (routeState.endIndex > 0) {
val maneuver = route.currentManeuver() val step = route.currentStep()
val curDistance = maneuver.length val curDistance = step.distance
val percent = val percent =
100 * (routeState.endIndex - routeState.currentShapeIndex) / (routeState.endIndex - routeState.beginIndex) 100 * (step.maneuver.waypoints.size - step.waypointIndex) / (step.maneuver.waypoints.size)
val time = curDistance * percent / 100 val time = curDistance * percent / 100
leftDistance += time leftDistance += time
}
return leftDistance return leftDistance
} }
@@ -311,7 +285,6 @@ open class RouteModel() {
currentTurnIcon = R.drawable.ic_roundabout_ccw currentTurnIcon = R.drawable.ic_roundabout_ccw
} }
} }
//routeState.maneuverType = type
return Pair(type, currentTurnIcon) return Pair(type, currentTurnIcon)
} }
@@ -321,7 +294,6 @@ open class RouteModel() {
fun hasArrived(type: Int): Boolean { fun hasArrived(type: Int): Boolean {
// return leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE && type == ManeuverType.DestinationRight.value
return type == ManeuverType.DestinationRight.value return type == ManeuverType.DestinationRight.value
|| type == ManeuverType.Destination.value || type == ManeuverType.Destination.value
|| type == ManeuverType.DestinationLeft.value || type == ManeuverType.DestinationLeft.value

View File

@@ -6,5 +6,5 @@
android:tint="?attr/colorControlNormal"> android:tint="?attr/colorControlNormal">
<path <path
android:fillColor="@android:color/white" android:fillColor="@android:color/white"
android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840Z"/> android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840ZM258,742L480,644L702,742L480,228L258,742ZM480,644L480,644L480,644L480,644Z"/>
</vector> </vector>