This commit is contained in:
Dimitris
2026-03-15 17:18:02 +01:00
parent 619ceb9f83
commit 5198725879
46 changed files with 840 additions and 1326 deletions

View File

@@ -176,15 +176,21 @@ class RouteModelTest {
@Test
fun simulate() {
for ((index, waypoint) in routeModel.curRoute.waypoints.withIndex()) {
val curLocation = location(waypoint[0], waypoint[1])
if (routeModel.isNavigating()) {
val curLocation = location(waypoint[0], waypoint[1])
if (index in 0..routeModel.curRoute.waypoints.size) {
//runBlocking { delay(1000) }
val start = System.currentTimeMillis()
routeModel.updateLocation(curLocation, NavigationViewModel(TomTomRepository()))
val stepData = routeModel.currentStep()
println("${stepData.instruction} ${System.currentTimeMillis() - start}")
// val nextData = routeModel.nextStep()
//println("${stepData.instruction} ${System.currentTimeMillis() - start}")
if (stepData.lane.isNotEmpty()) {
println(stepData.street)
stepData.lane.forEach {
println("${it.indications} ${it.valid}")
}
}
// val nextData = routeModel.nextStep()
}
}
}
@@ -192,17 +198,17 @@ class RouteModelTest {
@Test
fun `leftStepDistance Inglolstädter `() {
val location: Location = location( 11.584578, 48.183653)
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()) )
val location: Location = location(11.584578, 48.183653)
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
val step = routeModel.currentStep()
assertEquals(step.leftStepDistance, 645.0, 1.0)
}
@Test
fun `leftStepDistance Vogelhart `() {
val location: Location = location( 11.578911, 48.185565)
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()) )
val location: Location = location(11.578911, 48.185565)
routeModel.updateLocation(location, NavigationViewModel(TomTomRepository()))
val step = routeModel.currentStep()
assertEquals(step.leftStepDistance , 34.0, 1.0)
assertEquals(step.leftStepDistance, 34.0, 1.0)
}
}

View File

@@ -2,13 +2,11 @@ package com.kouros.navigation.car.map
import android.location.Location
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -17,10 +15,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
@@ -36,7 +32,6 @@ import com.kouros.navigation.data.NavigationColor
import com.kouros.navigation.data.RouteColor
import com.kouros.navigation.data.SpeedColor
import com.kouros.navigation.utils.isMetricSystem
import com.kouros.navigation.utils.location
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.camera.rememberCameraState
@@ -63,7 +58,6 @@ import org.maplibre.compose.sources.Source
import org.maplibre.compose.sources.getBaseSource
import org.maplibre.compose.sources.rememberGeoJsonSource
import org.maplibre.compose.style.BaseStyle
import org.maplibre.spatialk.geojson.BoundingBox
import org.maplibre.spatialk.geojson.Position

View File

@@ -114,7 +114,11 @@ class RouteCarModel : RouteModel() {
)
.setRemainingTimeColor(CarColor.GREEN)
.setRemainingDistanceColor(CarColor.BLUE)
.setTripText(CarText.create("$traffic min"))
if (traffic > 0) {
travelBuilder.setTripText(CarText.create("$traffic min"))
travelBuilder.setTripIcon(createCarIcon(carContext, R.drawable.warning_24px))
}
if (navState.travelMessage.isNotEmpty()) {
travelBuilder.setTripIcon(createCarIcon(carContext, R.drawable.warning_24px))
travelBuilder.setTripText(CarText.create(navState.travelMessage))
@@ -143,7 +147,7 @@ class RouteCarModel : RouteModel() {
}
val laneType =
Lane.Builder()
.addDirection(LaneDirection.create(laneDirection, true))
.addDirection(LaneDirection.create(laneDirection, it.valid))
.build()
step.addLane(laneType)
}

View File

