package com.mogo.map import android.os.Looper import com.mogo.eagle.core.data.map.MogoLocation import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i import com.mogo.eagle.core.utilcode.mogo.logger.Logger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_MAP import com.mogo.map.MogoData.Companion.mogoMapData import com.mogo.map.entities.BusStation import com.mogo.map.entities.CrossRoad import com.mogo.map.entities.Lane import com.mogo.map.location.GDLocationClient.Companion.gdLocationClient import com.mogo.map.utils.HDMapUtils.getHDCityCode import com.zhidaoauto.map.data.point.LonLatPoint import com.zhidaoauto.map.data.road.CenterLine import com.zhidaoauto.map.data.road.RoadCross import com.zhidaoauto.map.data.road.RoadNameInfo import com.zhidaoauto.map.data.road.RoadRectInfos import com.zhidaoauto.map.data.road.RoutePath import com.zhidaoauto.map.data.routeinfo.RoadInfo import com.zhidaoauto.map.sdk.open.MapAutoApi import com.zhidaoauto.map.sdk.open.abs.IResult import com.zhidaoauto.map.sdk.open.abs.OnHdDataDownByCityListener import com.zhidaoauto.map.sdk.open.data.CityInfo import com.zhidaoauto.map.sdk.open.data.MapDataApi import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit.SECONDS import java.util.concurrent.atomic.AtomicReference /** * 地图数据工具,涉及到数据调用可能会有耗时,建议IO操作 * 地图call回调在主线程,有需要io操作的业务建议切换线程或由MapDataWrapper线程池操作 */ object MapDataWrapper : IMogoData { private const val TAG = "MapDataWrapper" fun init() { mogoMapData.init(this) } /** * 设置debug模式 */ override fun setDebugMode(debugMode: Boolean) { MapAutoApi.setDebugMode(debugMode) } /** * 获取车道中心线数据 * @param lon 经度 * @param lat 纬度 * @param angle 角度 * @param call 回调 */ @Synchronized override fun getCenterLineInfo( lon: Double, lat: Double, angle: Float, call: ((CenterLine?) -> Unit) ) { MapDataApi.getCenterLineInfo( lon, lat, angle, object : IResult { override fun result( code: Int, result: CenterLine? ) { call.invoke(result) } }) } /** * 按距离获取道路数据 * @param lon 经度 * @param lat 纬度 * @param angle 角度 * @param call 回调 */ @Synchronized override fun getCenterLineRangeInfo( lon: Double, lat: Double, angle: Float, distance: Float, call: ((CenterLine?) -> Unit) ) { try { MapDataApi.getCenterLineRangeInfo(lon, lat, angle, distance, false, 6, object : IResult { override fun result(code: Int, result: CenterLine?) { call.invoke(result) } }) } catch (t: Throwable) { t.printStackTrace() } } /** * 获取车道限速 * @param lon 经度 * @param lat 纬度 * @param angle 角度 * @param call 回调 */ @Synchronized override fun getLimitSpeed(lon: Double, lat: Double, angle: Float, call: ((Int) -> Unit)) { MapDataApi.getLimitSpeed(lon, lat, angle, object : IResult { override fun result(code: Int, result: RoadInfo?) { call.invoke(result?.speed ?: 0) } }) } /** * 获取道路角度 * @param lon 经度 * @param lat 纬度 * @param angle 角度 * @param call 回调(主线程) */ @Synchronized override fun getRoadAngle(lon: Double, lat: Double, angle: Float, call: ((Double) -> Unit)) { MapDataApi.getRoadRectInfo(lon, lat, angle, object : IResult { override fun result(code: Int, result: RoadRectInfos?) { call.invoke(result?.angle ?: 0.0) } }) } /** * 获取道路宽度 */ @Synchronized override fun getRoadWidth( lon: Double, lat: Double, angle: Float, isGpsLocation: Boolean, isRTK: Boolean ): Float { val singlePointRoadInfo = MapDataApi.getSinglePointMatchRoad(lon, lat, angle, isGpsLocation, isRTK) return singlePointRoadInfo?.laneWidth ?: 0.0f } /** * 获取行车方向 * * @return */ @Synchronized override fun getAngle( startLon: Double, startLat: Double, endLon: Double, endLat: Double ): Float { return MapAutoApi.getAngle(startLon, startLat, endLon, endLat) } /** * 获取瓦片id * * @param lon 经度 * @param lat 纬度 * @return 瓦片id */ @Synchronized override fun getTileId(lon: Double, lat: Double): Long { return MapAutoApi.getTileID(lon, lat, 13) // 13为默认获取瓦片层级级别 } @Synchronized override fun getCityCode(): Int? { return getHDCityCode(gdLocationClient.lastCityCode) } /** * 通过cityCode获取HDMap对应缓存城市 */ @Synchronized override fun cacheHDDataByCity( progress: (cityId: Int, progress: Double) -> Unit, result: (cityId: Int, state: Int) -> Unit ) { val gdCityCode = gdLocationClient.lastCityCode i(M_MAP + TAG, "gdCityCode is:$gdCityCode") val id = getHDCityCode(gdCityCode) if (id != null && id > 0) { MapDataApi.cacheHDDataByCity(id, object : OnHdDataDownByCityListener { override fun onMapHDDataCacheProgressByCity(id: Int, p: Double) { progress.invoke(id, p * 100) } override fun onMapHDDataCacheStateByCity(id: Int, state: Int) { result.invoke(id, state) } }) }else{ result.invoke(0, 0) } } /** * 通过经纬度信息,获取HDMap对应缓存城市 */ @Synchronized override fun cacheHDDataByCityByLonLat( location: MogoLocation, progress: (cityId: Int, progress: Double) -> Unit, result: (cityId: Int, state: Int) -> Unit ) { i(M_MAP + TAG, "location lon is:" + location.longitude + ",lat is:" + location.latitude) MapDataApi.cacheHDDataByCityByLonLat( location.longitude, location.latitude, object : OnHdDataDownByCityListener { override fun onMapHDDataCacheProgressByCity(id: Int, p: Double) { progress.invoke(id, p * 100) } override fun onMapHDDataCacheStateByCity(id: Int, state: Int) { result.invoke(id, state) } }) } /** * 当前城市离线数据是否已缓存 */ @Synchronized override fun isCityDataCached(cache: ((Boolean) -> Unit)) { val cityCode = gdLocationClient.lastCityCode i(M_MAP + TAG, "gdCityCode is:$cityCode") val id = getHDCityCode(cityCode) if (id != null) { MapDataApi.getAllCityCode(object : IResult> { override fun result(code: Int, result: ArrayList?) { if (result != null) { for (cityInfo in result) { if (id == cityInfo.cityCode) { cache.invoke(cityInfo.isCache) } } } } }) } else { cache.invoke(false) } } @Synchronized override fun cancelDownloadCacheData() { MapDataApi.cancelCacheHDData() } override fun getRoadInfo( lon: Double, lat: Double, angle: Float ): com.mogo.map.entities.RoadInfo { if (Looper.getMainLooper() == Looper.myLooper()) { throw AssertionError() } val latch = CountDownLatch(1) var tempCode: Int = Int.MIN_VALUE var tempData: RoadNameInfo? = null Logger.d(TAG, "getRoadInfo --- 1 ---") MapDataApi.getRoadName(lon, lat, angle, object : IResult { override fun result(code: Int, result: RoadNameInfo?) { try { Logger.d(TAG, "getRoadInfo ==> code: $code, result: $result") tempCode = code tempData = result } finally { latch.countDown() } } }) try { if (latch.await(5, SECONDS)) { Logger.d(TAG, "getRoadInfo --- 2 ---: code -> $tempCode, data -> $tempData") } else { Logger.d(TAG, "getRoadInfo --- 3 ---: code -> $tempCode, data -> $tempData") } } catch (e: InterruptedException) { e.printStackTrace() } return com.mogo.map.entities.RoadInfo( tempCode, tempData?.tile_id?.toLong() ?: 0L, tempData?.road_id?.toInt() ?: 0, tempData?.road_name ?: "" ) } override fun getLaneInfo(tileId: Long, roadId: Int): List { return MapDataApi.getLaneInfo(tileId, roadId)?.map { itx -> Lane( itx.laneId, itx.laneWidth, itx.laneLatLonPoints.map { Pair(it.longitude, it.latitude) }) } ?: emptyList() } @Synchronized override fun getBusStation( routeList: ArrayList, resultUnit: ((MutableList) -> Unit) ) { val resultList = mutableListOf() MapDataApi.getBusStation(routeList, object : IResult { override fun result(code: Int, result: RoutePath?) { result?.steps?.forEach { it?.busStations.forEach { val busStation = BusStation( it.busStationPoints, it.id.toLong(), it.roadId, it.type, -1, -1 ) resultList.add(busStation) } } resultUnit.invoke(resultList) } }) } override fun getCrossRoad(lon: Double, lat: Double, angle: Double): CrossRoad? { if (Looper.getMainLooper() == Looper.myLooper()) { throw AssertionError() } val latch = CountDownLatch(1) Logger.d(TAG, "getCrossRoad --- 1 ---") val temp = AtomicReference() MapDataApi.getCrossRoad(lon, lat, angle.toFloat(), object : IResult { override fun result(code: Int, result: RoadCross?) { try { Logger.d(TAG, "getCrossRoad --- 1 - 1 ---") temp.set( CrossRoad( result?.status ?: 0, result?.tile_id ?: "", result?.cross_id ?: "", result?.tile_id_end ?: "", result?.cross_id_end ?: "" ) ) } finally { latch.countDown() } } }) try { Logger.d(TAG, "getCrossRoad --- 2 ---") if (latch.await(5, SECONDS)) { Logger.d(TAG, "getCrossRoad --- 3 ---") } else { Logger.d(TAG, "getCrossRoad --- 4 ---") } } catch (e: InterruptedException) { e.printStackTrace() } return temp.get() } }