我想画一条轨迹线时,移动与我的手机设备类似,它如何在三星健康应用程序时,步行/跑步/徒步旅行。
在我的应用程序中,我将每个新的位置存储到数组中,并根据这个位置数组绘制一条跟踪线。问题是位置数组的大小很快就会变得非常大。
我想知道例如在三星健康或其他应用程序中,他们正在处理这个问题?一方面,我想保持绘制的轨迹线,直到用户停止/完成当前会话,另一方面,我不想让位置数组太大,所以它会使性能成为问题。
在活动的顶部:
private var points: ArrayList<LatLng>? = null
private var line: Polyline? = null
字符串
内部onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
points = ArrayList()
}
型
onMapReady
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
mMap.uiSettings.isMyLocationButtonEnabled = false
try {
mMap.isMyLocationEnabled = false
mMap.uiSettings.isZoomControlsEnabled = true
line = mMap.addPolyline(PolylineOptions())
} catch (e: SecurityException) {
e.printStackTrace()
}
}
型
initializeMapWithLocation方法,每次新位置添加到points数组时,我都会添加位置。
private fun initializeMapWithLocation(userLocation: LatLng) {
mMap.uiSettings.isMyLocationButtonEnabled = false
try {
mMap.isMyLocationEnabled = false
mMap.uiSettings.isZoomControlsEnabled = true
val selectedMarkerType = MarkerType.CUSTOM_2
val markerIcon = if (selectedMarkerType == MarkerType.DEFAULT) {
BitmapDescriptorFactory.defaultMarker()
} else {
val originalBitmap = BitmapFactory.decodeResource(resources, selectedMarkerType.resourceId)
val width = (originalBitmap.width * selectedMarkerType.scale).toInt()
val height = (originalBitmap.height * selectedMarkerType.scale).toInt()
val scaledMarker = Bitmap.createScaledBitmap(originalBitmap, width, height, false)
BitmapDescriptorFactory.fromBitmap(scaledMarker)
}
if (marker == null) {
// Create a new marker if it doesn't exist yet
marker = mMap.addMarker(
MarkerOptions()
.position(userLocation)
.icon(markerIcon)
.title("Marker Title")
)
// Inflate the custom info window layout
val infoWindowView = layoutInflater.inflate(R.layout.custom_info_window, null)
// Set the custom info window as the tag of the marker
marker?.tag = infoWindowView
// Set the custom InfoWindow adapter for the marker
mMap.setInfoWindowAdapter(CustomInfoWindowAdapter())
} else {
// Set the new position of the existing marker
updateMarkerPosition(userLocation)
if (points != null) {
points!!.add(userLocation)
line?.points = points as ArrayList<LatLng>
} else {
// Initialize the points list if it's null
points = ArrayList()
points!!.add(userLocation)
}
// Get the custom info window layout from the marker's tag
val infoWindowView = marker?.tag as View
// Find the TextViews in the custom layout
val latitudeTextView = infoWindowView.findViewById<TextView>(R.id.latitudeTextView)
val longitudeTextView = infoWindowView.findViewById<TextView>(R.id.longitudeTextView)
// Set the latitude and longitude values in the InfoWindow
latitudeTextView.text = "Latitude: ${userLocation.latitude}"
longitudeTextView.text = "Longitude: ${userLocation.longitude}"
// Show the info window
marker?.showInfoWindow()
}
if (!initialZoomCompleted) {
val initialZoom = 5.0F
val targetZoom = 16.0F
val zoomSpeed = 500
animateZoomIn(userLocation, initialZoom, targetZoom, zoomSpeed, false)
initialZoomCompleted = true
}
} catch (e: SecurityException) {
e.printStackTrace()
}
}
型
我在顶部的onCreate之前使用并调用了initializeMapWithLocation方法
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location ->
// Handle the new location here
val newLocation = LatLng(location.latitude, location.longitude)
initializeMapWithLocation(newLocation)
loadingProgressBar.visibility = View.GONE
loadingMapTextView.visibility = View.GONE
}
}
}
型
1条答案
按热度按时间xpcnnkqh1#
有很多不同的方法可以做到这一点。基本的想法是你想过滤点-你想只保留一个子集的点。几个基本的方法是:
基于时间-每X秒/分钟只保留1个点。这将减少重复的点。你通常不会真的关心一秒一秒的位置细分(GPS噪音足够大,无论如何都没用)。
基于位置-只保留距离前一个点Y米或更远的点。这几乎是一个要求,因为GPS是嘈杂的,几乎不会报告相同的位置两次,即使站着不动。
删除冗余数据--如果你在时间1有一个点A,在时间2有一个点B,在时间3有一个点C,并且A、B和C都在一条线上(同样,因为如果它们靠近一条线,数据就会有噪声)--删除B。知道A和C是多余的。
丢弃明显的错误-你偶尔会得到一个刚刚关闭的GPS阅读。这在城市中心和山区是非常明显的,那里的信号反弹将显示随机读数块关闭。这些应该被检测和丢弃。一个简单的方法来检测它是,如果它没有意义的位置明智的与前一点和下一点-它将需要突然改变方向和速度。
你可以得到比这更好的,但这些都是一些简单的编码技术(特别是前两个)。