Amenities
This commit is contained in:
@@ -14,8 +14,8 @@ android {
|
||||
applicationId = "com.kouros.navigation"
|
||||
minSdk = 33
|
||||
targetSdk = 36
|
||||
versionCode = 9
|
||||
versionName = "0.1.3.9"
|
||||
versionCode = 10
|
||||
versionName = "0.1.3.10"
|
||||
base.archivesName = "navi-$versionName"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -72,23 +72,17 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
val routeData = MutableLiveData("")
|
||||
|
||||
val viewModel = ViewModel(NavigationRepository())
|
||||
val routeModel = RouteModel()
|
||||
|
||||
var tilt = 50.0
|
||||
|
||||
val useMock = true
|
||||
val stepData: MutableLiveData<StepData> by lazy {
|
||||
MutableLiveData<StepData>()
|
||||
}
|
||||
|
||||
val nextStepData: MutableLiveData<StepData> by lazy {
|
||||
MutableLiveData<StepData>()
|
||||
}
|
||||
|
||||
var lastLocation = location(0.0, 0.0)
|
||||
|
||||
val observer = Observer<String> { newRoute ->
|
||||
if (newRoute.isNotEmpty()) {
|
||||
routeModel.startNavigation(newRoute)
|
||||
@@ -188,7 +182,7 @@ class MainActivity : ComponentActivity() {
|
||||
sheetPeekHeightState.value = 128.dp
|
||||
}
|
||||
}
|
||||
NavigationTheme() {
|
||||
NavigationTheme {
|
||||
BottomSheetScaffold(
|
||||
snackbarHost = {
|
||||
SnackbarHost(hostState = snackbarHostState)
|
||||
|
||||
@@ -14,6 +14,7 @@ import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
@@ -28,16 +29,34 @@ import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
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.MapLibre
|
||||
import com.kouros.navigation.car.map.NavigationImage
|
||||
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.utils.NavigationUtils.getBooleanKeyValue
|
||||
import org.maplibre.compose.camera.CameraPosition
|
||||
import org.maplibre.compose.camera.CameraState
|
||||
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.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.spatialk.geojson.Position
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -77,7 +96,7 @@ fun MapView(
|
||||
Column {
|
||||
NavigationInfo(step)
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
MapLibre(applicationContext, cameraState, baseStyle, route, "", position)
|
||||
MapLibre(applicationContext, cameraState, baseStyle, route, ViewStyle.VIEW)
|
||||
LocationTrackingEffect(
|
||||
locationState = userLocationState,
|
||||
) {
|
||||
@@ -97,3 +116,5 @@ fun MapView(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ fun SearchSheet(
|
||||
}
|
||||
}
|
||||
if (recentPlaces.value != null) {
|
||||
println("Recent Places ${recentPlaces.value}")
|
||||
val textFieldState = rememberTextFieldState()
|
||||
val items = listOf(recentPlaces)
|
||||
if (items.isNotEmpty()) {
|
||||
@@ -108,7 +107,7 @@ fun Home(
|
||||
closeSheet()
|
||||
}) {
|
||||
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",
|
||||
modifier = Modifier.size(24.dp, 24.dp),
|
||||
)
|
||||
@@ -222,7 +221,6 @@ private fun SearchPlaces(
|
||||
street = place.address.road
|
||||
)
|
||||
viewModel.saveRecent(pl)
|
||||
println("Save $pl")
|
||||
val toLocation =
|
||||
location(place.lon.toDouble(), place.lat.toDouble())
|
||||
viewModel.loadRoute(context, location, toLocation)
|
||||
|
||||
@@ -21,7 +21,6 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
@@ -63,7 +62,6 @@ class SurfaceRenderer(
|
||||
private var visibleArea = MutableLiveData(
|
||||
Rect(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
var stableArea = Rect()
|
||||
var width = 0
|
||||
var height = 0
|
||||
@@ -71,11 +69,9 @@ class SurfaceRenderer(
|
||||
val routeData = MutableLiveData("")
|
||||
val speed = MutableLiveData(0F)
|
||||
lateinit var centerLocation: Location
|
||||
var preview = false
|
||||
var viewStyle = ViewStyle.VIEW
|
||||
var previewDistance = 0.0
|
||||
val previewRouteData = MutableLiveData("")
|
||||
lateinit var mapView: ComposeView
|
||||
var panView = false
|
||||
var tilt = 55.0
|
||||
var countDownTimerActive = false
|
||||
val mSurfaceCallback: SurfaceCallback = object : SurfaceCallback {
|
||||
@@ -171,18 +167,16 @@ class SurfaceRenderer(
|
||||
|
||||
@Composable
|
||||
fun MapView() {
|
||||
val stateWidth = visibleArea.observeAsState()
|
||||
val position: CameraPosition? by cameraPosition.observeAsState()
|
||||
val route: String? by routeData.observeAsState()
|
||||
val previewRoute: String? by previewRouteData.observeAsState()
|
||||
val paddingValues = getPaddingValues(width - stateWidth.value!!.width(), height, preview)
|
||||
val paddingValues = getPaddingValues(height, viewStyle)
|
||||
val cameraState = cameraState(paddingValues, position, tilt)
|
||||
|
||||
val baseStyle = remember {
|
||||
mutableStateOf(BaseStyle.Uri(Constants.STYLE))
|
||||
}
|
||||
DarkMode(carContext, baseStyle)
|
||||
MapLibre(carContext, cameraState, baseStyle, route, previewRoute, position)
|
||||
MapLibre(carContext, cameraState, baseStyle, route, viewStyle)
|
||||
ShowPosition(cameraState, position, paddingValues)
|
||||
}
|
||||
|
||||
@@ -192,25 +186,32 @@ class SurfaceRenderer(
|
||||
position: CameraPosition?,
|
||||
paddingValues: PaddingValues
|
||||
) {
|
||||
val cameraDuration = duration(preview, position!!.bearing, lastBearing)
|
||||
val cameraDuration =
|
||||
duration(viewStyle == ViewStyle.PREVIEW, position!!.bearing, lastBearing)
|
||||
var bearing = position.bearing
|
||||
var zoom = position.zoom
|
||||
var target = position.target
|
||||
var localTilt = tilt
|
||||
val currentSpeed: Float? by speed.observeAsState()
|
||||
if (!preview) {
|
||||
if (routeModel.isNavigating()) {
|
||||
DrawImage(paddingValues, currentSpeed, width, height)
|
||||
} else {
|
||||
when (viewStyle) {
|
||||
ViewStyle.VIEW -> {
|
||||
DrawImage(paddingValues, currentSpeed, width, height)
|
||||
}
|
||||
} else {
|
||||
|
||||
ViewStyle.PREVIEW -> {
|
||||
bearing = 0.0
|
||||
zoom = previewZoom(previewDistance)
|
||||
target = Position(centerLocation.longitude, centerLocation.latitude)
|
||||
localTilt = 0.0
|
||||
}
|
||||
LaunchedEffect(position) {
|
||||
|
||||
else -> {
|
||||
bearing = 0.0
|
||||
localTilt = 0.0
|
||||
zoom = 12.0
|
||||
}
|
||||
}
|
||||
LaunchedEffect(position, viewStyle) {
|
||||
cameraState.animateTo(
|
||||
finalPosition = CameraPosition(
|
||||
bearing = bearing,
|
||||
@@ -234,7 +235,7 @@ class SurfaceRenderer(
|
||||
/** Handles the map zoom-in and zoom-out events. */
|
||||
fun handleScale(zoomSign: Int) {
|
||||
synchronized(this) {
|
||||
panView = true
|
||||
viewStyle = ViewStyle.PAN_VIEW
|
||||
val newZoom = if (zoomSign < 0) {
|
||||
cameraPosition.value!!.zoom - 1.0
|
||||
} else {
|
||||
@@ -259,9 +260,9 @@ class SurfaceRenderer(
|
||||
|
||||
fun updateLocation(location: Location) {
|
||||
synchronized(this) {
|
||||
if (!preview) {
|
||||
if (viewStyle == ViewStyle.VIEW || viewStyle == ViewStyle.PAN_VIEW) {
|
||||
val bearing = bearing(lastLocation, location, cameraPosition.value!!.bearing)
|
||||
val zoom = if (!panView) {
|
||||
val zoom = if (viewStyle == ViewStyle.VIEW) {
|
||||
calculateZoom(location.speed.toDouble())
|
||||
} else {
|
||||
cameraPosition.value!!.zoom
|
||||
@@ -280,12 +281,6 @@ class SurfaceRenderer(
|
||||
val lastLocationTimer = lastLocation
|
||||
checkUpdate(mainThreadHandler, lastLocationTimer)
|
||||
}
|
||||
} else {
|
||||
updateCameraPosition(
|
||||
0.0,
|
||||
previewZoom(previewDistance),
|
||||
Position(centerLocation.longitude, centerLocation.latitude)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,7 +290,7 @@ class SurfaceRenderer(
|
||||
lastLocationTimer: Location
|
||||
) {
|
||||
mainThreadHandler.post {
|
||||
object : CountDownTimer(5000, 1000) {
|
||||
object : CountDownTimer(3000, 1000) {
|
||||
override fun onTick(millisUntilFinished: Long) {}
|
||||
override fun onFinish() {
|
||||
countDownTimerActive = false
|
||||
@@ -313,7 +308,7 @@ class SurfaceRenderer(
|
||||
bearing = bearing,
|
||||
zoom = zoom,
|
||||
tilt = tilt,
|
||||
padding = getPaddingValues(width - visibleArea.value!!.width(), height, preview),
|
||||
padding = getPaddingValues(height, viewStyle),
|
||||
target = target
|
||||
)
|
||||
)
|
||||
@@ -321,28 +316,41 @@ class SurfaceRenderer(
|
||||
|
||||
fun setRouteData() {
|
||||
routeData.value = routeModel.route.routeGeoJson
|
||||
previewRouteData.value = ""
|
||||
preview = false
|
||||
panView = false
|
||||
viewStyle = ViewStyle.VIEW
|
||||
}
|
||||
|
||||
fun setPreviewRouteData(routeModel: RouteModel) {
|
||||
previewRouteData.value = routeModel.route.routeGeoJson
|
||||
centerLocation = routeModel.route.centerLocation
|
||||
preview = true
|
||||
previewDistance = routeModel.route.distance
|
||||
viewStyle = ViewStyle.PREVIEW
|
||||
with(routeModel) {
|
||||
routeData.value = route.routeGeoJson
|
||||
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.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)
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
companion
|
||||
@@ -352,3 +360,7 @@ class SurfaceRenderer(
|
||||
}
|
||||
|
||||
|
||||
enum class ViewStyle {
|
||||
VIEW, PREVIEW, PAN_VIEW, SEARCH_VIEW
|
||||
|
||||
}
|
||||
@@ -9,10 +9,7 @@ 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.material3.Badge
|
||||
import androidx.compose.material3.BadgedBox
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
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.sp
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.car.ViewStyle
|
||||
import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
|
||||
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.rememberCameraState
|
||||
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.CircleLayer
|
||||
import org.maplibre.compose.layers.FillLayer
|
||||
import org.maplibre.compose.layers.LineLayer
|
||||
import org.maplibre.compose.layers.SymbolLayer
|
||||
import org.maplibre.compose.location.LocationPuck
|
||||
import org.maplibre.compose.location.LocationPuckColors
|
||||
import org.maplibre.compose.location.LocationPuckSizes
|
||||
@@ -54,6 +58,8 @@ 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.Feature
|
||||
import org.maplibre.spatialk.geojson.FeatureCollection
|
||||
import org.maplibre.spatialk.geojson.Position
|
||||
|
||||
|
||||
@@ -83,8 +89,7 @@ fun MapLibre(
|
||||
cameraState: CameraState,
|
||||
baseStyle: MutableState<BaseStyle.Uri>,
|
||||
route: String?,
|
||||
previewRoute: String?,
|
||||
position: CameraPosition?
|
||||
viewStyle: ViewStyle
|
||||
) {
|
||||
MaplibreMap(
|
||||
options = MapOptions(
|
||||
@@ -98,45 +103,58 @@ fun MapLibre(
|
||||
if (!getBooleanKeyValue(context = context, SHOW_THREED_BUILDING)) {
|
||||
BuildingLayer(tiles)
|
||||
}
|
||||
RouteLayer(route, previewRoute, position!!.zoom)
|
||||
RouteLayer(route, viewStyle)
|
||||
}
|
||||
//Puck(cameraState, lastLocation)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RouteLayer(routeData: String?, previewRoute: String?, zoom: Double) {
|
||||
val width = zoom - 2
|
||||
if (routeData!!.isNotEmpty()) {
|
||||
val routes =
|
||||
rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
fun RouteLayer(routeData: String?, viewStyle: ViewStyle) {
|
||||
if (routeData != null && routeData.isNotEmpty()) {
|
||||
println(routeData)
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
if (viewStyle == ViewStyle.VIEW) {
|
||||
LineLayer(
|
||||
id = "routes-casing",
|
||||
id = "routes-casing$viewStyle",
|
||||
source = routes,
|
||||
color = const(Color.White),
|
||||
width = const((width+2).dp),
|
||||
width =
|
||||
interpolate(
|
||||
type = exponential(1.2f),
|
||||
input = zoom(),
|
||||
5 to const(0.4.dp),
|
||||
6 to const(0.8.dp),
|
||||
7 to const(2.0.dp),
|
||||
20 to const(24.dp),
|
||||
),
|
||||
)
|
||||
LineLayer(
|
||||
id = "routes",
|
||||
id = "routes$viewStyle",
|
||||
source = routes,
|
||||
color = const(RouteColor),
|
||||
width = const(width.dp),
|
||||
width =
|
||||
interpolate(
|
||||
type = exponential(1.2f),
|
||||
input = zoom(),
|
||||
5 to const(0.4.dp),
|
||||
6 to const(0.7.dp),
|
||||
7 to const(1.75.dp),
|
||||
20 to const(22.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)
|
||||
)
|
||||
}
|
||||
if (previewRoute!!.isNotEmpty()) {
|
||||
val routes =
|
||||
rememberGeoJsonSource(GeoJsonData.JsonString(previewRoute))
|
||||
LineLayer(
|
||||
id = "routes-casing-pre",
|
||||
source = routes,
|
||||
color = const(Color.White),
|
||||
width = const(6.dp),
|
||||
)
|
||||
LineLayer(
|
||||
id = "routes-pre",
|
||||
source = routes,
|
||||
color = const(RouteColor),
|
||||
width = const(4.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +181,10 @@ fun NavigationImage(padding: PaddingValues, width: Int, height: Int) {
|
||||
val imageSize = (height / 6)
|
||||
val color = remember { NavigationColor }
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(padding)) {
|
||||
Canvas(modifier =Modifier
|
||||
.size(imageSize.dp, imageSize.dp)) {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.size(imageSize.dp, imageSize.dp)
|
||||
) {
|
||||
scale(scaleX = 1f, scaleY = 0.7f) {
|
||||
drawCircle(Color.DarkGray.copy(alpha = 0.2f))
|
||||
}
|
||||
@@ -259,11 +279,11 @@ fun DarkMode(context: Context, baseStyle: MutableState<BaseStyle.Uri>) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getPaddingValues(width: Int, height: Int, preView: Boolean): PaddingValues {
|
||||
return if (preView) {
|
||||
PaddingValues(start = 150.dp, bottom = 0.dp)
|
||||
} else {
|
||||
PaddingValues(start = 50.dp, top = distanceFromTop(height).dp)
|
||||
fun getPaddingValues(height: Int, viewStyle: ViewStyle): PaddingValues {
|
||||
return when (viewStyle) {
|
||||
ViewStyle.VIEW -> PaddingValues(start = 50.dp, top = distanceFromTop(height).dp)
|
||||
ViewStyle.PREVIEW -> PaddingValues(start = 150.dp, bottom = 0.dp)
|
||||
else -> PaddingValues(start = 450.dp, bottom = 0.dp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,16 @@ import android.location.Location
|
||||
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.core.graphics.drawable.IconCompat
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.car.SurfaceRenderer
|
||||
import com.kouros.navigation.car.ViewStyle
|
||||
import com.kouros.navigation.data.Category
|
||||
import com.kouros.navigation.data.Constants
|
||||
|
||||
@@ -21,7 +24,7 @@ class CategoriesScreen(
|
||||
) : Screen(carContext) {
|
||||
|
||||
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.CHARGING_STATION, name = carContext.getString(R.string.charging_station))
|
||||
)
|
||||
@@ -29,12 +32,17 @@ class CategoriesScreen(
|
||||
override fun onGetTemplate(): Template {
|
||||
val itemListBuilder = ItemList.Builder()
|
||||
.setNoItemsMessage("No categories to show")
|
||||
|
||||
categories.forEach {
|
||||
it.name
|
||||
itemListBuilder.addItem(
|
||||
Row.Builder()
|
||||
.setTitle(it.name)
|
||||
.setImage(CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
carContext,
|
||||
com.kouros.android.cars.carappservice.R.drawable.ev_station_24px
|
||||
)
|
||||
)
|
||||
.build())
|
||||
.setOnClickListener {
|
||||
screenManager
|
||||
.pushForResult(
|
||||
@@ -56,6 +64,8 @@ class CategoriesScreen(
|
||||
)
|
||||
}
|
||||
|
||||
surfaceRenderer.viewStyle = ViewStyle.SEARCH_VIEW
|
||||
|
||||
val header = Header.Builder()
|
||||
.setStartHeaderAction(Action.BACK)
|
||||
.setTitle("title")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.kouros.navigation.car.screen
|
||||
|
||||
import android.location.Location
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.CarToast
|
||||
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.Row
|
||||
import androidx.car.app.model.Template
|
||||
import androidx.car.app.navigation.model.MapController
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate
|
||||
import androidx.car.app.versioning.CarAppApiLevels
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import com.kouros.data.R
|
||||
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.overpass.Elements
|
||||
import com.kouros.navigation.model.ViewModel
|
||||
import com.kouros.navigation.utils.NavigationUtils.createGeoJson
|
||||
import com.kouros.navigation.utils.location
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -38,35 +43,50 @@ class CategoryScreen(
|
||||
|
||||
val observer = Observer<List<Elements>> { newElements ->
|
||||
elements = newElements
|
||||
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 {
|
||||
viewModel.elements.observe(this, observer)
|
||||
viewModel.getAmenities(category, location)
|
||||
invalidate()
|
||||
}
|
||||
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
|
||||
val listBuilder = ItemList.Builder()
|
||||
if (carContext.getCarAppApiLevel() > CarAppApiLevels.LEVEL_1) {
|
||||
var index = 0
|
||||
val listLimit = min(
|
||||
10,
|
||||
100,
|
||||
carContext.getCarService(ConstraintManager::class.java)
|
||||
.getContentLimit(
|
||||
ConstraintManager.CONTENT_LIMIT_TYPE_LIST
|
||||
)
|
||||
)
|
||||
elements.forEach {
|
||||
//listBuilder.addItem(createRow(it.tags!!.operator.toString(), it.tags?.capacity.toString()))
|
||||
if (index++ < listLimit) {
|
||||
listBuilder.addItem(
|
||||
Row.Builder()
|
||||
.setOnClickListener({
|
||||
.setOnClickListener {
|
||||
val location = location(it.lon!!, it.lat!!)
|
||||
surfaceRenderer.setLocation(location)
|
||||
})
|
||||
.setTitle(secondText(it.tags?.capacity.toString()))
|
||||
surfaceRenderer.setCategoryLocation(location)
|
||||
}
|
||||
.setTitle(it.tags.operator.toString())
|
||||
.setImage(
|
||||
CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
@@ -76,44 +96,17 @@ class CategoryScreen(
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.addText(it.tags!!.operator.toString())
|
||||
.addText(secondText(it.tags?.capacity.toString()))
|
||||
.addText(it.tags.network.toString())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
val header = Header.Builder()
|
||||
.setStartHeaderAction(Action.BACK)
|
||||
.setTitle(carContext.getString(R.string.charging_station))
|
||||
.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()
|
||||
.setContentTemplate(
|
||||
ListTemplate.Builder()
|
||||
@@ -121,7 +114,11 @@ class CategoryScreen(
|
||||
.setSingleList(listBuilder.build())
|
||||
.build()
|
||||
)
|
||||
.setActionStrip(actionStrip)
|
||||
.setMapController(
|
||||
MapController.Builder().setMapActionStrip(
|
||||
getMapActionStrip()
|
||||
).build()
|
||||
)
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
@@ -140,4 +137,27 @@ class CategoryScreen(
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.lifecycle.Observer
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.car.NavigationCarAppService
|
||||
import com.kouros.navigation.car.SurfaceRenderer
|
||||
import com.kouros.navigation.car.ViewStyle
|
||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||
import com.kouros.navigation.data.Constants.DESTINATION_ARRIVAL_DISTANCE
|
||||
import com.kouros.navigation.data.NavigationRepository
|
||||
@@ -237,7 +238,7 @@ class NavigationScreen(
|
||||
val actionStripBuilder = ActionStrip.Builder()
|
||||
.addAction(zoomPlus())
|
||||
.addAction(zoomMinus())
|
||||
if (surfaceRenderer.panView) {
|
||||
if (surfaceRenderer.viewStyle == ViewStyle.PAN_VIEW) {
|
||||
actionStripBuilder
|
||||
.addAction(
|
||||
panAction()
|
||||
@@ -362,7 +363,7 @@ class NavigationScreen(
|
||||
)
|
||||
.build()
|
||||
).setOnClickListener {
|
||||
surfaceRenderer.panView = false
|
||||
surfaceRenderer.viewStyle = ViewStyle.VIEW
|
||||
}
|
||||
.build()
|
||||
}
|
||||
@@ -410,7 +411,7 @@ class NavigationScreen(
|
||||
|
||||
fun stopNavigation() {
|
||||
listener.stopNavigation()
|
||||
surfaceRenderer.routeData.postValue("")
|
||||
surfaceRenderer.routeData.value = ""
|
||||
invalidate()
|
||||
}
|
||||
|
||||
|
||||
@@ -105,19 +105,21 @@ class PlaceListScreen(
|
||||
it.street,
|
||||
avatar = null
|
||||
)
|
||||
screenManager
|
||||
.pushForResult(
|
||||
RoutePreviewScreen(
|
||||
carContext,
|
||||
surfaceRenderer,
|
||||
place
|
||||
)
|
||||
) { obj: Any? ->
|
||||
if (obj != null) {
|
||||
setResult(obj)
|
||||
setResult(place)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
// screenManager
|
||||
// .pushForResult(
|
||||
// RoutePreviewScreen(
|
||||
// carContext,
|
||||
// surfaceRenderer,
|
||||
// place
|
||||
// )
|
||||
// ) { obj: Any? ->
|
||||
// if (obj != null) {
|
||||
// setResult(obj)
|
||||
// finish()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
.build()
|
||||
)
|
||||
|
||||
@@ -15,16 +15,12 @@
|
||||
*/
|
||||
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.text.SpannableString
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.CarToast
|
||||
import androidx.car.app.Screen
|
||||
import androidx.car.app.constraints.ConstraintManager
|
||||
import androidx.car.app.model.Action
|
||||
import androidx.car.app.model.Action.FLAG_PRIMARY
|
||||
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.Place
|
||||
import com.kouros.navigation.model.ViewModel
|
||||
import com.kouros.navigation.utils.location
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
@@ -57,9 +54,7 @@ class RoutePreviewScreen(
|
||||
private var destination: Place
|
||||
) :
|
||||
Screen(carContext) {
|
||||
private var mIsFavorite = false
|
||||
|
||||
private var mItemLimit = 0
|
||||
private var isFavorite = false
|
||||
|
||||
val vieModel = ViewModel(NavigationRepository())
|
||||
|
||||
@@ -76,19 +71,11 @@ class RoutePreviewScreen(
|
||||
|
||||
init {
|
||||
vieModel.previewRoute.observe(this, observer)
|
||||
val location = Location(LocationManager.GPS_PROVIDER)
|
||||
location.latitude = destination.latitude
|
||||
location.longitude = destination.longitude
|
||||
val location = location(destination.longitude, destination.latitude)
|
||||
vieModel.loadPreviewRoute(carContext, surfaceRenderer.lastLocation, location)
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
mItemLimit =
|
||||
carContext.getCarService(ConstraintManager::class.java)
|
||||
.getContentLimit(
|
||||
ConstraintManager.CONTENT_LIMIT_TYPE_ROUTE_LIST
|
||||
)
|
||||
|
||||
val navigateActionIcon: CarIcon = CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
carContext, R.drawable.baseline_assistant_navigation_24
|
||||
@@ -145,7 +132,7 @@ class RoutePreviewScreen(
|
||||
CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
carContext,
|
||||
if (mIsFavorite)
|
||||
if (isFavorite)
|
||||
R.drawable.ic_favorite_filled_white_24dp
|
||||
else
|
||||
R.drawable.ic_favorite_white_24dp
|
||||
@@ -154,10 +141,10 @@ class RoutePreviewScreen(
|
||||
.build()
|
||||
)
|
||||
.setOnClickListener {
|
||||
mIsFavorite = !mIsFavorite
|
||||
isFavorite = !isFavorite
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
if (mIsFavorite)
|
||||
if (isFavorite)
|
||||
carContext
|
||||
.getString(R.string.favorites)
|
||||
else
|
||||
@@ -174,10 +161,10 @@ class RoutePreviewScreen(
|
||||
|
||||
private fun deleteFavoriteAction(): Action = Action.Builder()
|
||||
.setOnClickListener {
|
||||
if (mIsFavorite) {
|
||||
if (isFavorite) {
|
||||
vieModel.deleteFavorite(destination)
|
||||
}
|
||||
mIsFavorite = !mIsFavorite
|
||||
isFavorite = !isFavorite
|
||||
finish()
|
||||
}
|
||||
.setIcon(
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.car.SurfaceRenderer
|
||||
import com.kouros.navigation.car.ViewStyle
|
||||
import com.kouros.navigation.data.Category
|
||||
import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.NavigationRepository
|
||||
@@ -76,6 +77,7 @@ class SearchScreen(
|
||||
location,
|
||||
)
|
||||
) { obj: Any? ->
|
||||
surfaceRenderer.viewStyle = ViewStyle.VIEW
|
||||
if (obj != null) {
|
||||
setResult(obj)
|
||||
finish()
|
||||
|
||||
@@ -58,7 +58,6 @@ dependencies {
|
||||
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.maplibre.compose)
|
||||
implementation("hu.supercluster:overpasser:0.2.2")
|
||||
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
|
||||
@@ -68,8 +68,9 @@ data class StepData (
|
||||
|
||||
|
||||
// GeoJSON data classes
|
||||
|
||||
@Serializable
|
||||
data class GeoJsonLineString(
|
||||
data class GeoJsonType(
|
||||
val type: String,
|
||||
val coordinates: List<List<Double>>
|
||||
)
|
||||
@@ -77,7 +78,7 @@ data class GeoJsonLineString(
|
||||
@Serializable
|
||||
data class GeoJsonFeature(
|
||||
val type: String,
|
||||
val geometry: GeoJsonLineString
|
||||
val geometry: GeoJsonType,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@@ -156,7 +157,7 @@ object Constants {
|
||||
|
||||
const val FAVORITES: String = "Favorites"
|
||||
|
||||
const val GAS_STATION: String ="GasStation"
|
||||
const val FUEL_STATION: String ="fuel"
|
||||
|
||||
const val PHARMACY: String ="pharmacy"
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ data class Route(
|
||||
points.add(point)
|
||||
}
|
||||
pointLocations = points
|
||||
routeGeoJson = createGeoJson(waypoints)
|
||||
routeGeoJson = createGeoJson("LineString", waypoints)
|
||||
centerLocation = createCenterLocation(routeGeoJson)
|
||||
return Route(
|
||||
maneuvers,
|
||||
|
||||
@@ -9,6 +9,6 @@ data class Elements (
|
||||
@SerializedName("id" ) var id : Long? = null,
|
||||
@SerializedName("lat" ) var lat : Double? = null,
|
||||
@SerializedName("lon" ) var lon : Double? = null,
|
||||
@SerializedName("tags" ) var tags : Tags? = Tags()
|
||||
@SerializedName("tags" ) var tags : Tags = Tags()
|
||||
|
||||
)
|
||||
@@ -1,45 +1,25 @@
|
||||
package com.kouros.navigation.data
|
||||
package com.kouros.navigation.data.overpass
|
||||
|
||||
import android.location.Location
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.kouros.navigation.data.overpass.Amenity
|
||||
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 com.kouros.navigation.utils.NavigationUtils
|
||||
import java.io.OutputStreamWriter
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
|
||||
class Overpass {
|
||||
|
||||
val overpassUrl = "https://overpass.kumi.systems/api/interpreter"
|
||||
fun getAmenities(category: String, location: Location) : List<Elements> {
|
||||
val boundingBox = getOverpassBbox(location, 2.0)
|
||||
val bb = getBoundingBox2(location, 2.0)
|
||||
val url = "https://overpass.kumi.systems/api/interpreter"
|
||||
val httpURLConnection = URL(url).openConnection() as HttpURLConnection
|
||||
val boundingBox = NavigationUtils.getOverpassBbox(location, 2.0)
|
||||
val bb = NavigationUtils.getBoundingBox2(location, 2.0)
|
||||
val httpURLConnection = URL(overpassUrl).openConnection() as HttpURLConnection
|
||||
httpURLConnection.requestMethod = "POST"
|
||||
httpURLConnection.setRequestProperty(
|
||||
"Accept",
|
||||
"application/json"
|
||||
)
|
||||
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
|
||||
val test = """
|
||||
|[out:json];
|
||||
@@ -56,12 +36,9 @@ class Overpass {
|
||||
outputStreamWriter.flush()
|
||||
// Check if the connection is successful
|
||||
val responseCode = httpURLConnection.responseCode
|
||||
println("Overpass: $responseCode")
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
val response = httpURLConnection.inputStream.bufferedReader()
|
||||
.use { it.readText() } // defaults to UTF-8
|
||||
|
||||
|
||||
val gson = GsonBuilder().serializeNulls().create()
|
||||
val overpass = gson.fromJson(response, Amenity::class.java)
|
||||
println("Overpass: $response")
|
||||
@@ -17,6 +17,6 @@ data class Tags (
|
||||
@SerializedName("operator:wikipedia" ) var operatorWikipedia : String? = null,
|
||||
@SerializedName("ref" ) var ref : 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
|
||||
|
||||
)
|
||||
@@ -52,7 +52,6 @@ open class RouteModel() {
|
||||
this.routeState = routeState.copy(
|
||||
route = null,
|
||||
isNavigating = false,
|
||||
// destination = Place(),
|
||||
arrived = false,
|
||||
maneuverType = 0,
|
||||
currentShapeIndex = 0,
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Locations
|
||||
import com.kouros.navigation.data.NavigationRepository
|
||||
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.SearchFilter
|
||||
@@ -118,7 +118,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
|
||||
.orderDesc(Place_.lastDate)
|
||||
.build()
|
||||
val results = query.find()
|
||||
println("Favorites $results")
|
||||
query.close()
|
||||
for (place in results) {
|
||||
val plLocation = location(place.longitude, place.latitude)
|
||||
@@ -233,7 +232,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
|
||||
val address = repository.reverseAddress(location)
|
||||
val gson = GsonBuilder().serializeNulls().create()
|
||||
val place = gson.fromJson(address, SearchResult::class.java)
|
||||
println(place.address.road)
|
||||
return place.address.road
|
||||
}
|
||||
|
||||
@@ -271,7 +269,6 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
|
||||
val current = LocalDateTime.now(ZoneOffset.UTC)
|
||||
place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond()
|
||||
placeBox.put(place)
|
||||
println("Save Place $place")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import com.kouros.navigation.data.BoundingBox
|
||||
import com.kouros.navigation.data.Constants.SHARED_PREF_KEY
|
||||
import com.kouros.navigation.data.GeoJsonFeature
|
||||
import com.kouros.navigation.data.GeoJsonFeatureCollection
|
||||
import com.kouros.navigation.data.GeoJsonLineString
|
||||
import com.kouros.navigation.data.GeoJsonType
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.maplibre.geojson.FeatureCollection
|
||||
import org.maplibre.geojson.Point
|
||||
@@ -23,12 +23,9 @@ import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sin
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@@ -149,9 +146,8 @@ object NavigationUtils {
|
||||
// 4. Create and return the Location object.
|
||||
return location(centerPoint.longitude(), centerPoint.latitude())
|
||||
}
|
||||
fun createGeoJson(lineCoordinates: List<List<Double>>): String {
|
||||
|
||||
val lineString = GeoJsonLineString(type = "LineString", coordinates = lineCoordinates)
|
||||
fun createGeoJson(type : String, lineCoordinates: List<List<Double>>): String {
|
||||
val lineString = GeoJsonType(type = type, coordinates = lineCoordinates)
|
||||
val feature = GeoJsonFeature(type = "Feature", geometry = lineString)
|
||||
val featureCollection =
|
||||
GeoJsonFeatureCollection(type = "FeatureCollection", features = listOf(feature))
|
||||
@@ -159,6 +155,8 @@ object NavigationUtils {
|
||||
return jsonString
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun getOverpassBbox(location: Location, radius: Double): String {
|
||||
val bbox = getBoundingBox(location.longitude, location.latitude, radius)
|
||||
val neLon = bbox["ne"]?.get("lon")
|
||||
|
||||
Reference in New Issue
Block a user