Restaurants
This commit is contained in:
@@ -17,8 +17,8 @@ android {
|
||||
applicationId = "com.kouros.navigation"
|
||||
minSdk = 33
|
||||
targetSdk = 37
|
||||
versionCode = 107
|
||||
versionName = "0.3.0.107"
|
||||
versionCode = 108
|
||||
versionName = "0.3.0.108"
|
||||
base.archivesName = "navi-$versionName"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -755,7 +755,11 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
val duration = Duration.between(current, lastTrafficDate)
|
||||
if (showTraffic && duration.abs().seconds > TRAFFIC_UPDATE) {
|
||||
lastTrafficDate = current
|
||||
navigationViewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
|
||||
navigationViewModel.loadTraffic(
|
||||
carContext,
|
||||
location,
|
||||
surfaceRenderer.carOrientation
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,20 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.data.ClosedColor
|
||||
import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||
import com.kouros.navigation.data.HeavyColor
|
||||
import com.kouros.navigation.data.LaneColor
|
||||
import com.kouros.navigation.data.NavigationColorDark
|
||||
import com.kouros.navigation.data.NavigationColorLight
|
||||
import com.kouros.navigation.data.PharmacyColor
|
||||
import com.kouros.navigation.data.QueuingColor
|
||||
import com.kouros.navigation.data.RoadworksColor
|
||||
import com.kouros.navigation.data.RouteColor
|
||||
import com.kouros.navigation.data.SlowColor
|
||||
import com.kouros.navigation.data.SpeedColor
|
||||
import com.kouros.navigation.data.StationaryColor
|
||||
import com.kouros.navigation.data.ViewStyle
|
||||
import com.kouros.navigation.utils.GeoUtils.createEndCollection
|
||||
import com.kouros.navigation.utils.GeoUtils.createPointCollection
|
||||
@@ -180,6 +188,12 @@ fun RouteLayer(routeData: String?) {
|
||||
fun TrafficLayer(trafficData: Map<String, String>) {
|
||||
trafficData.forEach {
|
||||
val traffic = rememberGeoJsonSource(GeoJsonData.JsonString(it.value))
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}-casing",
|
||||
source = traffic,
|
||||
color = const(Color.White),
|
||||
width = routeLineWidth(base = 2.dp, isCasing = true),
|
||||
)
|
||||
LineLayer(
|
||||
id = "traffic-${it.key}",
|
||||
source = traffic,
|
||||
@@ -289,13 +303,13 @@ fun trafficImage(key: String): Expression<ImageValue> {
|
||||
|
||||
fun trafficColor(key: String): Expression<ColorValue> {
|
||||
when (key) {
|
||||
"queuing" -> return const(Color(0xFFC46E53))
|
||||
"slow" -> return const(Color(0xFFC43E3E))
|
||||
"stationary" -> return const(Color(0xFF910A0A))
|
||||
"heavy" -> return const(Color(0xFF6B0404))
|
||||
"roadworks" -> return const(Color(0xFFDAA707))
|
||||
"closed" -> return const(Color(0xFF210C0F))
|
||||
"lane" -> return const(Color(0xFFEFBAC1))
|
||||
"queuing" -> return const(QueuingColor)
|
||||
"slow" -> return const(SlowColor)
|
||||
"stationary" -> return const(StationaryColor)
|
||||
"heavy" -> return const(HeavyColor)
|
||||
"roadworks" -> return const(RoadworksColor)
|
||||
"closed" -> return const(ClosedColor)
|
||||
"lane" -> return const(LaneColor)
|
||||
}
|
||||
return const(Color.Blue)
|
||||
}
|
||||
@@ -306,11 +320,14 @@ fun AmenityLayer(routeData: String?) {
|
||||
var color = const(Color.Red)
|
||||
var img = image(painterResource(R.drawable.local_pharmacy_24px), drawAsSdf = true)
|
||||
if (routeData.contains(Constants.CHARGING_STATION)) {
|
||||
color = const(Color(0xFF054603))
|
||||
color = const(PharmacyColor)
|
||||
img = image(painterResource(R.drawable.ev_station_24px), drawAsSdf = true)
|
||||
} else if (routeData.contains(Constants.FUEL_STATION)) {
|
||||
color = const(Color.Blue)
|
||||
img = image(painterResource(R.drawable.local_gas_station_24), drawAsSdf = true)
|
||||
} else if (routeData.contains(Constants.RESTAURANT)) {
|
||||
color = const(Color.Magenta)
|
||||
img = image(painterResource(R.drawable.restaurant_24px), drawAsSdf = true)
|
||||
}
|
||||
val routes = rememberGeoJsonSource(GeoJsonData.JsonString(routeData))
|
||||
SymbolLayer(
|
||||
|
||||
@@ -4,6 +4,8 @@ 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.GridItem
|
||||
import androidx.car.app.model.GridTemplate
|
||||
import androidx.car.app.model.Header
|
||||
import androidx.car.app.model.ItemList
|
||||
import androidx.car.app.model.ListTemplate
|
||||
@@ -16,6 +18,7 @@ import com.kouros.navigation.data.Category
|
||||
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
||||
import com.kouros.navigation.data.Constants.FUEL_STATION
|
||||
import com.kouros.navigation.data.Constants.PHARMACY
|
||||
import com.kouros.navigation.data.Constants.RESTAURANT
|
||||
import com.kouros.navigation.data.ViewStyle
|
||||
import com.kouros.navigation.model.NavigationViewModel
|
||||
|
||||
@@ -30,22 +33,18 @@ class CategoriesScreen(
|
||||
var categories: List<Category> = listOf(
|
||||
Category(id = FUEL_STATION, name = carContext.getString(R.string.fuel_station)),
|
||||
Category(id = PHARMACY, name = carContext.getString(R.string.pharmacy)),
|
||||
Category(id = CHARGING_STATION, name = carContext.getString(R.string.charging_station))
|
||||
Category(id = CHARGING_STATION, name = carContext.getString(R.string.charging_station)),
|
||||
Category(id = RESTAURANT, name = carContext.getString(R.string.restaurant))
|
||||
)
|
||||
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
val itemListBuilder = ItemList.Builder()
|
||||
.setNoItemsMessage("No categories to show")
|
||||
categories.forEach {
|
||||
itemListBuilder.addItem(
|
||||
Row.Builder()
|
||||
.setTitle(it.name)
|
||||
GridItem.Builder()
|
||||
.setImage(carIcon(carContext, it.id, -1))
|
||||
.setTitle(it.name)
|
||||
.setOnClickListener {
|
||||
category = it.id
|
||||
screenManager
|
||||
@@ -55,7 +54,7 @@ class CategoriesScreen(
|
||||
surfaceRenderer,
|
||||
category,
|
||||
navigationViewModel,
|
||||
)
|
||||
)
|
||||
) { obj: Any? ->
|
||||
if (obj != null) {
|
||||
setResult(obj)
|
||||
@@ -63,20 +62,19 @@ class CategoriesScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
.setBrowsable(true)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
surfaceRenderer.viewStyle = ViewStyle.AMENITY_VIEW
|
||||
|
||||
val header = Header.Builder()
|
||||
.setStartHeaderAction(Action.BACK)
|
||||
.setTitle(carContext.getString(R.string.category_title))
|
||||
.build()
|
||||
|
||||
return ListTemplate.Builder()
|
||||
.setHeader(header)
|
||||
return GridTemplate.Builder()
|
||||
.setHeader(
|
||||
Header.Builder()
|
||||
.setStartHeaderAction(Action.BACK)
|
||||
.setTitle(carContext.getString(R.string.category_title))
|
||||
.build()
|
||||
)
|
||||
.setSingleList(itemListBuilder.build())
|
||||
.build()
|
||||
}
|
||||
@@ -88,7 +86,7 @@ fun carIcon(context: CarContext, category: String, index: Int): CarIcon {
|
||||
CHARGING_STATION -> R.drawable.ev_station_24px
|
||||
FUEL_STATION -> R.drawable.local_gas_station_24
|
||||
PHARMACY -> R.drawable.local_pharmacy_24px
|
||||
else -> R.drawable.ic_place_white_24dp
|
||||
else -> R.drawable.restaurant_24px
|
||||
}
|
||||
return CarIcon.Builder(IconCompat.createWithResource(context, resId)).build()
|
||||
} else {
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Constants.CHARGING_STATION
|
||||
import com.kouros.navigation.data.Constants.FUEL_STATION
|
||||
import com.kouros.navigation.data.Constants.PHARMACY
|
||||
import com.kouros.navigation.data.Constants.RESTAURANT
|
||||
import com.kouros.navigation.data.Constants.TAG
|
||||
import com.kouros.navigation.data.Place
|
||||
import com.kouros.navigation.data.overpass.Elements
|
||||
@@ -52,7 +53,6 @@ class CategoryScreen(
|
||||
|
||||
) : Screen(carContext), CategoryObserverCallback {
|
||||
|
||||
|
||||
val repository = getSettingsRepository(carContext)
|
||||
|
||||
val settingsViewModel = getSettingsViewModel(carContext)
|
||||
@@ -77,7 +77,6 @@ class CategoryScreen(
|
||||
})
|
||||
|
||||
navigationViewModel.elements.observe(this, categoryObserver)
|
||||
//navigationViewModel.getAmenities(carContext, category, surfaceRenderer.lastLocation)
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
@@ -94,12 +93,10 @@ class CategoryScreen(
|
||||
)
|
||||
)
|
||||
elements.forEach {
|
||||
if (it.tags.operator != null) {
|
||||
if (index++ < listLimit) {
|
||||
listBuilder.addItem(
|
||||
createItem(it, category, index)
|
||||
)
|
||||
}
|
||||
if (index++ < listLimit) {
|
||||
listBuilder.addItem(
|
||||
createItem(it, category, index)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +130,7 @@ class CategoryScreen(
|
||||
CHARGING_STATION -> R.string.charging_station
|
||||
FUEL_STATION -> R.string.fuel_station
|
||||
PHARMACY -> R.string.pharmacy
|
||||
else -> R.string.no_places
|
||||
else -> R.string.restaurant
|
||||
}
|
||||
return carContext.getString(resId)
|
||||
}
|
||||
@@ -154,10 +151,10 @@ class CategoryScreen(
|
||||
}
|
||||
.setTitle(name)
|
||||
.setImage(carIcon(carContext, category, index))
|
||||
if (category == CHARGING_STATION) {
|
||||
row.addText("${it.tags.socketType2} X Typ 2 ${it.tags.socketType2Output}")
|
||||
} else {
|
||||
row.addText(carText(" ${it.e5} / ${it.e10} € ${it.tags.openingHours}"))
|
||||
when (category) {
|
||||
CHARGING_STATION -> row.addText("${it.tags.socketType2} X Typ 2 ${it.tags.socketType2Output}")
|
||||
FUEL_STATION -> row.addText(carText("${it.e5} / ${it.e10} € ${it.tags.openingHours}"))
|
||||
RESTAURANT, PHARMACY ->row.addText(carText(it.tags.openingHours))
|
||||
}
|
||||
if (it.distance < 1000) {
|
||||
row.addText("${(it.distance).toInt()} m")
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.kouros.navigation.car.screen
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.util.Log
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.CarToast
|
||||
@@ -13,7 +12,6 @@ import androidx.car.app.model.Action
|
||||
import androidx.car.app.model.Action.FLAG_DEFAULT
|
||||
import androidx.car.app.model.Action.FLAG_IS_PERSISTENT
|
||||
import androidx.car.app.model.CarColor
|
||||
import androidx.car.app.model.CarIcon
|
||||
import androidx.car.app.model.CarText
|
||||
import androidx.car.app.model.DurationSpan
|
||||
import androidx.car.app.model.ForegroundCarColorSpan
|
||||
@@ -26,7 +24,6 @@ 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.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.Observer
|
||||
@@ -35,7 +32,6 @@ import androidx.lifecycle.lifecycleScope
|
||||
import com.kouros.data.R
|
||||
import com.kouros.navigation.car.SurfaceRenderer
|
||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||
import com.kouros.navigation.data.Constants.TAG
|
||||
import com.kouros.navigation.data.Place
|
||||
import com.kouros.navigation.data.ViewStyle
|
||||
import com.kouros.navigation.data.route.Routes
|
||||
@@ -377,7 +373,6 @@ class RoutePreviewScreen(
|
||||
surfaceRenderer.carOrientation
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class RoutePreviewType {
|
||||
|
||||
@@ -50,7 +50,7 @@ fun createNumberIcon(category: String, number: String): IconCompat {
|
||||
CHARGING_STATION -> Color.GREEN
|
||||
FUEL_STATION -> Color.BLUE
|
||||
PHARMACY -> Color.RED
|
||||
else -> Color.WHITE
|
||||
else -> Color.MAGENTA
|
||||
}
|
||||
paint.color = color
|
||||
canvas.drawCircle(size / 2f, size / 2f, size / 2f, paint)
|
||||
|
||||
@@ -12,3 +12,13 @@ val SpeedColor = Color(0xFF262525)
|
||||
val MaxSpeedColor = Color(0xFFB71515)
|
||||
|
||||
val PlaceColor = Color(0xFF868005)
|
||||
|
||||
val QueuingColor = Color(0xFFC46E53)
|
||||
val SlowColor = Color(0xFFC43E3E)
|
||||
val StationaryColor = Color(0xFF910A0A)
|
||||
val HeavyColor = Color(0xFF6B0404)
|
||||
val RoadworksColor = Color(0xFFDAA707)
|
||||
val ClosedColor = Color(0xFF280C10)
|
||||
val LaneColor = Color(0xFFEFBAC1)
|
||||
|
||||
val PharmacyColor = Color(0xFF054603)
|
||||
@@ -122,6 +122,8 @@ object Constants {
|
||||
|
||||
const val CHARGING_STATION: String ="charging_station"
|
||||
|
||||
const val RESTAURANT: String ="restaurant"
|
||||
|
||||
/** The initial location to use as an anchor for searches. */
|
||||
val homeVogelhart = location(11.5793748, 48.185749)
|
||||
val homeHohenwaldeck = location( 11.594322, 48.1164817)
|
||||
|
||||
@@ -75,7 +75,7 @@ abstract class NavigationRepository {
|
||||
"Accept",
|
||||
"application/json"
|
||||
) // The format of response we want to get from the server
|
||||
httpURLConnection.setRequestProperty("User-Agent", "email=nominatim@kouros-online.de")
|
||||
httpURLConnection.setRequestProperty("User-Agent", "email=online@kouros-online.de")
|
||||
httpURLConnection.requestMethod = "GET"
|
||||
val responseCode = httpURLConnection.responseCode
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
|
||||
@@ -136,6 +136,7 @@ class Overpass {
|
||||
}
|
||||
}
|
||||
|
||||
Log.w("OverpassApi", searchQuery)
|
||||
val responseCode = connection.responseCode
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
val response = connection.inputStream.bufferedReader().use { it.readText() }
|
||||
|
||||
@@ -21,7 +21,7 @@ data class Tags(
|
||||
val capacity: String = "",
|
||||
val motorcar: String = "",
|
||||
val network: String = "",
|
||||
val openingHours: String = "",
|
||||
@SerializedName("opening_hours") val openingHours: String = "",
|
||||
val operator: String = "",
|
||||
val operatorShort: String = "",
|
||||
val operatorWikidata: String = "",
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.kouros.navigation.data.NavigationRepository
|
||||
import com.kouros.navigation.data.Place
|
||||
import com.kouros.navigation.data.Places
|
||||
import com.kouros.navigation.data.SearchFilter
|
||||
import com.kouros.navigation.data.fuel.FuelPrice
|
||||
import com.kouros.navigation.data.fuel.FuelPrices
|
||||
import com.kouros.navigation.data.fuel.Station
|
||||
import com.kouros.navigation.data.fuel.Stations
|
||||
@@ -28,15 +27,14 @@ import com.kouros.navigation.data.nominatim.SearchResult
|
||||
import com.kouros.navigation.data.overpass.ElementSearch
|
||||
import com.kouros.navigation.data.overpass.Elements
|
||||
import com.kouros.navigation.data.overpass.Overpass
|
||||
import com.kouros.navigation.repository.SettingsRepository
|
||||
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
||||
import com.kouros.navigation.utils.GeoUtils.transferCoordinates
|
||||
import com.kouros.navigation.utils.bearingPositive
|
||||
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
||||
import com.kouros.navigation.utils.getSettingsRepository
|
||||
import com.kouros.navigation.utils.getSettingsViewModel
|
||||
import com.kouros.navigation.utils.isNumeric
|
||||
import com.kouros.navigation.utils.location
|
||||
import com.kouros.navigation.utils.settingsViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -220,7 +218,11 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
* Fetches traffic incident data and categorizes by severity.
|
||||
* Posts categorized traffic map to traffic LiveData.
|
||||
*/
|
||||
fun loadTraffic(context: Context, currentLocation: Location, carOrientation: Float) {
|
||||
fun loadTraffic(
|
||||
context: Context,
|
||||
currentLocation: Location,
|
||||
carOrientation: Float,
|
||||
) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val data = repository.getTraffic(
|
||||
@@ -400,18 +402,8 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
fun getAmenities(carContext: Context, category: String, location: Location, lastFuelUpdate: Long = 0) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val repository = getSettingsRepository(carContext)
|
||||
var fuelPrices: List<Station>
|
||||
val amenities = Overpass().getAmenities("amenity", category, location, 5.0)
|
||||
val now = System.currentTimeMillis()
|
||||
if (category == Constants.FUEL_STATION && ((now - lastFuelUpdate) > TANKER_KOENIG_DELAY)) {
|
||||
fuelPrices = FuelPrices().getFuelPrices(location, 5)
|
||||
repository.setLastFuelPrices(System.currentTimeMillis())
|
||||
repository.setFuelPrices(gson.toJson(Stations(fuelPrices)))
|
||||
} else {
|
||||
val fuels = repository.fuelPricesFlow.first()
|
||||
fuelPrices =
|
||||
gson.fromJson(fuels, Stations::class.java).stations
|
||||
}
|
||||
val fuelPrices = fuelStations(category, lastFuelUpdate, location, repository)
|
||||
val distAmenities = mutableListOf<Elements>()
|
||||
amenities.forEach {
|
||||
val plLocation =
|
||||
@@ -428,6 +420,28 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fuelStations(
|
||||
category: String,
|
||||
lastFuelUpdate: Long,
|
||||
location: Location,
|
||||
repository: SettingsRepository
|
||||
): List<Station> {
|
||||
var fuelPrices = emptyList<Station>()
|
||||
if (category == Constants.FUEL_STATION) {
|
||||
val now = System.currentTimeMillis()
|
||||
if ((now - lastFuelUpdate) > TANKER_KOENIG_DELAY) {
|
||||
fuelPrices = FuelPrices().getFuelPrices(location, 5)
|
||||
repository.setLastFuelPrices(System.currentTimeMillis())
|
||||
repository.setFuelPrices(gson.toJson(Stations(fuelPrices)))
|
||||
} else {
|
||||
val fuels = repository.fuelPricesFlow.first()
|
||||
fuelPrices =
|
||||
gson.fromJson(fuels, Stations::class.java).stations
|
||||
}
|
||||
}
|
||||
return fuelPrices
|
||||
}
|
||||
|
||||
fun addFuelPrice(fuel: Elements, fuelPrices: List<Station>, location: Location) {
|
||||
fuelPrices.forEach {
|
||||
if (fuel.tags.name.equals(it.brand, ignoreCase = true)) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.kouros.navigation.utils
|
||||
|
||||
import android.location.Location
|
||||
import android.util.Log
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import org.maplibre.geojson.FeatureCollection
|
||||
@@ -24,6 +23,8 @@ import kotlin.math.sin
|
||||
|
||||
object GeoUtils {
|
||||
|
||||
const val EARTH_RADIUS = 6371.0 // in km
|
||||
|
||||
fun snapLocation(location: Location, stepCoordinates: List<Point>): Location {
|
||||
val newLocation = Location(location)
|
||||
val oldPoint = Point.fromLngLat(location.longitude, location.latitude)
|
||||
@@ -151,11 +152,10 @@ object GeoUtils {
|
||||
* @return latMin, latMax, lngMin, lngMax
|
||||
*/
|
||||
fun calculateSquareRadius(lat: Double, lng: Double, radius: Double): String {
|
||||
val earthRadius = 6371.0 // earth radius in km
|
||||
val latMin = lat - toDegrees(radius / earthRadius)
|
||||
val latMax = lat + toDegrees(radius / earthRadius)
|
||||
val lngMin = lng - toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
||||
val lngMax = lng + toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
||||
val latMin = lat - toDegrees(radius / EARTH_RADIUS)
|
||||
val latMax = lat + toDegrees(radius / EARTH_RADIUS)
|
||||
val lngMin = lng - toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||
val lngMax = lng + toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||
|
||||
return "$lngMin,$latMin,$lngMax,$latMax"
|
||||
}
|
||||
@@ -165,11 +165,10 @@ object GeoUtils {
|
||||
lon: Double,
|
||||
radius: Double
|
||||
): String {
|
||||
val earthRadius = 6371.0
|
||||
val maxLat = lat + toDegrees(radius / earthRadius)
|
||||
val minLat = lat - toDegrees(radius / earthRadius)
|
||||
val maxLon = lon + toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
||||
val minLon = lon - toDegrees(radius / earthRadius / cos(toRadians(lat)))
|
||||
val maxLat = lat + toDegrees(radius / EARTH_RADIUS)
|
||||
val minLat = lat - toDegrees(radius / EARTH_RADIUS)
|
||||
val maxLon = lon + toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||
val minLon = lon - toDegrees(radius / EARTH_RADIUS / cos(toRadians(lat)))
|
||||
|
||||
return "$minLat,$minLon,$maxLat,$maxLon"
|
||||
}
|
||||
@@ -229,21 +228,21 @@ object GeoUtils {
|
||||
fun movePoint(
|
||||
latitude: Double,
|
||||
longitude: Double,
|
||||
distanceMeters: Double = 7.0,
|
||||
distanceMeters: Double = 8.0,
|
||||
bearingDegrees: Double = 0.0
|
||||
): org.maplibre.spatialk.geojson.Point {
|
||||
val earthRadius = 6371000.0 // meters
|
||||
val radius = EARTH_RADIUS * 1000 // meters
|
||||
val bearingRadians = toRadians(bearingDegrees)
|
||||
val lat1 = toRadians(latitude)
|
||||
val lon1 = toRadians(longitude)
|
||||
|
||||
val lat2 = asin(
|
||||
sin(lat1) * cos(distanceMeters / earthRadius) +
|
||||
cos(lat1) * sin(distanceMeters / earthRadius) * cos(bearingRadians)
|
||||
sin(lat1) * cos(distanceMeters / radius) +
|
||||
cos(lat1) * sin(distanceMeters / radius) * cos(bearingRadians)
|
||||
)
|
||||
val lon2 = lon1 + atan2(
|
||||
sin(bearingRadians) * sin(distanceMeters / earthRadius) * cos(lat1),
|
||||
cos(distanceMeters / earthRadius) - sin(lat1) * sin(lat2)
|
||||
sin(bearingRadians) * sin(distanceMeters / radius) * cos(lat1),
|
||||
cos(distanceMeters / radius) - sin(lat1) * sin(lat2)
|
||||
)
|
||||
return org.maplibre.spatialk.geojson.Point(toDegrees(lon2), toDegrees(lat2))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,880L280,514Q229,500 194.5,458Q160,416 160,360L160,80L240,80L240,360L280,360L280,80L360,80L360,360L400,360L400,80L480,80L480,360Q480,416 445.5,458Q411,500 360,514L360,880L280,880ZM680,880L680,560L560,560L560,280Q560,197 618.5,138.5Q677,80 760,80L760,880L680,880Z"/>
|
||||
</vector>
|
||||
@@ -73,4 +73,5 @@
|
||||
<string name="engine_type">Motortyp</string>
|
||||
<string name="alternative_routes">Alternative Routen</string>
|
||||
<string name="wait">Warten</string>
|
||||
<string name="restaurant">Restaurant</string>
|
||||
</resources>
|
||||
|
||||
@@ -57,4 +57,5 @@
|
||||
<string name="engine_type">Τύπος κινητήρα</string>
|
||||
<string name="alternative_routes">Εναλλακτικές διαδρομές</string>
|
||||
<string name="wait">Περιμένετε</string>
|
||||
<string name="restaurant">Restaurant</string>
|
||||
</resources>
|
||||
|
||||
@@ -57,4 +57,5 @@
|
||||
<string name="engine_type">Typ silnika</string>
|
||||
<string name="alternative_routes">Alternatywne trasy</string>
|
||||
<string name="wait">Czekaj</string>
|
||||
<string name="restaurant">Restaurant</string>
|
||||
</resources>
|
||||
|
||||
@@ -60,4 +60,5 @@
|
||||
<string name="engine_type">Engine type</string>
|
||||
<string name="alternative_routes">Alternative routes</string>
|
||||
<string name="wait">Wait</string>
|
||||
<string name="restaurant">Restaurant</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user