diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/MarkerDrawerManager.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/MarkerDrawerManager.kt index f69b8bfeb1..c126b702a8 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/MarkerDrawerManager.kt +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/smp/MarkerDrawerManager.kt @@ -5,7 +5,9 @@ import android.util.Log import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.LatLng import com.mogo.eagle.core.utilcode.util.CoordinateUtils -import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils +import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils.getAngleDiff +import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils.getLineAngle +import com.mogo.eagle.core.utilcode.util.LocationUtils import io.reactivex.Observable import io.reactivex.ObservableOnSubscribe import io.reactivex.android.schedulers.AndroidSchedulers @@ -132,54 +134,94 @@ object MarkerDrawerManager { var currentIndex = 0 //记录疑似点 // 是否超过200KM var isLongDistance = false - if (routePoints.isNotEmpty()) { - //基础点 - val baseLatLng = routePoints[0] - newPoints.add(LatLng(baseLatLng.latitude, baseLatLng.longitude)) - var baseDiffDis = CoordinateUtils.calculateLineDistance( - realLon, realLat, baseLatLng.longitude, baseLatLng.latitude - ) // lon,lat, prelon, prelat - if (baseDiffDis > 200000) { - isLongDistance = true - } - val size = routePoints.size - for (i in 1 until size) { - val latLng = routePoints[i] - // 深拷贝数据用于高德地图上轨迹线的绘制 - newPoints.add(LatLng(latLng.latitude, latLng.longitude)) - if (isLongDistance) continue - val diff = CoordinateUtils.calculateLineDistance( - realLon, realLat, latLng.longitude, latLng.latitude - ) - if (baseDiffDis > diff) { - baseDiffDis = diff - // 距离最近的时候判断是否走过 - if (DrivingDirectionUtils.getDegreeOfCar2Poi2( - realLon, - realLat, + var distance = 0.0 + var tmpDistance: Double + var angle = 0.0 + routePoints.forEachIndexed { index, latLng -> + newPoints.add(LatLng(latLng.latitude, latLng.longitude)) + when (index) { + 0 -> { + distance = LocationUtils.pointToLine( + latLng.longitude, + latLng.latitude, + routePoints[index + 1].longitude, + routePoints[index + 1].latitude, + realLon, + realLat + ) + if (distance > 200000) { + isLongDistance = true + } + } + + routePoints.size - 1 -> {} + else -> { + // 车到两轨迹点距离最短(距离这条路最近) + tmpDistance = LocationUtils.pointToLine( + latLng.longitude, + latLng.latitude, + routePoints[index + 1].longitude, + routePoints[index + 1].latitude, + realLon, + realLat + ) + if (tmpDistance <= distance) { + // 车此刻运动方向与两轨迹点朝向的夹角小于90(结合距离线段最近则车在两点之间,意味着已走过第index个轨迹点) + angle = getLineAngle( latLng.longitude, latLng.latitude, - heading - ) >= 90 - ) { - currentIndex = i + routePoints[index + 1].longitude, + routePoints[index + 1].latitude + ) + if (getAngleDiff(angle, heading) < 90) { + if (index < currentIndex) { + return@forEachIndexed + } else { + distance = tmpDistance + currentIndex = index + } + } } } } - Log.d("MarkerDrawerManager", "当次计算已走过的点的索引为:$currentIndex,存储的上次索引为:$lastArrivedIndex, ,起点为:(${newPoints[0].longitude},${newPoints[0].latitude}),终点为:(${newPoints.last().longitude},${newPoints.last().latitude})") - if (!isLongDistance) { - // 过滤缓存的非当次轨迹的索引,并且出现车已走过索引跳跃过大时视为无效复用上一次计算结果 - if (currentIndex < lastArrivedIndex || (lastArrivedIndex >= 0 && currentIndex - lastArrivedIndex >= 10)) { - if (lastArrivedIndex < size) { - currentIndex = lastArrivedIndex - } - } else { - lastArrivedIndex = currentIndex - } - if (size >= 2) { - newPoints.add(currentIndex + 1, LatLng(realLat, realLon)) - return currentIndex + 1 - } + } + Log.d( + "MarkerDrawerManager", "起点为:(${newPoints[0].longitude},${newPoints[0].latitude}),终点为:(${newPoints.last().longitude},${newPoints.last().latitude})" + ) + if (!isLongDistance && currentIndex > 0) { + val size = routePoints.size +// // 对于非法结果,需要纠正 +// if (currentIndex < lastArrivedIndex || (lastArrivedIndex > 0 && currentIndex - lastArrivedIndex > 5)) { +// val lastNextIndex = lastArrivedIndex + 1 +// var isLastNextArrived = false +// if (lastNextIndex in 0 until size) { +// if (DrivingDirectionUtils.getDegreeOfCar2Poi2( +// realLon, +// realLat, +// routePoints[lastNextIndex].longitude, +// routePoints[lastNextIndex].latitude, +// heading +// ) >= 90 +// ) { +// isLastNextArrived = true +// } +// } +// +// if (isLastNextArrived) { +// currentIndex = lastNextIndex +// lastArrivedIndex = currentIndex +// } else { +// if (lastArrivedIndex in 0 until size) { +// currentIndex = lastArrivedIndex +// } +// } +// } else { +// lastArrivedIndex = currentIndex +// } + if (size >= 2) { + Log.d("MarkerDrawerManager", "最终绘制的已走过index为:$currentIndex,车所在位置为:${currentIndex + 1}") + newPoints.add(currentIndex + 1, LatLng(realLat, realLon)) + return currentIndex + 1 } } return 0 diff --git a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/OverMapView.kt b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/OverMapView.kt index fbd634cfa3..ed4793e385 100644 --- a/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/OverMapView.kt +++ b/core/function-impl/mogo-core-function-map/src/main/java/com/mogo/eagle/core/function/view/OverMapView.kt @@ -88,6 +88,7 @@ class OverMapView @JvmOverloads constructor( private var mContext: Context? = null private var mTilt = 0f private var overLayerView: TextView? = null + @Volatile private var isMapLoaded = false @@ -112,10 +113,18 @@ class OverMapView @JvmOverloads constructor( var arrivedBitmap: BitmapDescriptor? = null var unArrivedBitmap: BitmapDescriptor? = null var transparentBitmap: BitmapDescriptor? = null + private val pointBitmap by lazy { + BitmapDescriptorFactory.fromResource(R.drawable.loc_azure_bg) + } + private val markerOptionsList by lazy { + ArrayList() + } + private var isDebug = true // 绘制轨迹线的集合 private val textureList: MutableList = ArrayList() private val texIndexList: MutableList = ArrayList() + @Volatile private var mLocation: MogoLocation? = null private var isFirstLocation = true @@ -123,6 +132,7 @@ class OverMapView @JvmOverloads constructor( var currMarkerList: ArrayList? = null var siteMarkerList: ArrayList? = null var siteNameList: ArrayList? = null + private var pointMarkers: ArrayList? = null @Volatile private var isFirst = true @@ -148,6 +158,7 @@ class OverMapView @JvmOverloads constructor( private const val DRAW_POLY_LINE = 1 private const val DRAW_CAR_LOCATION = 2 private const val CLEAR_POLY_LINE = 3 + private const val CLEAR_POINT_MARKERS = 4 private const val DRAW_V2X_MARKERS = 1 private const val DISPLAY_OVER_VIEW = 2 @@ -235,6 +246,16 @@ class OverMapView @JvmOverloads constructor( overLayerView?.visibility = View.GONE } + fun setDebugMode(isDebug: Boolean) { + this.isDebug = isDebug + if (!isDebug) { + Message.obtain().apply { + what = CLEAR_POINT_MARKERS + frequentHandler?.sendMessage(this) + } + } + } + /** * siteLatLngs: 高德坐标集合 * bitmap: Marker对应的图片 @@ -362,6 +383,10 @@ class OverMapView @JvmOverloads constructor( what = CLEAR_POLY_LINE frequentHandler?.sendMessage(this) } + Message.obtain().apply { + what = CLEAR_POINT_MARKERS + frequentHandler?.sendMessage(this) + } mStartMarker?.isVisible = false mEndMarker?.isVisible = false @@ -778,6 +803,7 @@ class OverMapView @JvmOverloads constructor( * @param locIndex */ private fun realDrawPolyline(coordinates: List, locIndex: Int) { + val drawPointMarkers = isDebug && pointMarkers.isNullOrEmpty() val time = System.currentTimeMillis() if (textureList.size > 0) { textureList.clear() @@ -785,6 +811,7 @@ class OverMapView @JvmOverloads constructor( if (texIndexList.size > 0) { texIndexList.clear() } + if (drawPointMarkers) markerOptionsList.clear() if (isClearArrived) { textureList.add(transparentBitmap)// index:0 } else { @@ -793,7 +820,15 @@ class OverMapView @JvmOverloads constructor( } // 未走过的纹理 textureList.add(unArrivedBitmap)// index:1 + for (i in coordinates.indices) { + if (drawPointMarkers) { + markerOptionsList.add(MarkerOptions().also { + it.icon(pointBitmap) + it.anchor(0.5f, 0.5f) + it.position(coordinates[i]) + }) + } // 线段数比点数少一个 if (i == 0) continue if (i <= locIndex) { @@ -802,6 +837,9 @@ class OverMapView @JvmOverloads constructor( texIndexList.add(1) } } + if (drawPointMarkers) { + pointMarkers = mAMap?.addMarkers(markerOptionsList, false) + } if (mCoveredPolyline != null) { mCoveredPolyline!!.options.customTextureList = textureList mCoveredPolyline!!.options.customTextureIndex = texIndexList @@ -863,7 +901,8 @@ class OverMapView @JvmOverloads constructor( //设置希望展示的地图缩放级别 Log.d(TAG, "切换视角展示车,定位为:${mLocation!!.longitude},${mLocation!!.latitude}") val cameraPosition = CameraPosition.Builder() - .target(LatLng(mLocation!!.latitude, mLocation!!.longitude)).tilt(mTilt).zoom(zoomLevel.toFloat()).build() + .target(LatLng(mLocation!!.latitude, mLocation!!.longitude)).tilt(mTilt) + .zoom(zoomLevel.toFloat()).build() mAMap!!.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)) } } @@ -1006,6 +1045,13 @@ class OverMapView @JvmOverloads constructor( mCoveredPolyline?.points = emptyList() } + private fun realClearPointMarkers() { + pointMarkers?.forEach { + it.destroy() + } + pointMarkers = null + } + private fun realClearSitePolyline() { mSitePolyline?.points = emptyList() } @@ -1165,16 +1211,23 @@ class OverMapView @JvmOverloads constructor( realDrawPolyline(first, second) } } + DRAW_CAR_LOCATION -> { removeMessages(DRAW_CAR_LOCATION) (msg.obj as MogoLocation).apply { realDrawCarMarker(this) } } + CLEAR_POLY_LINE -> { removeMessages(CLEAR_POLY_LINE) realClearPolyline() } + + CLEAR_POINT_MARKERS -> { + removeMessages(CLEAR_POINT_MARKERS) + realClearPointMarkers() + } } } } @@ -1192,57 +1245,68 @@ class OverMapView @JvmOverloads constructor( realDrawSitePolyline(first, second) } } + DRAW_V2X_MARKERS -> { removeMessages(DRAW_V2X_MARKERS) (msg.obj as ArrayList).apply { realDrawV2XMarkers(this) } } + DISPLAY_OVER_VIEW -> { removeMessages(DISPLAY_OVER_VIEW) realDisplayOverView() } + INCLUDE_SITES_OVER_VIEW -> { removeMessages(INCLUDE_SITES_OVER_VIEW) (msg.obj as List).also { realIncludeSitePointsAndRefresh(it) } } + DRAW_START_AND_END -> { removeMessages(DRAW_START_AND_END) (msg.obj as List).also { realDrawStartAndEndMarker(it) } } + CLEAR_SITE_POLYLINE -> { removeMessages(CLEAR_SITE_POLYLINE) MarkerDrawerManager.isStopCalculate = false realClearSitePolyline() } + CLEAR_V2X_MARKERS -> { removeMessages(CLEAR_V2X_MARKERS) realClearV2XMarkers() } + DRAW_SITE_NAME -> { removeMessages(DRAW_SITE_NAME) (msg.obj as ArrayList).also { realDrawSiteNames(it) } } + CLEAR_SITE_NAME -> { removeMessages(CLEAR_SITE_NAME) realClearSiteNameViews() } + DRAW_SITE_MARKER -> { (msg.obj as ArrayList).also { realDrawSiteMarkers(it) } removeMessages(DRAW_SITE_MARKER) } + CLEAR_SITE_MARKER -> { removeMessages(CLEAR_SITE_MARKER) realClearSiteMarkers() } + DRAW_INF_STRUCTURE -> { removeMessages(DRAW_INF_STRUCTURE) (msg.obj as ArrayList).also { diff --git a/core/function-impl/mogo-core-function-map/src/main/res/drawable-xhdpi/loc_azure_bg.png b/core/function-impl/mogo-core-function-map/src/main/res/drawable-xhdpi/loc_azure_bg.png new file mode 100644 index 0000000000..dc778d7d28 Binary files /dev/null and b/core/function-impl/mogo-core-function-map/src/main/res/drawable-xhdpi/loc_azure_bg.png differ diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/DrivingDirectionUtils.java b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/DrivingDirectionUtils.java index eb79646a84..6d0c419431 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/DrivingDirectionUtils.java +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/DrivingDirectionUtils.java @@ -153,4 +153,43 @@ public class DrivingDirectionUtils { return 180 - Math.abs(Math.abs(angle1 - angle2) - 180); } + /** + * + * @param dx1 + * @param dy1 + * @param dx2 + * @param dy2 + * @return 两点组成的线段与正北的夹角 + */ + public static double getLineAngle(double dx1, double dy1, double dx2, double dy2) { + return getAngleToNorth((dx2 - dx1), (dy2 - dy1)); + } + + public static double getAngleToNorth(double x, double y) { + double resAngle = 0; + + if (0 == x && 0 == y) { + resAngle = -400; + } else if (0 == y) { + if (0 < x) { + resAngle = 90; + } else { + resAngle = 270; + } + } else if (0 == x) { + if (0 < y) { + resAngle = 0; + } else { + resAngle = 180; + } + } else if (0 < y) { + resAngle = (Math.atan((x / y)) * 180 / PI); + if (0 > resAngle) { + resAngle += 360; + } + } else { + resAngle = (180 + Math.atan((x / y)) * 180 / PI); + } + return resAngle; + } } diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/LocationUtils.java b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/LocationUtils.java index 72d2d21990..5d709ac3cf 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/LocationUtils.java +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/util/LocationUtils.java @@ -68,6 +68,8 @@ public class LocationUtils { } double p = (a + b + c) / 2;// 半周长 double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积 + // 如果三个点在一条直线上则求出来的面积为NaN + if (Double.isNaN(s)) return 0.0; space = 2 * s / a;// 返回点到线的距离(利用三角形面积公式求高) return space; }