This commit is contained in:
Dimitris
2025-12-30 16:11:30 +01:00
parent 45c8bb5ccc
commit 9f356bd728
24 changed files with 139 additions and 34 deletions

View File

@@ -20,6 +20,7 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.Navigation"> android:theme="@style/Theme.Navigation">
<meta-data <meta-data

View File

@@ -11,6 +11,7 @@ import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.osrm.OsrmRepository import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.valhalla.ValhallaRepository import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.di.appModule import com.kouros.navigation.di.appModule
import com.kouros.navigation.model.BaseStyleModel
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
@@ -28,7 +29,7 @@ class MainApplication : Application() {
super.onCreate() super.onCreate()
ObjectBox.init(this); ObjectBox.init(this);
appContext = applicationContext appContext = applicationContext
setIntKeyValue(appContext!!, RouteEngine.VALHALLA.ordinal, ROUTE_ENGINE) setIntKeyValue(appContext!!, RouteEngine.OSRM.ordinal, ROUTE_ENGINE)
navigationViewModel = getRouteEngine(appContext!!) navigationViewModel = getRouteEngine(appContext!!)
startKoin { startKoin {
androidLogger(Level.DEBUG) androidLogger(Level.DEBUG)

View File

@@ -3,13 +3,15 @@ package com.kouros.navigation.di
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.osrm.OsrmRepository import com.kouros.navigation.data.osrm.OsrmRepository
import com.kouros.navigation.data.valhalla.ValhallaRepository import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.BaseStyleModel
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module import org.koin.dsl.module
import kotlin.math.sin
val appModule = module { val appModule = module {
viewModelOf(::ViewModel) viewModelOf(::ViewModel)
singleOf(::ValhallaRepository) singleOf(::ValhallaRepository)
singleOf(::OsrmRepository) singleOf(::OsrmRepository)
} }

View File

@@ -33,7 +33,8 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" /> <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
<application android:requestLegacyExternalStorage="true"> <application android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true">
<meta-data <meta-data
android:name="androidx.car.app.minCarApiLevel" android:name="androidx.car.app.minCarApiLevel"
android:value="1" /> android:value="1" />

View File

@@ -157,6 +157,7 @@ class NavigationSession : Session(), NavigationScreen.Listener {
carContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager carContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
if (location != null) { if (location != null) {
navigationViewModel.loadRecentPlace(location = location, carContext)
updateLocation(location) updateLocation(location)
locationManager.requestLocationUpdates( locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LocationManager.GPS_PROVIDER,

View File

@@ -192,7 +192,7 @@ class SurfaceRenderer(
val cameraDuration = val cameraDuration =
duration(viewStyle == ViewStyle.PREVIEW, position!!.bearing, lastBearing) duration(viewStyle == ViewStyle.PREVIEW, position!!.bearing, lastBearing)
val currentSpeed: Float? by speed.observeAsState() val currentSpeed: Float? by speed.observeAsState()
if (viewStyle == ViewStyle.VIEW) { if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
DrawNavigationImages( DrawNavigationImages(
paddingValues, paddingValues,
currentSpeed, currentSpeed,

View File

@@ -1,7 +1,8 @@
package com.kouros.navigation.car.map package com.kouros.navigation.car.map
import android.location.Location
import android.content.Context import android.content.Context
import android.content.res.AssetFileDescriptor
import android.location.Location
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -33,9 +34,9 @@ import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.data.NavigationColor import com.kouros.navigation.data.NavigationColor
import com.kouros.navigation.data.RouteColor import com.kouros.navigation.data.RouteColor
import com.kouros.navigation.data.SpeedColor import com.kouros.navigation.data.SpeedColor
import com.kouros.navigation.model.BaseStyleModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
import com.kouros.navigation.utils.location
import org.maplibre.compose.camera.CameraPosition import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.CameraState import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.camera.rememberCameraState import org.maplibre.compose.camera.rememberCameraState
@@ -92,6 +93,8 @@ fun MapLibre(
viewStyle: ViewStyle, viewStyle: ViewStyle,
speedCameras: String? = "" speedCameras: String? = ""
) { ) {
//val baseStyle = BaseStyleModel().readStyle(context)
MaplibreMap( MaplibreMap(
options = MapOptions( options = MapOptions(
ornamentOptions = ornamentOptions =
@@ -115,6 +118,7 @@ fun MapLibre(
//Puck(cameraState, lastLocation) //Puck(cameraState, lastLocation)
} }
} }
@Composable @Composable
fun RouteLayer(routeData: String?) { fun RouteLayer(routeData: String?) {
if (routeData != null && routeData.isNotEmpty()) { if (routeData != null && routeData.isNotEmpty()) {
@@ -191,6 +195,7 @@ fun SpeedCameraLayer(speedCameras: String?) {
) )
} }
} }
@Composable @Composable
fun BuildingLayer(tiles: Source) { fun BuildingLayer(tiles: Source) {
Anchor.Replace("building-3d") { Anchor.Replace("building-3d") {
@@ -369,6 +374,7 @@ private fun MaxSpeed(
@Composable @Composable
fun DarkMode(context: Context, baseStyle: MutableState<BaseStyle.Uri>) { fun DarkMode(context: Context, baseStyle: MutableState<BaseStyle.Uri>) {
val darkMode = getIntKeyValue(context, Constants.DARK_MODE_SETTINGS) val darkMode = getIntKeyValue(context, Constants.DARK_MODE_SETTINGS)
if (darkMode == 0) { if (darkMode == 0) {
baseStyle.value = BaseStyle.Uri(Constants.STYLE) baseStyle.value = BaseStyle.Uri(Constants.STYLE)
} }
@@ -385,7 +391,11 @@ fun DarkMode(context: Context, baseStyle: MutableState<BaseStyle.Uri>) {
fun getPaddingValues(height: Int, viewStyle: ViewStyle): PaddingValues { fun getPaddingValues(height: Int, viewStyle: ViewStyle): PaddingValues {
return when (viewStyle) { return when (viewStyle) {
ViewStyle.VIEW -> PaddingValues(start = 50.dp, top = distanceFromTop(height).dp) ViewStyle.VIEW, ViewStyle.PAN_VIEW -> PaddingValues(
start = 50.dp,
top = distanceFromTop(height).dp
)
ViewStyle.PREVIEW -> PaddingValues(start = 150.dp, bottom = 0.dp) ViewStyle.PREVIEW -> PaddingValues(start = 150.dp, bottom = 0.dp)
else -> PaddingValues(start = 250.dp, bottom = 0.dp) else -> PaddingValues(start = 250.dp, bottom = 0.dp)
} }

View File

@@ -29,6 +29,8 @@ import androidx.car.app.model.CarIcon
import androidx.car.app.model.CarText import androidx.car.app.model.CarText
import androidx.car.app.model.DateTimeWithZone import androidx.car.app.model.DateTimeWithZone
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import androidx.car.app.navigation.model.Lane
import androidx.car.app.navigation.model.LaneDirection
import androidx.car.app.navigation.model.Maneuver import androidx.car.app.navigation.model.Maneuver
import androidx.car.app.navigation.model.Step import androidx.car.app.navigation.model.Step
import androidx.car.app.navigation.model.TravelEstimate import androidx.car.app.navigation.model.TravelEstimate
@@ -46,6 +48,13 @@ class RouteCarModel() : RouteModel() {
val stepData = currentStep() val stepData = currentStep()
val currentStepCueWithImage: SpannableString = val currentStepCueWithImage: SpannableString =
createString(stepData.instruction) createString(stepData.instruction)
val straightNormal =
Lane.Builder()
.addDirection(LaneDirection.create(LaneDirection.SHAPE_STRAIGHT, false))
.build()
val step = val step =
Step.Builder(currentStepCueWithImage) Step.Builder(currentStepCueWithImage)
.setManeuver( .setManeuver(
@@ -54,12 +63,17 @@ class RouteCarModel() : RouteModel() {
.build() .build()
) )
.setRoad(routeState.destination.street!!) .setRoad(routeState.destination.street!!)
.build() stepData.lane.forEach {
return step if (it.indications.isNotEmpty() ) {
step.setLanesImage(createCarIcon(carContext, R.drawable.lanes))
step.addLane(straightNormal)
}
}
return step.build()
} }
/** Returns the next [Step] with information such as the cue text and images. */ /** Returns the next [Step] with information such as the cue text and images. */
fun nextStep(carContext: CarContext): Step? { fun nextStep(carContext: CarContext): Step {
val stepData = nextStep() val stepData = nextStep()
val currentStepCueWithImage: SpannableString = val currentStepCueWithImage: SpannableString =
createString(stepData.instruction) createString(stepData.instruction)

View File

@@ -11,11 +11,12 @@ import androidx.car.app.model.Action.FLAG_DEFAULT
import androidx.car.app.model.ActionStrip import androidx.car.app.model.ActionStrip
import androidx.car.app.model.CarColor import androidx.car.app.model.CarColor
import androidx.car.app.model.CarIcon import androidx.car.app.model.CarIcon
import androidx.car.app.model.CarText
import androidx.car.app.model.Distance import androidx.car.app.model.Distance
import androidx.car.app.model.Header import androidx.car.app.model.Header
import androidx.car.app.model.MessageTemplate import androidx.car.app.model.MessageTemplate
import androidx.car.app.model.Template import androidx.car.app.model.Template
import androidx.car.app.navigation.model.Lane
import androidx.car.app.navigation.model.LaneDirection
import androidx.car.app.navigation.model.Maneuver import androidx.car.app.navigation.model.Maneuver
import androidx.car.app.navigation.model.MapWithContentTemplate import androidx.car.app.navigation.model.MapWithContentTemplate
import androidx.car.app.navigation.model.MessageInfo import androidx.car.app.navigation.model.MessageInfo
@@ -29,13 +30,11 @@ import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.car.navigation.RouteCarModel import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.Place 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.GeoUtils import com.kouros.navigation.utils.GeoUtils
import com.kouros.navigation.utils.bearing
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@@ -102,13 +101,12 @@ class NavigationScreen(
coordinates.add(listOf(it.lon!!, it.lat!!)) coordinates.add(listOf(it.lon!!, it.lat!!))
} }
val speedData = GeoUtils.createPointCollection(coordinates, "radar") val speedData = GeoUtils.createPointCollection(coordinates, "radar")
surfaceRenderer.speedCamerasData.value =speedData surfaceRenderer.speedCamerasData.value = speedData
} }
init { init {
viewModel.route.observe(this, observer) viewModel.route.observe(this, observer)
viewModel.recentPlace.observe(this, recentObserver) viewModel.recentPlace.observe(this, recentObserver)
viewModel.loadRecentPlace(location = surfaceRenderer.lastLocation)
viewModel.placeLocation.observe(this, placeObserver) viewModel.placeLocation.observe(this, placeObserver)
viewModel.speedCameras.observe(this, speedObserver) viewModel.speedCameras.observe(this, speedObserver)
} }
@@ -369,6 +367,7 @@ class NavigationScreen(
.build() .build()
).setOnClickListener { ).setOnClickListener {
surfaceRenderer.handleScale(1) surfaceRenderer.handleScale(1)
invalidate()
} }
.build() .build()
} }
@@ -385,6 +384,7 @@ class NavigationScreen(
.build() .build()
).setOnClickListener { ).setOnClickListener {
surfaceRenderer.handleScale(-1) surfaceRenderer.handleScale(-1)
invalidate()
} }
.build() .build()
} }
@@ -401,6 +401,7 @@ class NavigationScreen(
.build() .build()
).setOnClickListener { ).setOnClickListener {
surfaceRenderer.viewStyle = ViewStyle.VIEW surfaceRenderer.viewStyle = ViewStyle.VIEW
invalidate()
} }
.build() .build()
} }

View File

@@ -6,6 +6,7 @@ import com.kouros.navigation.data.Constants.home2Location
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.NavigationRepository
import com.kouros.navigation.data.SearchFilter import com.kouros.navigation.data.SearchFilter
import com.kouros.navigation.data.valhalla.ValhallaRepository
import com.kouros.navigation.model.RouteModel import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import org.junit.Test import org.junit.Test
@@ -16,7 +17,7 @@ import org.junit.Test
*/ */
class ViewModelTest { class ViewModelTest {
val repo = NavigationRepository() val repo = ValhallaRepository()
val viewModel = ViewModel(repo) val viewModel = ViewModel(repo)
val model = RouteModel() val model = RouteModel()
@@ -33,6 +34,6 @@ class ViewModelTest {
toLocation.longitude = home2Location.longitude toLocation.longitude = home2Location.longitude
val route = repo.getRoute(fromLocation, toLocation, SearchFilter()) val route = repo.getRoute(fromLocation, toLocation, SearchFilter())
model.startNavigation(route) //model.startNavigation(route)
} }
} }

View File

@@ -19,6 +19,7 @@ package com.kouros.navigation.data
import android.location.Location import android.location.Location
import android.location.LocationManager import android.location.LocationManager
import android.net.Uri import android.net.Uri
import com.kouros.navigation.data.route.Lane
import io.objectbox.annotation.Entity import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id import io.objectbox.annotation.Id
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@@ -63,7 +64,9 @@ data class StepData (
var arrivalTime : Long, var arrivalTime : Long,
var leftDistance: Double var leftDistance: Double,
var lane: List<Lane> = listOf(Lane(valid = false, indications = emptyList())),
) )

View File

@@ -5,6 +5,7 @@ import com.google.gson.annotations.SerializedName
data class Intersections( data class Intersections(
@SerializedName("in") var inV: Int? = null,
@SerializedName("out") var out: Int? = null, @SerializedName("out") var out: Int? = null,
@SerializedName("entry") var entry: ArrayList<Boolean> = arrayListOf(), @SerializedName("entry") var entry: ArrayList<Boolean> = arrayListOf(),
@SerializedName("bearings") var bearings: ArrayList<Int> = arrayListOf(), @SerializedName("bearings") var bearings: ArrayList<Int> = arrayListOf(),

View File

@@ -4,7 +4,9 @@ import android.location.Location
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.SearchFilter import com.kouros.navigation.data.SearchFilter
private const val routeUrl = "https://kouros-online.de/osrm/route/v1/driving/" //private const val routeUrl = "https://kouros-online.de/osrm/route/v1/driving/"
private const val routeUrl = "http://192.168.1.37:5000/route/v1/driving/"
class OsrmRepository : NavigationRepository() { class OsrmRepository : NavigationRepository() {
override fun getRoute( override fun getRoute(

View File

@@ -1,6 +1,8 @@
package com.kouros.navigation.data.osrm package com.kouros.navigation.data.osrm
import com.kouros.navigation.data.Route import com.kouros.navigation.data.Route
import com.kouros.navigation.data.route.Intersection
import com.kouros.navigation.data.route.Lane
import com.kouros.navigation.data.route.Leg import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.data.route.Maneuver as RouteManeuver import com.kouros.navigation.data.route.Maneuver as RouteManeuver
import com.kouros.navigation.data.route.Step import com.kouros.navigation.data.route.Step
@@ -13,11 +15,12 @@ class OsrmRoute {
fun mapToOsrm(routeJson: OsrmResponse, builder: Route.Builder) { fun mapToOsrm(routeJson: OsrmResponse, builder: Route.Builder) {
val waypoints = mutableListOf<List<Double>>() val waypoints = mutableListOf<List<Double>>()
val summary = Summary() val summary = Summary()
summary.distance = routeJson.routes.first().distance!! summary.distance = routeJson.routes.first().distance!! / 1000
summary.duration = routeJson.routes.first().duration!! summary.duration = routeJson.routes.first().duration!! / 1000
val steps = mutableListOf<Step>() val steps = mutableListOf<Step>()
var stepIndex = 0 var stepIndex = 0
routeJson.routes.first().legs.first().steps.forEach { routeJson.routes.first().legs.first().steps.forEach {
val intersections = mutableListOf<Intersection>()
if (it.maneuver != null) { if (it.maneuver != null) {
val points = decodePolyline(it.geometry!!, 5) val points = decodePolyline(it.geometry!!, 5)
waypoints.addAll(points) waypoints.addAll(points)
@@ -27,7 +30,17 @@ class OsrmRoute {
type = convertType(it.maneuver!!), type = convertType(it.maneuver!!),
waypoints = points waypoints = points
) )
val step = Step( index = stepIndex, name = it.name!!, distance = it.distance!!, duration = it.duration!!, maneuver = maneuver) it.intersections.forEach { it2 ->
if (it2.location[0] != 0.0) {
val lanes = mutableListOf<Lane>()
it2.lanes.forEach { it3 ->
val lane = Lane(it3.valid, it3.indications)
lanes.add(lane)
}
intersections.add(Intersection(it2.location, lanes))
}
}
val step = Step( index = stepIndex, name = it.name!!, distance = it.distance!! / 1000, duration = it.duration!!, maneuver = maneuver, intersection = intersections)
steps.add(step) steps.add(step)
stepIndex += 1 stepIndex += 1
} }
@@ -58,6 +71,11 @@ class OsrmRoute {
newType = androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_RIGHT newType = androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_RIGHT
} }
} }
ManeuverType.turn.value -> {
if (maneuver.modifier == "left") {
newType = androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_LEFT
}
}
} }
return newType return newType
} }

View File

@@ -0,0 +1,8 @@
package com.kouros.navigation.data.route
import java.util.Collections
data class Intersection(
val location: ArrayList<Double> = arrayListOf(0.0, 0.0),
val lane : List<Lane> = Collections.emptyList<Lane>(),
)

View File

@@ -0,0 +1,6 @@
package com.kouros.navigation.data.route
data class Lane (
val valid: Boolean,
var indications: List<String>,
)

View File

@@ -1,10 +1,11 @@
package com.kouros.navigation.data.route package com.kouros.navigation.data.route
class Step( data class Step(
var index : Int = 0, var index : Int = 0,
var waypointIndex : Int = 0, var waypointIndex : Int = 0,
val maneuver: Maneuver, val maneuver: Maneuver,
val duration: Double = 0.0, val duration: Double = 0.0,
val distance: Double = 0.0, val distance: Double = 0.0,
val name : String = "", val name : String = "",
val intersection: List<Intersection> = mutableListOf(),
) )

View File

@@ -0,0 +1,15 @@
package com.kouros.navigation.model
import android.content.Context
import com.kouros.data.R
import org.maplibre.compose.style.BaseStyle
class BaseStyleModel {
fun readStyle(context: Context): BaseStyle.Json {
println("Read Style")
val liberty = context.resources.openRawResource(R.raw.liberty)
val libertyString = liberty.bufferedReader().use { it.readText() }
val baseStyle = BaseStyle.Json(libertyString)
return baseStyle
}
}

View File

@@ -12,6 +12,8 @@ import com.kouros.navigation.data.Place
import com.kouros.navigation.data.Route import com.kouros.navigation.data.Route
import com.kouros.navigation.data.RouteEngine import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.StepData import com.kouros.navigation.data.StepData
import com.kouros.navigation.data.route.Intersection
import com.kouros.navigation.data.route.Lane
import com.kouros.navigation.data.route.Leg import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue import com.kouros.navigation.utils.NavigationUtils.getIntKeyValue
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
@@ -37,6 +39,7 @@ open class RouteModel() {
val lastSpeedLocation: Location = location(0.0, 0.0), val lastSpeedLocation: Location = location(0.0, 0.0),
val lastSpeedIndex: Int = 0, val lastSpeedIndex: Int = 0,
val maxSpeed: Int = 0, val maxSpeed: Int = 0,
val location: Location = location(0.0, 0.0),
) )
var routeState = RouteState() var routeState = RouteState()
@@ -74,6 +77,7 @@ open class RouteModel() {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
fun updateLocation(location: Location, viewModel: ViewModel) { fun updateLocation(location: Location, viewModel: ViewModel) {
routeState = routeState.copy(location = location)
findStep(location) findStep(location)
updateSpeedLimit(location, viewModel) updateSpeedLimit(location, viewModel)
} }
@@ -103,6 +107,19 @@ open class RouteModel() {
//println("Current Index ${route.currentStep} WayPoint: ${route.currentStep().waypointIndex}") //println("Current Index ${route.currentStep} WayPoint: ${route.currentStep().waypointIndex}")
} }
private fun currentIntersection(location: Location): Intersection {
var inter = Intersection()
var nearestDistance = 100000.0f
route.currentStep().intersection.forEach {
val distance = location.distanceTo(location(it.location[0], it.location[1]))
if (distance < nearestDistance) {
nearestDistance = distance
inter = it
}
}
return inter
}
fun updateSpeedLimit(location: Location, viewModel: ViewModel) = runBlocking { fun updateSpeedLimit(location: Location, viewModel: ViewModel) = runBlocking {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
// speed limit // speed limit
@@ -136,26 +153,28 @@ open class RouteModel() {
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 relevantStep = if (shouldAdvance) {
route.nextStep() // This advances the route's state route.nextStep() // This advances the route's state
} else { } else {
route.currentStep() route.currentStep()
} }
// Safely get the street name from the maneuver // Safely get the street name from the maneuver
val streetName = relevantManeuver.name val streetName = relevantStep.name
if (shouldAdvance) { if (shouldAdvance) {
maneuverType = relevantManeuver.maneuver.type maneuverType = relevantStep.maneuver.type
} }
val maneuverIconPair = maneuverIcon(maneuverType) val maneuverIconPair = maneuverIcon(maneuverType)
routeState = routeState.copy(maneuverType = maneuverIconPair.first) routeState = routeState.copy(maneuverType = maneuverIconPair.first)
// Construct and return the final StepData object // Construct and return the final StepData object
val intersection = currentIntersection(routeState.location)
return StepData( return StepData(
streetName, streetName,
distanceToNextStep, distanceToNextStep,
maneuverIconPair.first, maneuverIconPair.first,
maneuverIconPair.second, maneuverIconPair.second,
arrivalTime(), arrivalTime(),
travelLeftDistance() travelLeftDistance(),
intersection.lane
) )
} }

View File

@@ -67,7 +67,7 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
MutableLiveData() MutableLiveData()
} }
fun loadRecentPlace(location: Location) { fun loadRecentPlace(location: Location, context: Context) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val placeBox = boxStore.boxFor(Place::class) val placeBox = boxStore.boxFor(Place::class)
@@ -79,12 +79,12 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
query.close() query.close()
for (place in results) { for (place in results) {
val plLocation = location(place.longitude, place.latitude) val plLocation = location(place.longitude, place.latitude)
//val distance = repository.getRouteDistance(location, plLocation, SearchFilter()) val distance = repository.getRouteDistance(location, plLocation, SearchFilter(), context)
//place.distance = distance.toFloat() place.distance = distance.toFloat()
//if (place.distance == 0F) { if (place.distance > 1F) {
recentPlace.postValue(place) recentPlace.postValue(place)
return@launch return@launch
//} }
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -13,7 +13,7 @@ junitVersion = "1.3.0"
espressoCore = "3.7.0" espressoCore = "3.7.0"
kotlinxSerializationJson = "1.9.0" kotlinxSerializationJson = "1.9.0"
lifecycleRuntimeKtx = "2.10.0" lifecycleRuntimeKtx = "2.10.0"
composeBom = "2025.12.00" composeBom = "2025.12.01"
appcompat = "1.7.1" appcompat = "1.7.1"
material = "1.13.0" material = "1.13.0"
carApp = "1.7.0" carApp = "1.7.0"