[Feat]新增全览地图View

This commit is contained in:
chenfufeng
2023-02-01 11:20:32 +08:00
parent 1e7bd1c749
commit f0d9f701ed
7 changed files with 729 additions and 4 deletions

View File

@@ -0,0 +1,143 @@
package com.mogo.eagle.core.function.overview
import androidx.lifecycle.*
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.constants.HostConst
import com.mogo.eagle.core.data.map.Infrastructure
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.overview.db.OverviewDb
import com.mogo.eagle.core.function.overview.remote.OverViewServiceApi
import com.mogo.eagle.core.function.overview.remote.V2XEvent
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit
object OverViewDataManager {
const val TAG = "OverViewDataManager"
private val overviewDao by lazy {
OverviewDb.getDb(AbsMogoApplication.getApp()).overviewDao()
}
private val _infStructures = MutableLiveData<List<Infrastructure>>()
private val _V2XEvents = MutableLiveData<List<V2XEvent>>()
private var disposable: Disposable? = null
val infStructures
get() = _infStructures
private val _infStructuresMap = _infStructures
.switchMap { infStructures ->
liveData {
val map = HashMap<String, ArrayList<Infrastructure>>()
infStructures.forEach {
val geoHash = it.geoHash
if (geoHash == null) {
return@forEach
} else {
if (!map.containsKey(geoHash)) {
val list = ArrayList<Infrastructure>()
list.add(it)
map[geoHash] = list
} else {
map[geoHash]?.add(it)
}
}
}
emit(map)
}
}
val infStructuresMap
get() = _infStructuresMap
fun fetchInfStructures() {
ProcessLifecycleOwner.get().lifecycleScope.launch {
val data = try {
// 只查找摄像头
overviewDao.listInfStructures(0)
// overviewDao.listAllInfStructures()
} catch (e: Exception) {
e.printStackTrace()
null
}
data?.let {
_infStructures.value = it
}
}
}
fun updateGeoHash(id: Int, geoHash: String) {
ProcessLifecycleOwner.get().lifecycleScope.launch {
try {
overviewDao.updateGeoHash(id, geoHash)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun getAllV2XEventsByLineId(sn: String) {
if (disposable != null && !disposable!!.isDisposed) {
disposable!!.dispose()
}
// 1分钟查询一次
disposable = Observable.interval(2000, 60000, TimeUnit.MILLISECONDS)
.flatMap {
val lineId = getLineId()
if (lineId > 0) {
MoGoRetrofitFactory.getInstance(HostConst.getHost())
.create(OverViewServiceApi::class.java)
.queryAllV2XEventsByLineId(lineId.toString(), sn)
.map {
if (it.code == 200 || it.code == 0) {
CallerLogger.d(SceneConstant.M_MAP + TAG, "请求成功size为${it.result?.v2XEventList?.size}")
return@map it.result?.v2XEventList
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "请求失败code为${it.code}")
return@map ArrayList()
}
}
} else {
Observable.just(ArrayList())
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
it?.apply {
_V2XEvents.value = this
}
}
}
fun getV2XEventLiveData() = _V2XEvents
fun stopQueryV2XEvents() {
disposable?.dispose()
}
private fun getLineId(): Long {
var lineId: Long = -1
val parameter = CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo()
.autopilotControlParameters
if (parameter != null) {
if (parameter.autoPilotLine != null) {
lineId = parameter.autoPilotLine!!.lineId
CallerLogger.d(SceneConstant.M_MAP + TAG, "lineId为:$lineId")
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "parameter.autoPilotLine为null")
}
} else {
CallerLogger.d(SceneConstant.M_MAP + TAG, "parameter为null")
}
return lineId
}
}

View File

@@ -5,6 +5,8 @@ import android.app.Application
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.mogo.eagle.core.function.overview.db.OverviewDao
import com.mogo.eagle.core.function.overview.db.OverviewDb
import com.mogo.eagle.core.function.overview.vm.OverViewModel
class ViewModelFactory private constructor(

View File

@@ -1,4 +1,4 @@
package com.mogo.eagle.core.function.overview
package com.mogo.eagle.core.function.overview.db
import androidx.room.Dao
import androidx.room.Query

View File

@@ -1,4 +1,4 @@
package com.mogo.eagle.core.function.overview
package com.mogo.eagle.core.function.overview.db
import android.content.Context
import androidx.room.Database

View File

@@ -0,0 +1,580 @@
package com.mogo.eagle.core.function.overview.view
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.widget.RelativeLayout
import android.widget.TextView
import ch.hsr.geohash.GeoHash
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdate
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.TextureMapView
import com.amap.api.maps.model.*
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.map.Infrastructure
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager.getGlobalPath
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ20ListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager.showVideoDialog
import com.mogo.eagle.core.function.map.R
import com.mogo.eagle.core.function.overview.InfStructureManager
import com.mogo.eagle.core.function.overview.InfStructureManager.getData
import com.mogo.eagle.core.function.overview.OverViewDataManager
import com.mogo.eagle.core.function.overview.remote.V2XEvent
import com.mogo.eagle.core.function.smp.MakerWithCount
import com.mogo.eagle.core.function.smp.MarkerDrawerManager
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.callback
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.coordinateConverterWgsToGcj
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.lonLat
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.planningPoints
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.startLoopCalCarLocation
import com.mogo.eagle.core.function.smp.MarkerDrawerManager.updateRoutePoints
import com.mogo.eagle.core.function.smp.V2XMarkerView
import com.mogo.eagle.core.utilcode.kotlin.lifecycleOwner
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils.isTaxi
import com.mogo.eagle.core.utilcode.mogo.MapAssetStyleUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import me.jessyan.autosize.utils.AutoSizeUtils
import mogo.telematics.pad.MessagePad
/**
* 全览地图View
*
* @author chenfufeng
*/
class OverMapView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr), IMoGoChassisLocationGCJ02Listener {
private var mMapView: TextureMapView? = null
private var mAMap: AMap? = null
private val zoomLevel = 15
private var mCameraUpdate: CameraUpdate? = null
private var mContext: Context? = null
private val mTilt = 60f
private var overLayerView: TextView? = null
// 全局路径规划中的GeoHash网格
private val pathMap: MutableMap<String?, ArrayList<Infrastructure>?> = HashMap()
private val posInfMap: MutableMap<LatLng?, ArrayList<Infrastructure>?> = HashMap()
// =============绘制轨迹线相关=============
private var mCarMarker: Marker? = null
private var mCompassMarker: Marker? = null
private var mStartMarker: Marker? = null
private var mEndMarker: Marker? = null
private var mBottomPolyline: Polyline? = null
private var mCoveredPolyline: Polyline? = null
// 计算索引并设置对应的Bitmap
var arrivedBitmap: BitmapDescriptor? = null
var unArrivedBitmap: BitmapDescriptor? = null
// 绘制轨迹线的集合
private val textureList: MutableList<BitmapDescriptor?> = ArrayList()
private val texIndexList: MutableList<Int> = ArrayList()
private var mLocation: MessagePad.GnssInfo? = null
private var isFirstLocation = true
var mCustomMapStyleOptions: CustomMapStyleOptions? = null
var currMarkerList: ArrayList<Marker>? = null
companion object {
const val TAG = "OverMapView"
}
init {
try {
initView(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
// =================必须通知高德地图生命周期的变化=================
fun onCreateView(savedInstanceState: Bundle?) {
if (mMapView != null) {
mMapView!!.onCreate(savedInstanceState)
}
}
fun onResume() {
if (mMapView != null) {
mMapView!!.onResume()
}
}
fun onPause() {
if (mMapView != null) {
mMapView!!.onPause()
}
}
fun onDestroy() {
if (mMapView != null) {
mMapView!!.onDestroy()
}
if (mMapView != null) {
mMapView!!.onDestroy()
}
}
// =================必须通知高德地图生命周期的变化=================
private fun initView(context: Context) {
mContext = context
val smpView = LayoutInflater.from(context).inflate(R.layout.module_overview_map_view, this)
mMapView = smpView.findViewById(R.id.aMapView)
overLayerView = findViewById(R.id.overLayer)
if (isTaxi(FunctionBuildConfig.appIdentityMode)) {
overLayerView?.background = resources.getDrawable(R.drawable.amap_reset)
arrivedBitmap = BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_arrived)
unArrivedBitmap =
BitmapDescriptorFactory.fromResource(R.drawable.taxi_map_arrow_un_arrive)
} else {
overLayerView?.background = resources.getDrawable(R.drawable.amap_reset_bus)
arrivedBitmap = BitmapDescriptorFactory.fromResource(R.drawable.arrow_arrived_img)
unArrivedBitmap = BitmapDescriptorFactory.fromResource(R.drawable.amap_bus_smooth_route)
}
CallerPlanningRottingListenerManager.addListener(TAG, moGoAutopilotPlanningListener)
initAMapView(context)
// 注册定位监听
CallerChassisLocationGCJ20ListenerManager.addListener(TAG, this)
//设置全览模式
overLayerView?.setOnClickListener { displayCustomOverView() }
}
private fun initAMapView(context: Context) {
Log.d(TAG, "initAMapView")
mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel.toFloat())
mAMap = mMapView!!.map
mCustomMapStyleOptions = CustomMapStyleOptions()
if (isTaxi(FunctionBuildConfig.appIdentityMode)) {
mCustomMapStyleOptions!!.styleData =
MapAssetStyleUtils.getAssetsStyle(getContext(), "over_view_style.data")
mCustomMapStyleOptions!!.styleExtraData =
MapAssetStyleUtils.getAssetsExtraStyle(getContext(), "over_view_style_extra.data")
} else {
mCustomMapStyleOptions!!.styleData =
MapAssetStyleUtils.getAssetsStyle(getContext(), "over_view_style_bus.data")
mCustomMapStyleOptions!!.styleExtraData =
MapAssetStyleUtils.getAssetsExtraStyle(
getContext(),
"over_view_style_extra_bus.data"
)
}
mAMap?.setOnMapLoadedListener {
Log.d(TAG, "---onMapLoaded---")
if (mCustomMapStyleOptions != null) {
// 加载自定义样式
mCustomMapStyleOptions!!.isEnable = true
// 设置自定义样式
mAMap?.setCustomMapStyle(mCustomMapStyleOptions)
}
// 实时路况图层关闭必须添加在loaded结束之后,其他位置不生效
mAMap?.isTrafficEnabled = false
}
setUpMap()
customOptions()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
OverViewDataManager.infStructuresMap.observe(lifecycleOwner) { list ->
InfStructureManager.saveData(list)
}
// 查询本地数据库中的摄像头数据
OverViewDataManager.fetchInfStructures()
// 主动查一次全局路径规划的数据
getGlobalPath()
// 定时查询V2X事件
OverViewDataManager.getV2XEventLiveData().observe(lifecycleOwner) {
showV2XEventMarkers(it)
}
OverViewDataManager.getAllV2XEventsByLineId(MoGoAiCloudClientConfig.getInstance().sn)
}
private fun setUpMap() {
// 地图文字标注
mAMap!!.showMapText(true)
//设置希望展示的地图缩放级别
mAMap!!.moveCamera(mCameraUpdate)
//设置地图的样式
val uiSettings = mAMap!!.uiSettings
//地图缩放级别的交换按钮
uiSettings.isZoomControlsEnabled = false
//所有手势
uiSettings.setAllGesturesEnabled(true)
//隐藏指南针
uiSettings.isCompassEnabled = false
//设置倾斜手势是否可用。
uiSettings.isTiltGesturesEnabled = true
//隐藏默认的定位按钮
uiSettings.isMyLocationButtonEnabled = false
//设置Logo下边界距离屏幕底部的边距,设置为负值即可
uiSettings.setLogoBottomMargin(-150)
Log.d(TAG, "before onMapLoaded")
}
/**
* 自定义导航View和路况状态
*/
private fun customOptions() {
if (isTaxi(FunctionBuildConfig.appIdentityMode)) {
mCarMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_car_icon))
.anchor(0.5f, 0.5f)
)
mCompassMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.amap_custom_corner))
.anchor(0.5f, 0.5f)
)
} else {
mCarMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_bus_icon))
.anchor(0.5f, 0.5f)
)
mCompassMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.amap_bus_corner))
.anchor(0.5f, 0.5f)
)
}
mStartMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_start))
)
mEndMarker = mAMap!!.addMarker(
MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.module_small_map_view_dir_end))
)
}
private val moGoAutopilotPlanningListener: IMoGoPlanningRottingListener =
object : IMoGoPlanningRottingListener {
/**
* 根据全路径获取起始点和经停点进行导航路线绘制
* 自动驾驶启动后获得数据,获取全路径的具体时间要进行路测
* 室内某个bag包自动驾驶启动8s后返回
*/
override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) {
Log.d(TAG, "onAutopilotRotting")
handlePlanningData(globalPathResp!!.wayPointsList)
}
}
fun handlePlanningData(locationList: List<MessagePad.Location>) {
val list: List<MessagePad.Location> = locationList
// 转成高德坐标系并存储
updateRoutePoints(list, mContext!!)
val planningPointList: List<LatLng> = planningPoints
UiThreadHandler.post {
displayCustomOverView()
drawStartAndEndMarker(planningPointList)
}
callback = object : MarkerDrawerManager.Callback {
override fun onLocationChanged(planningPoints: List<LatLng>, locIndex: Int) {
// 每1s刷新一下轨迹线
UiThreadHandler.post {
if (planningPoints.isNotEmpty()) {
drawPolyline(planningPoints, locIndex)
}
}
}
}
startLoopCalCarLocation()
UiThreadHandler.post { drawInfrastructureMarkers(locationList) }
}
/**
* 显示V2X事件的Marker
*/
fun showV2XEventMarkers(v2XEvents: List<V2XEvent>?) {
if (v2XEvents == null || v2XEvents.isEmpty()) return
clearV2XMarkers()
val markerOptionsList = ArrayList<MarkerOptions>()
for ((_, _, _, center, _, _, poiType, coordinateType) in v2XEvents) {
if (center != null) {
center.lon
val markerOption = MarkerOptions()
var latLng: LatLng = if (coordinateType == null || coordinateType == 0) {
LatLng(center.lat, center.lon)
} else {
// wgs84坐标系需转成高德坐标系
coordinateConverterWgsToGcj(mContext!!, center.lat, center.lon)
}
markerOption.position(latLng)
markerOption.anchor(0.13f, 1f)
markerOption.icon(
BitmapDescriptorFactory.fromBitmap(
getV2XBitmap(
poiType
)
)
)
markerOptionsList.add(markerOption)
}
}
if (markerOptionsList.size > 0) {
drawV2XMarkers(markerOptionsList)
}
}
fun drawV2XMarkers(markerOptionsList: ArrayList<MarkerOptions>?) {
currMarkerList = mAMap!!.addMarkers(markerOptionsList, false)
}
private fun getV2XBitmap(poiType: String?): Bitmap {
val marker = V2XMarkerView(context, null, 0, poiType)
marker.measure(
MeasureSpec.makeMeasureSpec(AutoSizeUtils.dp2px(mContext, 229f), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(AutoSizeUtils.dp2px(mContext, 96f), MeasureSpec.EXACTLY)
)
marker.layout(0, 0, marker.measuredWidth, marker.measuredHeight)
val bitmap = Bitmap.createBitmap(marker.width, marker.height, Bitmap.Config.ARGB_8888)
marker.draw(Canvas(bitmap))
return bitmap
}
fun clearV2XMarkers() {
if (currMarkerList != null) {
for (marker in currMarkerList!!) {
marker.destroy()
}
currMarkerList = null
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
// 注册定位监听
CallerChassisLocationGCJ20ListenerManager.removeListener(TAG)
CallerPlanningRottingListenerManager.removeListener(TAG)
OverViewDataManager.stopQueryV2XEvents()
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
return false
}
fun clearCustomPolyline() {
if (mBottomPolyline != null) {
mBottomPolyline!!.remove()
}
if (mCoveredPolyline != null) {
mCoveredPolyline!!.remove()
}
}
/**
* 绘制新基建Markers(比如:摄像头)
*
* @param locationList
*/
private fun drawInfrastructureMarkers(locationList: List<MessagePad.Location>?) {
if (locationList == null) return
if (pathMap.isNotEmpty()) {
pathMap.clear()
}
var geoHash: String?
var infList: ArrayList<Infrastructure>?
for (i in locationList.indices) {
val latLng = coordinateConverterWgsToGcj(mContext!!, locationList[i])
geoHash =
GeoHash.withCharacterPrecision(latLng.latitude, latLng.longitude, 7).toBase32()
// 网格内的轨迹点只取一次s
if (!pathMap.containsKey(geoHash)) {
// 从缓存的新基建数据中去取对应geoHash的新基建数据集合
infList = getData()[geoHash]
if (infList != null) {
pathMap[geoHash] = infList
}
}
}
drawInfMarkers(pathMap)
}
private fun drawInfMarkers(infStruMap: Map<String?, ArrayList<Infrastructure>?>) {
// 绘制新基建数据
if (posInfMap.isNotEmpty()) {
posInfMap.clear()
}
val markerOptionsList: ArrayList<MarkerOptions?> = ArrayList()
for (structureList in infStruMap.values) {
// 每个GeoHash内根据坐标系象限分散开摄像头icon显示
val markerOption = MarkerOptions()
val latLng = LatLng(
java.lang.Double.valueOf(structureList!![0].lat!!),
java.lang.Double.valueOf(structureList[0].lon!!)
)
markerOption.position(latLng)
val bitmap = getBitmap(structureList.size)
markerOption.icon(
BitmapDescriptorFactory.fromBitmap(
bitmap
)
)
markerOption.zIndex(2f)
posInfMap[latLng] = structureList
markerOptionsList.add(markerOption)
}
mAMap!!.addMarkers(markerOptionsList, false)
mAMap!!.setOnMarkerClickListener { marker: Marker ->
val infList: List<Infrastructure>? = posInfMap[marker.position]
// 如果是摄像头
if (infList != null) {
showVideoDialog(infList)
return@setOnMarkerClickListener true
}
false
}
}
private fun getBitmap(count: Int): Bitmap {
val marker = MakerWithCount(context)
marker.setCount(count)
marker.measure(
MeasureSpec.makeMeasureSpec(116, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(116, MeasureSpec.EXACTLY)
)
marker.layout(0, 0, marker.measuredWidth, marker.measuredHeight)
val bitmap = Bitmap.createBitmap(marker.width, marker.height, Bitmap.Config.ARGB_8888)
marker.draw(Canvas(bitmap))
return bitmap
}
/**
* 进入自定义全览模式
*/
private fun displayCustomOverView() {
val linePointsLatLng = planningPoints
if (linePointsLatLng.size > 1) {
//圈定地图显示范围
//存放经纬度
val boundsBuilder = LatLngBounds.Builder()
for (i in linePointsLatLng.indices) {
boundsBuilder.include(linePointsLatLng[i])
}
val currentLatLng = LatLng(mLocation!!.latitude, mLocation!!.longitude)
boundsBuilder.include(currentLatLng)
val cameraPosition = CameraPosition.Builder().tilt(mTilt).build()
//第二个参数为四周留空宽度
mAMap!!.moveCamera(
CameraUpdateFactory.newLatLngBoundsRect(
boundsBuilder.build(),
100,
100,
100,
100
)
)
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
} else {
//设置希望展示的地图缩放级别
val cameraPosition = CameraPosition.Builder()
.target(mCarMarker!!.position).tilt(0f).zoom(zoomLevel.toFloat()).build()
mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
/**
* 绘制自车
*
* @param location
*/
private fun drawCarMarker(location: MessagePad.GnssInfo?) {
if (location == null) return
if (mCarMarker != null) {
val currentLatLng = LatLng(location.latitude, location.longitude)
mCarMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCarMarker!!.position = currentLatLng
mCarMarker!!.setToTop()
if (mCompassMarker != null) {
mCompassMarker!!.rotateAngle = (360 - location.heading).toFloat()
mCompassMarker!!.position = currentLatLng
}
}
}
/**
* 绘制起始点、终点
*/
private fun drawStartAndEndMarker(coordinates: List<LatLng>) {
if (mStartMarker != null) {
mStartMarker!!.isVisible = false
}
if (mEndMarker != null) {
mEndMarker!!.isVisible = false
}
if (coordinates.size > 2) {
// 设置开始结束Marker位置
val startLatLng = coordinates[0]
val endLatLng = coordinates[coordinates.size - 1]
mStartMarker!!.position = startLatLng
mEndMarker!!.position = endLatLng
mStartMarker!!.isVisible = true
mEndMarker!!.isVisible = true
}
}
/**
* 绘制轨迹线
*
* @param coordinates
* @param locIndex
*/
private fun drawPolyline(coordinates: List<LatLng>, locIndex: Int) {
if (textureList.size > 0) {
textureList.clear()
}
if (texIndexList.size > 0) {
texIndexList.clear()
}
for (i in coordinates.indices) {
if (i <= locIndex) {
// 已走过的置灰
textureList.add(arrivedBitmap)
} else {
// 未走过的纹理
textureList.add(unArrivedBitmap)
}
texIndexList.add(i)
}
if (mAMap != null && coordinates.size > 2) {
//设置线段纹理
val polylineOptions = PolylineOptions()
polylineOptions.addAll(coordinates)
polylineOptions.width(14f) //线段宽度
polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound)
polylineOptions.customTextureList = textureList
polylineOptions.customTextureIndex = texIndexList
// 绘制线
mBottomPolyline = mCoveredPolyline
mCoveredPolyline = mAMap!!.addPolyline(polylineOptions)
if (mBottomPolyline != null) {
mBottomPolyline!!.remove()
}
}
}
override fun onChassisLocationGCJ02(gnssInfo: MessagePad.GnssInfo?) {
mLocation = gnssInfo
lonLat = Pair(gnssInfo!!.longitude, gnssInfo.latitude)
drawCarMarker(gnssInfo)
if (isFirstLocation) {
displayCustomOverView()
isFirstLocation = false
}
}
}

View File

@@ -4,7 +4,7 @@ import androidx.lifecycle.*
import com.mogo.commons.constants.HostConst
import com.mogo.eagle.core.data.map.Infrastructure
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager.getAutoPilotStatusInfo
import com.mogo.eagle.core.function.overview.OverviewDao
import com.mogo.eagle.core.function.overview.db.OverviewDao
import com.mogo.eagle.core.function.overview.remote.OverViewServiceApi
import com.mogo.eagle.core.function.overview.remote.V2XEvent
import com.mogo.eagle.core.network.MoGoRetrofitFactory