App DrawItem and Search

This commit is contained in:
Dimitris
2025-12-09 15:52:27 +01:00
parent f70ca6e8fe
commit aeca6ff237
25 changed files with 868 additions and 654 deletions

View File

@@ -2,8 +2,10 @@ package com.kouros.navigation.data
import androidx.compose.ui.graphics.Color
val NavigationColor = Color(0xFF368605)
val NavigationColor = Color(0xFF052186)
val RouteColor = Color(0xFF5582D0)
val SpeedColor = Color(0xFF262525)
val SpeedColor = Color(0xFF262525)
val PlaceColor = Color(0xFF868005)

View File

@@ -62,7 +62,6 @@ data class ContactData(
data class StepData (
var instruction: String,
var leftDistance: Double,
var bearing: Double
)
@@ -138,8 +137,6 @@ object Constants {
const val STYLE: String = "https://kouros-online.de/liberty.json"
const val STYLE_DARK: String = "https://kouros-online.de/liberty_night.json"
//const val STYLE: String = "https://tiles.openfreemap.org/styles/liberty"
const val TAG: String = "Navigation"
const val CONTACTS: String = "Contacts"
@@ -175,6 +172,8 @@ object Constants {
const val MAXIMAL_ROUTE_DEVIATION = 100.0
const val DESTINATION_ARRIVAL_DISTANCE = 20.0
}

View File

@@ -39,11 +39,11 @@ class NavigationRepository {
// motorway, trunk, primary, secondary, tertiary, unclassified, residential, service_other.
// exclude_toll
fun getRoute(currentLocation: Location, location: Location, SearchFilter: SearchFilter): String {
fun getRoute(currentLocation: Location, location: Location, searchFilter: SearchFilter): String {
SearchFilter
val vLocation = listOf(
Locations(lat = currentLocation.latitude, lon = currentLocation.longitude, search_filter = SearchFilter),
Locations(lat = location.latitude, lon = location.longitude, search_filter = SearchFilter)
Locations(lat = currentLocation.latitude, lon = currentLocation.longitude, search_filter = searchFilter),
Locations(lat = location.latitude, lon = location.longitude, search_filter = searchFilter)
)
val valhallaLocation = ValhallaLocation(
locations = vLocation,

View File

@@ -47,9 +47,9 @@
"source": "openmaptiles",
"source-layer": "park",
"paint": {
"fill-color": "#d8e8c8",
"fill-color": "rgba(78, 100, 56, 1)",
"fill-opacity": 0.7,
"fill-outline-color": "rgba(95, 208, 100, 1)"
"fill-outline-color": "rgba(39, 78, 40, 1)"
}
},
{
@@ -101,7 +101,7 @@
"filter": ["==", ["get", "class"], "grass"],
"paint": {
"fill-antialias": false,
"fill-color": "rgba(176, 213, 154, 1)",
"fill-color": "rgba(21, 32, 15, 1)",
"fill-opacity": 0.3
}
},
@@ -153,7 +153,7 @@
"source": "openmaptiles",
"source-layer": "landuse",
"filter": ["==", ["get", "class"], "cemetery"],
"paint": {"fill-color": "hsl(75,37%,81%)"}
"paint": {"fill-color": "rgba(65, 74, 92, 1)"}
},
{
"id": "landuse_hospital",
@@ -169,7 +169,7 @@
"source": "openmaptiles",
"source-layer": "landuse",
"filter": ["==", ["get", "class"], "school"],
"paint": {"fill-color": "rgb(236,238,204)"}
"paint": {"fill-color": "rgba(65, 74, 92, 1)"}
},
{
"id": "waterway_tunnel",
@@ -905,7 +905,6 @@
],
"layout": {"line-cap": "round", "line-join": "round"},
"paint": {
"line-color": "#cfcdca",
"line-width": [
"interpolate",
["exponential", 1.2],
@@ -916,7 +915,8 @@
4,
20,
11
]
],
"line-color": "rgba(65, 74, 92, 1)"
}
},
{
@@ -975,7 +975,6 @@
],
"layout": {"line-cap": "round", "line-join": "round"},
"paint": {
"line-color": "#cfcdca",
"line-opacity": ["interpolate", ["linear"], ["zoom"], 12, 0, 12.5, 1],
"line-width": [
"interpolate",
@@ -989,7 +988,8 @@
4,
20,
20
]
],
"line-color": "rgba(65, 74, 92, 1)"
}
},
{
@@ -1095,7 +1095,7 @@
],
"layout": {"line-join": "round"},
"paint": {
"line-color": "hsl(0,0%,100%)",
"line-color": "rgba(65, 74, 92, 1)",
"line-dasharray": [1, 0.7],
"line-width": [
"interpolate",
@@ -1219,7 +1219,6 @@
],
"layout": {"line-cap": "round", "line-join": "round"},
"paint": {
"line-color": "rgba(195, 190, 190, 1)",
"line-width": [
"interpolate",
["exponential", 1.2],
@@ -1230,7 +1229,8 @@
2.5,
20,
18
]
],
"line-color": "rgba(65, 74, 92, 1)"
}
},
{

View File

@@ -30,8 +30,6 @@ open class RouteModel() {
var distanceToStepEnd = 0F
var bearing = 0F
var beginIndex = 0
var endIndex = 0
@@ -57,7 +55,7 @@ open class RouteModel() {
val currentDistance: Double
/** Returns the current [Step] with information such as the cue text and images. */
get() {
return ((leftStepDistance() * 1000).roundToInt().toDouble() / 10.0).roundToInt() * 10.0
return ((leftStepDistance()).roundToInt().toDouble() / 10.0).roundToInt() * 10.0
}
fun updateLocation(location: Location) {
@@ -86,14 +84,7 @@ open class RouteModel() {
route.pointLocations[currentShapeIndex].longitude(),
route.pointLocations[currentShapeIndex].latitude()
)
// if (currentShapeIndex < route.pointLocations.size) {
// val nextLocation = location(
// route.pointLocations[currentShapeIndex + 1].latitude(),
// route.pointLocations[currentShapeIndex + 1].longitude()
// )
// bearing = curLocation.bearingTo(nextLocation)
// }
val distanceStepLeft = leftStepDistance() * 1000
val distanceStepLeft = leftStepDistance()
when (distanceStepLeft) {
in 0.0..NEXT_STEP_THRESHOLD -> {
if (route.currentManeuverIndex < route.maneuvers.size) {
@@ -104,7 +95,7 @@ open class RouteModel() {
}
}
}
return StepData(text, distanceStepLeft, bearing.toDouble())
return StepData(text, distanceStepLeft)
}
/** Calculates the index in a maneuver. */
@@ -174,16 +165,17 @@ open class RouteModel() {
return timeLeft
}
/** Returns the current [Step] left distance in km. */
/** Returns the current [Step] left distance in m. */
fun leftStepDistance(): Double {
val maneuver = route.currentManeuver()
var leftDistance = maneuver.length
if (endIndex > 0) {
leftDistance = (distanceToStepEnd / 1000).toDouble()
leftDistance = distanceToStepEnd.toDouble()
}
return leftDistance
return leftDistance * 1000
}
/** Returns the left distance in km. */
fun travelLeftDistance(): Double {
var leftDistance = 0.0
for (i in route.currentManeuverIndex + 1..<route.maneuvers.size) {

View File

@@ -3,11 +3,14 @@ package com.kouros.navigation.model
import android.content.Context
import android.location.Geocoder
import android.location.Location
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.GsonBuilder
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.Place
@@ -64,20 +67,21 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val results = query.find()
query.close()
for (place in results) {
val plLocation = location(place.longitude,place.latitude)
// val distance = repository.getRouteDistance(location, plLocation)
val plLocation = location(place.longitude, place.latitude)
//val distance = repository.getRouteDistance(location, plLocation, SearchFilter())
//place.distance = distance.toFloat()
if (place.distance == 0F) {
recentPlace.postValue(place)
return@launch
}
//if (place.distance == 0F) {
recentPlace.postValue(place)
return@launch
//}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun loadPlaces(context: Context, location: Location) {
fun loadRecentPlaces(context: Context, location: Location) {
viewModelScope.launch(Dispatchers.IO) {
try {
val placeBox = boxStore.boxFor(Place::class)
@@ -89,7 +93,8 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
query.close()
for (place in results) {
val plLocation = location(place.longitude, place.latitude)
val distance = repository.getRouteDistance(location, plLocation, getSearchFilter(context))
val distance =
repository.getRouteDistance(location, plLocation, getSearchFilter(context))
place.distance = distance.toFloat()
}
places.postValue(results)
@@ -110,8 +115,9 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
val results = query.find()
query.close()
for (place in results) {
val plLocation = location(place.longitude, place.latitude )
val distance = repository.getRouteDistance(location, plLocation, getSearchFilter(context))
val plLocation = location(place.longitude, place.latitude)
val distance =
repository.getRouteDistance(location, plLocation, getSearchFilter(context))
place.distance = distance.toFloat()
}
favorites.postValue(results)
@@ -124,7 +130,13 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
fun loadRoute(context: Context, currentLocation: Location, location: Location) {
viewModelScope.launch(Dispatchers.IO) {
try {
route.postValue(repository.getRoute(currentLocation, location, getSearchFilter(context)))
route.postValue(
repository.getRoute(
currentLocation,
location,
getSearchFilter(context)
)
)
} catch (e: Exception) {
e.printStackTrace()
}
@@ -134,7 +146,13 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
fun loadPreviewRoute(context: Context, currentLocation: Location, location: Location) {
viewModelScope.launch(Dispatchers.IO) {
try {
previewRoute.postValue(repository.getRoute(currentLocation, location, getSearchFilter(context)))
previewRoute.postValue(
repository.getRoute(
currentLocation,
location,
getSearchFilter(context)
)
)
} catch (e: Exception) {
e.printStackTrace()
}
@@ -155,9 +173,13 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
) {
for (adr in it) {
if (addressLines.size > 1) {
val plLocation = location( adr.longitude, adr.latitude)
val plLocation = location(adr.longitude, adr.latitude)
val distance =
repository.getRouteDistance(currentLocation, plLocation, getSearchFilter(context))
repository.getRouteDistance(
currentLocation,
plLocation,
getSearchFilter(context)
)
contactList.add(
Place(
id = address.contactId,
@@ -201,7 +223,7 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
}
}
fun reverseAddress(location: Location ): String {
fun reverseAddress(location: Location): String {
val address = repository.reverseAddress(location)
val gson = GsonBuilder().serializeNulls().create()
val place = gson.fromJson(address, SearchResult::class.java)
@@ -213,16 +235,20 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
place.category = Constants.FAVORITES
savePlace(place)
}
fun saveRecent(place: Place) {
place.category = Constants.RECENT
savePlace(place)
}
fun savePlace(place: Place) {
viewModelScope.launch(Dispatchers.IO) {
try {
val placeBox = boxStore.boxFor(Place::class)
val query = placeBox
.query(Place_.name.equal(place.name!!).and(Place_.category.equal(place.category!!)))
.query(
Place_.name.equal(place.name!!).and(Place_.category.equal(place.category!!))
)
.build()
val results = query.find()
query.close()
@@ -247,12 +273,15 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
place.category = Constants.RECENT
deletePlace(place)
}
fun deletePlace(place: Place) {
viewModelScope.launch(Dispatchers.IO) {
try {
val placeBox = boxStore.boxFor(Place::class)
val query = placeBox
.query(Place_.name.equal(place.name!!).and(Place_.category.equal(place.category!!)))
.query(
Place_.name.equal(place.name!!).and(Place_.category.equal(place.category!!))
)
.build()
val results = query.find()
query.close()
@@ -267,11 +296,11 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
fun getSearchFilter(context: Context): SearchFilter {
val avoidMotorway = NavigationUtils.getBooleanKeyValue(
val avoidMotorway = NavigationUtils.getBooleanKeyValue(
context = context,
Constants.AVOID_MOTORWAY
)
val avoidTollway = NavigationUtils.getBooleanKeyValue(
val avoidTollway = NavigationUtils.getBooleanKeyValue(
context = context,
Constants.AVOID_TOLLWAY
)
@@ -280,5 +309,28 @@ class ViewModel(private val repository: NavigationRepository) : ViewModel() {
.avoidTollway(avoidTollway)
.build()
}
}
fun loadPlaces2(context: Context, location: Location): SnapshotStateList<Place?> {
val results = listOf<Place>()
try {
val placeBox = boxStore.boxFor(Place::class)
val query = placeBox
.query(Place_.name.notEqual("").and(Place_.category.equal(Constants.RECENT)))
.orderDesc(Place_.lastDate)
.build()
val results = query.find()
query.close()
for (place in results) {
val plLocation = location(place.longitude, place.latitude)
val distance =
repository.getRouteDistance(location, plLocation, getSearchFilter(context))
place.distance = distance.toFloat()
}
} catch (e: Exception) {
e.printStackTrace()
}
return results.toMutableStateList()
}
}

View File

@@ -11,7 +11,6 @@ import com.kouros.navigation.data.GeoJsonLineString
import kotlinx.serialization.json.Json
import org.maplibre.geojson.Point
import org.maplibre.turf.TurfMisc
import org.maplibre.turf.TurfMeasurement
import java.lang.Math.toDegrees
import java.lang.Math.toRadians
import kotlin.math.asin
@@ -151,20 +150,38 @@ object NavigationUtils {
fun calculateZoom(speed: Double?): Double {
if (speed == null) {
return 18.0
return 17.0
}
val zoom = when (speed.toInt()) {
val speedKmh = (speed * 3.6).toInt()
val zoom = when (speedKmh) {
in 0..10 -> 17.0
in 11..20 -> 17.0
in 21..30 -> 17.0
in 31..40 -> 16.0
in 41..50 -> 15.0
in 51..60 -> 14.0
else -> 14
in 11..30 -> 16.0
in 31..50 -> 16.0
in 51..60 -> 15.0
else -> 15
}
return zoom.toDouble()
}
fun bearing(fromLocation: Location, toLocation: Location ) : Double {
fun previewZoom(previewDistance: Double): Double {
when (previewDistance) {
in 0.0..10.0 -> {
return 13.0
}
in 10.0..20.0 -> {
return 11.0
}
in 20.0..30.0 -> {
return 10.0
}
}
return 9.0
}
fun bearing(fromLocation: Location, toLocation: Location, oldBearing: Double) : Double {
val distance = fromLocation.distanceTo(toLocation)
if (distance < 1.0) {
return oldBearing
}
val bearing = fromLocation.bearingTo(toLocation).toInt().toDouble()
return bearing
}