Amenities

This commit is contained in:
Dimitris
2025-12-17 09:31:12 +01:00
parent d546ede0e5
commit ed24e71473
21 changed files with 284 additions and 246 deletions

View File

@@ -14,8 +14,8 @@ android {
applicationId = "com.kouros.navigation" applicationId = "com.kouros.navigation"
minSdk = 33 minSdk = 33
targetSdk = 36 targetSdk = 36
versionCode = 9 versionCode = 10
versionName = "0.1.3.9" versionName = "0.1.3.10"
base.archivesName = "navi-$versionName" base.archivesName = "navi-$versionName"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -72,23 +72,17 @@ import kotlin.time.Duration.Companion.seconds
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
val routeData = MutableLiveData("") val routeData = MutableLiveData("")
val viewModel = ViewModel(NavigationRepository()) val viewModel = ViewModel(NavigationRepository())
val routeModel = RouteModel() val routeModel = RouteModel()
var tilt = 50.0 var tilt = 50.0
val useMock = true val useMock = true
val stepData: MutableLiveData<StepData> by lazy { val stepData: MutableLiveData<StepData> by lazy {
MutableLiveData<StepData>() MutableLiveData<StepData>()
} }
val nextStepData: MutableLiveData<StepData> by lazy { val nextStepData: MutableLiveData<StepData> by lazy {
MutableLiveData<StepData>() MutableLiveData<StepData>()
} }
var lastLocation = location(0.0, 0.0) var lastLocation = location(0.0, 0.0)
val observer = Observer<String> { newRoute -> val observer = Observer<String> { newRoute ->
if (newRoute.isNotEmpty()) { if (newRoute.isNotEmpty()) {
routeModel.startNavigation(newRoute) routeModel.startNavigation(newRoute)
@@ -188,7 +182,7 @@ class MainActivity : ComponentActivity() {
sheetPeekHeightState.value = 128.dp sheetPeekHeightState.value = 128.dp
} }
} }
NavigationTheme() { NavigationTheme {
BottomSheetScaffold( BottomSheetScaffold(
snackbarHost = { snackbarHost = {
SnackbarHost(hostState = snackbarHostState) SnackbarHost(hostState = snackbarHostState)

View File

@@ -14,6 +14,7 @@ import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
@@ -28,16 +29,34 @@ import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.window.layout.WindowMetricsCalculator import androidx.window.layout.WindowMetricsCalculator
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.car.map.BuildingLayer
import com.kouros.navigation.car.map.DarkMode import com.kouros.navigation.car.map.DarkMode
import com.kouros.navigation.car.map.MapLibre import com.kouros.navigation.car.map.MapLibre
import com.kouros.navigation.car.map.NavigationImage import com.kouros.navigation.car.map.NavigationImage
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.data.RouteColor
import com.kouros.navigation.data.StepData import com.kouros.navigation.data.StepData
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
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
import org.maplibre.compose.expressions.dsl.const
import org.maplibre.compose.expressions.dsl.exponential
import org.maplibre.compose.expressions.dsl.interpolate
import org.maplibre.compose.expressions.dsl.zoom
import org.maplibre.compose.layers.CircleLayer
import org.maplibre.compose.layers.LineLayer
import org.maplibre.compose.location.LocationTrackingEffect import org.maplibre.compose.location.LocationTrackingEffect
import org.maplibre.compose.location.UserLocationState import org.maplibre.compose.location.UserLocationState
import org.maplibre.compose.map.MapOptions
import org.maplibre.compose.map.MaplibreMap
import org.maplibre.compose.map.OrnamentOptions
import org.maplibre.compose.sources.GeoJsonData
import org.maplibre.compose.sources.GeoJsonSource
import org.maplibre.compose.sources.getBaseSource
import org.maplibre.compose.sources.rememberGeoJsonSource
import org.maplibre.compose.style.BaseStyle import org.maplibre.compose.style.BaseStyle
import org.maplibre.spatialk.geojson.Position import org.maplibre.spatialk.geojson.Position
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -77,8 +96,8 @@ fun MapView(
Column { Column {
NavigationInfo(step) NavigationInfo(step)
Box(contentAlignment = Alignment.Center) { Box(contentAlignment = Alignment.Center) {
MapLibre(applicationContext, cameraState, baseStyle, route, "", position) MapLibre(applicationContext, cameraState, baseStyle, route, ViewStyle.VIEW)
LocationTrackingEffect( LocationTrackingEffect(
locationState = userLocationState, locationState = userLocationState,
) { ) {
cameraState.animateTo( cameraState.animateTo(
@@ -97,3 +116,5 @@ fun MapView(
} }
} }

View File

@@ -75,7 +75,6 @@ fun SearchSheet(
} }
} }
if (recentPlaces.value != null) { if (recentPlaces.value != null) {
println("Recent Places ${recentPlaces.value}")
val textFieldState = rememberTextFieldState() val textFieldState = rememberTextFieldState()
val items = listOf(recentPlaces) val items = listOf(recentPlaces)
if (items.isNotEmpty()) { if (items.isNotEmpty()) {
@@ -108,7 +107,7 @@ fun Home(
closeSheet() closeSheet()
}) { }) {
Icon( Icon(
painter = painterResource(id = com.google.android.gms.base.R.drawable.common_full_open_on_phone), painter = painterResource(id = R.drawable.ic_place_white_24dp),
"Home", "Home",
modifier = Modifier.size(24.dp, 24.dp), modifier = Modifier.size(24.dp, 24.dp),
) )
@@ -222,7 +221,6 @@ private fun SearchPlaces(
street = place.address.road street = place.address.road
) )
viewModel.saveRecent(pl) viewModel.saveRecent(pl)
println("Save $pl")
val toLocation = val toLocation =
location(place.lon.toDouble(), place.lat.toDouble()) location(place.lon.toDouble(), place.lat.toDouble())
viewModel.loadRoute(context, location, toLocation) viewModel.loadRoute(context, location, toLocation)

View File

@@ -21,7 +21,6 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
@@ -63,7 +62,6 @@ class SurfaceRenderer(
private var visibleArea = MutableLiveData( private var visibleArea = MutableLiveData(
Rect(0, 0, 0, 0) Rect(0, 0, 0, 0)
) )
var stableArea = Rect() var stableArea = Rect()
var width = 0 var width = 0
var height = 0 var height = 0
@@ -71,11 +69,9 @@ class SurfaceRenderer(
val routeData = MutableLiveData("") val routeData = MutableLiveData("")
val speed = MutableLiveData(0F) val speed = MutableLiveData(0F)
lateinit var centerLocation: Location lateinit var centerLocation: Location
var preview = false var viewStyle = ViewStyle.VIEW
var previewDistance = 0.0 var previewDistance = 0.0
val previewRouteData = MutableLiveData("")
lateinit var mapView: ComposeView lateinit var mapView: ComposeView
var panView = false
var tilt = 55.0 var tilt = 55.0
var countDownTimerActive = false var countDownTimerActive = false
val mSurfaceCallback: SurfaceCallback = object : SurfaceCallback { val mSurfaceCallback: SurfaceCallback = object : SurfaceCallback {
@@ -171,18 +167,16 @@ class SurfaceRenderer(
@Composable @Composable
fun MapView() { fun MapView() {
val stateWidth = visibleArea.observeAsState()
val position: CameraPosition? by cameraPosition.observeAsState() val position: CameraPosition? by cameraPosition.observeAsState()
val route: String? by routeData.observeAsState() val route: String? by routeData.observeAsState()
val previewRoute: String? by previewRouteData.observeAsState() val paddingValues = getPaddingValues(height, viewStyle)
val paddingValues = getPaddingValues(width - stateWidth.value!!.width(), height, preview)
val cameraState = cameraState(paddingValues, position, tilt) val cameraState = cameraState(paddingValues, position, tilt)
val baseStyle = remember { val baseStyle = remember {
mutableStateOf(BaseStyle.Uri(Constants.STYLE)) mutableStateOf(BaseStyle.Uri(Constants.STYLE))
} }
DarkMode(carContext, baseStyle) DarkMode(carContext, baseStyle)
MapLibre(carContext, cameraState, baseStyle, route, previewRoute, position) MapLibre(carContext, cameraState, baseStyle, route, viewStyle)
ShowPosition(cameraState, position, paddingValues) ShowPosition(cameraState, position, paddingValues)
} }
@@ -192,25 +186,32 @@ class SurfaceRenderer(
position: CameraPosition?, position: CameraPosition?,
paddingValues: PaddingValues paddingValues: PaddingValues
) { ) {
val cameraDuration = duration(preview, position!!.bearing, lastBearing) val cameraDuration =
duration(viewStyle == ViewStyle.PREVIEW, position!!.bearing, lastBearing)
var bearing = position.bearing var bearing = position.bearing
var zoom = position.zoom var zoom = position.zoom
var target = position.target var target = position.target
var localTilt = tilt var localTilt = tilt
val currentSpeed: Float? by speed.observeAsState() val currentSpeed: Float? by speed.observeAsState()
if (!preview) { when (viewStyle) {
if (routeModel.isNavigating()) { ViewStyle.VIEW -> {
DrawImage(paddingValues, currentSpeed, width, height)
} else {
DrawImage(paddingValues, currentSpeed, width, height) DrawImage(paddingValues, currentSpeed, width, height)
} }
} else {
bearing = 0.0 ViewStyle.PREVIEW -> {
zoom = previewZoom(previewDistance) bearing = 0.0
target = Position(centerLocation.longitude, centerLocation.latitude) zoom = previewZoom(previewDistance)
localTilt = 0.0 target = Position(centerLocation.longitude, centerLocation.latitude)
localTilt = 0.0
}
else -> {
bearing = 0.0
localTilt = 0.0
zoom = 12.0
}
} }
LaunchedEffect(position) { LaunchedEffect(position, viewStyle) {
cameraState.animateTo( cameraState.animateTo(
finalPosition = CameraPosition( finalPosition = CameraPosition(
bearing = bearing, bearing = bearing,
@@ -234,7 +235,7 @@ class SurfaceRenderer(
/** Handles the map zoom-in and zoom-out events. */ /** Handles the map zoom-in and zoom-out events. */
fun handleScale(zoomSign: Int) { fun handleScale(zoomSign: Int) {
synchronized(this) { synchronized(this) {
panView = true viewStyle = ViewStyle.PAN_VIEW
val newZoom = if (zoomSign < 0) { val newZoom = if (zoomSign < 0) {
cameraPosition.value!!.zoom - 1.0 cameraPosition.value!!.zoom - 1.0
} else { } else {
@@ -259,9 +260,9 @@ class SurfaceRenderer(
fun updateLocation(location: Location) { fun updateLocation(location: Location) {
synchronized(this) { synchronized(this) {
if (!preview) { if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
val bearing = bearing(lastLocation, location, cameraPosition.value!!.bearing) val bearing = bearing(lastLocation, location, cameraPosition.value!!.bearing)
val zoom = if (!panView) { val zoom = if (viewStyle == ViewStyle.VIEW) {
calculateZoom(location.speed.toDouble()) calculateZoom(location.speed.toDouble())
} else { } else {
cameraPosition.value!!.zoom cameraPosition.value!!.zoom
@@ -280,12 +281,6 @@ class SurfaceRenderer(
val lastLocationTimer = lastLocation val lastLocationTimer = lastLocation
checkUpdate(mainThreadHandler, lastLocationTimer) checkUpdate(mainThreadHandler, lastLocationTimer)
} }
} else {
updateCameraPosition(
0.0,
previewZoom(previewDistance),
Position(centerLocation.longitude, centerLocation.latitude)
)
} }
} }
} }
@@ -295,7 +290,7 @@ class SurfaceRenderer(
lastLocationTimer: Location lastLocationTimer: Location
) { ) {
mainThreadHandler.post { mainThreadHandler.post {
object : CountDownTimer(5000, 1000) { object : CountDownTimer(3000, 1000) {
override fun onTick(millisUntilFinished: Long) {} override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() { override fun onFinish() {
countDownTimerActive = false countDownTimerActive = false
@@ -313,7 +308,7 @@ class SurfaceRenderer(
bearing = bearing, bearing = bearing,
zoom = zoom, zoom = zoom,
tilt = tilt, tilt = tilt,
padding = getPaddingValues(width - visibleArea.value!!.width(), height, preview), padding = getPaddingValues(height, viewStyle),
target = target target = target
) )
) )
@@ -321,28 +316,41 @@ class SurfaceRenderer(
fun setRouteData() { fun setRouteData() {
routeData.value = routeModel.route.routeGeoJson routeData.value = routeModel.route.routeGeoJson
previewRouteData.value = "" viewStyle = ViewStyle.VIEW
preview = false
panView = false
} }
fun setPreviewRouteData(routeModel: RouteModel) { fun setPreviewRouteData(routeModel: RouteModel) {
previewRouteData.value = routeModel.route.routeGeoJson viewStyle = ViewStyle.PREVIEW
centerLocation = routeModel.route.centerLocation with(routeModel) {
preview = true routeData.value = route.routeGeoJson
previewDistance = routeModel.route.distance centerLocation = route.centerLocation
previewDistance = route.distance
}
updateCameraPosition(
0.0,
previewZoom(previewDistance),
Position(centerLocation.longitude, centerLocation.latitude)
)
} }
fun setLocation(location: Location) { fun setCategories(location: Location, route: String) {
viewStyle = ViewStyle.SEARCH_VIEW
routeData.value = route
updateCameraPosition(
0.0,
12.0,
target = Position(location.longitude, location.latitude)
)
}
fun setCategoryLocation(location: Location) {
viewStyle = ViewStyle.SEARCH_VIEW
cameraPosition.postValue( cameraPosition.postValue(
cameraPosition.value!!.copy( cameraPosition.value!!.copy(
bearing = 0.0,
zoom = 15.0,
tilt = 0.0,
padding = PaddingValues(start = 350.dp, bottom = 0.dp),
target = Position(location.longitude, location.latitude) target = Position(location.longitude, location.latitude)
) )
) )
} }
companion companion
@@ -352,3 +360,7 @@ class SurfaceRenderer(
} }
enum class ViewStyle {
VIEW, PREVIEW, PAN_VIEW, SEARCH_VIEW
}

View File

@@ -9,10 +9,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -28,6 +25,7 @@ import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.data.NavigationColor import com.kouros.navigation.data.NavigationColor
@@ -39,9 +37,15 @@ 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
import org.maplibre.compose.expressions.dsl.const import org.maplibre.compose.expressions.dsl.const
import org.maplibre.compose.expressions.dsl.exponential
import org.maplibre.compose.expressions.dsl.image
import org.maplibre.compose.expressions.dsl.interpolate
import org.maplibre.compose.expressions.dsl.zoom
import org.maplibre.compose.layers.Anchor import org.maplibre.compose.layers.Anchor
import org.maplibre.compose.layers.CircleLayer
import org.maplibre.compose.layers.FillLayer import org.maplibre.compose.layers.FillLayer
import org.maplibre.compose.layers.LineLayer import org.maplibre.compose.layers.LineLayer
import org.maplibre.compose.layers.SymbolLayer
import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationPuck
import org.maplibre.compose.location.LocationPuckColors import org.maplibre.compose.location.LocationPuckColors
import org.maplibre.compose.location.LocationPuckSizes import org.maplibre.compose.location.LocationPuckSizes
@@ -54,12 +58,14 @@ import org.maplibre.compose.sources.Source
import org.maplibre.compose.sources.getBaseSource import org.maplibre.compose.sources.getBaseSource
import org.maplibre.compose.sources.rememberGeoJsonSource import org.maplibre.compose.sources.rememberGeoJsonSource
import org.maplibre.compose.style.BaseStyle import org.maplibre.compose.style.BaseStyle
import org.maplibre.spatialk.geojson.Feature
import org.maplibre.spatialk.geojson.FeatureCollection
import org.maplibre.spatialk.geojson.Position import org.maplibre.spatialk.geojson.Position
@Composable @Composable
fun cameraState( fun cameraState(
padding : PaddingValues, padding: PaddingValues,
position: CameraPosition?, position: CameraPosition?,
tilt: Double, tilt: Double,
): CameraState { ): CameraState {
@@ -83,8 +89,7 @@ fun MapLibre(
cameraState: CameraState, cameraState: CameraState,
baseStyle: MutableState<BaseStyle.Uri>, baseStyle: MutableState<BaseStyle.Uri>,
route: String?, route: String?,
previewRoute: String?, viewStyle: ViewStyle
position: CameraPosition?
) { ) {
MaplibreMap( MaplibreMap(
options = MapOptions( options = MapOptions(
@@ -98,45 +103,58 @@ fun MapLibre(
if (!getBooleanKeyValue(context = context, SHOW_THREED_BUILDING)) { if (!getBooleanKeyValue(context = context, SHOW_THREED_BUILDING)) {
BuildingLayer(tiles) BuildingLayer(tiles)
} }
RouteLayer(route, previewRoute, position!!.zoom) RouteLayer(route, viewStyle)
} }
//Puck(cameraState, lastLocation) //Puck(cameraState, lastLocation)
} }
} }
@Composable @Composable
fun RouteLayer(routeData: String?, previewRoute: String?, zoom: Double) { fun RouteLayer(routeData: String?, viewStyle: ViewStyle) {
val width = zoom - 2 if (routeData != null && routeData.isNotEmpty()) {
if (routeData!!.isNotEmpty()) { println(routeData)
val routes = val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
rememberGeoJsonSource(GeoJsonData.JsonString(routeData)) if (viewStyle == ViewStyle.VIEW) {
LineLayer( LineLayer(
id = "routes-casing", id = "routes-casing$viewStyle",
source = routes, source = routes,
color = const(Color.White), color = const(Color.White),
width = const((width+2).dp), width =
) interpolate(
LineLayer( type = exponential(1.2f),
id = "routes", input = zoom(),
source = routes, 5 to const(0.4.dp),
color = const(RouteColor), 6 to const(0.8.dp),
width = const(width.dp), 7 to const(2.0.dp),
) 20 to const(24.dp),
} ),
if (previewRoute!!.isNotEmpty()) { )
val routes = LineLayer(
rememberGeoJsonSource(GeoJsonData.JsonString(previewRoute)) id = "routes$viewStyle",
LineLayer( source = routes,
id = "routes-casing-pre", color = const(RouteColor),
source = routes, width =
color = const(Color.White), interpolate(
width = const(6.dp), type = exponential(1.2f),
) input = zoom(),
LineLayer( 5 to const(0.4.dp),
id = "routes-pre", 6 to const(0.7.dp),
source = routes, 7 to const(1.75.dp),
color = const(RouteColor), 20 to const(22.dp),
width = const(4.dp), ),
) )
} else {
SymbolLayer(
id = "my-symbol-layer",
source = routes,
// Convert a drawable resource to a MapLibre image
// drawAsSdf = true allows us to tint the image programmatically
iconImage = image(painterResource(R.drawable.ic_place_white_24dp), drawAsSdf = true),
// Now we can apply any color we want!
iconColor = const(Color.Blue),
iconSize = const(1.5f)
)
}
} }
} }
@@ -154,17 +172,19 @@ fun BuildingLayer(tiles: Source) {
@Composable @Composable
fun DrawImage(padding: PaddingValues, speed: Float?, width: Int, height: Int) { fun DrawImage(padding: PaddingValues, speed: Float?, width: Int, height: Int) {
NavigationImage(padding, width,height) NavigationImage(padding, width, height)
Speed(width, height, speed) Speed(width, height, speed)
} }
@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 / 6)
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(modifier =Modifier Canvas(
.size(imageSize.dp, imageSize.dp)) { modifier = Modifier
.size(imageSize.dp, imageSize.dp)
) {
scale(scaleX = 1f, scaleY = 0.7f) { scale(scaleX = 1f, scaleY = 0.7f) {
drawCircle(Color.DarkGray.copy(alpha = 0.2f)) drawCircle(Color.DarkGray.copy(alpha = 0.2f))
} }
@@ -188,8 +208,8 @@ private fun Speed(
Box( Box(
modifier = Modifier modifier = Modifier
.padding( .padding(
start = width.dp- 250.dp, start = width.dp - 250.dp,
top = height.dp- 80.dp top = height.dp - 80.dp
), ),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
@@ -259,11 +279,11 @@ fun DarkMode(context: Context, baseStyle: MutableState<BaseStyle.Uri>) {
} }
} }
fun getPaddingValues(width: Int, height: Int, preView: Boolean): PaddingValues { fun getPaddingValues(height: Int, viewStyle: ViewStyle): PaddingValues {
return if (preView) { return when (viewStyle) {
PaddingValues(start = 150.dp, bottom = 0.dp) ViewStyle.VIEW -> PaddingValues(start = 50.dp, top = distanceFromTop(height).dp)
} else { ViewStyle.PREVIEW -> PaddingValues(start = 150.dp, bottom = 0.dp)
PaddingValues(start = 50.dp, top = distanceFromTop(height).dp) else -> PaddingValues(start = 450.dp, bottom = 0.dp)
} }
} }

View File

@@ -4,13 +4,16 @@ import android.location.Location
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.Screen import androidx.car.app.Screen
import androidx.car.app.model.Action import androidx.car.app.model.Action
import androidx.car.app.model.CarIcon
import androidx.car.app.model.Header import androidx.car.app.model.Header
import androidx.car.app.model.ItemList import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row import androidx.car.app.model.Row
import androidx.car.app.model.Template import androidx.car.app.model.Template
import androidx.core.graphics.drawable.IconCompat
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.data.Category import com.kouros.navigation.data.Category
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
@@ -21,7 +24,7 @@ class CategoriesScreen(
) : Screen(carContext) { ) : Screen(carContext) {
var categories: List<Category> = listOf( var categories: List<Category> = listOf(
Category(id = Constants.GAS_STATION, name = carContext.getString(R.string.gas_station)), Category(id = Constants.FUEL_STATION, name = carContext.getString(R.string.fuel_station)),
Category(id = Constants.PHARMACY, name = carContext.getString(R.string.pharmacy)), Category(id = Constants.PHARMACY, name = carContext.getString(R.string.pharmacy)),
Category(id = Constants.CHARGING_STATION, name = carContext.getString(R.string.charging_station)) Category(id = Constants.CHARGING_STATION, name = carContext.getString(R.string.charging_station))
) )
@@ -29,12 +32,17 @@ class CategoriesScreen(
override fun onGetTemplate(): Template { override fun onGetTemplate(): Template {
val itemListBuilder = ItemList.Builder() val itemListBuilder = ItemList.Builder()
.setNoItemsMessage("No categories to show") .setNoItemsMessage("No categories to show")
categories.forEach { categories.forEach {
it.name
itemListBuilder.addItem( itemListBuilder.addItem(
Row.Builder() Row.Builder()
.setTitle(it.name) .setTitle(it.name)
.setImage(CarIcon.Builder(
IconCompat.createWithResource(
carContext,
com.kouros.android.cars.carappservice.R.drawable.ev_station_24px
)
)
.build())
.setOnClickListener { .setOnClickListener {
screenManager screenManager
.pushForResult( .pushForResult(
@@ -56,6 +64,8 @@ class CategoriesScreen(
) )
} }
surfaceRenderer.viewStyle = ViewStyle.SEARCH_VIEW
val header = Header.Builder() val header = Header.Builder()
.setStartHeaderAction(Action.BACK) .setStartHeaderAction(Action.BACK)
.setTitle("title") .setTitle("title")

View File

@@ -1,6 +1,7 @@
package com.kouros.navigation.car.screen package com.kouros.navigation.car.screen
import android.location.Location import android.location.Location
import androidx.annotation.DrawableRes
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.CarToast import androidx.car.app.CarToast
import androidx.car.app.Screen import androidx.car.app.Screen
@@ -14,15 +15,19 @@ import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row import androidx.car.app.model.Row
import androidx.car.app.model.Template import androidx.car.app.model.Template
import androidx.car.app.navigation.model.MapController
import androidx.car.app.navigation.model.MapWithContentTemplate import androidx.car.app.navigation.model.MapWithContentTemplate
import androidx.car.app.versioning.CarAppApiLevels import androidx.car.app.versioning.CarAppApiLevels
import androidx.core.graphics.drawable.IconCompat import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.navigation.NavigationMessage
import com.kouros.navigation.data.Constants.homeLocation
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
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.NavigationUtils.createGeoJson
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
import kotlin.math.min import kotlin.math.min
@@ -38,82 +43,70 @@ class CategoryScreen(
val observer = Observer<List<Elements>> { newElements -> val observer = Observer<List<Elements>> { newElements ->
elements = newElements elements = newElements
invalidate() val coordinates = mutableListOf<List<Double>>()
val loc = location(0.0, 0.0)
elements.forEach {
if (loc.latitude == 0.0) {
loc.longitude = it.lon!!
loc.latitude = it.lat!!
}
if (coordinates.isEmpty())
coordinates.add(listOf(location.longitude, location.latitude))
}
if (elements.isNotEmpty()) {
val route = createGeoJson("Point", coordinates)
surfaceRenderer.setCategories(loc, route)
invalidate()
}
} }
init { init {
viewModel.elements.observe(this, observer) viewModel.elements.observe(this, observer)
viewModel.getAmenities(category, location) viewModel.getAmenities(category, location)
invalidate()
} }
override fun onGetTemplate(): Template { override fun onGetTemplate(): Template {
val listBuilder = ItemList.Builder() val listBuilder = ItemList.Builder()
if (carContext.getCarAppApiLevel() > CarAppApiLevels.LEVEL_1) { if (carContext.getCarAppApiLevel() > CarAppApiLevels.LEVEL_1) {
var index = 0
val listLimit = min( val listLimit = min(
10, 100,
carContext.getCarService(ConstraintManager::class.java) carContext.getCarService(ConstraintManager::class.java)
.getContentLimit( .getContentLimit(
ConstraintManager.CONTENT_LIMIT_TYPE_LIST ConstraintManager.CONTENT_LIMIT_TYPE_LIST
) )
) )
elements.forEach { elements.forEach {
//listBuilder.addItem(createRow(it.tags!!.operator.toString(), it.tags?.capacity.toString())) if (index++ < listLimit) {
listBuilder.addItem( listBuilder.addItem(
Row.Builder() Row.Builder()
.setOnClickListener({ .setOnClickListener {
val location = location(it.lon!!, it.lat!!) val location = location(it.lon!!, it.lat!!)
surfaceRenderer.setLocation(location) surfaceRenderer.setCategoryLocation(location)
}) }
.setTitle(secondText(it.tags?.capacity.toString())) .setTitle(it.tags.operator.toString())
.setImage( .setImage(
CarIcon.Builder( CarIcon.Builder(
IconCompat.createWithResource( IconCompat.createWithResource(
carContext, carContext,
com.kouros.android.cars.carappservice.R.drawable.ev_station_24px com.kouros.android.cars.carappservice.R.drawable.ev_station_24px
)
) )
.build()
) )
.build() .addText(it.tags.network.toString())
) .build()
.addText(it.tags!!.operator.toString()) )
.addText(secondText(it.tags?.capacity.toString())) }
.build()
)
} }
} }
val header = Header.Builder() val header = Header.Builder()
.setStartHeaderAction(Action.BACK) .setStartHeaderAction(Action.BACK)
.setTitle(carContext.getString(R.string.charging_station)) .setTitle(carContext.getString(R.string.charging_station))
.build() .build()
val actionStrip = ActionStrip.Builder()
.addAction(
Action.Builder()
.setOnClickListener {
CarToast.makeText(
carContext,
carContext.getString(
R.string.notification_demo
),
CarToast.LENGTH_SHORT
)
.show()
}
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.ic_place_white_24dp
)
).build()
)
.setFlags(Action.FLAG_IS_PERSISTENT)
.build()
)
.build()
val builder = MapWithContentTemplate.Builder() val builder = MapWithContentTemplate.Builder()
.setContentTemplate( .setContentTemplate(
ListTemplate.Builder() ListTemplate.Builder()
@@ -121,7 +114,11 @@ class CategoryScreen(
.setSingleList(listBuilder.build()) .setSingleList(listBuilder.build())
.build() .build()
) )
.setActionStrip(actionStrip) .setMapController(
MapController.Builder().setMapActionStrip(
getMapActionStrip()
).build()
)
return builder.build() return builder.build()
} }
@@ -140,4 +137,27 @@ class CategoryScreen(
return secondText return secondText
} }
fun getMapActionStrip(): ActionStrip {
return ActionStrip.Builder()
.addAction(
createAction(R.drawable.ic_zoom_in_24, 1)
)
.addAction(
createAction(R.drawable.ic_zoom_out_24, -1)
)
.addAction(Action.PAN)
.build()
}
private fun createAction(
@DrawableRes iconRes: Int,
scale: Int
): Action {
val navigationMessage = NavigationMessage(carContext)
return Action.Builder()
.setOnClickListener { surfaceRenderer.handleScale(scale) }
.setIcon(navigationMessage.createCarIcon(iconRes))
.build()
}
} }

View File

@@ -28,6 +28,7 @@ import androidx.lifecycle.Observer
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.car.NavigationCarAppService import com.kouros.navigation.car.NavigationCarAppService
import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.SurfaceRenderer
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.DESTINATION_ARRIVAL_DISTANCE import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
@@ -237,7 +238,7 @@ class NavigationScreen(
val actionStripBuilder = ActionStrip.Builder() val actionStripBuilder = ActionStrip.Builder()
.addAction(zoomPlus()) .addAction(zoomPlus())
.addAction(zoomMinus()) .addAction(zoomMinus())
if (surfaceRenderer.panView) { if (surfaceRenderer.viewStyle == ViewStyle.PAN_VIEW) {
actionStripBuilder actionStripBuilder
.addAction( .addAction(
panAction() panAction()
@@ -362,7 +363,7 @@ class NavigationScreen(
) )
.build() .build()
).setOnClickListener { ).setOnClickListener {
surfaceRenderer.panView = false surfaceRenderer.viewStyle = ViewStyle.VIEW
} }
.build() .build()
} }
@@ -410,7 +411,7 @@ class NavigationScreen(
fun stopNavigation() { fun stopNavigation() {
listener.stopNavigation() listener.stopNavigation()
surfaceRenderer.routeData.postValue("") surfaceRenderer.routeData.value = ""
invalidate() invalidate()
} }

View File

@@ -105,19 +105,21 @@ class PlaceListScreen(
it.street, it.street,
avatar = null avatar = null
) )
screenManager setResult(place)
.pushForResult( finish()
RoutePreviewScreen( // screenManager
carContext, // .pushForResult(
surfaceRenderer, // RoutePreviewScreen(
place // carContext,
) // surfaceRenderer,
) { obj: Any? -> // place
if (obj != null) { // )
setResult(obj) // ) { obj: Any? ->
finish() // if (obj != null) {
} // setResult(obj)
} // finish()
// }
// }
} }
.build() .build()
) )

View File

@@ -15,16 +15,12 @@
*/ */
package com.kouros.navigation.car.screen package com.kouros.navigation.car.screen
import android.graphics.drawable.Icon
import android.location.Location
import android.location.LocationManager
import android.os.CountDownTimer import android.os.CountDownTimer
import android.text.SpannableString import android.text.SpannableString
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.CarToast import androidx.car.app.CarToast
import androidx.car.app.Screen import androidx.car.app.Screen
import androidx.car.app.constraints.ConstraintManager
import androidx.car.app.model.Action import androidx.car.app.model.Action
import androidx.car.app.model.Action.FLAG_PRIMARY import androidx.car.app.model.Action.FLAG_PRIMARY
import androidx.car.app.model.ActionStrip import androidx.car.app.model.ActionStrip
@@ -47,6 +43,7 @@ import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.model.ViewModel import com.kouros.navigation.model.ViewModel
import com.kouros.navigation.utils.location
import java.math.BigDecimal import java.math.BigDecimal
import java.math.RoundingMode import java.math.RoundingMode
@@ -57,9 +54,7 @@ class RoutePreviewScreen(
private var destination: Place private var destination: Place
) : ) :
Screen(carContext) { Screen(carContext) {
private var mIsFavorite = false private var isFavorite = false
private var mItemLimit = 0
val vieModel = ViewModel(NavigationRepository()) val vieModel = ViewModel(NavigationRepository())
@@ -76,19 +71,11 @@ class RoutePreviewScreen(
init { init {
vieModel.previewRoute.observe(this, observer) vieModel.previewRoute.observe(this, observer)
val location = Location(LocationManager.GPS_PROVIDER) val location = location(destination.longitude, destination.latitude)
location.latitude = destination.latitude
location.longitude = destination.longitude
vieModel.loadPreviewRoute(carContext, surfaceRenderer.lastLocation, location) vieModel.loadPreviewRoute(carContext, surfaceRenderer.lastLocation, location)
} }
override fun onGetTemplate(): Template { override fun onGetTemplate(): Template {
mItemLimit =
carContext.getCarService(ConstraintManager::class.java)
.getContentLimit(
ConstraintManager.CONTENT_LIMIT_TYPE_ROUTE_LIST
)
val navigateActionIcon: CarIcon = CarIcon.Builder( val navigateActionIcon: CarIcon = CarIcon.Builder(
IconCompat.createWithResource( IconCompat.createWithResource(
carContext, R.drawable.baseline_assistant_navigation_24 carContext, R.drawable.baseline_assistant_navigation_24
@@ -145,7 +132,7 @@ class RoutePreviewScreen(
CarIcon.Builder( CarIcon.Builder(
IconCompat.createWithResource( IconCompat.createWithResource(
carContext, carContext,
if (mIsFavorite) if (isFavorite)
R.drawable.ic_favorite_filled_white_24dp R.drawable.ic_favorite_filled_white_24dp
else else
R.drawable.ic_favorite_white_24dp R.drawable.ic_favorite_white_24dp
@@ -154,10 +141,10 @@ class RoutePreviewScreen(
.build() .build()
) )
.setOnClickListener { .setOnClickListener {
mIsFavorite = !mIsFavorite isFavorite = !isFavorite
CarToast.makeText( CarToast.makeText(
carContext, carContext,
if (mIsFavorite) if (isFavorite)
carContext carContext
.getString(R.string.favorites) .getString(R.string.favorites)
else else
@@ -174,10 +161,10 @@ class RoutePreviewScreen(
private fun deleteFavoriteAction(): Action = Action.Builder() private fun deleteFavoriteAction(): Action = Action.Builder()
.setOnClickListener { .setOnClickListener {
if (mIsFavorite) { if (isFavorite) {
vieModel.deleteFavorite(destination) vieModel.deleteFavorite(destination)
} }
mIsFavorite = !mIsFavorite isFavorite = !isFavorite
finish() finish()
} }
.setIcon( .setIcon(

View File

@@ -16,6 +16,7 @@ import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.kouros.data.R import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.ViewStyle
import com.kouros.navigation.data.Category import com.kouros.navigation.data.Category
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
@@ -76,6 +77,7 @@ class SearchScreen(
location, location,
) )
) { obj: Any? -> ) { obj: Any? ->
surfaceRenderer.viewStyle = ViewStyle.VIEW
if (obj != null) { if (obj != null) {
setResult(obj) setResult(obj)
finish() finish()

View File

@@ -58,7 +58,6 @@ dependencies {
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)
implementation(libs.maplibre.compose) implementation(libs.maplibre.compose)
implementation("hu.supercluster:overpasser:0.2.2")
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)

View File

@@ -68,8 +68,9 @@ data class StepData (
// GeoJSON data classes // GeoJSON data classes
@Serializable @Serializable
data class GeoJsonLineString( data class GeoJsonType(
val type: String, val type: String,
val coordinates: List<List<Double>> val coordinates: List<List<Double>>
) )
@@ -77,7 +78,7 @@ data class GeoJsonLineString(
@Serializable @Serializable
data class GeoJsonFeature( data class GeoJsonFeature(
val type: String, val type: String,
val geometry: GeoJsonLineString val geometry: GeoJsonType,
) )
@Serializable @Serializable
@@ -156,7 +157,7 @@ object Constants {
const val FAVORITES: String = "Favorites" const val FAVORITES: String = "Favorites"
const val GAS_STATION: String ="GasStation" const val FUEL_STATION: String ="fuel"
const val PHARMACY: String ="pharmacy" const val PHARMACY: String ="pharmacy"

View File

@@ -95,7 +95,7 @@ data class Route(
points.add(point) points.add(point)
} }
pointLocations = points pointLocations = points
routeGeoJson = createGeoJson(waypoints) routeGeoJson = createGeoJson("LineString", waypoints)
centerLocation = createCenterLocation(routeGeoJson) centerLocation = createCenterLocation(routeGeoJson)
return Route( return Route(
maneuvers, maneuvers,

View File

@@ -9,6 +9,6 @@ data class Elements (
@SerializedName("id" ) var id : Long? = null, @SerializedName("id" ) var id : Long? = null,
@SerializedName("lat" ) var lat : Double? = null, @SerializedName("lat" ) var lat : Double? = null,
@SerializedName("lon" ) var lon : Double? = null, @SerializedName("lon" ) var lon : Double? = null,
@SerializedName("tags" ) var tags : Tags? = Tags() @SerializedName("tags" ) var tags : Tags = Tags()
) )

View File

@@ -1,45 +1,25 @@
package com.kouros.navigation.data package com.kouros.navigation.data.overpass
import android.location.Location import android.location.Location
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.kouros.navigation.data.overpass.Amenity import com.kouros.navigation.utils.NavigationUtils
import com.kouros.navigation.data.overpass.Elements
import com.kouros.navigation.utils.NavigationUtils.getBoundingBox2
import com.kouros.navigation.utils.NavigationUtils.getOverpassBbox
import hu.supercluster.overpasser.library.output.OutputFormat
import hu.supercluster.overpasser.library.output.OutputModificator
import hu.supercluster.overpasser.library.output.OutputOrder
import hu.supercluster.overpasser.library.output.OutputVerbosity
import hu.supercluster.overpasser.library.query.OverpassQuery
import java.io.OutputStreamWriter import java.io.OutputStreamWriter
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
class Overpass { class Overpass {
val overpassUrl = "https://overpass.kumi.systems/api/interpreter"
fun getAmenities(category: String, location: Location) : List<Elements> { fun getAmenities(category: String, location: Location) : List<Elements> {
val boundingBox = getOverpassBbox(location, 2.0) val boundingBox = NavigationUtils.getOverpassBbox(location, 2.0)
val bb = getBoundingBox2(location, 2.0) val bb = NavigationUtils.getBoundingBox2(location, 2.0)
val url = "https://overpass.kumi.systems/api/interpreter" val httpURLConnection = URL(overpassUrl).openConnection() as HttpURLConnection
val httpURLConnection = URL(url).openConnection() as HttpURLConnection
httpURLConnection.requestMethod = "POST" httpURLConnection.requestMethod = "POST"
httpURLConnection.setRequestProperty( httpURLConnection.setRequestProperty(
"Accept", "Accept",
"application/json" "application/json"
) )
httpURLConnection.setDoOutput(true); httpURLConnection.setDoOutput(true);
val query = OverpassQuery()
.format(OutputFormat.JSON)
.timeout(30)
.filterQuery()
.node()
.amenity("charging_station")
.tagNot("access", "private")
.boundingBox(bb.southernLat, bb.westernLon, bb.northerLat, bb.easternLon)
.end()
.output(OutputVerbosity.BODY, OutputModificator.CENTER, OutputOrder.QT, 100)
.build()
// define a query // define a query
val test = """ val test = """
|[out:json]; |[out:json];
@@ -56,12 +36,9 @@ class Overpass {
outputStreamWriter.flush() outputStreamWriter.flush()
// Check if the connection is successful // Check if the connection is successful
val responseCode = httpURLConnection.responseCode val responseCode = httpURLConnection.responseCode
println("Overpass: $responseCode")
if (responseCode == HttpURLConnection.HTTP_OK) { if (responseCode == HttpURLConnection.HTTP_OK) {
val response = httpURLConnection.inputStream.bufferedReader() val response = httpURLConnection.inputStream.bufferedReader()
.use { it.readText() } // defaults to UTF-8 .use { it.readText() } // defaults to UTF-8
val gson = GsonBuilder().serializeNulls().create() val gson = GsonBuilder().serializeNulls().create()
val overpass = gson.fromJson(response, Amenity::class.java) val overpass = gson.fromJson(response, Amenity::class.java)
println("Overpass: $response") println("Overpass: $response")

View File

@@ -17,6 +17,6 @@ data class Tags (
@SerializedName("operator:wikipedia" ) var operatorWikipedia : String? = null, @SerializedName("operator:wikipedia" ) var operatorWikipedia : String? = null,
@SerializedName("ref" ) var ref : String? = null, @SerializedName("ref" ) var ref : String? = null,
@SerializedName("socket:type2" ) var socketType2 : String? = null, @SerializedName("socket:type2" ) var socketType2 : String? = null,
@SerializedName("socket:type2:output" ) var socketType2Ooutput : String? = null @SerializedName("socket:type2:output" ) var socketType2Output : String? = null
) )

View File

@@ -52,7 +52,6 @@ open class RouteModel() {
this.routeState = routeState.copy( this.routeState = routeState.copy(
route = null, route = null,
isNavigating = false, isNavigating = false,
// destination = Place(),
arrived = false, arrived = false,
maneuverType = 0, maneuverType = 0,
currentShapeIndex = 0, currentShapeIndex = 0,

View File

@@ -13,7 +13,7 @@ import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Locations import com.kouros.navigation.data.Locations
import com.kouros.navigation.data.NavigationRepository import com.kouros.navigation.data.NavigationRepository
import com.kouros.navigation.data.ObjectBox.boxStore import com.kouros.navigation.data.ObjectBox.boxStore
import com.kouros.navigation.data.Overpass import com.kouros.navigation.data.overpass.Overpass
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.Place_ import com.kouros.navigation.data.Place_
import com.kouros.navigation.data.SearchFilter import com.kouros.navigation.data.SearchFilter
@@ -118,7 +118,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
.orderDesc(Place_.lastDate) .orderDesc(Place_.lastDate)
.build() .build()
val results = query.find() val results = query.find()
println("Favorites $results")
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)
@@ -233,7 +232,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val address = repository.reverseAddress(location) val address = repository.reverseAddress(location)
val gson = GsonBuilder().serializeNulls().create() val gson = GsonBuilder().serializeNulls().create()
val place = gson.fromJson(address, SearchResult::class.java) val place = gson.fromJson(address, SearchResult::class.java)
println(place.address.road)
return place.address.road return place.address.road
} }
@@ -271,7 +269,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val current = LocalDateTime.now(ZoneOffset.UTC) val current = LocalDateTime.now(ZoneOffset.UTC)
place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond() place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond()
placeBox.put(place) placeBox.put(place)
println("Save Place $place")
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }

View File

@@ -8,7 +8,7 @@ import com.kouros.navigation.data.BoundingBox
import com.kouros.navigation.data.Constants.SHARED_PREF_KEY import com.kouros.navigation.data.Constants.SHARED_PREF_KEY
import com.kouros.navigation.data.GeoJsonFeature import com.kouros.navigation.data.GeoJsonFeature
import com.kouros.navigation.data.GeoJsonFeatureCollection import com.kouros.navigation.data.GeoJsonFeatureCollection
import com.kouros.navigation.data.GeoJsonLineString import com.kouros.navigation.data.GeoJsonType
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.maplibre.geojson.FeatureCollection import org.maplibre.geojson.FeatureCollection
import org.maplibre.geojson.Point import org.maplibre.geojson.Point
@@ -23,12 +23,9 @@ import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle import java.time.format.FormatStyle
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.sin
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -149,9 +146,8 @@ object NavigationUtils {
// 4. Create and return the Location object. // 4. Create and return the Location object.
return location(centerPoint.longitude(), centerPoint.latitude()) return location(centerPoint.longitude(), centerPoint.latitude())
} }
fun createGeoJson(lineCoordinates: List<List<Double>>): String { fun createGeoJson(type : String, lineCoordinates: List<List<Double>>): String {
val lineString = GeoJsonType(type = type, coordinates = lineCoordinates)
val lineString = GeoJsonLineString(type = "LineString", coordinates = lineCoordinates)
val feature = GeoJsonFeature(type = "Feature", geometry = lineString) val feature = GeoJsonFeature(type = "Feature", geometry = lineString)
val featureCollection = val featureCollection =
GeoJsonFeatureCollection(type = "FeatureCollection", features = listOf(feature)) GeoJsonFeatureCollection(type = "FeatureCollection", features = listOf(feature))
@@ -159,6 +155,8 @@ object NavigationUtils {
return jsonString return jsonString
} }
fun getOverpassBbox(location: Location, radius: Double): String { fun getOverpassBbox(location: Location, radius: Double): String {
val bbox = getBoundingBox(location.longitude, location.latitude, radius) val bbox = getBoundingBox(location.longitude, location.latitude, radius)
val neLon = bbox["ne"]?.get("lon") val neLon = bbox["ne"]?.get("lon")