ref: 6c4c53cab51fb8832ffdb2ce5df4fb587dd16209
app/src/main/java/xyz/apiote/bimba/czwek/api/transitousQueryables.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
// SPDX-FileCopyrightText: Adam Evyčędo // // SPDX-License-Identifier: AGPL-3.0-or-later package xyz.apiote.bimba.czwek.api import android.content.Context import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.api.transitous.api.GeocodeApi import xyz.apiote.bimba.czwek.api.transitous.api.MapApi import xyz.apiote.bimba.czwek.api.transitous.model.Match import xyz.apiote.bimba.czwek.repo.Position import xyz.apiote.bimba.czwek.repo.Queryable import xyz.apiote.bimba.czwek.repo.Stop import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.units.DistanceUnit import xyz.apiote.bimba.czwek.units.Km import xyz.apiote.bimba.czwek.units.Metre import java.util.Locale import kotlin.math.PI import kotlin.math.abs import kotlin.math.cos val MetresPerDegreeLatitude = Metre(111320.0) suspend fun getTransitousQueryables(query: String, context: Context): List<Queryable> { if (!isNetworkAvailable(context)) { throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) } return withContext(Dispatchers.IO) { GeocodeApi().geocode(query, Locale.getDefault().language).filter { it.type == Match.Type.STOP } .map { Stop(it) } } } suspend fun locateTransitousQueryables( br: Position, tl: Position, context: Context ): List<Queryable> { if (!isNetworkAvailable(context)) { throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) } val dLat = abs(br.latitude - tl.latitude) / 2 var dLon = abs(br.longitude - tl.longitude) / 2 val centre = Position(abs(br.latitude + tl.latitude) / 2, abs(br.longitude + tl.longitude) / 2) val latitudeLimit = Km(10.0).meters()/MetresPerDegreeLatitude.meters() // ~radius in degrees latitude val corners = if (dLat > latitudeLimit) { dLon = dLon * latitudeLimit / dLat val newBr = Position(centre.latitude-latitudeLimit, centre.longitude+dLon) val newTL = Position(centre.latitude+latitudeLimit, centre.longitude-dLon) Pair(newBr.toString(), newTL.toString()) } else { Pair(br.toString(), tl.toString()) } return withContext(Dispatchers.IO) { MapApi().stops(corners.first, corners.second).filter { it.stopId != null }.map { Stop(it) } } } suspend fun locateTransitousQueryables( position: Position, context: Context, radius: DistanceUnit = Metre(500.0) ): List<Queryable> { if (!isNetworkAvailable(context)) { throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) } val deltaLatitude = radius.meters() / MetresPerDegreeLatitude.meters() val deltaLongitude = radius.meters() / (cos(position.latitude * PI / 180) / 360 * 40075000) val br = Position(position.latitude - deltaLatitude, position.longitude + deltaLongitude) val tl = Position(position.latitude + deltaLatitude, position.longitude - deltaLongitude) return locateTransitousQueryables(br, tl, context).map { when (it) { is Stop -> it else -> null } }.filterNotNull().sortedWith(Stop.distanceComparator(position)) } |