Overpass Performance, ApplicationConfig
This commit is contained in:
@@ -29,6 +29,7 @@ android {
|
||||
|
||||
buildConfigField("String", "USER", "\"${properties.getProperty("USER") ?: ""}\"")
|
||||
buildConfigField("String", "PASSWORD", "\"${properties.getProperty("PASSWORD") ?: ""}\"")
|
||||
buildConfigField("String", "TANKER_KOENIG_API_KEY", "\"${properties.getProperty("TANKER_KOENIG_API_KEY") ?: ""}\"")
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
|
||||
@@ -4,14 +4,16 @@ import com.kouros.data.BuildConfig
|
||||
|
||||
data class ApplicationConfig(
|
||||
val user: String,
|
||||
val password: String
|
||||
val password: String,
|
||||
val tankerKoenigApiKey: String
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun load(): ApplicationConfig {
|
||||
return ApplicationConfig(
|
||||
user = BuildConfig.USER,
|
||||
password = BuildConfig.PASSWORD
|
||||
password = BuildConfig.PASSWORD,
|
||||
tankerKoenigApiKey = BuildConfig.TANKER_KOENIG_API_KEY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,18 +21,19 @@ private val gson = GsonBuilder().serializeNulls().create()
|
||||
|
||||
const val sort = "&sort=dist&type=all"
|
||||
|
||||
const val apiKey = "&apikey=fc9900c9-8f02-4b28-990d-dc6067228c59"
|
||||
|
||||
val useLocal = BuildConfig.DEBUG
|
||||
|
||||
class FuelPrices : NavigationRepository() {
|
||||
|
||||
private val config by lazy { com.kouros.navigation.data.ApplicationConfig.load() }
|
||||
|
||||
fun getFuelPrices(location: Location, radius: Int) : List<Station> {
|
||||
|
||||
val url = if (useLocal) {
|
||||
"http://192.168.1.37/fuel.json"
|
||||
} else {
|
||||
"${tankerKoenigUrl}lat=${location.latitude}&lng=${location.longitude}&rad=${radius}$sort$apiKey"
|
||||
"${tankerKoenigUrl}lat=${location.latitude}&lng=${location.longitude}&rad=${radius}$sort&apikey=${config.tankerKoenigApiKey}"
|
||||
}
|
||||
|
||||
val prices = fetchUrl(
|
||||
@@ -49,7 +50,7 @@ class FuelPrices : NavigationRepository() {
|
||||
carOrientation: Float,
|
||||
searchFilter: SearchFilter
|
||||
): String {
|
||||
TODO("Not yet implemented")
|
||||
return ""
|
||||
}
|
||||
|
||||
override fun getTraffic(
|
||||
|
||||
@@ -51,7 +51,7 @@ class Overpass {
|
||||
}
|
||||
|
||||
val searchQuery = """
|
||||
|[out:json];
|
||||
|[out:json][timeout:10];
|
||||
|(
|
||||
| ${searchClauses.joinToString(";")};
|
||||
|);
|
||||
@@ -75,7 +75,7 @@ class Overpass {
|
||||
val searchLocation ="way[\"highway\"~\"^(primary|secondary|tertiary|residential|motorway)$\"][name](around:50, $lineString)";
|
||||
|
||||
val searchQuery = """
|
||||
|[out:json];
|
||||
|[out:json][timeout:10];
|
||||
|(
|
||||
| ${searchLocation};
|
||||
|);
|
||||
|
||||
@@ -51,6 +51,8 @@ import kotlin.collections.first
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.comparisons.compareBy
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* ViewModel for navigation-related data operations.
|
||||
@@ -58,6 +60,8 @@ import kotlin.math.absoluteValue
|
||||
*/
|
||||
class NavigationViewModel(private val repository: NavigationRepository) : ViewModel() {
|
||||
|
||||
private val overpass = Overpass()
|
||||
|
||||
/** LiveData containing the calculated route JSON string */
|
||||
val route: MutableLiveData<String> by lazy {
|
||||
MutableLiveData()
|
||||
@@ -411,7 +415,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val repository = getSettingsRepository(carContext)
|
||||
val amenities = Overpass().getAmenities("amenity", category, location, 5.0)
|
||||
val amenities = overpass.getAmenities("amenity", category, location, 5.0)
|
||||
val fuelPrices = fuelStations(category, lastFuelUpdate, location, repository)
|
||||
val distAmenities = mutableListOf<Elements>()
|
||||
amenities.forEach {
|
||||
@@ -473,7 +477,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
fun getSpeedCameras(location: Location, radius: Double) {
|
||||
synchronized(this) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val amenities = Overpass().getAmenities("highway", "speed_camera", location, radius)
|
||||
val amenities = overpass.getAmenities("highway", "speed_camera", location, radius)
|
||||
val distAmenities = mutableListOf<Elements>()
|
||||
amenities.forEach {
|
||||
val plLocation =
|
||||
@@ -509,43 +513,46 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
*/
|
||||
fun calculateSpeedLimit(location: Location, routeBearing: Float, countryCode: String): Int {
|
||||
var speed = 0
|
||||
var element: Elements?
|
||||
val search = mutableListOf<ElementSearch>()
|
||||
|
||||
synchronized(this) {
|
||||
speedElements.filter { it.type == "way" }.forEach {
|
||||
var distance: Float
|
||||
var maxDistance = 1000F
|
||||
var geometryFirstLocation = location(0.0, 0.0)
|
||||
var geometryLastLocation = location(0.0, 0.0)
|
||||
for ((geoIndex, geo) in it.geometry.withIndex()) {
|
||||
if (geoIndex == 0) {
|
||||
geometryFirstLocation = location(geo.lon, geo.lat)
|
||||
}
|
||||
if (geoIndex == it.geometry.size - 1) {
|
||||
geometryLastLocation = location(geo.lon, geo.lat)
|
||||
}
|
||||
val geometryLocation = location(geo.lon, geo.lat)
|
||||
distance = geometryLocation.distanceTo(location)
|
||||
if (distance < maxDistance) {
|
||||
maxDistance = distance
|
||||
}
|
||||
// Equirectangular projection at the user's latitude. Closest-point ranking
|
||||
// doesn't need geodesic accuracy, so we skip Location.distanceTo (Vincenty)
|
||||
// and avoid allocating a Location per geometry vertex.
|
||||
val userLat = location.latitude
|
||||
val userLon = location.longitude
|
||||
val metersPerDegLat = 111_320.0
|
||||
val metersPerDegLon = metersPerDegLat * cos(Math.toRadians(userLat))
|
||||
|
||||
for (element in speedElements) {
|
||||
if (element.type != "way") continue
|
||||
val geometry = element.geometry
|
||||
if (geometry.isEmpty()) continue
|
||||
|
||||
var minDistanceSq = Double.MAX_VALUE
|
||||
for (geo in geometry) {
|
||||
val dx = (geo.lon - userLon) * metersPerDegLon
|
||||
val dy = (geo.lat - userLat) * metersPerDegLat
|
||||
val sq = dx * dx + dy * dy
|
||||
if (sq < minDistanceSq) minDistanceSq = sq
|
||||
}
|
||||
val streetBearing = geometryFirstLocation.bearingPositive(geometryLastLocation)
|
||||
if (isBearingValid(it, streetBearing, routeBearing)) {
|
||||
val minDistance = sqrt(minDistanceSq)
|
||||
|
||||
val first = geometry.first()
|
||||
val last = geometry.last()
|
||||
val streetBearing = location(first.lon, first.lat)
|
||||
.bearingPositive(location(last.lon, last.lat))
|
||||
|
||||
if (isBearingValid(element, streetBearing, routeBearing)) {
|
||||
search.add(
|
||||
ElementSearch(
|
||||
it,
|
||||
maxDistance.toDouble(),
|
||||
streetBearing.absoluteValue
|
||||
)
|
||||
ElementSearch(element, minDistance, streetBearing.absoluteValue)
|
||||
)
|
||||
}
|
||||
}
|
||||
val result =
|
||||
search.sortedWith(compareBy<ElementSearch> { it.distance }.thenByDescending { it.bearing })
|
||||
if (result.isNotEmpty()) {
|
||||
element = result.first().element
|
||||
val element = result.first().element
|
||||
speed = if (element.tags.maxspeed == "none" && element.tags.highway == "motorway") {
|
||||
countryCodeSpeedLimit(countryCode)
|
||||
} else {
|
||||
@@ -585,7 +592,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
synchronized(this) {
|
||||
val lineString = "${location.latitude},${location.longitude}"
|
||||
val elements =
|
||||
Overpass().getSpeedLimit(SPEED_UPDATE_DISTANCE, lineString, street, roadNumbers)
|
||||
overpass.getSpeedLimit(SPEED_UPDATE_DISTANCE, lineString, street, roadNumbers)
|
||||
speedElements.clear()
|
||||
speedElements.addAll(elements)
|
||||
}
|
||||
@@ -740,7 +747,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
fun loadCurrentLocation(location: Location) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
synchronized(this) {
|
||||
val elements = Overpass().getStreet(location)
|
||||
val elements = overpass.getStreet(location)
|
||||
if (elements.isNotEmpty()) {
|
||||
val points = mutableListOf<Point>()
|
||||
elements.first().geometry.forEach {
|
||||
|
||||
@@ -17,6 +17,7 @@ class RouteCalculator(var routeModel: RouteModel) {
|
||||
|
||||
var bestMatch: StepMatch? = null
|
||||
var lastSpeedLocation: Location = location(0.0, 0.0)
|
||||
var lastLocalSpeedLocation: Location = location(0.0, 0.0)
|
||||
|
||||
var lastSpeedIndex: Int = 0
|
||||
|
||||
@@ -157,13 +158,16 @@ class RouteCalculator(var routeModel: RouteModel) {
|
||||
if ((distance > SPEED_UPDATE_DISTANCE * 2) || lastSpeedIndex < routeModel.route.currentStepIndex) {
|
||||
lastSpeedIndex = routeModel.route.currentStepIndex
|
||||
lastSpeedLocation = location
|
||||
// Force the local re-match on the next GPS fix once new elements arrive.
|
||||
lastLocalSpeedLocation = location(0.0, 0.0)
|
||||
|
||||
viewModel.updateSpeedLimit(
|
||||
location,
|
||||
routeModel.route.currentStep().street,
|
||||
routeModel.currentStep().roadNumbers
|
||||
)
|
||||
} else {
|
||||
} else if (lastLocalSpeedLocation.distanceTo(location) >= NEAREST_LOCATION_DISTANCE) {
|
||||
lastLocalSpeedLocation = location
|
||||
viewModel.getSpeedLimit(
|
||||
location,
|
||||
routeModel.navState.routeBearing,
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user