[Feat]新增全览地图View
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user