Osrm
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ 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)
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -108,7 +107,6 @@ class NavigationScreen(
|
|||||||
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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>(),
|
||||||
|
)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.kouros.navigation.data.route
|
||||||
|
|
||||||
|
data class Lane (
|
||||||
|
val valid: Boolean,
|
||||||
|
var indications: List<String>,
|
||||||
|
)
|
||||||
@@ -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(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
BIN
common/data/src/main/res/drawable/lanes.png
Normal file
BIN
common/data/src/main/res/drawable/lanes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user