Compare commits
2 Commits
ddae6f2189
...
1b8abbd4eb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b8abbd4eb | ||
|
|
d0a07e1315 |
@@ -41,12 +41,9 @@ import com.google.android.gms.location.LocationServices
|
|||||||
import com.kouros.navigation.MainApplication.Companion.navigationViewModel
|
import com.kouros.navigation.MainApplication.Companion.navigationViewModel
|
||||||
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
|
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
|
||||||
import com.kouros.navigation.data.Constants.homeLocation
|
import com.kouros.navigation.data.Constants.homeLocation
|
||||||
import com.kouros.navigation.data.NavigationRepository
|
|
||||||
import com.kouros.navigation.data.StepData
|
import com.kouros.navigation.data.StepData
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
|
||||||
import com.kouros.navigation.model.MockLocation
|
import com.kouros.navigation.model.MockLocation
|
||||||
import com.kouros.navigation.model.RouteModel
|
import com.kouros.navigation.model.RouteModel
|
||||||
import com.kouros.navigation.model.ViewModel
|
|
||||||
import com.kouros.navigation.ui.theme.NavigationTheme
|
import com.kouros.navigation.ui.theme.NavigationTheme
|
||||||
import com.kouros.navigation.utils.bearing
|
import com.kouros.navigation.utils.bearing
|
||||||
import com.kouros.navigation.utils.calculateZoom
|
import com.kouros.navigation.utils.calculateZoom
|
||||||
@@ -114,13 +111,16 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
|
locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
|
||||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
|
||||||
|
fusedLocationClient.lastLocation
|
||||||
|
.addOnSuccessListener { location : android.location.Location? ->
|
||||||
if (useMock) {
|
if (useMock) {
|
||||||
mock = MockLocation(locationManager)
|
mock = MockLocation(locationManager)
|
||||||
mock.setMockLocation(
|
mock.setMockLocation(
|
||||||
homeLocation.latitude,
|
location?.latitude ?: homeLocation.latitude,
|
||||||
homeLocation.longitude
|
location?.longitude ?: homeLocation.longitude
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
CheckPermissionScreen()
|
CheckPermissionScreen()
|
||||||
@@ -165,11 +165,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
val step: StepData? by stepData.observeAsState()
|
val step: StepData? by stepData.observeAsState()
|
||||||
val nextStep: StepData? by nextStepData.observeAsState()
|
val nextStep: StepData? by nextStepData.observeAsState()
|
||||||
|
|
||||||
fun openSheet() {
|
|
||||||
scope.launch { scaffoldState.bottomSheetState.expand() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun closeSheet() {
|
fun closeSheet() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
scaffoldState.bottomSheetState.partialExpand()
|
scaffoldState.bottomSheetState.partialExpand()
|
||||||
@@ -236,13 +231,13 @@ 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
|
||||||
&& leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
|
&& leftStepDistance() < DESTINATION_ARRIVAL_DISTANCE
|
||||||
) {
|
) {
|
||||||
stopNavigation()
|
// stopNavigation()
|
||||||
routeState = routeState.copy(arrived = true)
|
routeState = routeState.copy(arrived = true)
|
||||||
routeData.value = ""
|
routeData.value = ""
|
||||||
}
|
}
|
||||||
@@ -302,20 +297,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(600L) //
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class RouteCarModel() : RouteModel() {
|
|||||||
|
|
||||||
val dismissAction: Action = createToastAction(
|
val dismissAction: Action = createToastAction(
|
||||||
carContext,
|
carContext,
|
||||||
R.string.speed_camera, R.string.exit_action_title,
|
R.string.exit_action_title, R.string.exit_action_title,
|
||||||
FLAG_DEFAULT
|
FLAG_DEFAULT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ import com.kouros.navigation.data.Place
|
|||||||
import com.kouros.navigation.data.nominatim.SearchResult
|
import com.kouros.navigation.data.nominatim.SearchResult
|
||||||
import com.kouros.navigation.data.overpass.Elements
|
import com.kouros.navigation.data.overpass.Elements
|
||||||
import com.kouros.navigation.model.ViewModel
|
import com.kouros.navigation.model.ViewModel
|
||||||
|
import com.kouros.navigation.utils.bearing
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
class NavigationScreen(
|
class NavigationScreen(
|
||||||
carContext: CarContext,
|
carContext: CarContext,
|
||||||
@@ -490,7 +492,12 @@ class NavigationScreen(
|
|||||||
}
|
}
|
||||||
val sortedList = updatedCameras.sortedWith(compareBy { it.distance })
|
val sortedList = updatedCameras.sortedWith(compareBy { it.distance })
|
||||||
val camera = sortedList.first()
|
val camera = sortedList.first()
|
||||||
if (camera.distance < 80) {
|
val bearingSpeedCamera = location.bearingTo(location(camera.lon!!, camera.lat!!))
|
||||||
|
val bearingRoute = surfaceRenderer.lastLocation.bearingTo(location)
|
||||||
|
|
||||||
|
if (camera.distance < 80
|
||||||
|
&& (bearingSpeedCamera.absoluteValue - bearingRoute.absoluteValue).absoluteValue < 15.0
|
||||||
|
) {
|
||||||
routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed)
|
routeModel.showSpeedCamera(carContext, camera.distance, camera.tags.maxspeed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -179,3 +179,6 @@ object Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class RouteEngine {
|
||||||
|
VALHALLA, OSRM, GRAPHHOPPER
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -2,125 +2,97 @@ 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.osrm.OsrmResponse
|
||||||
import com.kouros.navigation.data.valhalla.Summary
|
import com.kouros.navigation.data.osrm.OsrmRoute
|
||||||
import com.kouros.navigation.data.valhalla.Trip
|
import com.kouros.navigation.data.route.Leg
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaJson
|
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.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>,
|
|
||||||
|
|
||||||
/**
|
val routeEngine: Int,
|
||||||
* The distance traveled from origin to destination.
|
val summary: Summary?,
|
||||||
*
|
val legs: List<Leg>?,
|
||||||
* @return a double number with unit meters
|
val routeGeoJson: String = "",
|
||||||
* @since 1.0.0
|
val centerLocation : Location = location(0.0, 0.0),
|
||||||
*/
|
var currentStep : Int = 0,
|
||||||
val distance: Double,
|
val waypoints: List<List<Double>>?,
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
data class Builder (
|
||||||
* 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>>,
|
|
||||||
|
|
||||||
/**
|
var routeEngine : Int = RouteEngine.VALHALLA.ordinal,
|
||||||
* List of [List<Point>] objects. Each `Point` is an input coordinate
|
var summary: Summary? = null,
|
||||||
* snapped to the road and path network. The `waypoint` appear in the list in the order of
|
var legs: List<Leg>? = null,
|
||||||
* the input coordinates.
|
var routeGeoJson: String = "",
|
||||||
*
|
var centerLocation: Location = location(0.0, 0.0),
|
||||||
* @since 1.0.0
|
var waypoints : List<List<Double>>? = null,) {
|
||||||
*/
|
|
||||||
val pointLocations: List<Point>,
|
|
||||||
|
|
||||||
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<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)
|
|
||||||
|
|
||||||
|
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)
|
if (routeEngine == RouteEngine.VALHALLA.ordinal) {
|
||||||
trip = routeJson.trip
|
val jsonObject: Map<String, JsonElement> = Json.parseToJsonElement(route).jsonObject
|
||||||
|
val routeJson = gson.fromJson(jsonObject["trip"].toString(), ValhallaResponse::class.java)
|
||||||
|
ValhallaRoute().mapJsonToValhalla(routeJson, this)
|
||||||
|
} else {
|
||||||
|
val osrmJson = gson.fromJson(route, OsrmResponse::class.java)
|
||||||
|
OsrmRoute().mapToOsrm(osrmJson, 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.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.kouros.navigation.data.osrm
|
|||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
|
||||||
data class OsrmJson (
|
data class OsrmResponse (
|
||||||
|
|
||||||
@SerializedName("code" ) var code : String? = null,
|
@SerializedName("code" ) var code : String? = null,
|
||||||
@SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(),
|
@SerializedName("routes" ) var routes : ArrayList<Routes> = arrayListOf(),
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.kouros.navigation.data.osrm
|
||||||
|
|
||||||
|
import com.kouros.navigation.data.Route
|
||||||
|
import com.kouros.navigation.data.valhalla.ValhallaResponse
|
||||||
|
|
||||||
|
class OsrmRoute {
|
||||||
|
|
||||||
|
fun mapToOsrm(routeJson: OsrmResponse, builder: Route.Builder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ class Overpass {
|
|||||||
|);
|
|);
|
||||||
|out body;
|
|out body;
|
||||||
""".trimMargin()
|
""".trimMargin()
|
||||||
|
println("way[highway](around:$radius,$linestring)")
|
||||||
return overpassApi(httpURLConnection, searchQuery)
|
return overpassApi(httpURLConnection, searchQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +61,6 @@ class Overpass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> {
|
fun overpassApi(httpURLConnection: HttpURLConnection, searchQuery: String) : List<Elements> {
|
||||||
// Send the JSON we created
|
|
||||||
val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
|
val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
|
||||||
outputStreamWriter.write(searchQuery)
|
outputStreamWriter.write(searchQuery)
|
||||||
outputStreamWriter.flush()
|
outputStreamWriter.flush()
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Leg(
|
||||||
|
var steps : List<Step> = arrayListOf()
|
||||||
|
)
|
||||||
@@ -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>>,
|
||||||
|
)
|
||||||
@@ -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 = "",
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Summary(
|
||||||
|
var duration : Double = 0.0,
|
||||||
|
var distance : Double = 0.0,
|
||||||
|
)
|
||||||
@@ -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 = ""
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -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,
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
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 Trip (
|
|
||||||
|
|
||||||
@SerializedName("locations" ) var locations : ArrayList<Locations> = arrayListOf(),
|
|
||||||
@SerializedName("legs" ) var legs : ArrayList<Legs> = arrayListOf(),
|
|
||||||
@SerializedName("summary" ) var summary : Summary = Summary(),
|
|
||||||
@SerializedName("status_message" ) var statusMessage : String = "",
|
|
||||||
@SerializedName("status" ) var status : Int = 0,
|
|
||||||
@SerializedName("units" ) var units : String = "",
|
|
||||||
@SerializedName("language" ) var language : String = "",
|
|
||||||
|
|
||||||
)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
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 ValhallaJson (
|
|
||||||
|
|
||||||
@SerializedName("trip" ) var trip : Trip = Trip(),
|
|
||||||
@SerializedName("id" ) var id : String = ""
|
|
||||||
|
|
||||||
)
|
|
||||||
@@ -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 = "",
|
||||||
|
|
||||||
|
)
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
val lastSpeedLocation: Location = location(0.0, 0.0),
|
||||||
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,41 @@ 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
|
||||||
if (routeState.lastSpeedIndex < route.currentManeuverIndex) {
|
val distance = routeState.lastSpeedLocation.distanceTo(location)
|
||||||
routeState = routeState.copy(lastSpeedIndex = route.currentManeuverIndex)
|
if (distance > 500 || routeState.lastSpeedIndex < route.currentStep) {
|
||||||
|
routeState = routeState.copy(lastSpeedIndex = route.currentStep)
|
||||||
|
routeState = routeState.copy(lastSpeedLocation = location)
|
||||||
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 +104,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 +144,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 +154,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 +174,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 +198,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 +211,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 +287,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 +296,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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user