diff --git a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/homepage/HomeView.kt b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/homepage/HomeView.kt index 4060c0e58e..041376229b 100644 --- a/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/homepage/HomeView.kt +++ b/OCH/taxi/unmanned-passenger/src/main/java/com/mogo/och/unmanned/passenger/ui/homepage/HomeView.kt @@ -24,6 +24,7 @@ import kotlinx.android.synthetic.main.taxi_p_home.view.lbv_go2_center import kotlinx.android.synthetic.main.taxi_p_home.view.leftEndGuideline import kotlinx.android.synthetic.main.taxi_p_home.view.midContainer import kotlinx.android.synthetic.main.taxi_p_home.view.midStartGuideline +import kotlinx.android.synthetic.main.taxi_p_home.view.preContainer class HomeView @JvmOverloads constructor( context: Context, @@ -87,37 +88,37 @@ class HomeView @JvmOverloads constructor( fun onCreate(savedInstanceState: Bundle?) { hdMapView.onCreate(savedInstanceState) -// preContainer.onCreate(savedInstanceState) + preContainer.onCreate(savedInstanceState) // decContainer.onCreate(savedInstanceState) } fun onSaveInstanceState(outState: Bundle) { hdMapView.onSaveInstanceState(outState) -// preContainer.onSaveInstanceState(outState) + preContainer.onSaveInstanceState(outState) // decContainer.onSaveInstanceState(outState) } fun onResume() { hdMapView.onResume() -// preContainer.onResume() + preContainer.onResume() // decContainer.onResume() } fun onLowMemory() { hdMapView.onLowMemory() -// preContainer.onLowMemory() + preContainer.onLowMemory() // decContainer.onLowMemory() } fun onPause() { hdMapView.onPause() -// preContainer.onPause() + preContainer.onPause() // decContainer.onPause() } fun onDestroy() { hdMapView.onDestroy() -// preContainer.onDestroy() + preContainer.onDestroy() // decContainer.onDestroy() } diff --git a/OCH/taxi/unmanned-passenger/src/main/res/layout/taxi_p_home.xml b/OCH/taxi/unmanned-passenger/src/main/res/layout/taxi_p_home.xml index 002fb38896..840733179f 100644 --- a/OCH/taxi/unmanned-passenger/src/main/res/layout/taxi_p_home.xml +++ b/OCH/taxi/unmanned-passenger/src/main/res/layout/taxi_p_home.xml @@ -26,33 +26,31 @@ android:id="@+id/midContainer" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/dp_10" - android:visibility="gone" - app:layout_constraintTop_toTopOf="parent" android:layout_marginStart="-6.5dp" android:layout_marginEnd="-6.5dp" + android:layout_marginBottom="@dimen/dp_10" + android:visibility="gone" + app:layout_constraintEnd_toStartOf="@id/rightStartGuideline" app:layout_constraintStart_toEndOf="@+id/midStartGuideline" - app:layout_constraintEnd_toStartOf="@id/rightStartGuideline"> + app:layout_constraintTop_toTopOf="parent"> - - - - - - - - - - - - - - - - - - + + diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/MapBizProvider.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/MapBizProvider.kt index f8dea9cacb..44d54f6b6e 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/MapBizProvider.kt +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/MapBizProvider.kt @@ -3,21 +3,19 @@ package com.mogo.eagle.core.function import android.content.Context import com.alibaba.android.arouter.facade.annotation.Route import com.mogo.commons.AbsMogoApplication -import com.mogo.eagle.core.data.config.FunctionBuildConfig import com.mogo.eagle.core.data.constants.MogoServicePaths import com.mogo.eagle.core.function.api.base.IMoGoFunctionServerProvider import com.mogo.eagle.core.function.api.map.roma.IMogoRoma import com.mogo.eagle.core.function.business.MapPointCloudSubscriber -import com.mogo.eagle.core.function.business.SpeedLimitDataManager import com.mogo.eagle.core.function.business.ai.AiCloudIdentifyDataManager.Companion.aiCloudIdentifyDataManager -import com.mogo.eagle.core.function.business.ai.RomaManager import com.mogo.eagle.core.function.business.ai.RomaManager.Companion.romaManager import com.mogo.eagle.core.function.business.identify.MapIdentifySubscriber import com.mogo.eagle.core.function.business.roadcross.RoadCrossCameraManager +import com.mogo.eagle.core.function.business.routeoverlay.DecisionDataManager import com.mogo.eagle.core.function.business.routeoverlay.MogoRouteOverlayManager +import com.mogo.eagle.core.function.business.routeoverlay.PredictionDataManager import com.mogo.eagle.core.function.business.trajectoryoverlay.MogoTrajectoryOverlayManager import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager -import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import com.mogo.eagle.core.utilcode.util.DeviceUtils import com.mogo.map.MapDataWrapper @@ -31,6 +29,8 @@ class MapBizProvider :IMoGoFunctionServerProvider, IMogoRoma { MapDataWrapper.init() MapIdentifySubscriber.instance MogoRouteOverlayManager.getInstance().init() + DecisionDataManager.getInstance() + PredictionDataManager.getInstance() MogoTrajectoryOverlayManager.getInstance().init() MapPointCloudSubscriber.instance RoadCrossCameraManager.instance.init(context) diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/identify/MapIdentifySubscriber.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/identify/MapIdentifySubscriber.kt index 9cbe1714c0..6c1555cac0 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/identify/MapIdentifySubscriber.kt +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/identify/MapIdentifySubscriber.kt @@ -7,6 +7,7 @@ import com.mogo.eagle.core.data.traffic.TrafficData import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener import com.mogo.eagle.core.function.api.base.IMoGoSubscriber import com.mogo.eagle.core.function.api.datacenter.obu.IMoGoObuStatusListener +import com.mogo.eagle.core.function.business.routeoverlay.PredictionDataManager import com.mogo.eagle.core.function.business.routeoverlay.PredictionOverlayDrawer import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager.getLocationHeading @@ -108,24 +109,15 @@ class MapIdentifySubscriber private constructor() : IMoGoSubscriber, if (preObj.predictionTrajectoryList == null || preObj.predictionTrajectoryList.size < 2) return@forEach carPoiList1 = preObj.predictionTrajectoryList[0].trajectoryPointsList carPoiList2 = preObj.predictionTrajectoryList[1].trajectoryPointsList - val largeType: Int location1 = LocationUtils.generateLocation(carPoiList1!![0].x, carPoiList1!![0].y, getLocationHeading()) location2 = LocationUtils.generateLocation(carPoiList2!![0].x, carPoiList2!![0].y, getLocationHeading()) if (location1 == null || location2 == null) return@forEach probability1 = preObj.predictionTrajectoryList[0].predictionProbability probability2 = preObj.predictionTrajectoryList[1].predictionProbability CallerAutopilotIdentifyListenerManager.invokeProbabilityChanged(probability1, probability2) -// if (probability1 >= probability2) { -//// MogoIdentifyManager.getInstance().updateGps(location1!!, MogoMap.SMALL_PRED_MAP) -// largeType = 2 -// } else { -//// MogoIdentifyManager.getInstance().updateGps(location2!!, MogoMap.SMALL_PRED_MAP) -// largeType = 3 -// } -// PredictionOverlayDrawer2.getInstance().drawPredictionList(carPoiList1, getLocationHeading(), false, 2, largeType) -// PredictionOverlayDrawer3.getInstance().drawPredictionList(carPoiList2, getLocationHeading(), false, 3, largeType) -// MogoIdentifyManager.getInstance().updateGps(location1!!, MogoMap.SMALL_PRED_MAP2) -// MogoIdentifyManager.getInstance().updateGps(location2!!, MogoMap.SMALL_PRED_MAP3) + + PredictionDataManager.getInstance()?.updateData(carPoiList1!!, 0) + PredictionDataManager.getInstance()?.updateData(carPoiList2!!, 2) } else { if (preObj.predictionTrajectoryList.isNullOrEmpty() || isUnKnownType(preObj.classtype) || mogoMap == null) return@forEach point = preObj.predictionTrajectoryList[0].trajectoryPointsList[0] diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/DecisionDataManager.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/DecisionDataManager.kt new file mode 100644 index 0000000000..04d64fcc27 --- /dev/null +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/DecisionDataManager.kt @@ -0,0 +1,116 @@ +package com.mogo.eagle.core.function.business.routeoverlay + +import android.os.Handler +import android.os.HandlerThread +import android.os.Looper +import android.os.Message +import android.util.Log +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningTrajectoryListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningTrajectoryListenerManager +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.map.MogoMap +import com.mogo.map.MogoMap.Companion.mapInstance +import mogo.telematics.pad.MessagePad + +class DecisionDataManager private constructor() : IMoGoPlanningTrajectoryListener { + + companion object { + private const val TAG = "DecisionDataManager" + private const val MSG_DATA_POINTS = 0 + private const val MSG_CHECK = 1 + + @Volatile + private var sInstance: DecisionDataManager? = null + fun getInstance(): DecisionDataManager? { + if (sInstance == null) { + synchronized(DecisionDataManager::class.java) { + if (sInstance == null) { + sInstance = DecisionDataManager() + } + } + } + return sInstance + } + } + + private var frequentHandler: FrequentHandler? = null + + private var lastUpdateTime = 0L + + init { + val frequentThread = HandlerThread("decision_thread") + frequentThread.start() + frequentHandler = FrequentHandler(frequentThread.looper) + frequentHandler?.sendEmptyMessageDelayed(MSG_CHECK, 1000) + CallerPlanningTrajectoryListenerManager.addListener(TAG, this) + } + + private fun updateData(data: FloatArray) { + frequentHandler?.removeMessages(MSG_DATA_POINTS) + val message = Message.obtain() + message.what = MSG_DATA_POINTS + message.obj = data + frequentHandler?.sendMessage(message) + } + + fun release() { + } + + private inner class FrequentHandler(looper: Looper) : Handler(looper) { + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + when (msg.what) { + MSG_DATA_POINTS -> { + lastUpdateTime = System.currentTimeMillis() + CallerAutopilotIdentifyListenerManager.invokeScreenPointsChanged(msg.obj as FloatArray) + } + MSG_CHECK -> { + val time = System.currentTimeMillis() + if (lastUpdateTime > 0 && time - lastUpdateTime >= 1000) { + CallerAutopilotIdentifyListenerManager.invokeScreenPointsChanged(floatArrayOf()) + } + sendEmptyMessageDelayed(MSG_CHECK, 1000) + } + } + } + } + + override fun onAutopilotTrajectory(trajectoryInfos: MutableList) { + ThreadUtils.getCpuPool().execute { + val mogoMap = mapInstance.getMogoMap(MogoMap.DEFAULT) + mogoMap?.let { map -> + val lonLatList = ArrayList() + trajectoryInfos.forEach { + map.toScreenLocation(it.longitude, it.latitude)?.let { point -> + lonLatList.add(point) + Log.d(TAG, "转换后的屏幕坐标为:(${point.x},${point.y})") + } + } + if (lonLatList.size > 0) { + val points = FloatArray(lonLatList.size * 2) + var x = 0f + var y = 0f + var offset = 0f + for (i in 0 until lonLatList.size) { + x = lonLatList[i].x * 238 / 808.toFloat() + points[i * 2] = x + + // TODO:需要根据UI布局而变化,成比例缩放(高精地图返回的y轴是镜像的,需要在y轴方向上翻转一下) + // float yB = heightB - (yA * (heightB / heightA)); + // yB = 480 - (yA * 480 / 1300) + y = (458 + 14 - lonLatList[i].y * 458 / 1300).toFloat() + if (i == 0) { + offset = 357 - y// carBitmapTop等于height * 0.78,offset = carBitmapTop - 1stY + } + points[i * 2 + 1] = y + offset + Log.d(TAG, "转换后的屏幕坐标为:(${x},${y})") + } + updateData(points) + } else { + updateData(floatArrayOf()) + } + } + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/PredictionDataManager.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/PredictionDataManager.kt new file mode 100644 index 0000000000..07b9736c4d --- /dev/null +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/business/routeoverlay/PredictionDataManager.kt @@ -0,0 +1,116 @@ +package com.mogo.eagle.core.function.business.routeoverlay + +import android.os.Handler +import android.os.HandlerThread +import android.os.Looper +import android.os.Message +import android.util.Log +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager +import com.mogo.map.MogoMap +import com.mogo.map.MogoMap.Companion.mapInstance + +class PredictionDataManager private constructor() { + + companion object { + private const val TAG = "PredictionDataManager" + private const val MSG_CHECK = 0 + private const val MSG_DATA_POINTS_0 = 1 + private const val MSG_DATA_POINTS_1 = 2 + + @Volatile + private var sInstance: PredictionDataManager? = null + fun getInstance(): PredictionDataManager? { + if (sInstance == null) { + synchronized(PredictionDataManager::class.java) { + if (sInstance == null) { + sInstance = PredictionDataManager() + } + } + } + return sInstance + } + } + + private var frequentHandler: FrequentHandler? = null + + private var lastUpdateTime = 0L + + init { + val frequentThread = HandlerThread("prediction_thread") + frequentThread.start() + frequentHandler = FrequentHandler(frequentThread.looper) + frequentHandler?.sendEmptyMessageDelayed(MSG_CHECK, 1000) + } + + fun updateData(dataList: List, index: Int = 0) { + val type = if (index == 0) MSG_DATA_POINTS_0 else MSG_DATA_POINTS_1 + frequentHandler?.removeMessages(type) + val message = Message.obtain() + message.what = type + message.obj = dataList + frequentHandler?.sendMessage(message) + } + + fun release() { + } + + private inner class FrequentHandler(looper: Looper) : Handler(looper) { + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + when (msg.what) { + MSG_DATA_POINTS_0, MSG_DATA_POINTS_1 -> { + val list = getDataList(msg.obj) + lastUpdateTime = System.currentTimeMillis() + CallerAutopilotIdentifyListenerManager.invokePreScrPointsChanged(list, if (msg.what == MSG_DATA_POINTS_0) 0 else 2) + } + MSG_CHECK -> { + val time = System.currentTimeMillis() + if (lastUpdateTime > 0 && time - lastUpdateTime >= 1000) { + CallerAutopilotIdentifyListenerManager.invokePreScrPointsChanged(floatArrayOf(), 0) + CallerAutopilotIdentifyListenerManager.invokePreScrPointsChanged(floatArrayOf(), 2) + } + sendEmptyMessageDelayed(MSG_CHECK, 1000) + } + } + } + + private fun getDataList(obj: Any): FloatArray { + val mogoMap = mapInstance.getMogoMap(MogoMap.DEFAULT) ?: return floatArrayOf() + val list = obj as List + val lonLatList = ArrayList() + var arr: DoubleArray? + var point: android.graphics.Point? + list.forEach { + arr = mogoMap.switchData(it.x, it.y, false)// UTM转wgs84 + if (arr == null || arr!!.size < 2) return@forEach + point = mogoMap.toScreenLocation(arr!![0], arr!![1])// wgs84转屏幕坐标 + if (point == null) return@forEach + lonLatList.add(point!!) + Log.d(TAG, "预测数据的屏幕坐标为:(${point!!.x},${point!!.y})") + } + if (lonLatList.size > 0) { + val points = FloatArray(lonLatList.size * 2) + var x = 0f + var y = 0f + var offset = 0f + for (i in 0 until lonLatList.size) { + x = lonLatList[i].x * 238 / 808.toFloat() + points[i * 2] = x + + // TODO:需要根据UI布局而变化,成比例缩放(高精地图返回的y轴是镜像的,需要在y轴方向上翻转一下) + // float yB = heightB - (yA * (heightB / heightA)); + // yB = 480 - (yA * 480 / 1300) + y = (458 + 14 - lonLatList[i].y * 458 / 1300).toFloat() + if (i == 0) { + offset = 357 - y// carBitmapTop等于height * 0.78,offset = carBitmapTop - 1stY + } + points[i * 2 + 1] = y + offset + Log.d(TAG, "预测数据转换后的屏幕坐标为:(${x},${y})") + } + return points + } else { + return floatArrayOf() + } + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/CoordinateAnimationView.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/CoordinateAnimationView.kt new file mode 100644 index 0000000000..f1c4aad045 --- /dev/null +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/CoordinateAnimationView.kt @@ -0,0 +1,713 @@ +package com.mogo.eagle.core.function.view + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.DashPathEffect +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +import android.util.AttributeSet +import android.util.Log +import android.view.SurfaceHolder +import android.view.SurfaceView +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager +import com.mogo.eagle.core.function.map.R +import me.jessyan.autosize.utils.AutoSizeUtils +import kotlin.math.min + +class CoordinateAnimationView @JvmOverloads constructor( + context: Context?, + attrs: AttributeSet? = null +) : + SurfaceView(context, attrs), SurfaceHolder.Callback, IMoGoAutopilotIdentifyListener { + + companion object { + private const val TAG = "CoordinateAnimationView" + + private const val UPDATE_INTERVAL = 1000 // 数据更新间隔(ms) + private const val MAX_POINTS = 500 // 最大点数 + private const val BUFFER_SIZE = MAX_POINTS * 2 // x,y坐标交替存储 + private const val FPS = 25 + } + + private var surfaceHolder: SurfaceHolder? = null + private var animationThread: AnimationThread? = null + + private var bufferA: Array? = null + private var bufferB: Array? = null + private var controlPoints: FloatArray? = null // 控制点缓冲区 + private var activePointCount = 0 + + @Volatile + private var activeBufferIndex = 0 + + @Volatile + private var drawingBufferIndex = 0 + + private var lastUpdateTime: Long = 0 + private var costTime: Long = 0 + private var fpsInterval: Int = 1000 / FPS + + @Volatile + private var dataChanged = false // 数据变化标志 + + @Volatile + private var isRunning = false + private var bezierPath: Path? = null // 贝塞尔曲线路径 + private var curvePaint: Paint? = null + private var carPaint: Paint? = null + + // private var circlePaint: Paint? = null + private var visibleRect: RectF? = null // 可见区域 + private var strokeWidth = 22f + + private var carBitmap: Bitmap? = null + + // 虚线相关参数 + private val DASH_LENGTH: Float = 46f // 虚线线段长度 + private val DASH_GAP: Float = 80f // 虚线间隔 + private val DASH_SPEED: Float = 8f // 虚线移动速度 + private var dashOffsetY = 0f // 虚线Y轴偏移量 + private var dashStrokeWidth = 3.6f + private var dashPaint: Paint? = null // 虚线画笔 + + private val leftPath by lazy { + Path() + } + + private val rightPath by lazy { + Path() + } + + private var index: Int = 1 + + init { + init(attrs) + } + + private fun init(attrs: AttributeSet?) { + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CoordinateAnimationView) + index = typedArray.getInt(R.styleable.CoordinateAnimationView_map_index, 1) + typedArray.recycle() + Log.d(TAG, "初始化地图的index为:${index}") + + surfaceHolder = holder + surfaceHolder!!.addCallback(this) + + curvePaint = Paint() + carPaint = Paint() + carPaint!!.isFilterBitmap = false + carPaint!!.isAntiAlias = true + carBitmap = getOriginBitmap( + R.drawable.decision_car_icon, + AutoSizeUtils.dp2px(context, 128f), + AutoSizeUtils.dp2px(context, 280f) + ) +// circlePaint = Paint() +// circlePaint!!.color = Color.RED +// circlePaint!!.style = Paint.Style.STROKE +// circlePaint!!.isAntiAlias = true + + curvePaint!!.setARGB(102, 48, 163, 255) +// curvePaint!!.shader = LinearGradient( +// 50f, 100f, 750f, 100f, +// intArrayOf(0x0FFF0000, 0xFF00FF00.toInt(), 0x0F0000FF), +// floatArrayOf(0f, 0.5f, 1f), +// Shader.TileMode.CLAMP +// ) + curvePaint!!.style = Paint.Style.STROKE + curvePaint!!.strokeWidth = strokeWidth + // 一定要设置抗锯齿,否则画贝塞尔曲线时会出现很多白色分割线 + curvePaint!!.isAntiAlias = true + // 线段连接处为圆弧 + curvePaint!!.strokeJoin = Paint.Join.ROUND + // 设置线冒样式 + curvePaint!!.strokeCap = Paint.Cap.SQUARE + + // 初始化虚线 + dashPaint = Paint() + dashPaint!!.setColor(Color.WHITE) + dashPaint!!.style = Paint.Style.STROKE + dashPaint!!.strokeWidth = dashStrokeWidth + dashPaint!!.isAntiAlias = true + dashPaint!!.pathEffect = DashPathEffect(floatArrayOf(DASH_LENGTH, DASH_GAP), 0f) + + bufferA = arrayOfNulls(MAX_POINTS) + bufferB = arrayOfNulls(MAX_POINTS) + + for (i in 0 until MAX_POINTS) { + bufferA!![i] = Point() + bufferB!![i] = Point() + } + + bezierPath = Path() + dataChanged = false + controlPoints = FloatArray(MAX_POINTS * 4)// 按照三阶贝塞尔曲线来创建 + visibleRect = RectF() + + // 启用硬件加速 + setLayerType(LAYER_TYPE_HARDWARE, null) + } + + private fun getOriginBitmap(resId: Int, desWidth: Int, desHeight: Int): Bitmap { + val bitmap = BitmapFactory.decodeResource(resources, resId) + val scaleWidth = (bitmap.width * 1.6).toInt() + val scaleHeight = (bitmap.height * 1.6).toInt() + Log.d(TAG, "$index-Bitmap width:$scaleWidth,height:$scaleHeight") + return Bitmap.createScaledBitmap( + bitmap, scaleWidth, + scaleHeight, true + ) + +// val options = BitmapFactory.Options() +// options.inJustDecodeBounds = true +// BitmapFactory.decodeResource(resources, resId, options) +// var inSampleSize = 1 +// if (options.outHeight > desHeight || options.outWidth > desWidth) { +// while ((options.outHeight / 2 / inSampleSize) >= desHeight && (options.outWidth / inSampleSize) >= desWidth) { +// inSampleSize *= 2// 每次翻倍,保证是 2 的幂次 +// } +// } +// options.inJustDecodeBounds = false +// options.inSampleSize = inSampleSize +// return BitmapFactory.decodeResource(resources, resId, options) + } + + override fun surfaceCreated(holder: SurfaceHolder) { + animationThread = AnimationThread() + animationThread!!.start() + isRunning = true + CallerAutopilotIdentifyListenerManager.addListener("${TAG}${this.hashCode()}", this) + } + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + val margin = strokeWidth * 2 + // 处理Surface尺寸变化 + visibleRect!!.set(margin, margin, width - margin, height - margin) + } + + override fun surfaceDestroyed(holder: SurfaceHolder) { + isRunning = false + var retry = true + while (retry) { + try { + animationThread!!.join() + retry = false + } catch (e: InterruptedException) { + e.printStackTrace() + } + } + CallerAutopilotIdentifyListenerManager.removeListener("${TAG}${this.hashCode()}") + carBitmap?.recycle() + carBitmap = null + bufferA = null + bufferB = null + controlPoints = null + } + + override fun screenPointsChanged(data: FloatArray, index: Int) { + if (index == this.index) { + updatePoints(data) + } + } + + override fun preScrPointsChanged(data: FloatArray, index: Int) { + if (index == this.index) { + updatePoints(data) + } + } + + private fun updatePoints(newPoints: FloatArray) { + if (!isRunning) { + Log.d(TAG, "$index-渲染线程未启动") + return + } + if (bufferA == null || bufferB == null) { + Log.d(TAG, "$index-updatePoints->缓冲区未初始化完成!") + return + } + // 获取可用缓冲区 + val targetBuffer: Array = if ((drawingBufferIndex == 0)) bufferB!! else bufferA!! + + // 重置目标缓冲区 + for (i in 0 until MAX_POINTS) { + targetBuffer[i]?.reset() + } + + // 填充新数据(不能超过最大点数) + val count = min(newPoints.size / 2, MAX_POINTS) + var p: Point? + for (i in 0 until count) { + p = targetBuffer[i] + p?.set(newPoints[i * 2], newPoints[i * 2 + 1]) + } + + activePointCount = count + activeBufferIndex = if (drawingBufferIndex == 0) 1 else 0 + dataChanged = true + + Log.d(TAG, "$index-数据已更新!") + } + + private fun drawMovingDashedPath(canvas: Canvas?) { + if (canvas == null) { + Log.d(TAG, "$index-画布为null!") + return + } + Log.d(TAG, "$index-开始绘制虚线!") + leftPath.rewind() + rightPath.rewind() + + // 两条虚线的X坐标(左右对称) + val leftLineX = width * 0.2f + val rightLineX = width * 0.8f + + // 计算当前虚线的偏移量(取模运算确保在一个周期内) + val offset = dashOffsetY % (DASH_LENGTH + DASH_GAP) + + // 绘制多条虚线线段,确保覆盖整个屏幕 + var y = offset + var endY = 0f + while (y < height + DASH_LENGTH + DASH_GAP) { + endY = min(y + DASH_LENGTH, height.toFloat()) + + leftPath.moveTo(leftLineX, y) + leftPath.lineTo(leftLineX, endY) + rightPath.moveTo(rightLineX, y) + rightPath.lineTo(rightLineX, endY) + + y += DASH_LENGTH + DASH_GAP// 步长 + } + canvas.drawPath(leftPath, dashPaint!!) + canvas.drawPath(rightPath, dashPaint!!) + + // 更新虚线偏移量 + dashOffsetY += DASH_SPEED + if (dashOffsetY > DASH_LENGTH + DASH_GAP) { + dashOffsetY -= (DASH_LENGTH + DASH_GAP) + } + } + + private fun drawCar(canvas: Canvas?) { + if (canvas == null) { + Log.d(TAG, "$index-画布为null!") + return + } + canvas.drawBitmap(carBitmap!!, (width - carBitmap!!.width) / 2f, height * 0.78f, carPaint!!) + } + + private fun drawPath(canvas: Canvas?) { + if (canvas == null) { + Log.d(TAG, "$index-画布为null!") + return + } + // 获取当前活跃的缓冲区 + val currentBuffer = if (activeBufferIndex == 0) bufferA else bufferB + drawingBufferIndex = activeBufferIndex + + // 绘制轨迹 + if (dataChanged) { + bezierPath?.rewind() + if (activePointCount > 0) { + // 计算贝塞尔曲线的控制点(二阶贝塞尔曲线性能更好) +// calculateControlPoints(currentBuffer, activePointCount, controlPoints!!) + calculateControlPoints2ndKind(currentBuffer, activePointCount, controlPoints!!) + + // 使用可见区域裁剪的贝塞尔曲线 +// drawClippedBezierPath(currentBuffer, activePointCount, controlPoints!!) + drawClippedBezier2ndKindPath(currentBuffer, activePointCount, controlPoints!!) + } + dataChanged = false + } else { + Log.d(TAG, "$index-数据未更新:${dataChanged}或无有效的点:${activePointCount}") + } + // 绘制贝塞尔曲线 + canvas.drawPath(bezierPath!!, curvePaint!!) + Log.d(TAG, "=====$index-渲染贝塞尔曲线完成!=====") + +// if (currentBuffer == null) { +// Log.d(TAG, "currentBuffer未初始化完成!") +// return +// } +// canvas.drawCircle(currentBuffer[0]!!.x, currentBuffer[0]!!.y, 30f, circlePaint!!) + } + + // 绘制可见区域内的贝塞尔曲线 + private fun drawClippedBezierPath( + points: Array?, + count: Int, + controlPoints: FloatArray + ) { + if (points.isNullOrEmpty()) { + Log.d(TAG, "$index-贝塞尔曲线点的个数为空,返回!") + return + } + var isFirstPoint = true + var wasLastPointVisible = false + var p: Point? + var nextPoint: Point? + var currentPointVisible = false + var nextPointVisible = false + var controlIndex: Int + var x: Float + var y: Float + var nextX: Float + var nextY: Float + var intersection: FloatArray? + + for (i in 0 until count - 1) { + p = points[i] + nextPoint = points[i + 1] + if (p == null || nextPoint == null) continue + x = p.x + y = p.y + nextX = nextPoint.x + nextY = nextPoint.y + + // 检查当前点和下一个点是否在可见区域内 + currentPointVisible = isPointVisible(x, y) + nextPointVisible = isPointVisible(nextX, nextY) + controlIndex = i * 2 + // 处理可见性变化 + if (currentPointVisible || nextPointVisible) { + // 如果是第一个可见点,移动到该点 + if (isFirstPoint) { + bezierPath!!.moveTo(x, y) + isFirstPoint = false + } + // 如果当前点和下一个点都可见,直接连接 + if (currentPointVisible && nextPointVisible) { + bezierPath!!.cubicTo( + controlPoints[controlIndex], controlPoints[controlIndex + 1], + controlPoints[controlIndex + 2], controlPoints[controlIndex + 3], + nextX, nextY + ) + } else if (currentPointVisible && !nextPointVisible) { +// intersection = findIntersection(x, y, nextX, nextY) +// if (intersection != null) { +// bezierPath!!.lineTo(intersection[0], intersection[1]) +// } + bezierPath!!.cubicTo( + controlPoints[controlIndex], controlPoints[controlIndex + 1], + controlPoints[controlIndex + 2], controlPoints[controlIndex + 3], + nextX, nextY + ) + } else if (!currentPointVisible && nextPointVisible) { +// intersection = findIntersection(nextX, nextY, x, y) +// if (intersection != null) { +// bezierPath!!.moveTo(intersection[0], intersection[1]) +// bezierPath!!.cubicTo( +// controlPoints[controlIndex], controlPoints[controlIndex + 1], +// controlPoints[controlIndex + 2], controlPoints[controlIndex + 3], +// nextX, nextY +// ) +// } + bezierPath!!.cubicTo( + controlPoints[controlIndex], controlPoints[controlIndex + 1], + controlPoints[controlIndex + 2], controlPoints[controlIndex + 3], + nextX, nextY + ) + } + wasLastPointVisible = true + } else { + // 如果连续不可见点,重置路径状态 + if (wasLastPointVisible) { + isFirstPoint = true + } + wasLastPointVisible = false + } + } + } + + // 计算贝塞尔曲线的控制点 + private fun calculateControlPoints( + points: Array?, + count: Int, + controlPoints: FloatArray + ) { + if (count < 3 || points.isNullOrEmpty()) { + Log.d(TAG, "$index-点的个数小于3,无法绘制贝塞尔曲线!") + return// 至少需要3个点才能计算控制点 + } + var prev: Point? + var current: Point? + var next: Point? + var controlIndex: Int + // 使用相邻点的中点作为控制点 + for (i in 1 until count - 1) { + prev = points[i - 1] + current = points[i] + next = points[i + 1] + controlIndex = i * 2 + if (current == null || prev == null || next == null) continue + + // 第一个控制点:当前点和前一个点的中点 + controlPoints[controlIndex] = (current.x + prev.x) / 2 + controlPoints[controlIndex + 1] = (current.y + prev.y) / 2 + + // 第二个控制点:当前点和下一个点的中点 + controlPoints[controlIndex + 2] = (current.x + next.x) / 2 + controlPoints[controlIndex + 3] = (current.y + next.y) / 2 + } + if (points[0] == null || points[count - 2] == null) return + // 特殊处理第一个和最后一个控制点 + controlPoints[0] = points[0]!!.x + controlPoints[1] = points[0]!!.y + + val lastIndex = (count - 2) * 2 + controlPoints[lastIndex] = points[count - 2]!!.x + controlPoints[lastIndex + 1] = points[count - 2]!!.y + } + + // 计算二阶贝塞尔曲线的控制点 + private fun calculateControlPoints2ndKind( + points: Array?, + count: Int, + controlPoints: FloatArray + ) { + if (count < 2 || points.isNullOrEmpty()) return // 至少需要2个点才能计算控制点 + var current: Point? + var next: Point? + var controlIndex: Int + var dx: Float + var dy: Float + // 简单算法:使用相邻点的中点作为控制点 + for (i in 0 until count - 1) { + current = points[i] + next = points[i + 1] + if (current == null || next == null) continue + controlIndex = i * 2 + + // 控制点:当前点和下一个点之间的中点,增加一定偏移使曲线更平滑 + dx = next.x - current.x + dy = next.y - current.y + + // 控制点位置 = 中点 + 一定比例的方向向量(使曲线更平滑) + controlPoints[controlIndex] = current.x + dx * 0.5f + controlPoints[controlIndex + 1] = current.y + dy * 0.5f + } + } + + /** + * 绘制可见区域内的二阶贝塞尔曲线 + */ + private fun drawClippedBezier2ndKindPath( + points: Array?, + count: Int, + controlPoints: FloatArray + ) { + if (points.isNullOrEmpty()) { + Log.d(TAG, "$index-贝塞尔曲线点的个数为空,返回!") + return + } + var isFirstPoint = true + var wasLastPointVisible = false +// var hasPath = false + + var p: Point? + var nextPoint: Point? + for (i in 0 until count - 1) { + p = points[i] + nextPoint = points[i + 1] + if (p == null || nextPoint == null) continue + val x = p.x + val y = p.y + val nextX = nextPoint.x + val nextY = nextPoint.y + + // 检查当前点和下一个点是否在可见区域内 + val currentPointVisible = isPointVisible(x, y) + val nextPointVisible = isPointVisible(nextX, nextY) + + // 处理可见性变化 + if (currentPointVisible || nextPointVisible) { + // 如果是第一个可见点,移动到该点 + if (isFirstPoint) { +// bezierPath!!.moveTo(x-strokeWidth/4, y) + bezierPath!!.moveTo(x, y) + isFirstPoint = false +// hasPath = true + } + + // 如果当前点和下一个点都可见,直接连接 + if (currentPointVisible && nextPointVisible) { + // 使用二阶贝塞尔曲线:quadTo方法(控制点x, 控制点y, 终点x, 终点y) + bezierPath!!.quadTo( + controlPoints[i * 2], controlPoints[i * 2 + 1], + nextX, nextY + ) +// hasPath = true + } else if (currentPointVisible && !nextPointVisible) { +// val intersection = findIntersection(x, y, nextX, nextY) +// if (intersection != null) { +// bezierPath!!.lineTo(intersection[0], intersection[1]) +//// hasPath = true +// } + bezierPath!!.lineTo( + controlPoints[i * 2], controlPoints[i * 2 + 1], + ) + } else if (!currentPointVisible && nextPointVisible) { +// val intersection = findIntersection(nextX, nextY, x, y) +// if (intersection != null) { +// bezierPath!!.moveTo(intersection[0], intersection[1]) +// // 绘制二阶贝塞尔曲线 +// val controlIndex = i * 2 +// bezierPath!!.quadTo( +// controlPoints[controlIndex], controlPoints[controlIndex + 1], +// nextX, nextY +// ) +//// hasPath = true +// } + bezierPath!!.lineTo( + controlPoints[i * 2], controlPoints[i * 2 + 1], + ) + } + wasLastPointVisible = true + } else { + // 如果连续不可见点,重置路径状态 + if (wasLastPointVisible) { + isFirstPoint = true + } + wasLastPointVisible = false + } + } +// if (count > 1 && hasPath) { +// val lastPoint = points[count - 1] ?: return +// val endX = lastPoint.x +// val endY = lastPoint.y +// +// // 添加一个微小的延伸,确保终点形状为方形 +// if (isPointVisible(endX, endY)) { +// bezierPath!!.lineTo(endX + strokeWidth / 4, endY) +// } +// } + Log.d(TAG, "=======$index-绘制二阶贝塞尔曲线完成=======!") + } + + /** + * 绘制二阶贝塞尔曲线 + */ + private fun drawBezierPath2ndKind(count: Int) { + + Log.d(TAG, "=======$index-绘制二阶贝塞尔曲线完成=======!") + } + + // 检查点是否在可见区域内(考虑线宽) + private fun isPointVisible(x: Float, y: Float): Boolean { + val extraMargin = strokeWidth / 2 + return visibleRect!!.contains(x, y) || + visibleRect!!.let { + it.inset(-extraMargin, -extraMargin)// 扩大(使用负数)边界以考虑线宽 + it.contains(x, y) + } + } + + // 计算线段与可见区域的交点 + private fun findIntersection(x1: Float, y1: Float, x2: Float, y2: Float): FloatArray? { +// // 简化版:只检查线段与可见区域边界的交点 +// // 实际应用中可能需要更复杂的贝塞尔曲线与矩形的交点计算 +// +// // 检查与左边界的交点 +// if ((x1 < visibleRect!!.left && x2 >= visibleRect!!.left) || +// (x1 >= visibleRect!!.left && x2 < visibleRect!!.left) +// ) { +// val t = (visibleRect!!.left - x1) / (x2 - x1) +// val y = y1 + t * (y2 - y1) +// if (y >= visibleRect!!.top && y <= visibleRect!!.bottom) { +// return floatArrayOf(visibleRect!!.left, y) +// } +// } +// +// // 检查与右边界的交点 +// if ((x1 < visibleRect!!.right && x2 >= visibleRect!!.right) || +// (x1 >= visibleRect!!.right && x2 < visibleRect!!.right) +// ) { +// val t = (visibleRect!!.right - x1) / (x2 - x1) +// val y = y1 + t * (y2 - y1) +// if (y >= visibleRect!!.top && y <= visibleRect!!.bottom) { +// return floatArrayOf(visibleRect!!.right, y) +// } +// } +// +// // 检查与上边界的交点 +// if ((y1 < visibleRect!!.top && y2 >= visibleRect!!.top) || +// (y1 >= visibleRect!!.top && y2 < visibleRect!!.top) +// ) { +// val t = (visibleRect!!.top - y1) / (y2 - y1) +// val x = x1 + t * (x2 - x1) +// if (x >= visibleRect!!.left && x <= visibleRect!!.right) { +// return floatArrayOf(x, visibleRect!!.top) +// } +// } +// +// // 检查与下边界的交点 +// if ((y1 < visibleRect!!.bottom && y2 >= visibleRect!!.bottom) || +// (y1 >= visibleRect!!.bottom && y2 < visibleRect!!.bottom) +// ) { +// val t = (visibleRect!!.bottom - y1) / (y2 - y1) +// val x = x1 + t * (x2 - x1) +// if (x >= visibleRect!!.left && x <= visibleRect!!.right) { +// return floatArrayOf(x, visibleRect!!.bottom) +// } +// } + + return null // 没有交点 + } + + private inner class AnimationThread : Thread() { + override fun run() { + var canvas: Canvas? + lastUpdateTime = System.currentTimeMillis() + + while (isRunning) { + canvas = null + try { + canvas = surfaceHolder!!.lockCanvas() + synchronized(surfaceHolder!!) { + // 绘制 + Log.d(TAG, "$index-准备绘制!") + // 清屏 + canvas?.drawColor(Color.rgb(231, 235, 238)) + drawMovingDashedPath(canvas) + drawPath(canvas) + drawCar(canvas) + } + } finally { + if (canvas != null) { + surfaceHolder!!.unlockCanvasAndPost(canvas) + } + } + + try { + costTime = fpsInterval - System.currentTimeMillis() + lastUpdateTime + if (costTime > 0) { + sleep(costTime) + } + } catch (e: InterruptedException) { + e.printStackTrace() + } + } + } + } + + // 轨迹点对象(可复用) + class Point { + var x: Float = 0f + var y: Float = 0f + var isActive: Boolean = false + + fun set(x: Float, y: Float) { + this.x = x + this.y = y + this.isActive = true + } + + fun reset() { + this.isActive = false + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/DecisionLayout.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/DecisionLayout.kt index d241c16476..f62c20d56f 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/DecisionLayout.kt +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/DecisionLayout.kt @@ -10,9 +10,6 @@ import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotIdentifyListener import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotIdentifyListenerManager import com.mogo.eagle.core.function.map.R import com.mogo.eagle.core.utilcode.util.ThreadUtils -import kotlinx.android.synthetic.main.layout_decision_container.view.decMapView -import kotlinx.android.synthetic.main.layout_decision_container.view.preDetailView2 -import kotlinx.android.synthetic.main.layout_decision_container.view.preDetailView3 import kotlinx.android.synthetic.main.layout_decision_container.view.tvPre1 import kotlinx.android.synthetic.main.layout_decision_container.view.tvPre2 import kotlinx.android.synthetic.main.layout_decision_container.view.tvPre3 @@ -39,21 +36,12 @@ class DecisionLayout @JvmOverloads constructor( } fun onCreate(savedInstanceState: Bundle?) { - decMapView.onCreate(savedInstanceState) - preDetailView2.onCreate(savedInstanceState) - preDetailView3.onCreate(savedInstanceState) } fun onSaveInstanceState(outState: Bundle) { - decMapView.onSaveInstanceState(outState) - preDetailView2.onSaveInstanceState(outState) - preDetailView3.onSaveInstanceState(outState) } fun onResume() { - decMapView.onResume() - preDetailView2.onResume() - preDetailView3.onResume() } @SuppressLint("SetTextI18n") @@ -81,20 +69,11 @@ class DecisionLayout @JvmOverloads constructor( } fun onLowMemory() { - decMapView.onLowMemory() - preDetailView2.onLowMemory() - preDetailView3.onLowMemory() } fun onPause() { - decMapView.onPause() - preDetailView2.onPause() - preDetailView3.onPause() } fun onDestroy() { - decMapView.onDestroy() - preDetailView2.onDestroy() - preDetailView3.onDestroy() } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-map/src/main/res/layout/layout_decision_container.xml b/core/function-impl/mogo-core-function-map/src/main/res/layout/layout_decision_container.xml index bab05abb53..9556fd75c3 100644 --- a/core/function-impl/mogo-core-function-map/src/main/res/layout/layout_decision_container.xml +++ b/core/function-impl/mogo-core-function-map/src/main/res/layout/layout_decision_container.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent" tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> - + app:map_index="0" + /> - + app:map_index="1" + /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:map_index="2" + /> + + + + \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt index dd1c8f58a3..09e721b832 100644 --- a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt @@ -236,7 +236,7 @@ object FunctionBuildConfig { */ @Volatile @JvmField - var isDrawPreIdentifyData = false + var isDrawPreIdentifyData = true /** * 地图是否绘制决策数据的Marker diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt index 444b62c551..93743b7a90 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/autopilot/IMoGoAutopilotIdentifyListener.kt @@ -61,4 +61,8 @@ interface IMoGoAutopilotIdentifyListener { fun onAutopilotV2nCongestionEvent(header: MessagePad.Header, rsi: MogoV2X.RSI_PB) {} fun onPredictionProbabilityChanged(pro1: Float, pro2: Float) {} + + fun screenPointsChanged(data: FloatArray, index: Int = 1) {} + + fun preScrPointsChanged(data: FloatArray, index: Int = 0) {} } \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotIdentifyListenerManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotIdentifyListenerManager.kt index c87b8e9974..dc10c87ca2 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotIdentifyListenerManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/autopilot/CallerAutopilotIdentifyListenerManager.kt @@ -73,4 +73,18 @@ object CallerAutopilotIdentifyListenerManager : CallerBase): List + + fun toScreenLocation(lon: Double, lat: Double): android.graphics.Point? } \ No newline at end of file diff --git a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.kt b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.kt index 381be25bcb..d3a4d4fb54 100644 --- a/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.kt +++ b/libraries/mogo-map/src/main/java/com/mogo/map/AMapWrapper.kt @@ -12,6 +12,7 @@ import com.mogo.map.overlay.wrapper.point.AMapPointWrapper import com.mogo.map.uicontroller.IMogoMapUIController import com.mogo.map.utils.ObjectUtils import com.zhidaoauto.map.data.point.LonLatPoint +import com.zhidaoauto.map.sdk.open.common.tools.MapTools import com.zhidaoauto.map.sdk.open.renders.marker.BatchMarkerOptions import com.zhidaoauto.map.sdk.open.renders.marker.Marker import com.zhidaoauto.map.sdk.open.renders.marker.MarkerOptions @@ -75,7 +76,8 @@ class AMapWrapper(map: MapAutoViewHelper?, mapView: MapAutoView, controller: IMo } val markerOptions = MarkerOptions(options.id, mMapView.getMapController()).setGps(true) .position(LonLatPoint(options.longitude, options.latitude, options.rotate.toDouble())) - val marker = Marker(markerOptions,mMapView.getMapController(), + val marker = Marker( + markerOptions, mMapView.getMapController(), mMapView.getMapController()?.getMarkerCall() ) marker.setDisplayAnimEnable(options.displayAnim) @@ -93,8 +95,8 @@ class AMapWrapper(map: MapAutoViewHelper?, mapView: MapAutoView, controller: IMo return null } if (options.isFilledIn) { - val delegate = mAMap?.drawPolygon(polylineOptions) - return AMapPolylineWrapper(options.id, delegate, mMapView) + val delegate = mAMap?.drawPolygon(polylineOptions) + return AMapPolylineWrapper(options.id, delegate, mMapView) } else { val delegate = (if (polylineOptions.lineWidth > 0) mAMap?.drawThickLine(polylineOptions) else mAMap?.drawLine( @@ -244,4 +246,22 @@ class AMapWrapper(map: MapAutoViewHelper?, mapView: MapAutoView, controller: IMo override fun switchData(x: Double, y: Double, isWgs84: Boolean): DoubleArray? { return mAMap?.switchData(x, y, isWgs84) } + + override fun toScreenLocations(data: List): List { + return MapTools.toScreenLocations(data, mMapView.getMapController()) + } + + override fun toScreenLocation(lon: Double, lat: Double): android.graphics.Point? { + val controller = mMapView.getMapController() + if (controller == null) { + return null + } else { + val pixel = controller.lonlatToPixels(lon, lat) + return if (pixel == null) { + null + } else { + android.graphics.Point(pixel.x.toInt(), pixel.y.toInt()) + } + } + } } \ No newline at end of file