Merge pull request #473 from meshtastic/osm-features

add osm map features
This commit is contained in:
Andre K
2022-08-30 17:32:43 -03:00
committed by GitHub
11 changed files with 120 additions and 43 deletions

View File

@@ -120,7 +120,9 @@ data class NodeInfo(
var deviceMetrics: DeviceMetrics? = null
) : Parcelable {
val batteryPctLevel get() = deviceMetrics?.batteryLevel
val batteryLevel get() = deviceMetrics?.batteryLevel
val voltage get() = deviceMetrics?.voltage
val batteryStr get() = String.format("%d%% %.2fV", batteryLevel, voltage ?: 0)
/**
* true if the device was heard from recently
@@ -150,6 +152,13 @@ data class NodeInfo(
return if (p != null && op != null) p.distance(op).toInt() else null
}
/// @return bearing to the other position in degrees
fun bearing(o: NodeInfo?): Int? {
val p = validPosition
val op = o?.validPosition
return if (p != null && op != null) p.bearing(op).toInt() else null
}
/// @return a nice human readable string for the distance, or null for unknown
fun distanceStr(o: NodeInfo?) = distance(o)?.let { dist ->
when {

View File

@@ -19,9 +19,9 @@ import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.QuickChatAction
import com.geeksville.mesh.repository.datastore.LocalConfigRepository
import com.geeksville.mesh.service.MeshService
import com.geeksville.mesh.util.GPSFormat
import com.geeksville.mesh.util.positionToMeter
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -215,6 +215,16 @@ class UIViewModel @Inject constructor(
}
}
fun gpsString(pos: Position): String {
return when (_localConfig.value?.display?.gpsFormat) {
ConfigProtos.Config.DisplayConfig.GpsCoordinateFormat.GpsFormatDec -> GPSFormat.dec(pos)
ConfigProtos.Config.DisplayConfig.GpsCoordinateFormat.GpsFormatDMS -> GPSFormat.toDMS(pos)
ConfigProtos.Config.DisplayConfig.GpsCoordinateFormat.GpsFormatUTM -> GPSFormat.toUTM(pos)
ConfigProtos.Config.DisplayConfig.GpsCoordinateFormat.GpsFormatMGRS -> GPSFormat.toMGRS(pos)
else -> GPSFormat.dec(pos)
}
}
@Suppress("MemberVisibilityCanBePrivate")
val isRouter: Boolean =
localConfig.value?.device?.role == ConfigProtos.Config.DeviceConfig.Role.Router

View File

@@ -70,7 +70,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
map.let {
if (view != null) {
mapController = map.controller
binding.fabStyleToggle.setOnClickListener {
binding.mapStyleButton.setOnClickListener {
chooseMapStyle()
}
model.nodeDB.nodes.value?.let { nodes ->
@@ -121,17 +121,22 @@ class MapFragment : ScreenFragment("Map"), Logging {
val mrkr = nodesWithPosition.map { node ->
val p = node.position!!
debug("Showing on map: $node")
val f = GeoPoint(p.latitude, p.longitude)
lateinit var marker: MarkerWithLabel
node.user?.let {
val label = it.longName + " " + formatAgo(p.time)
marker = MarkerWithLabel(map, label)
marker.title = label
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
marker.position = f
marker.title = buildString {
append("$label ${node.batteryStr}\n${model.gpsString(p)}")
model.nodeDB.ourNodeInfo?.let { our ->
val dist = our.distanceStr(node)
if (dist != null) append(" (${our.bearing(node)}° $dist)")
}
}
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
marker.position = GeoPoint(p.latitude, p.longitude)
marker.icon = ContextCompat.getDrawable(
requireActivity(),
R.drawable.ic_twotone_person_pin_24
R.drawable.ic_twotone_location_on_24
)
}
marker
@@ -238,12 +243,12 @@ class MapFragment : ScreenFragment("Map"), Logging {
val p = mPositionPixels
val textPaint = Paint()
textPaint.textSize = 50f
textPaint.textSize = 40f
textPaint.color = Color.RED
textPaint.isAntiAlias = true
textPaint.textAlign = Paint.Align.CENTER
c.drawText(mLabel, (p.x - 0).toFloat(), (p.y - 60).toFloat(), textPaint)
c.drawText(mLabel, (p.x - 0f), (p.y - 80f), textPaint)
}
}
}

View File

@@ -114,15 +114,9 @@ class UsersFragment : ScreenFragment("Users"), Logging {
val pos = n.validPosition
if (pos != null) {
val coords =
String.format("%.5f %.5f", pos.latitude, pos.longitude).replace(",", ".")
val html =
"<a href='geo:${pos.latitude},${pos.longitude}?z=17&label=${
URLEncoder.encode(
name,
"utf-8"
)
}'>${coords}</a>"
val html = "<a href='geo:${pos.latitude},${pos.longitude}?z=17&label=${
URLEncoder.encode(name, "utf-8")
}'>${model.gpsString(pos)}</a>"
holder.coordsView.text = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
holder.coordsView.movementMethod = LinkMovementMethod.getInstance()
holder.coordsView.visibility = View.VISIBLE
@@ -138,7 +132,7 @@ class UsersFragment : ScreenFragment("Users"), Logging {
} else {
holder.distanceView.visibility = View.INVISIBLE
}
renderBattery(n.batteryPctLevel, n.deviceMetrics?.voltage, holder)
renderBattery(n.batteryLevel, n.voltage, holder)
holder.lastTime.text = formatAgo(n.lastHeard)

View File

@@ -1,6 +1,10 @@
package com.geeksville.mesh.util
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.Position
import mil.nga.grid.features.Point
import mil.nga.mgrs.MGRS
import mil.nga.mgrs.utm.UTM
import kotlin.math.abs
import kotlin.math.acos
import kotlin.math.atan2
@@ -15,6 +19,42 @@ import kotlin.math.sin
* text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt.
******************************************************************************/
object GPSFormat {
fun dec(p: Position): String {
return String.format("%.5f %.5f", p.latitude, p.longitude).replace(",", ".")
}
fun toDMS(p: Position): String {
val lat = degreesToDMS(p.latitude, true)
val lon = degreesToDMS(p.longitude, false)
fun string(a: Array<String>) = String.format("%s°%s'%.5s\"%s", a[0], a[1], a[2], a[3])
return string(lat) + " " + string(lon)
}
fun toUTM(p: Position): String {
val UTM = UTM.from(Point.point(p.longitude, p.latitude))
return String.format(
"%s%s %.6s %.7s",
UTM.zone,
UTM.toMGRS().band,
UTM.easting,
UTM.northing
)
}
fun toMGRS(p: Position): String {
val MGRS = MGRS.from(Point.point(p.longitude, p.latitude))
return String.format(
"%s%s %s%s %05d %05d",
MGRS.zone,
MGRS.band,
MGRS.column,
MGRS.row,
MGRS.easting,
MGRS.northing
)
}
}
/**
* Format as degrees, minutes, secs