@@ -4,6 +4,8 @@ import android.location.Location
import android.location.LocationManager
import android.os.SystemClock
import androidx.lifecycle.LifecycleCoroutineScope
import com.kouros.navigation.data.Constants.homeVogelhart
import com.kouros.navigation.utils.location
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -17,6 +19,10 @@ class Simulation {
lifecycleScope: LifecycleCoroutineScope,
updateLocation: (Location) -> Unit
) {
// A92
//updateLocation(location(11.709508, 48.338923 ))
//updateLocation(homeVogelhart)
if (routeModel.navState.route.isRouteValid()) {
val points = routeModel.curRoute.waypoints
if (points.isEmpty()) return
@@ -38,7 +44,7 @@ class Simulation {
// Update your app's state as if a real GPS update occurred
updateLocation(fakeLocation)
// Wait before moving to the next point (e.g., every 1 second)
delay(1000)
delay(500)
lastLocation = fakeLocation
}
routeModel.stopNavigation()

View File

@@ -1,5 +1,6 @@
package com.kouros.navigation.car.screen
import androidx.activity.OnBackPressedCallback
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
@@ -40,8 +41,17 @@ class CategoriesScreen(
Category(id = CHARGING_STATION, name = carContext.getString(R.string.charging_station))
)
private val backPressedCallback = object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
navigationViewModel.elements.value = emptyList()
invalidate()
}
}
init {
navigationViewModel.elements.value = emptyList()
navigationViewModel.elements.observe(this, categoryObserver)
carContext.onBackPressedDispatcher.addCallback(this, backPressedCallback)
}
override fun onGetTemplate(): Template {

View File

@@ -530,8 +530,7 @@ class NavigationScreen(
* Pushes the search screen and handles the search result.
*/
private fun startSearchScreen() {
navigationViewModel.recentPlaces.value = emptyList()
navigationViewModel.previewRoute.value = ""
screenManager
.pushForResult(
SearchScreen(

View File

@@ -39,11 +39,12 @@ class PlaceListScreen(
private val places: List<Place>
) : Screen(carContext) {
val routeModel = RouteCarModel()
var place = Place()
var mPlaces = mutableListOf<Place>()
val previewObserver = Observer<String> { route ->
if (route.isNotEmpty()) {
val repository = getSettingsRepository(carContext)
@@ -70,21 +71,25 @@ class PlaceListScreen(
}
init {
loadPlaces()
// loadPlaces()
navigationViewModel.recentPlaces.value = emptyList()
navigationViewModel.previewRoute.value = ""
mPlaces.addAll(places)
navigationViewModel.previewRoute.observe(this, previewObserver)
}
override fun onGetTemplate(): Template {
val itemListBuilder = ItemList.Builder()
.setNoItemsMessage(carContext.getString(R.string.no_places))
places.forEach {
mPlaces.forEach {
val street = if (it.street != null) {
it.street
} else {
""
}
val row = Row.Builder()
// .setImage(contactIcon(it.avatar, it.category))
.setImage(contactIcon(null, it.category))
.setTitle("$street ${it.city}")
.setOnClickListener {
place = Place(
@@ -155,7 +160,7 @@ class PlaceListScreen(
carContext,
R.string.recent_Item_deleted, CarToast.LENGTH_LONG
).show()
loadPlaces()
mPlaces.remove(place)
invalidate()
}
.build()

View File

@@ -3,16 +3,17 @@ package com.kouros.navigation.car.screen.settings
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
import androidx.car.app.model.CarIcon
import androidx.car.app.model.Header
import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.Template
import androidx.car.app.model.Toggle
import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.lifecycleScope
import com.kouros.data.R
import com.kouros.navigation.car.screen.settings.PasswordSettings
import com.kouros.navigation.car.screen.settings.RoutingSettings
import com.kouros.navigation.car.navigation.NavigationUtils
import com.kouros.navigation.model.NavigationViewModel
import com.kouros.navigation.utils.getSettingsViewModel
import kotlinx.coroutines.flow.first
@@ -61,7 +62,8 @@ class NavigationSettings(
listBuilder.addItem(
buildRowForTemplate(
R.string.avoid_highways_row_title,
highwayToggle
highwayToggle,
NavigationUtils(carContext).createCarIcon(R.drawable.baseline_add_road_24)
)
)
@@ -71,7 +73,7 @@ class NavigationSettings(
settingsViewModel.onAvoidTollway(checked)
tollWayToggleState = !tollWayToggleState
}.setChecked(tollWayToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.avoid_tolls_row_title, tollwayToggle))
listBuilder.addItem(buildRowForTemplate(R.string.avoid_tolls_row_title, tollwayToggle, NavigationUtils(carContext).createCarIcon(R.drawable.baseline_toll_24)))
// Ferry
val ferryToggle: Toggle =
@@ -79,7 +81,7 @@ class NavigationSettings(
settingsViewModel.onAvoidFerry(checked)
ferryToggleState = !ferryToggleState
}.setChecked(ferryToggleState).build()
listBuilder.addItem(buildRowForTemplate(R.string.avoid_ferries, ferryToggle))
listBuilder.addItem(buildRowForTemplate(R.string.avoid_ferries, ferryToggle, NavigationUtils(carContext).createCarIcon(R.drawable.baseline_directions_boat_filled_24)))
// CarLocation
val carLocationToggle: Toggle =
@@ -91,7 +93,8 @@ class NavigationSettings(
listBuilder.addItem(
buildRowForTemplate(
R.string.use_car_location,
carLocationToggle
carLocationToggle,
NavigationUtils(carContext).createCarIcon(R.drawable.ic_place_white_24dp)
)
)
@@ -118,10 +121,11 @@ class NavigationSettings(
.build()
}
private fun buildRowForTemplate(title: Int, toggle: Toggle): Row {
private fun buildRowForTemplate(title: Int, toggle: Toggle, icon: CarIcon): Row {
return Row.Builder()
.setTitle(carContext.getString(title))
.setToggle(toggle)
.setImage(icon)
.build()
}

View File

@@ -62,7 +62,7 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.maplibre.compose)
implementation(libs.androidx.compose.material.icons.extended)
//implementation(libs.androidx.compose.material.icons.extended)
testImplementation(libs.junit)
testImplementation(libs.mockito.core)
testImplementation(libs.mockito.kotlin)

View File

@@ -62,7 +62,7 @@ data class StepData (
var icon: Int,
var arrivalTime : Long,
var leftDistance: Double,
var lane: List<Lane> = listOf(Lane(location(0.0, 0.0), valid = false, indications = emptyList())),
var lane: List<Lane> = listOf(Lane(location(0.0, 0.0), valid = false, indications = emptyList(), 0, 0)),
var exitNumber: Int = 0,
var message: String = "",
)
@@ -116,7 +116,7 @@ object Constants {
val homeVogelhart = location(11.5793748, 48.185749)
val homeHohenwaldeck = location( 11.594322, 48.1164817)
const val NEXT_STEP_THRESHOLD = 1000.0
const val NEXT_STEP_THRESHOLD = 500.0
const val MAXIMAL_SNAP_CORRECTION = 50.0

View File

@@ -15,6 +15,7 @@ data class NavigationState (
val lastLocation: Location = location(0.0, 0.0),
val currentLocation: Location = location(0.0, 0.0),
val routeBearing: Float = 0F,
// index of current route in the list of routes
val currentRouteIndex: Int = 0,
val destination: Place = Place(),
val carConnection: Int = 0,

View File

@@ -48,7 +48,9 @@ class OsrmRoute {
val lane = Lane(
location(it2.location[0], it2.location[1]),
it3.valid,
it3.indications
it3.indications,
0,
0
)
lanes.add(lane)
}

View File

@@ -4,5 +4,5 @@ import java.util.Collections
data class Intersection(
val location: List<Double> = listOf(0.0, 0.0),
val lane : List<Lane> = Collections.emptyList<Lane>(),
val lane : List<Lane> = Collections.emptyList(),
)

View File

@@ -6,4 +6,6 @@ data class Lane (
val location: Location,
val valid: Boolean,
var indications: List<String>,
val startIndex: Int,
val endIndex: Int,
)

View File

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

View File

@@ -10,5 +10,6 @@ data class Maneuver(
val location: Location,
val exit: Int = 0,
val street: String = "",
val message: String = ""
val message: String = "",
val pointIndex : Int = 0,
)

View File

@@ -35,7 +35,6 @@ class TomTomRoute {
}
var stepDistance = 0.0
var stepDuration = 0.0
val allIntersections = mutableListOf<Intersection>()
val steps = mutableListOf<Step>()
var lastPointIndex = 0
for (index in 1..<route.guidance.instructions.size) {
@@ -56,46 +55,59 @@ class TomTomRoute {
instruction.point.longitude, instruction.point.latitude
),
street = maneuverStreet,
message = instruction.message
message = instruction.message,
pointIndex = instruction.pointIndex
)
lastPointIndex = instruction.pointIndex
val intersections = mutableListOf<Intersection>()
route.sections?.forEach { section ->
val lanes = mutableListOf<Lane>()
var startIndex = 0
section.lanes?.forEach { itLane ->
val lane = Lane(
location(
waypoints[section.startPointIndex][0],
waypoints[section.startPointIndex][1]
),
itLane.directions.first() == itLane.follow,
itLane.directions
)
startIndex = section.startPointIndex
lanes.add(lane)
}
intersections.add(Intersection(waypoints[startIndex], lanes))
if (section.sectionType == "LANES" && section.startPointIndex <= lastPointIndex && section.endPointIndex >= lastPointIndex) {
val lanes = mutableListOf<Lane>()
var startIndex = 0
var lastLane: Lane? = null
section.lanes?.forEach { itLane ->
val lane = Lane(
location = location(
waypoints[section.startPointIndex][0],
waypoints[section.startPointIndex][1]
),
valid = itLane.directions.first() == itLane.follow,
indications = itLane.directions,
startIndex = startIndex,
endIndex = section.endPointIndex
)
startIndex = section.startPointIndex
if (lastLane == null
|| (!(lastLane.valid && lane.valid
&& lastLane.indications == lane.indications))
) {
lanes.add(lane)
}
lastLane = lane
}
intersections.add(Intersection(waypoints[startIndex], lanes))
}
stepDistance =
route.guidance.instructions[index].routeOffsetInMeters - stepDistance
stepDuration =
route.guidance.instructions[index].travelTimeInSeconds - stepDuration
val step = Step(
index = stepIndex,
street = street,
distance = stepDistance,
duration = stepDuration,
maneuver = maneuver,
intersection = intersections
)
stepDistance = route.guidance.instructions[index].routeOffsetInMeters.toDouble()
stepDuration = route.guidance.instructions[index].travelTimeInSeconds.toDouble()
steps.add(step)
stepIndex += 1
}
allIntersections.addAll(intersections)
stepDistance = route.guidance.instructions[index].routeOffsetInMeters - stepDistance
stepDuration = route.guidance.instructions[index].travelTimeInSeconds - stepDuration
val step = Step(
index = stepIndex,
street = street,
distance = stepDistance,
duration = stepDuration,
maneuver = maneuver,
intersection = intersections
)
stepDistance = route.guidance.instructions[index].routeOffsetInMeters.toDouble()
stepDuration = route.guidance.instructions[index].travelTimeInSeconds.toDouble()
steps.add(step)
stepIndex += 1
}
legs.add(Leg(steps, allIntersections))
legs.add(Leg(steps))
val routeGeoJson = createLineStringCollection(waypoints)
val centerLocation = createCenterLocation(createLineStringCollection(waypoints))
val newRoute = com.kouros.navigation.data.route.Routes(
@@ -184,8 +196,7 @@ class TomTomRoute {
}
"TAKE_EXIT" -> {
newType = androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SHARP_RIGHT
newType = androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SLIGHT_RIGHT
}
}
return newType
@@ -195,8 +206,7 @@ class TomTomRoute {
private fun exitNumber(
instruction: Instruction
): Int {
return if (instruction.exitNumber == null
|| instruction.exitNumber.isEmpty()
return if (instruction.exitNumber.isNullOrEmpty()
) {
0
} else {

View File

@@ -65,12 +65,15 @@ class IconMapper() {
currentTurnIcon = R.drawable.ic_roundabout_ccw
}
Maneuver.TYPE_U_TURN_LEFT -> {
currentTurnIcon = R.drawable.ic_turn_u_turn_left
}
Maneuver.TYPE_U_TURN_RIGHT -> {
currentTurnIcon = R.drawable.ic_turn_u_turn_right
}
Maneuver.TYPE_MERGE_LEFT -> {
currentTurnIcon = R.drawable.ic_turn_merge_symmetrical
}
@@ -136,10 +139,12 @@ class IconMapper() {
"right_slight", "slight_right" -> {
when (stepData.currentManeuverType) {
Maneuver.TYPE_TURN_SLIGHT_RIGHT -> LaneDirection.SHAPE_NORMAL_RIGHT
Maneuver.TYPE_KEEP_RIGHT -> LaneDirection.SHAPE_SLIGHT_RIGHT
else
-> LaneDirection.SHAPE_UNKNOWN
}
}
else -> {
LaneDirection.SHAPE_UNKNOWN
}
@@ -151,8 +156,7 @@ class IconMapper() {
val bitmaps = mutableListOf<Bitmap>()
stepData.lane.forEach { lane ->
if (lane.indications.isNotEmpty()) {
Collections.sort<String>(lane.indications)
val resource = laneToResource(lane.indications, stepData)
val resource = laneToResource(lane.indications.sorted(), stepData)
if (resource.isNotEmpty()) {
val id = resourceId(resource)
val bitMap = BitmapFactory.decodeResource(context.resources, id)
@@ -222,11 +226,21 @@ class IconMapper() {
"right" -> if (stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_RIGHT) "${direction}_o" else "${direction}_x"
"left" -> if (stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_LEFT) "${direction}_o" else "${direction}_x"
"straight" -> if (stepData.currentManeuverType == Maneuver.TYPE_STRAIGHT) "${direction}_o" else "${direction}_x"
"straight" -> if (stepData.currentManeuverType == Maneuver.TYPE_STRAIGHT
|| stepData.currentManeuverType == Maneuver.TYPE_KEEP_LEFT
|| stepData.currentManeuverType == Maneuver.TYPE_KEEP_RIGHT
) "${direction}_o" else "${direction}_x"
"right_slight", "slight_right" -> if (stepData.currentManeuverType == Maneuver.TYPE_TURN_SLIGHT_RIGHT
|| stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_RIGHT) "slight_right_o" else "slight_right_x"
|| stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_RIGHT
|| stepData.currentManeuverType == Maneuver.TYPE_KEEP_RIGHT
) "slight_right_o" else "slight_right_x"
"left_slight", "slight_left" -> if (stepData.currentManeuverType == Maneuver.TYPE_TURN_SLIGHT_LEFT
|| stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_LEFT) "slight_left_o" else "slight_left_x"
|| stepData.currentManeuverType == Maneuver.TYPE_TURN_NORMAL_LEFT
|| stepData.currentManeuverType == Maneuver.TYPE_KEEP_LEFT
) "slight_left_o" else "slight_left_x"
else -> {
""
}

View File

@@ -550,14 +550,15 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
val rp = settingsRepository.recentPlacesFlow.first()
val places = mutableListOf<Place>()
if (rp.isNotEmpty()) {
val recentPlaces =
val rPlaces =
gson.fromJson(rp, Places::class.java).places.sortedBy { it.lastDate }
for (curPlace in recentPlaces) {
for (curPlace in rPlaces) {
if (curPlace.name != place.name || curPlace.category != place.category) {
places.add(curPlace)
}
}
settingsRepository.setRecentPlaces(gson.toJson(Places(places)))
recentPlaces.value = places
}
} catch (e: Exception) {
e.printStackTrace()

View File

@@ -31,7 +31,7 @@ class RouteCalculator(var routeModel: RouteModel) {
}
}
if (nearestDistance < NEAREST_LOCATION_DISTANCE) {
break;
break
}
}
}

View File

@@ -11,6 +11,7 @@ import com.kouros.navigation.data.StepData
import com.kouros.navigation.data.route.Lane
import com.kouros.navigation.data.route.Leg
import com.kouros.navigation.data.route.Routes
import com.kouros.navigation.data.route.Step
import com.kouros.navigation.utils.location
import kotlin.math.absoluteValue
@@ -29,6 +30,9 @@ open class RouteModel {
val curLeg: Leg
get() = navState.route.routes[navState.currentRouteIndex].legs.first()
val currentStep: Step
get() = navState.route.nextStep(0)
fun startNavigation(routeString: String) {
navState = navState.copy(
route = Route.Builder()
@@ -69,42 +73,11 @@ open class RouteModel {
navState = navState.copy(lastLocation = navState.currentLocation)
}
fun currentStep(): StepData {
val distanceToNextStep = routeCalculator.leftStepDistance()
// Determine the maneuver type and corresponding icon
val currentStep = navState.route.nextStep(0)
var streetName = currentStep.maneuver.street
var curManeuverType = currentStep.maneuver.type
if (navState.nextStep) {
if (distanceToNextStep > NEXT_STEP_THRESHOLD) {
streetName = currentStep.street
curManeuverType = Maneuver.TYPE_STRAIGHT
}
}
val exitNumber = currentStep.maneuver.exit
val maneuverIcon = navState.iconMapper.maneuverIcon(curManeuverType)
navState = navState.copy(maneuverType = curManeuverType)
// Construct and return the final StepData object
return StepData(
instruction = streetName,
street = currentStep.street,
leftStepDistance = distanceToNextStep,
currentManeuverType = navState.maneuverType,
icon = maneuverIcon,
arrivalTime = routeCalculator.arrivalTime(),
leftDistance = routeCalculator.travelLeftDistance(),
lane = currentLanes(),
exitNumber = exitNumber,
message = currentStep.maneuver.message
)
}
fun nextStep(): StepData {
val distanceToNextStep = routeCalculator.leftStepDistance()
val currentStep = navState.route.nextStep(0)
val nextStep = navState.route.nextStep(1)
var streetName = nextStep.street
var maneuverType = currentStep.maneuver.type
var maneuverType = currentStep.maneuver.type
if (distanceToNextStep < NEXT_STEP_THRESHOLD) {
streetName = nextStep.maneuver.street
maneuverType = nextStep.maneuver.type
@@ -128,16 +101,13 @@ open class RouteModel {
private fun currentLanes(): List<Lane> {
var lanes = emptyList<Lane>()
if (navState.route.legs().isNotEmpty()) {
navState.route.legs().first().intersection.forEach {
currentStep.intersection.forEach {
if (it.lane.isNotEmpty()) {
val distance =
navState.lastLocation.distanceTo(location(it.location[0], it.location[1]))
val sectionBearing =
navState.lastLocation.bearingTo(location(it.location[0], it.location[1]))
val bearingDeviation =
(navState.routeBearing.absoluteValue - sectionBearing.absoluteValue).absoluteValue
if (distance < NEXT_STEP_THRESHOLD && bearingDeviation < 10) {
if (distance < NEXT_STEP_THRESHOLD) {
lanes = it.lane
return@forEach
}
}
}
@@ -145,6 +115,36 @@ open class RouteModel {
return lanes
}
fun currentStep(): StepData {
val distanceToNextStep = routeCalculator.leftStepDistance()
// Determine the maneuver type and corresponding icon
var streetName = currentStep.maneuver.street
var curManeuverType = currentStep.maneuver.type
if (navState.nextStep) {
if (distanceToNextStep > NEXT_STEP_THRESHOLD) {
streetName = currentStep.street
curManeuverType = Maneuver.TYPE_STRAIGHT
}
}
val exitNumber = currentStep.maneuver.exit
val maneuverIcon = navState.iconMapper.maneuverIcon(curManeuverType)
navState = navState.copy(maneuverType = curManeuverType)
val currentLanes = currentLanes()
// Construct and return the final StepData object
return StepData(
instruction = streetName,
street = currentStep.street,
leftStepDistance = distanceToNextStep,
currentManeuverType = navState.maneuverType,
icon = maneuverIcon,
arrivalTime = routeCalculator.arrivalTime(),
leftDistance = routeCalculator.travelLeftDistance(),
lane = currentLanes,
exitNumber = exitNumber,
message = currentStep.maneuver.message
)
}
fun isNavigating(): Boolean {
return navState.navigating
}

View File

@@ -0,0 +1,26 @@
<!--
Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,18l0,-3l-2,0l0,3l-3,0l0,2l3,0l0,3l2,0l0,-3l3,0l0,-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M18,4h2v9h-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M4,4h2v16h-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M11,4h2v4h-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M11,10h2v4h-2z"/>
<path android:fillColor="@android:color/white" android:pathData="M11,16h2v4h-2z"/>
</vector>

View File

@@ -0,0 +1,21 @@
<!--
Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,21c-1.39,0 -2.78,-0.47 -4,-1.32c-2.44,1.71 -5.56,1.71 -8,0C6.78,20.53 5.39,21 4,21H2v2h2c1.38,0 2.74,-0.35 4,-0.99c2.52,1.29 5.48,1.29 8,0c1.26,0.65 2.62,0.99 4,0.99h2v-2H20zM3.95,19H4c1.6,0 3.02,-0.88 4,-2c0.98,1.12 2.4,2 4,2s3.02,-0.88 4,-2c0.98,1.12 2.4,2 4,2h0.05l1.9,-6.68c0.11,-0.37 0.04,-1.06 -0.66,-1.28L20,10.62V6c0,-1.1 -0.9,-2 -2,-2h-3V1H9v3H6C4.9,4 4,4.9 4,6v4.62l-1.29,0.42c-0.63,0.19 -0.81,0.84 -0.66,1.28L3.95,19zM6,6h12v3.97L12,8L6,9.97V6z"/>
</vector>

View File

@@ -0,0 +1,22 @@
<!--
Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15,4c-4.42,0 -8,3.58 -8,8s3.58,8 8,8 8,-3.58 8,-8 -3.58,-8 -8,-8zM15,18c-3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6 6,2.69 6,6 -2.69,6 -6,6z"/>
<path android:fillColor="@android:color/white" android:pathData="M3,12c0,-2.61 1.67,-4.83 4,-5.65V4.26C3.55,5.15 1,8.27 1,12s2.55,6.85 6,7.74v-2.09c-2.33,-0.82 -4,-3.04 -4,-5.65z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

File diff suppressed because it is too large Load Diff