From 95f2209cc6fbc368e477431d929d83de92545eda Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Fri, 15 Sep 2023 13:31:37 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=BC=80=E5=8F=91=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/navinfo/omqs/bean/NaviRoute.kt | 43 ++ .../main/java/com/navinfo/omqs/bean/Route.kt | 24 - .../omqs/ui/activity/map/MainActivity.kt | 6 +- .../omqs/ui/activity/map/MainViewModel.kt | 228 ++----- .../omqs/ui/activity/map/SignAdapter.kt | 1 + .../ui/fragment/tasklist/TaskViewModel.kt | 3 - .../java/com/navinfo/omqs/util/NaviEngine.kt | 611 +++++++++++++++++- app/src/main/res/drawable-xxhdpi/t0201000.png | Bin 0 -> 4713 bytes app/src/main/res/layout/adapter_sign.xml | 21 +- .../library/map/handler/BaseHandler.kt | 2 +- .../library/map/handler/LineHandler.kt | 14 + .../library/map/source/OMDBDataDecoder.java | 2 +- .../collect/library/utils/FootAndDistance.kt | 145 +++++ .../collect/library/utils/GeometryTools.java | 215 +----- 14 files changed, 907 insertions(+), 408 deletions(-) create mode 100644 app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt delete mode 100644 app/src/main/java/com/navinfo/omqs/bean/Route.kt create mode 100644 app/src/main/res/drawable-xxhdpi/t0201000.png create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/utils/FootAndDistance.kt diff --git a/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt b/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt new file mode 100644 index 00000000..23004845 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt @@ -0,0 +1,43 @@ +package com.navinfo.omqs.bean + +import com.navinfo.collect.library.data.entity.RenderEntity +import com.navinfo.collect.library.utils.GeometryTools +import org.oscim.core.GeoPoint + +data class NaviRoute( + //我是整条路径中的第几段路径 + var indexInPath: Int = -1, + //link id + val linkId: String, + //起点id + var sNode: String = "", + //终点id + var eNode: String = "", + //方向 + var direct: Int = 0, + //道路名称 + var name: String = "", + //路段总长 + var length: Double = 0.0, + //当前link在整段路径中的起点 + var startIndexInPath: Int = -1, + //当前link在整段路径中的终点 + var endIndexIntPath: Int = -1, + var itemList: MutableList? = null +) { + var pointList: MutableList = mutableListOf() + get() { + return field + } + set(value) { + length = GeometryTools.getDistance(value) + field = value + } +} + +data class NaviRouteItem( + var index: Int, + val data: RenderEntity, + val linkId: String, + var distance: Int = -1 +) diff --git a/app/src/main/java/com/navinfo/omqs/bean/Route.kt b/app/src/main/java/com/navinfo/omqs/bean/Route.kt deleted file mode 100644 index e57ec794..00000000 --- a/app/src/main/java/com/navinfo/omqs/bean/Route.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.navinfo.omqs.bean - -import com.navinfo.collect.library.utils.GeometryTools -import com.navinfo.collect.library.utils.GeometryToolsKt -import org.locationtech.jts.geom.Geometry -import org.oscim.core.GeoPoint - -data class Route( - val linkId: String, - var sNode: String = "", - var eNode: String = "", - var direct: Int = 0, - var name: String = "", - var length: Double = 0.0, -) { - var pointList: MutableList = mutableListOf() - get() { - return field - } - set(value) { - length = GeometryTools.getDistance(value) - field = value - } -} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index db33d350..29057ef4 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -388,8 +388,12 @@ class MainActivity : BaseActivity() { } } + viewModel.listDataMessage.observe(this) { + Toast.makeText(this, it, Toast.LENGTH_SHORT).show() + } + viewModel.liveDataItemList.observe(this) { - if(it.isNotEmpty()) { + if (it.isNotEmpty()) { if (leftFragment == null || leftFragment !is ItemListFragment) { leftFragment = ItemListFragment { binding.mainActivityLeftFragment.visibility = View.GONE diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index aa57839a..df519994 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -123,6 +123,11 @@ class MainViewModel @Inject constructor( */ val liveDataItemList = MutableLiveData>() + /** + * 提示信息 + */ + val listDataMessage = MutableLiveData() + private var traceTag: String = "TRACE_TAG" /** @@ -217,15 +222,15 @@ class MainViewModel @Inject constructor( private var currentMapZoomLevel: Int = 0 //导航信息 - private var naviEngine: NaviEngine = NaviEngine() + private var naviEngine: NaviEngine? = null + + //规划成功 + private var naviPathSuccess = false // 定义一个互斥锁 private val naviMutex = Mutex() - init { - - mapController.mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition -> when (e) { Map.SCALE_EVENT, Map.MOVE_EVENT, Map.ROTATE_EVENT -> liveDataCenterPoint.value = @@ -317,45 +322,28 @@ class MainViewModel @Inject constructor( MapParamUtils.setTaskId(sharedPreferences.getInt(Constant.SELECT_TASK_ID, -1)) socketServer = SocketServer(mapController, traceDataBase, sharedPreferences) -// viewModelScope.launch(Dispatchers.Default) { -// naviTestFlow().collect { -// naviMutex.lock() -// if (naviEngine.geometry != null) { -// //定义垂线 -// val pointPairDistance = PointPairDistance() -// val coordinate = Coordinate(it.longitude, it.latitude) -// DistanceToPoint.computeDistance( -// naviEngine.geometry, -// coordinate, -// pointPairDistance -// ) -// if (pointPairDistance.getCoordinate(0) !== null) { -// val line = GeometryTools.createLineString( -// mutableListOf( -// it, -// GeoPoint( -// pointPairDistance.getCoordinate(0).y, -// pointPairDistance.getCoordinate(0).x -// ) -// ) -// ) -// mapController.lineHandler.showLine(line.toText()) + viewModelScope.launch(Dispatchers.Default) { +// naviTestFlow().collect { point -> +// if (naviPathSuccess) { +// naviEngine?.let { +// naviMutex.lock() +// it.bindingRoute(null, point) +// naviMutex.unlock() // } // } -// naviMutex.unlock() // } -// } - } - - - fun naviTestFlow(): Flow = flow { - - while (true) { - emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) - delay(1000) } } + +// fun naviTestFlow(): Flow = flow { +// +// while (true) { +// emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) +// delay(1000) +// } +// } + /** * 获取当前任务 */ @@ -365,7 +353,7 @@ class MainViewModel @Inject constructor( val res = realm.where(TaskBean::class.java).equalTo("id", id).findFirst() if (res != null) { currentTaskBean = realm.copyFromRealm(res) - planningPath(currentTaskBean!!) +// planningPath(currentTaskBean!!) } } @@ -375,135 +363,44 @@ class MainViewModel @Inject constructor( // Toast.makeText(context, "正在计算导航路径", Toast.LENGTH_SHORT).show() viewModelScope.launch(Dispatchers.Default) { naviMutex.lock() - naviEngine = NaviEngine() - val pathList = mutableListOf() - val realm = Realm.getDefaultInstance() - for (link in taskBean.hadLinkDvoList) { - //测线不参与导航 - if (link.linkStatus == 3) { - continue - } - val route = Route( - linkId = link.linkPid, - ) - route.pointList = GeometryTools.getGeoPoints(link.geometry) - //查询每条link的snode,enode - val res1 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res1?.let { + naviEngine = NaviEngine( + niMapController = mapController, + callback = object : OnNaviEngineCallbackListener { + override fun planningPathSuccess() { + naviPathSuccess = true + listDataMessage.postValue("导航路径规划完成") + } - val snodePid = it.properties["snodePid"] - if (snodePid != null) { - route.sNode = snodePid + override fun planningPathError(errorCode: Int, errorMessage: String) { + naviPathSuccess = false + listDataMessage.postValue(errorMessage) } - val enodePid = it.properties["enodePid"] - if (enodePid != null) { - route.eNode = enodePid - } - } - //查询每条link的方向 - val res2 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_LINK_DIRECT.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res2?.let { - val direct = it.properties["direct"] - if (direct != null) { - route.direct = direct.toInt() - } - } - //查询每条link的名称 - val res3 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_LINK_NAME.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res3?.let { - route.name = "${it.properties["name"]}" - } - pathList.add(route) - } - //用来存储最终的导航路径 - val newRouteList = mutableListOf() - //比对路径排序用的 - val tempRouteList = pathList.toMutableList() - //先找到一根有方向的link,确定起终点 - var routeStart: Route? = null - for (i in tempRouteList.indices) { - val route = pathList[i] - //只要时单方向的就行 - if (route.direct == 2 || route.direct == 3) { - routeStart = route - tempRouteList.removeAt(i) - break - } - } - if (routeStart != null) { - var sNode = "" - var eNode = "" - //如果snode,enode是顺方向,geometry 不动,否则反转 - if (routeStart.direct == 3) { - routeStart.pointList.reverse() - sNode = routeStart.eNode - eNode = routeStart.sNode - } else { - sNode = routeStart.sNode - eNode = routeStart.eNode - } - newRouteList.add(routeStart) - var bBreak = true - while (bBreak) { - //先找其实link的后续link - var bHasNext = false - for (route in tempRouteList) { - //如果是link 的e 对下个link的s,方向不用动,否则下个link的geometry反转 - if (route.sNode != "" && eNode == route.sNode) { - newRouteList.add(route) - tempRouteList.remove(route) - eNode = route.eNode - bHasNext = true - break - } else if (route.eNode != "" && eNode == route.eNode) { - route.pointList.reverse() - newRouteList.add(route) - tempRouteList.remove(route) - eNode = route.sNode - bHasNext = true - break + + override fun bindingResults(list: List) { + val signList = mutableListOf() + for (naviRouteItem in list) { + val signBean = SignBean( + iconId = SignUtil.getSignIcon(naviRouteItem.data), + iconText = SignUtil.getSignIconText(naviRouteItem.data), + linkId = naviRouteItem.linkId, + distance = naviRouteItem.distance, + name = SignUtil.getSignNameText(naviRouteItem.data), + bottomRightText = SignUtil.getSignBottomRightText(naviRouteItem.data), + renderEntity = naviRouteItem.data, + isMoreInfo = SignUtil.isMoreInfo(naviRouteItem.data), + index = SignUtil.getRoadInfoIndex(naviRouteItem.data) + ) + signList.add(signBean) } + liveDataSignList.postValue(signList) } - //先找其实link的起始link - var bHasLast = false - for (route in tempRouteList) { - //如果是link 的s 对上个link的e,方向不用动,否则下个link的geometry反转 - if (route.eNode != "" && sNode == route.eNode) { - newRouteList.add(0, route) - tempRouteList.remove(route) - sNode = route.sNode - bHasLast = true - break - } else if (route.sNode != "" && sNode == route.sNode) { - route.pointList.reverse() - newRouteList.add(0, route) - tempRouteList.remove(route) - sNode = route.eNode - bHasLast = true - break - } - } - if (tempRouteList.size == 0) { - bBreak = false - } else { - if (!bHasLast && !bHasNext) { - bBreak = false - //TODO 处理错误,路径不完整 - } - } - } - } - naviEngine.routeList = newRouteList + }) + listDataMessage.postValue("开始导航路径规划") + naviEngine!!.planningPath(taskBean) naviMutex.unlock() } } else { -// Toast.makeText(context, "数据未安装,无法计算导航路径", Toast.LENGTH_SHORT).show() + listDataMessage.postValue("数据未安装,无法计算导航路径") } } @@ -720,14 +617,9 @@ class MainViewModel @Inject constructor( continue } - val distance = GeometryTools.distanceToDouble( - point, GeometryTools.createGeoPoint(element.geometry) - ) - val signBean = SignBean( iconId = SignUtil.getSignIcon(element), iconText = SignUtil.getSignIconText(element), - distance = distance.toInt(), linkId = linkId, name = SignUtil.getSignNameText(element), bottomRightText = SignUtil.getSignBottomRightText(element), @@ -735,7 +627,7 @@ class MainViewModel @Inject constructor( isMoreInfo = SignUtil.isMoreInfo(element), index = SignUtil.getRoadInfoIndex(element) ) - Log.e("jingo", "捕捉到的数据code ${element.code}") +// Log.e("jingo", "捕捉到的数据code ${element.code}") when (element.code) { DataCodeEnum.OMDB_MULTI_DIGITIZED.code,//上下线分离 DataCodeEnum.OMDB_CON_ACCESS.code,//全封闭 @@ -864,6 +756,7 @@ class MainViewModel @Inject constructor( */ fun onClickLocationButton() { mapController.locationLayerHandler.animateToCurrentPosition() + planningPath(currentTaskBean!!) } /** @@ -872,6 +765,7 @@ class MainViewModel @Inject constructor( fun onClickMenu() { menuState = !menuState liveDataMenuState.postValue(menuState) + naviEngine!!.bindingRoute(null, mapController.mMapView.vtmMap.mapPosition.geoPoint) } override fun onCleared() { @@ -1004,7 +898,7 @@ class MainViewModel @Inject constructor( * */ fun refreshOMDBLayer(layerConfigList: List) { // 根据获取到的配置信息,筛选未勾选的图层名称 - if (layerConfigList != null && !layerConfigList.isEmpty()) { + if (layerConfigList != null && layerConfigList.isNotEmpty()) { val omdbVisibleList = mutableListOf() layerConfigList.forEach { omdbVisibleList.addAll(it.tableMap.filter { entry -> diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt index 4a04a0b4..f8023e57 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt @@ -128,6 +128,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) : } else { bd.signMainInfo.visibility = View.GONE } + bd.signDistanceText.text = "${item.distance}米" bd.signSecondIcon.text = "" if (item.renderEntity.code == DataCodeEnum.OMDB_SPEEDLIMIT.code) { val minSpeed = SignUtil.getSpeedLimitMinText(item.renderEntity) diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt index d9773ef2..eef58ebc 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskViewModel.kt @@ -12,18 +12,15 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.navinfo.collect.library.data.dao.impl.TraceDataBase import com.navinfo.collect.library.data.entity.* -import com.navinfo.collect.library.enums.DataCodeEnum import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.OnGeoPointClickListener import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.MapParamUtils import com.navinfo.omqs.Constant -import com.navinfo.omqs.bean.Route import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.http.NetResult import com.navinfo.omqs.http.NetworkService import com.navinfo.omqs.tools.FileManager -import com.navinfo.omqs.ui.activity.login.LoginStatus import com.navinfo.omqs.ui.dialog.FirstDialog import com.navinfo.omqs.util.DateTimeUtil import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt index 863ed36c..178c1735 100644 --- a/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt +++ b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt @@ -1,25 +1,626 @@ package com.navinfo.omqs.util +import android.util.Log +import com.navinfo.collect.library.data.entity.NiLocation +import com.navinfo.collect.library.data.entity.RenderEntity +import com.navinfo.collect.library.data.entity.TaskBean +import com.navinfo.collect.library.enums.DataCodeEnum +import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.utils.GeometryTools -import com.navinfo.omqs.bean.Route +import com.navinfo.omqs.bean.NaviRoute +import com.navinfo.omqs.bean.NaviRouteItem +import io.realm.Realm +import io.realm.RealmQuery import org.locationtech.jts.geom.LineString +import org.locationtech.jts.geom.Point import org.oscim.core.GeoPoint -class NaviEngine { +public interface OnNaviEngineCallbackListener { + fun planningPathSuccess() + fun planningPathError(errorCode: Int, errorMessage: String) + fun bindingResults(list: List) +} + + +class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngineCallbackListener) { + + + private val QUERY_KEY_LIST = arrayOf( + DataCodeEnum.OMDB_SPEEDLIMIT.name, + DataCodeEnum.OMDB_SPEEDLIMIT_COND.name, + DataCodeEnum.OMDB_SPEEDLIMIT_VAR.name, + DataCodeEnum.OMDB_TRAFFICLIGHT.name, + DataCodeEnum.OMDB_RESTRICTION.name, + DataCodeEnum.OMDB_LANEINFO.name, + DataCodeEnum.OMDB_TRAFFIC_SIGN.name, + DataCodeEnum.OMDB_WARNINGSIGN.name, + DataCodeEnum.OMDB_TOLLGATE.name + ) + + /** + * 偏离距离 单位:米 + */ + private val DEVIATION_DISTANCE = 150000 + + /** + * 偏离次数上限 + */ + private val DEVIATION_COUNT = 3 + + /** + * 局部匹配时,走过的路段还记录100米 + */ + private val PASSED_ROUTE_DISTANCE = 100 + + /** + * 局部匹配时,没走过的路段还记录1000米 + */ + private val NEXT_ROUTE_DISTANCE = 1000 + + /** + * 最远显示距离 米 + */ + private val FARTHEST_DISPLAY_DISTANCE = 550 + + /** + * 绑定失败次数 + */ + private var errorCount = 0 + + /** + * 当前邦定的那段route + */ + private var routeIndex = -1 + + /** + * 当前绑定的link上哪个point + */ + private var footIndex = -1 + + /** + * 绑定的垂足坐标 + */ + private var footPoint: GeoPoint? = null + + /** + * 上一次定位绑到路线的距离 + */ + private var lastDistance = -1 + + /** + * 整条路的几何 + */ var geometry: LineString? = null - var routeList = mutableListOf() + + /** + * 临时路径 + */ + var tempGeometry: LineString? = null + + /** + * 定位点集合 + */ + private var locationList: MutableList = mutableListOf() + + /** + * 局部匹配时的路段 + */ + var tempRoutList = mutableListOf() + + /** + * 所有路段集合 + */ + var routeList = mutableListOf() get() { return field } set(value) { val list = mutableListOf() - list.addAll(value[0].pointList) + val fRoute = value[0] + //第一个路段加入 + list.addAll(fRoute.pointList) + //起始点位置 + fRoute.startIndexInPath = 0 + var startPoint = fRoute.pointList.size - 1 + //终点位置 + fRoute.endIndexIntPath = startPoint + fRoute.indexInPath = 0 + for (i in 1 until value.size) { - val list2 = value[i].pointList + val route = value[i] + route.startIndexInPath = startPoint + if (route.itemList != null) { + for (naviItem in route.itemList!!) { + naviItem.index += startPoint + } + } + startPoint += route.pointList.size - 1 + route.endIndexIntPath = startPoint + route.indexInPath = i + val list2 = ArrayList(route.pointList.toList()) list2.removeAt(0) list.addAll(list2) } geometry = GeometryTools.createLineString(list) field = value } + + /** + * 计算路径 + */ + suspend fun planningPath(taskBean: TaskBean) { + + val pathList = mutableListOf() + val realm = Realm.getDefaultInstance() + for (link in taskBean.hadLinkDvoList) { + //测线不参与导航 + if (link.linkStatus == 3) { + continue + } + val route = NaviRoute( + linkId = link.linkPid, + ) + + route.pointList = GeometryTools.getGeoPoints(link.geometry) + //查询每条link的snode,enode + val res1 = realm.where(RenderEntity::class.java) + .equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() + .equalTo("properties['linkPid']", link.linkPid).findFirst() + res1?.let { + + val snodePid = it.properties["snodePid"] + if (snodePid != null) { + route.sNode = snodePid + } + val enodePid = it.properties["enodePid"] + if (enodePid != null) { + route.eNode = enodePid + } + } + //查询每条link的方向 + val res2 = realm.where(RenderEntity::class.java) + .equalTo("table", DataCodeEnum.OMDB_LINK_DIRECT.name).and() + .equalTo("properties['linkPid']", link.linkPid).findFirst() + res2?.let { + val direct = it.properties["direct"] + if (direct != null) { + route.direct = direct.toInt() + } + } + //查询每条link的名称 + val res3 = realm.where(RenderEntity::class.java) + .equalTo("table", DataCodeEnum.OMDB_LINK_NAME.name).and() + .equalTo("properties['linkPid']", link.linkPid).findFirst() + res3?.let { + route.name = "${it.properties["name"]}" + } + pathList.add(route) + } + //用来存储最终的导航路径 + val newRouteList = mutableListOf() + //比对路径排序用的 + val tempRouteList = pathList.toMutableList() + //先找到一根有方向的link,确定起终点 + var routeStart: NaviRoute? = null + for (i in tempRouteList.indices) { + val route = pathList[i] + //只要时单方向的就行 + if (route.direct == 2 || route.direct == 3) { + routeStart = route + tempRouteList.removeAt(i) + break + } + } + if (routeStart != null) { + var sNode = "" + var eNode = "" + //如果sNode,eNode是顺方向,geometry 不动,否则反转 + if (routeStart.direct == 3) { + routeStart.pointList.reverse() + sNode = routeStart.eNode + eNode = routeStart.sNode + } else { + sNode = routeStart.sNode + eNode = routeStart.eNode + } + newRouteList.add(routeStart) + var bBreak = true + while (bBreak) { + //先找其实link的后续link + var bHasNext = false + for (route in tempRouteList) { + //如果是link 的e 对下个link的s,方向不用动,否则下个link的geometry反转 + if (route.sNode != "" && eNode == route.sNode) { + newRouteList.add(route) + tempRouteList.remove(route) + eNode = route.eNode + bHasNext = true + break + } else if (route.eNode != "" && eNode == route.eNode) { + route.pointList.reverse() + newRouteList.add(route) + tempRouteList.remove(route) + eNode = route.sNode + bHasNext = true + break + } + } + //先找其实link的起始link + var bHasLast = false + for (route in tempRouteList) { + //如果是link 的s 对上个link的e,方向不用动,否则下个link的geometry反转 + if (route.eNode != "" && sNode == route.eNode) { + newRouteList.add(0, route) + tempRouteList.remove(route) + sNode = route.sNode + bHasLast = true + break + } else if (route.sNode != "" && sNode == route.sNode) { + route.pointList.reverse() + newRouteList.add(0, route) + tempRouteList.remove(route) + sNode = route.eNode + bHasLast = true + break + } + } + if (tempRouteList.size == 0) { + bBreak = false + } else { + if (!bHasLast && !bHasNext) { + bBreak = false + callback.planningPathError(1, "路径不连通!") + realm.close() + return + } + } + } + } + val itemMap: MutableMap> = mutableMapOf() + //查询每根link上的关联要素 + for (route in newRouteList) { + //常规点限速 + var res = realm.where(RenderEntity::class.java) + .equalTo("properties['linkPid']", route.linkId).and().`in`( + "table", + QUERY_KEY_LIST + ).findAll() + if (res != null) { + Log.e("jingo", "道路查询预警要素 ${route.linkId} ${res.size}条数据") + for (r in res) { + Log.e("jingo", "道路查询预警要素 ${r.name}") + insertItemToRoute(realm, route, r, itemMap) + } + } +// //条件点限速 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_SPEEDLIMIT_COND.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //可变点限速 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_SPEEDLIMIT_VAR.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //交通灯 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_TRAFFICLIGHT.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //普通交限 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //车信 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_LANEINFO.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //交通标牌 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_TRAFFIC_SIGN.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //警示信息 +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_WARNINGSIGN.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } +// //OMDB_TOLLGATE +// res = realm.where(RenderEntity::class.java) +// .equalTo("table", DataCodeEnum.OMDB_TOLLGATE.name).and() +// .equalTo("properties['linkPid']", route.linkId).findAll() +// if(res != null){ +// for(r in res) +// insertItemToRoute(realm, route, r, itemMap) +// } + //对路径上的要素进行排序 + if (itemMap.isNotEmpty()) { + route.itemList = mutableListOf() + for (i in route.pointList.indices) { + val point = route.pointList[i] + if (itemMap.containsKey(point)) { + val rEList = itemMap[point] + for (item in rEList!!) { + val naviRouteItem = NaviRouteItem(i, item, route.linkId) + route.itemList!!.add(naviRouteItem) + } + } + } + route.itemList!!.sortBy { it.index } + } + } + realm.close() + routeList = newRouteList + callback.planningPathSuccess() + niMapController.lineHandler.showLine(geometry!!.toText()) + } + + /** + * 将要素绑定到路径上 + */ + private fun insertItemToRoute( + realm: Realm, + route: NaviRoute, + res: RenderEntity?, + itemMap: MutableMap> + ) { + if (res != null) { + val geometry = GeometryTools.createGeometry(res.geometry) + if (geometry is Point) { + //获取一个垂足点 + val footAndDistance = GeometryTools.pointToLineDistance( + GeoPoint( + geometry.coordinate.y, geometry.coordinate.x + ), GeometryTools.createLineString(route.pointList) + ) + val point = GeoPoint( + footAndDistance.getCoordinate(0).y, footAndDistance.getCoordinate(0).x + ) + niMapController.markerHandle.addMarker(point, res.id, res.name) + route.pointList.add(footAndDistance.footIndex + 1, point) + if (itemMap.containsKey(point)) { + itemMap[point]!!.add(realm.copyFromRealm(res)) + } else { + itemMap[point] = mutableListOf(realm.copyFromRealm(res)) + } + } else if (geometry is LineString) { + //如果是线型数据,取路径的最后一个点 + val endPoint = route.pointList.last() + if (itemMap.containsKey(endPoint)) { + itemMap[endPoint]!!.add(realm.copyFromRealm(res)) + } else { + itemMap[endPoint] = mutableListOf(realm.copyFromRealm(res)) + } + } + } + } + + /** + * 绑定道路 + */ + fun bindingRoute(location: NiLocation?, point: GeoPoint) { + if (geometry != null) { + //还没有绑定到路径的时候 + if (routeIndex < 0) { + val pointPairDistance = GeometryTools.pointToLineDistance(point, geometry) + //定义垂线 + //定位点到垂足距离不超过30米 + if (pointPairDistance.getMeterDistance() < DEVIATION_DISTANCE) { + footIndex = pointPairDistance.footIndex + Log.e( + "jingo", + "当前绑定到了整条路线的第 $footIndex 点 ${pointPairDistance.getMeterDistance()} " + ) + val lastRouteIndex = routeIndex + for (i in routeList.indices) { + val route = routeList[i] + if (route.startIndexInPath <= footIndex && route.endIndexIntPath >= footIndex) { + routeIndex = route.indexInPath + Log.e( + "jingo", + "当前绑定到了整条路线id ${route.linkId} " + ) + niMapController.lineHandler.showLine(route.pointList) + footPoint = GeoPoint( + pointPairDistance.getCoordinate(0).y, + pointPairDistance.getCoordinate(0).x + ) + val listPoint = mutableListOf(point, footPoint!!) + niMapController.lineHandler.showLine( + listPoint + ) + + if (lastRouteIndex != routeIndex) { + createTempPath() + } + matchingItem() + errorCount = 0 + break + } + } + } else { + deviationUp() + } + } else if (tempGeometry != null && tempRoutList.isNotEmpty()) { + val pointPairDistance = GeometryTools.pointToLineDistance(point, tempGeometry) + //定义垂线 + //定位点到垂足距离不超过30米 + if (pointPairDistance.getMeterDistance() < DEVIATION_DISTANCE) { + footIndex = pointPairDistance.footIndex + tempRoutList[0].startIndexInPath + Log.e("jingo", "局部 当前绑定到了整条路线的第 $footIndex 点") + val lastRouteIndex = routeIndex + for (i in tempRoutList.indices) { + val route = tempRoutList[i] + if (route.startIndexInPath <= footIndex && route.endIndexIntPath >= footIndex) { + routeIndex = route.indexInPath + Log.e( + "jingo", + "局部 当前绑定到了整条路线id ${route.linkId} " + ) + niMapController.lineHandler.showLine(route.pointList) + footPoint = GeoPoint( + pointPairDistance.getCoordinate(0).y, + pointPairDistance.getCoordinate(0).x + ) + + val listPoint = mutableListOf(point, footPoint!!) + niMapController.lineHandler.showLine( + listPoint + ) + + if (lastRouteIndex != routeIndex) { + createTempPath() + } + matchingItem() + errorCount = 0 + break + } + } + } else { + deviationUp() + } + } + } + } + + /** + * 匹配要素 + * @point:定位点 + */ + private fun matchingItem() { + if (routeIndex > -1 && tempRoutList.isNotEmpty() && tempGeometry != null) { + //道路前方一定距离范围内的要素信息 + val bindingItemList = mutableListOf() + //临时局部路径的游标对应整条路径的游标 + val tempFootIndex = footIndex + tempRoutList[0].startIndexInPath + //定位点到要素的路径距离 + var distance = 0.0 + //计算要素路径距离的点集合 + val disPoints = mutableListOf(footPoint!!) + //下一个要素的起点游标 + var tempIndex = footIndex + 1 + for(route in tempRoutList) { + if( route.indexInPath < routeIndex) + continue + if (route.itemList != null && route.itemList!!.isNotEmpty()) { + for (naviItem in route.itemList!!) { + if (naviItem.index > tempFootIndex) { + val rightI = naviItem.index - tempRoutList[0].startIndexInPath + 1 + for (i in tempIndex until rightI) { + val geo = tempGeometry!!.coordinates[i] + disPoints.add(GeoPoint(geo.y, geo.x)) + } + tempIndex = rightI + distance = GeometryTools.getDistance(disPoints) + if (distance < FARTHEST_DISPLAY_DISTANCE && distance > -1) { + naviItem.distance = distance.toInt() + bindingItemList.add(naviItem) + } else { + break + } + } + } + if(distance >= FARTHEST_DISPLAY_DISTANCE){ + break + } + } + } + callback.bindingResults(bindingItemList) + } + } + + /** + * 创建临时局部路径 + */ + private fun createTempPath() { + tempRoutList.clear() + tempGeometry = null + if (routeIndex > -1 && routeIndex < routeList.size && footPoint != null) { + val route = routeList[routeIndex] + //当前垂足点在这个路段中是第几个坐标 + tempRoutList.add(route) + var distance = 0.0 + //已经走过的路是否有100米 + var i = routeIndex - 1 + while (i >= 0 && distance < PASSED_ROUTE_DISTANCE) { + val routeT = routeList[i] + tempRoutList.add(0, routeT) + distance += routeT.length + i-- + } + distance = 0.0 + //没走过的路是否有1000米 + var j = routeIndex + 1 + while (j < routeList.size && distance < NEXT_ROUTE_DISTANCE) { + val routeT = routeList[j] + tempRoutList.add(routeT) + distance += routeT.length + j++ + } + } + val list = mutableListOf() + val fRoute = tempRoutList[0] + //第一个路段加入 + list.addAll(fRoute.pointList) + + for (i in 1 until tempRoutList.size) { + val route = tempRoutList[i] + val list2 = ArrayList(route.pointList.toList()) + list2.removeAt(0) + list.addAll(list2) + } + tempGeometry = GeometryTools.createLineString(list) + } + + /** + * 判断是否完全偏离 + */ + private fun deviationUp() { + errorCount++ + if (errorCount >= DEVIATION_COUNT) { + bindingReset() + } + } + + /** + * 绑定重置 + */ + private fun bindingReset() { + //绑定失败次数 + errorCount = 0 + //当前邦定的那段route + routeIndex = -1 + //当前绑定的link上哪个point + footIndex = -1 + //上一次定位绑到路线的距离 + lastDistance = -1 + //垂足坐标 + footPoint = null + //定位点集合 + locationList.clear() + } + } \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/t0201000.png b/app/src/main/res/drawable-xxhdpi/t0201000.png new file mode 100644 index 0000000000000000000000000000000000000000..6f438e81d0c387b9361b2b5fb9c57ff9f7f75bf0 GIT binary patch literal 4713 zcmb7mXEfYj)b3A7qJ#)R5YeR|M2l{WHe~ePTl5-68NG%?v}iF5qLU$_M<;q8LiFAT zqxW*<>tM6^Tz0FWp^WYhrw$L4muOMrJf)51yp zZh_DRqUQzx#1#Jq4uD8|3;;w*w$jq7sy5CrXEz&X7e)nXX+{@UXDeF=O91eiL~3~I z#-C70%$-<1&<2n1{!DfV0+?A)1YKl$S!7=TvrsZ}P)S$2T1dYG8VI75sI zq^-Ll5SJ1%kIzW9+S_VC@vJ9>1V9uH zkn&uf6&F+om}&*7bK*9)0+}cf^DF%35}ZK2DqeZqz=k`3N3?G21CS{Ym;&bP0~m#H z0qLg{{dkN}yiA_qrujk>m#`WL4$$12*q{7%nD0?d;t;Lp{_gxD(_*W`Pp}#F3o5{byW!fJ}K1 zJ881AGKS~UiBsy{WM60iOlku*b7w|;Q-qoNL_^+Zk#M0)(9`s9s$F9APl$+#x7p0U zHSjD&O5E@*IL}A=AKzN9r@VK8_Xto*adURa)q681j}rChwO)MiYp0Vnmg~;2fUD>i z=tcgYhMbh2_H;kis4^>c!hfm9$uM;%E|PBq@a{1rT@l86k^ra=D$UAO_bPiGn*Dch za3e`|hdlt0{{h!$TH-i>%$lDUegXjTO=mG64jiCAIcEs~>en9|79>zZI|u+kCNt<| zsnosuEss#mq-ibm_080{W_M*k_gS08$iR1(1D_Cmdz>UiquDGnj$c`dN1OQ&u|QVQ z@>+;wZJyjP2;)M1*Yt6E>*M+lg!ocj1QcdWA`uVGqsN&C2&hw{@tMsa{9gid7&jsw zsWG>Ax#r*&g6-mrAT0Y_u8)MH3_<6yQ(cU_pDsVu%fC(tDpSMzgX<3ZRlq>|sUy=3 z4dZ`c6quA{kEX47Djrysm5+YA?hXU|K1EvuqF<9*eV#Bg{2VT8`capby_3pfMOQ#O zM!q!cFc5LVLeFU!hAOl+~d3d9QbkSPdPjz*5e zFqv%{lpPc6*gd;UP!@<{OpdFLeGsei<)Zuda`hvT_J~C&VHT@;P6D~2fTiRLer^UY zI3=@4t-mn+4?$6cNQSa3;v^7y4MWn2$=qDZ24qJQFAk*1cLmgFeBh*i4fs+nXrnp_2+Tac7}2$ReF0Lj+0sP3SNVxsEcwcOJMkGX2&VL0u- zDw!LUoozuq?p)A$aQi?tq}__FP*!nP$kq4#IHVmv=XZrC(i8`n21o{cxbV0nxqgn> z6E0R;@OycFKKlQ)0vd1K%J# z>Nz6am_f@QIUZ&oQEy_$uxN%iJp2TLu`~{^g)DaaVlCF~zuMNIcS9En9`@SQ#Kb zY1BBXdn;OaG|fKUtZ|}#>M|-US2nF(F;XzHGifr(xA#txQql?PtG0wTT>D7-FG^v| z5W|Ua9Mf@7rPE2hpDL2tTUAh;THNN5>Nxjk@lni+;TK05PLr>8kuH*~D&tiQP-4+N<5-p2NlCwnAQ zYdGeA%6H1}?oC{w-Kia}968EPtxKIQo^bp#(~Bv7Yfo!&8;=H1_l{9>=b!HiP+wULR8t331Ewfek!~4hh^0?~L%q zyhi3Z@kSQ^G5-|*dza}KqUXI=F{e!n@O`R1AO<+w?O^{dksq9`dIgEmpaQowO+jyJ!$0ax1H3tM=+A=~j31(5U zGM)8{dUa!_V^&m_+Ry45 zMX@idNbSU9p&3y>>2sS8Dst`}e1t0M9Pl`rFTYq0l(c2WW>JF^?D;sRO#|B&-J3;$SM@hS*Zon$q&|8ZW)QdFCeBIx3b(4QkI?r}v}PLxyv6r8$Ci_!A2gx_g~U4)uRoP?{ya)56*%j~ZwPyrfPv zLAjs`N={4VYE~C@lubr`kKm4zle3D|J=+)vCI{n$I?-$Tq1a$2H9GWRm!z0(FKUI( z#8Gh;_RZVwD7wF*zo#Ehz)WDFuco3K@1$>F7A-yrLEOWH>@2S$B9^;eibMIIdi?M?_J52v* zYAPdiR2PhT3K4NxNey(KOx;F!R=ViFByE*iX?Zr6=j*eiy8dn8_w?`nxs-tFBLWNr z&M_>~!V~eiZiGAit4O{KesmJj) zwI|UIblS)}#_Pvr55z>*S%r(Y-BjD#-?%lFBT zvdFPS#UL3N=tyWA_TLS}FXWfyQw;X_Yu~^zZr|7Dt`;xe4(eWx?-HLy4mOp*3lChe z-wS_;bh30Z)DOVL_wp`_2d4b6HQ3s@&IX2*=a-;s)dTdoMQ8qy%8A69@AW13N$9}^ z+i(Wo?QfIO0-~-20N!i>5EudgXE(RF0RZki0I+Ea03u%jfZF+sNxK{X-~p;oP1%a+ z3LpZ2euqLCfpQRVV+;V|p-_*4+gMJBLl?y1=fr$x#9?mp(e?GUdm!j*oas5CsNrZbL8gchMu1O>C>kS3=E8nj7&^S%*@OzEG(?7 ztZZy-?Ck8%o;`d1{P~L)FJ8WU$-%+F$;rvZ#r5jdD{gLX9v+_8uV3@>^78TV@$>Tw z2nYxY3ch*sMo36VSXfv@L_}0nR7^}vTwMG%wWOpZ2n3Rnk^+Ol($dm0GBUEVvT|~A z^78T!2t+|aK~Yih?c29dC{#&FNm*H0MMXtbRaH$*Oz0?j9ZG&C$M?8Ao-;o;#C5fL9he*E<5Q)Fc1 z=g*&`qN1Xsqhn%XVq;_D;^Mx1`4S%=pOBD{n3$N9l$4yD{PpYCl#~<%0+E`UnwFM^ zL?YAE(=#$MGBY#3efyS`m32!~PEJm4Zf;&)UVeUlK|w)bVPR2G(f9A)Q7BY#adAmW z$&VjDN=r+B{`^^1R#skKUQtm|Sy@?CRaISGT~kx@>({T^+SS?m zrsn46mX?;**4E#@f48-@wYRr-baZrfc6N1jb$567^z`)h_V)Gl_4oG=3=G`%$7S5{V5S6A28*4Ee8H#RmlH#adD%+}V{_V)J9&JGrf-QC^Y+uPgU-#<7w zI6OQ&IyyQ&K0Y})IXyi+J3Bi+Kfk!RxV*f)ZP(j=zHQW;fr)JZ!2hHmBcq12Hiyfx7ll-+4!7}%k(+O*!Y}RN*o*qp{0xit3nL4 zh-b!ev(X?trNI9@hwyDO35Wi-q8;d>r5Lf7cP+?YE4@DUa=Fp3i(=tISFSO!`q-&X z!YZ3^2&qI$OH$D|^d_^8;Yt0G*pT;H^0ROpuB~!B~>KuKx1<|H<&8dvBH!)Jcq75eElS z-LdJO2Sip>31ISJcM&xImreemf8^e!{f~4!aUXN6?KL6>9{z>KWXtG!34w#pzI}(mh0*g&n!Jx9^7yWFF83R zpyMhAwg&@D&(RADjjMm($(dw?|6Z$|QCkJa@QYLlI6oUF#<(=jJ6Kt^ z$=g<(J^ay*oKa?A9-P=08%l2^zuGT4T6W()KD6{~-?Vl^Fwm<^eH@u-ck*(`IBnM} zoI73L%~qM%*e#vm-(yvq^3zEDj`m+DXZniVt#qOC+Gw5d_iyELB-2F=u9k7lPU#3f z?7gz|-<9@xve+7Tc8GDzlVd<2s7)j$JU#rjM7DNMuCAm*bN9do=Z50mu*)^aV|220 z(a3t1Xq|=cpn!7m^pf!CXik$8eZIey4Na0XD!~b40v9XebZv6Ii=wTtPd8sN4<9PGr!i>%BHJ + + + @@ -81,7 +94,7 @@ android:layout_alignParentTop="true" android:layout_marginLeft="172dp" android:layout_marginTop="4dp" - android:visibility="gone" - android:background="@drawable/icon_evaluation" /> + android:background="@drawable/icon_evaluation" + android:visibility="gone" /> \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/BaseHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/BaseHandler.kt index 1efce364..6d7317bd 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/BaseHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/BaseHandler.kt @@ -10,7 +10,7 @@ abstract class BaseHandler(context: AppCompatActivity, mapView: NIMapView) { protected val mMapView: NIMapView = mapView fun addLayer(layer: Layer, groupType: NIMapView.LAYER_GROUPS) { - Log.e("jingo", "增加了图层 ${layer.toString()}") +// Log.e("jingo", "增加了图层 ${layer.toString()}") mMapView.vtmMap.layers().add( layer, groupType.groupIndex diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LineHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LineHandler.kt index d4b830b8..139b2816 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LineHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LineHandler.kt @@ -10,6 +10,7 @@ import com.navinfo.collect.library.map.layers.MultiLinesLayer import com.navinfo.collect.library.map.layers.OmdbTaskLinkLayer import com.navinfo.collect.library.utils.GeometryTools import org.oscim.android.canvas.AndroidBitmap +import org.oscim.core.GeoPoint import org.oscim.layers.marker.ItemizedLayer import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener import org.oscim.layers.marker.MarkerInterface @@ -112,6 +113,18 @@ class LineHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler( layer } + /** + * 高亮一条线 + */ + fun showLine(list:List) { + try { + mDefaultPathLayer.clearPath() + mDefaultPathLayer.setPoints(list) + mDefaultPathLayer.isEnabled = true + } catch (e: Exception) { + Toast.makeText(mContext, "高亮路线失败 ${e.message}", Toast.LENGTH_SHORT).show() + } + } /** * 高亮一条线 @@ -126,6 +139,7 @@ class LineHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler( } } + /** * 取消高亮线 */ diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java index a84895ab..fdb2b98a 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java @@ -77,7 +77,7 @@ public class OMDBDataDecoder extends TileDecoder { properties.putAll(renderEntity.getProperties()); parseGeometry(renderEntity.getTable(), renderEntity.getWkt(), properties); }else{ - Log.e("qj","render"+renderEntity.name+"=="+renderEntity.getZoomMin()+"==="+renderEntity.getZoomMax()+"==="+renderEntity.getEnable()); +// Log.e("qj","render"+renderEntity.name+"=="+renderEntity.getZoomMin()+"==="+renderEntity.getZoomMax()+"==="+renderEntity.getEnable()); } } }); diff --git a/collect-library/src/main/java/com/navinfo/collect/library/utils/FootAndDistance.kt b/collect-library/src/main/java/com/navinfo/collect/library/utils/FootAndDistance.kt new file mode 100644 index 00000000..3a3d3e23 --- /dev/null +++ b/collect-library/src/main/java/com/navinfo/collect/library/utils/FootAndDistance.kt @@ -0,0 +1,145 @@ +package com.navinfo.collect.library.utils + +import org.locationtech.jts.geom.* +import org.locationtech.jts.io.WKTWriter +import org.oscim.core.GeoPoint + +class FootAndDistance(private val point: GeoPoint) { + + private val pt = arrayOf(Coordinate(), Coordinate()) + private var distance = Double.NaN + private var isNull = true + var footIndex = 0 + + /** + * Initializes this instance. + */ + fun initialize() { + isNull = true + } + + /** + * Initializes the points, computing the distance between them. + * @param p0 the 1st point + * @param p1 the 2nd point + */ + fun initialize(p0: Coordinate, p1: Coordinate) { + initialize(p0, p1, p0.distance(p1)) + } + + /** + * Initializes the points, avoiding recomputing the distance. + * @param p0 the 1st point + * @param p1 the 2nd point + * @param distance the distance between p0 and p1 + */ + fun initialize(p0: Coordinate, p1: Coordinate, distance: Double) { + pt[0].setCoordinate(p0) + pt[1].setCoordinate(p1) + this.distance = distance + isNull = false + } + + /** + * Gets the distance between the paired points + * @return the distance between the paired points + */ + fun getDistance(): Double { + return distance + } + + /** + * Gets the paired points + * @return the paired points + */ + fun getCoordinates(): Array { + return pt + } + + /** + * Gets one of the paired points + * @param i the index of the paired point (0 or 1) + * @return A point + */ + fun getCoordinate(i: Int): Coordinate { + return pt[i] + } + + + fun setMinimum(p0: Coordinate, p1: Coordinate): Boolean { + if (isNull) { + initialize(p0, p1) + return true + } + val dist = p0.distance(p1) + if (dist < distance) { + initialize(p0, p1, dist) + return true + } + return false + } + + override fun toString(): String { + return WKTWriter.toLineString(pt[0], pt[1]) + } + + + fun getMeterDistance(): Double { + return if (!distance.isNaN() && pt.isNotEmpty()) + GeometryTools.getDistance( + point.latitude, + point.longitude, + pt[0].y, + pt[0].x + ) + else { + Double.NaN + } + } + + fun computeDistance(geom: Geometry, pt: Coordinate) { + when (geom) { + is LineString -> { + computeDistance(geom, pt) + } + is Polygon -> { + computeDistance(geom, pt) + } + is GeometryCollection -> { + for (i in 0 until geom.numGeometries) { + val g = geom.getGeometryN(i) + computeDistance(g, pt) + } + } + else -> { // assume geom is Point + setMinimum(geom.coordinate, pt) + } + } + } + + fun computeDistance(line: LineString, pt: Coordinate) { + val tempSegment = LineSegment() + val coords = line.coordinates + for (i in 0 until (coords.size - 1)) { + tempSegment.setCoordinates(coords[i], coords[i + 1]) + // this is somewhat inefficient - could do better + val closestPt = tempSegment.closestPoint(pt) + if (setMinimum(closestPt, pt)) { + footIndex = i + } + } + } + + fun computeDistance(segment: LineSegment, pt: Coordinate) { + val closestPt = segment.closestPoint(pt) + setMinimum(closestPt, pt) + } + + fun computeDistance(poly: Polygon, pt: Coordinate) { + computeDistance(poly.exteriorRing, pt) + for (i in 0 until poly.numInteriorRing) { + computeDistance(poly.getInteriorRingN(i), pt) + } + } + +} \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java index 4ac644d2..d782ec22 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java @@ -4,9 +4,6 @@ import android.graphics.Point; import android.os.Build; import android.util.Log; -import org.jetbrains.annotations.NotNull; -import org.locationtech.jts.algorithm.distance.DistanceToPoint; -import org.locationtech.jts.algorithm.distance.PointPairDistance; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -428,148 +425,6 @@ public class GeometryTools { } - public static GeoPoint getLineStringCenter(String lineString) { - List points = getGeoPoints(lineString); - return getLineStringCenter(points); - } - - public static GeoPoint getLineStringCenter(List points) { - if (points != null && points.size() > 1) { - if (points.size() == 2) { - double x1 = points.get(0).getLongitude(); - double y1 = points.get(0).getLatitude(); - double x2 = points.get(1).getLongitude(); - double y2 = points.get(1).getLatitude(); - GeoPoint newPoint = new GeoPoint((y1 + y2) / 2, (x1 + x2) / 2); - return newPoint; - } else { - double total = 0; - ArrayList dList = new ArrayList(); - for (int i = 0; i < points.size() - 1; i++) { - double lt = total; - double dis = distanceToDouble(points.get(i), points.get(i + 1)); - dList.add(lt + dis); - total += dis; - } - total = total / 2; - for (int i = 0; i < dList.size(); i++) { - double a = dList.get(i); - double b = 0; - if (i > 0) { - b = dList.get(i - 1); - } - if (a > total) { - if (a - total < 4) { - return points.get(i); - } - double dx = (a - total) * 0.5 / (a - b); - GeoPoint point1 = points.get(i); - GeoPoint point2 = points.get(i + 1); - double x; - if (point1.getLongitude() < point2.getLongitude()) { - x = (point2.getLongitude() - point1.getLongitude()) * dx; - x = point2.getLongitude() - x; - } else { - x = (point1.getLongitude() - point2.getLongitude()) * dx; - x = point2.getLongitude() + x; - } - double y; - if (point1.getLatitude() > point2.getLatitude()) { - y = (point1.getLatitude() - point2.getLatitude()) * dx; - y = point2.getLatitude() + y; - } else { - y = (point2.getLatitude() - point1.getLatitude()) * dx; - y = point2.getLatitude() - y; - } - GeoPoint geoPoint = new GeoPoint(y, x); - return geoPoint; - } else { - if (total - a < 4) { - return points.get(i + 1); - } - } - } - } - } - return null; - } - - public static GeoPoint getLineStringCenter(List points, int[] index) { - if (points != null && points.size() > 1) { - if (points.size() == 2) { - double x1 = points.get(0).getLongitude(); - double y1 = points.get(0).getLatitude(); - double x2 = points.get(1).getLongitude(); - double y2 = points.get(1).getLatitude(); - GeoPoint newPoint = new GeoPoint((y1 + y2) / 2, (x1 + x2) / 2); - if (index != null && index.length > 1) { - index[0] = 0; - index[1] = 1; - } - return newPoint; - } else { - double total = 0; - ArrayList dList = new ArrayList(); - for (int i = 0; i < points.size() - 1; i++) { - double lt = total; - double dis = distance(points.get(i).toString(), points.get(i + 1).toString()); - dList.add(lt + dis); - total += dis; - } - total = total / 2; - for (int i = 0; i < dList.size(); i++) { - double a = dList.get(i); - double b = 0; - if (i > 0) { - b = dList.get(i - 1); - } - if (a > total) { - if (a - total < 4) { - if (index != null && index.length > 1) { - index[0] = i; - index[1] = i + 1; - } - return points.get(i); - } - double dx = (a - total) * 0.5 / (a - b); - GeoPoint point1 = points.get(i); - GeoPoint point2 = points.get(i + 1); - double x; - if (point1.getLongitude() < point2.getLongitude()) { - x = (point2.getLongitude() - point1.getLongitude()) * dx; - x = point2.getLongitude() - x; - } else { - x = (point1.getLongitude() - point2.getLongitude()) * dx; - x = point2.getLongitude() + x; - } - double y; - if (point1.getLatitude() > point2.getLatitude()) { - y = (point1.getLatitude() - point2.getLatitude()) * dx; - y = point2.getLatitude() + y; - } else { - y = (point2.getLatitude() - point1.getLatitude()) * dx; - y = point2.getLatitude() - y; - } - GeoPoint geoPoint = new GeoPoint(y, x); - if (index != null && index.length > 1) { - index[0] = i; - index[1] = i + 1; - } - return geoPoint; - } else { - if (total - a < 4) { - if (index != null && index.length > 1) { - index[0] = i; - index[1] = i + 1; - } - return points.get(i + 1); - } - } - } - } - } - return null; - } /** * LINESTRING (116.4206899999999933 39.9620999999999995, @@ -1142,39 +997,6 @@ public class GeometryTools { return null; } - /** - * 点与几何最近点位置 - * - * @param list - * @param geoPoint - * @return geopoint - * @author qiji - */ - public static GeoPoint getZuijinGeoPoint(List list, GeoPoint geoPoint) {//MapManager.getInstance().getMap().getMapCenterGeoLocation()屏幕中心点 - - if (list == null || list.size() == 0 || geoPoint == null) - return null; - - double dis = 0; - - GeoPoint geo = null; - - for (GeoPoint geopoint : list) { - - double disTemp = distanceToDouble(geoPoint, geopoint); - - if (dis == 0 || dis < disTemp) { - - dis = disTemp; - - geo = geopoint; - - } - - } - - return geo; - } public static String GeometryFormatDouble5(String geometry) { try { @@ -1315,8 +1137,6 @@ public class GeometryTools { } - - public enum SNAP_TYPE { /** * 像素 @@ -1552,7 +1372,7 @@ public class GeometryTools { */ public static double getDistance(List list) { if (list.size() < 2) { - return 0; + return -1; } double dis = 0; for (int i = 0; i < list.size() - 1; i++) { @@ -1600,6 +1420,12 @@ public class GeometryTools { */ private static final double EARTH_RADIUS = 6371000.0; + /** + * 距离转米 + * @param distance + * @param latitude + * @return + */ public static double convertDistanceToDegree(double distance, double latitude) { double radianDistance = distance / EARTH_RADIUS; double radianLatitude = Math.toRadians(latitude); @@ -1639,28 +1465,13 @@ public class GeometryTools { return point; } - public static List pointToLineDistance(GeoPoint point, List pointList) { - Coordinate coordinate = geoPointToMercator(point); - Coordinate[] cs = new Coordinate[pointList.size()]; + public static FootAndDistance pointToLineDistance(GeoPoint point, Geometry geometry) { + //定义垂线 + FootAndDistance pointPairDistance = new FootAndDistance(point); + Coordinate coordinate = new Coordinate(point.getLongitude(), point.getLatitude()); + pointPairDistance.computeDistance(geometry,coordinate); - for (int i = 0; i < pointList.size(); i++) { - Coordinate c = geoPointToMercator(pointList.get(i)); - cs[i] = c; - } - GeometryFactory factory = new GeometryFactory(); - LineString lineString = factory.createLineString(cs); - PointPairDistance pointPairDistance = new PointPairDistance(); - DistanceToPoint.computeDistance( - lineString, - coordinate, - pointPairDistance - ); - - List newPoints = new ArrayList(); - for (int i = 0; i < pointPairDistance.getCoordinates().length; i++) { - newPoints.add(mercatorToGeoPoint(pointPairDistance.getCoordinate(i))); - } - return newPoints; + return pointPairDistance; } } From 923475b199afe08fed3cf20f1f5092047070be89 Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Fri, 15 Sep 2023 16:16:36 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B4=A9=E6=BA=83?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vtm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtm b/vtm index 3ea6a7c9..d31e10f1 160000 --- a/vtm +++ b/vtm @@ -1 +1 @@ -Subproject commit 3ea6a7c90627e6e8ea10b3896004d9082167a7ff +Subproject commit d31e10f1483d49ecec361b79497394c9b7983687 From 607d4c290ab7330996b57798a4daf54c117462df Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Wed, 20 Sep 2023 09:42:53 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E9=A2=84=E8=AD=A6=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/navinfo/omqs/bean/NaviRoute.kt | 2 +- .../com/navinfo/omqs/db/RealmOperateHelper.kt | 6 +- .../omqs/ui/activity/map/MainActivity.kt | 66 +++- .../omqs/ui/activity/map/MainViewModel.kt | 371 +++++++++++------- .../omqs/ui/activity/map/SignAdapter.kt | 21 +- .../ui/fragment/tasklist/TaskListAdapter.kt | 1 + .../ui/fragment/tasklist/TaskListFragment.kt | 6 +- .../java/com/navinfo/omqs/util/NaviEngine.kt | 297 +++++++------- vtm | 2 +- 9 files changed, 453 insertions(+), 319 deletions(-) diff --git a/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt b/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt index 23004845..dc1f3b72 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/NaviRoute.kt @@ -16,7 +16,7 @@ data class NaviRoute( //方向 var direct: Int = 0, //道路名称 - var name: String = "", + var name: RenderEntity? = null, //路段总长 var length: Double = 0.0, //当前link在整段路径中的起点 diff --git a/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt b/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt index b9ba12e8..0f7f1cfe 100644 --- a/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt +++ b/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt @@ -200,7 +200,7 @@ class RealmOperateHelper() { var link: RenderEntity? = null val realm = getSelectTaskRealmInstance() val realmR = - getSelectTaskRealmTools(RenderEntity::class.java, true).equalTo("table", "OMDB_RD_LINK") + realm.where(RenderEntity::class.java).equalTo("table", "OMDB_RD_LINK") .equalTo("properties['${LinkTable.linkPid}']", linkPid).findFirst() if (realmR != null) { link = realm.copyFromRealm(realmR) @@ -287,14 +287,14 @@ class RealmOperateHelper() { .findAll() } else { // 查询realm中对应tile号的数据 - if(Constant.CATCH_ALL){ + if (Constant.CATCH_ALL) { realmList = getSelectTaskRealmTools(RenderEntity::class.java, false) .greaterThanOrEqualTo("tileX", xStart) .lessThanOrEqualTo("tileX", xEnd) .greaterThanOrEqualTo("tileY", yStart) .lessThanOrEqualTo("tileY", yEnd) .findAll() - }else{ + } else { realmList = getSelectTaskRealmTools(RenderEntity::class.java, false) .greaterThanOrEqualTo("tileX", xStart) .lessThanOrEqualTo("tileX", xEnd) diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index a8c188aa..e59700f6 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -27,6 +27,7 @@ import com.blankj.utilcode.util.ClipboardUtils import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.tabs.TabLayout import com.navinfo.collect.library.data.entity.RenderEntity +import com.navinfo.collect.library.data.entity.TaskBean import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.handler.MeasureLayerHandler import com.navinfo.omqs.Constant @@ -38,6 +39,7 @@ import com.navinfo.omqs.databinding.ActivityMainBinding import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager import com.navinfo.omqs.tools.LayerConfigUtils import com.navinfo.omqs.ui.activity.BaseActivity +import com.navinfo.omqs.ui.dialog.LoadingDialog import com.navinfo.omqs.ui.fragment.console.ConsoleFragment import com.navinfo.omqs.ui.fragment.itemlist.ItemListFragment import com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment @@ -47,6 +49,7 @@ import com.navinfo.omqs.ui.fragment.tasklist.TaskManagerFragment import com.navinfo.omqs.ui.other.BaseToast import com.navinfo.omqs.ui.widget.RecyclerViewSpacesItemDecoration import com.navinfo.omqs.util.FlowEventBus +import com.navinfo.omqs.util.NaviStatus import com.navinfo.omqs.util.SignUtil import com.navinfo.omqs.util.SpeakMode import dagger.hilt.android.AndroidEntryPoint @@ -66,6 +69,12 @@ class MainActivity : BaseActivity() { private lateinit var binding: ActivityMainBinding private val viewModel by viewModels() + private val loadingDialog by lazy { + MaterialAlertDialogBuilder( + this, + com.google.android.material.R.style.MaterialAlertDialog_Material3_Animation + ).setMessage("正在计算路线中...").setCancelable(false).show() + } /** * 左侧fragment @@ -280,9 +289,10 @@ class MainActivity : BaseActivity() { //道路绑定,名称变化 viewModel.liveDataRoadName.observe(this) { if (it != null) { + binding.mainActivityRoadName.visibility = View.VISIBLE binding.mainActivityRoadName.text = it.properties["name"] } else { - binding.mainActivityRoadName.text = " " + binding.mainActivityRoadName.visibility = View.INVISIBLE } } @@ -325,7 +335,7 @@ class MainActivity : BaseActivity() { 7, RoundingMode.HALF_UP ) },${BigDecimal(it.latitude).setScale(7, RoundingMode.HALF_UP)}" - if(Constant.AUTO_LOCATION){ + if (Constant.AUTO_LOCATION) { viewModel.startAutoLocationTimer() } binding.mainActivityLocation.setImageResource(R.drawable.icon_location) @@ -334,8 +344,8 @@ class MainActivity : BaseActivity() { Log.e("qj", "异常 $e") } } - viewModel.liveDataAutoLocation.observe(this){ - if(it==true){ + viewModel.liveDataAutoLocation.observe(this) { + if (it == true) { onClickLocation() } } @@ -418,6 +428,52 @@ class MainActivity : BaseActivity() { Toast.makeText(this, it, Toast.LENGTH_SHORT).show() } + viewModel.liveDataNaviStatus.observe(this) { + when (it) { + NaviStatus.NAVI_STATUS_PATH_ERROR_BLOCKED -> { + Toast.makeText( + this, + "路径不通,请检查", + Toast.LENGTH_SHORT + ).show() + if (loadingDialog.isShowing) + loadingDialog.dismiss() + } + NaviStatus.NAVI_STATUS_PATH_PLANNING -> { + if (!loadingDialog.isShowing) + loadingDialog.show() + } + NaviStatus.NAVI_STATUS_PATH_ERROR_NODE -> { + Toast.makeText( + this, + "查询link基本信息表失败(node表)", + Toast.LENGTH_SHORT + ).show() + loadingDialog.dismiss() + } + + NaviStatus.NAVI_STATUS_PATH_ERROR_DIRECTION -> { + Toast.makeText( + this, + "查询link基本信息表失败(方向表)", + Toast.LENGTH_SHORT + ).show() + loadingDialog.dismiss() + } + NaviStatus.NAVI_STATUS_PATH_SUCCESS -> { + loadingDialog.dismiss() + } + NaviStatus.NAVI_STATUS_DISTANCE_OFF -> { + Toast.makeText( + this, + "偏离路线", + Toast.LENGTH_SHORT + ).show() + } + NaviStatus.NAVI_STATUS_DIRECTION_OFF -> TODO() + } + } + viewModel.liveDataItemList.observe(this) { if (it.isNotEmpty()) { if (leftFragment == null || leftFragment !is ItemListFragment) { @@ -1102,7 +1158,7 @@ class MainActivity : BaseActivity() { * 路径规划 */ fun onClickRouteFragment() { - Toast.makeText(this, "功能开发中", Toast.LENGTH_SHORT).show() + viewModel.planningPath() } /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 492a7f18..0d34ffbc 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -86,7 +86,7 @@ class MainViewModel @Inject constructor( private var mCameraDialog: CommonDialog? = null //路径计算 - val liveDataPlanningPathStatus = MutableLiveData() + val liveDataNaviStatus = MutableLiveData() //地图点击捕捉到的质检数据ID列表 val liveDataQsRecordIdList = MutableLiveData>() @@ -124,6 +124,7 @@ class MainViewModel @Inject constructor( */ val listDataMessage = MutableLiveData() + private var traceTag: String = "TRACE_TAG" /** @@ -201,9 +202,11 @@ class MainViewModel @Inject constructor( /** * 测量类型 */ - var measuringType: MeasureLayerHandler.MEASURE_TYPE = - MeasureLayerHandler.MEASURE_TYPE.DISTANCE + var measuringType: MeasureLayerHandler.MEASURE_TYPE = MeasureLayerHandler.MEASURE_TYPE.DISTANCE + /** + * 捕捉到的上一条link + */ var linkIdCache = "" private var lastNiLocaion: NiLocation? = null @@ -230,8 +233,8 @@ class MainViewModel @Inject constructor( //导航信息 private var naviEngine: NaviEngine? = null - //规划成功 - private var naviPathSuccess = false + // 0:不导航 1:导航 2:暂停 + private var naviEngineStatus = 0 // 定义一个互斥锁 private val naviMutex = Mutex() @@ -257,8 +260,7 @@ class MainViewModel @Inject constructor( /** * 处理点击道路捕捉回调功能 */ - mapController.mMapView.addOnNIMapClickListener( - TAG, + mapController.mMapView.addOnNIMapClickListener(TAG, //处理地图点击操作 object : OnGeoPointClickListener { override fun onMapClick(tag: String, point: GeoPoint) { @@ -283,8 +285,7 @@ class MainViewModel @Inject constructor( */ object : OnQsRecordItemClickListener { override fun onQsRecordList(tag: String, list: MutableList) { - if (tag == TAG) - liveDataQsRecordIdList.value = list + if (tag == TAG) liveDataQsRecordIdList.value = list } }, /** @@ -292,8 +293,7 @@ class MainViewModel @Inject constructor( */ object : OnTaskLinkItemClickListener { override fun onTaskLink(tag: String, taskLinkId: String) { - if (tag == TAG) - liveDataTaskLink.value = taskLinkId + if (tag == TAG) liveDataTaskLink.value = taskLinkId } }, /** @@ -301,8 +301,7 @@ class MainViewModel @Inject constructor( */ object : ONNoteItemClickListener { override fun onNote(tag: String, noteId: String) { - if (tag == TAG) - liveDataNoteId.value = noteId + if (tag == TAG) liveDataNoteId.value = noteId } }, @@ -311,11 +310,9 @@ class MainViewModel @Inject constructor( */ object : OnNiLocationItemListener { override fun onNiLocation(tag: String, index: Int, it: NiLocation) { - if (tag == TAG) - liveDataNILocationList.value = it + if (tag == TAG) liveDataNILocationList.value = it } - } - ) + }) viewModelScope.launch(Dispatchers.IO) { getTaskBean() @@ -339,26 +336,26 @@ class MainViewModel @Inject constructor( socketServer = SocketServer(mapController, traceDataBase, sharedPreferences) viewModelScope.launch(Dispatchers.Default) { -// naviTestFlow().collect { point -> -// if (naviPathSuccess) { -// naviEngine?.let { -// naviMutex.lock() -// it.bindingRoute(null, point) -// naviMutex.unlock() -// } -// } -// } + naviTestFlow().collect { point -> + if (naviEngineStatus == 1) { + naviEngine?.let { + naviMutex.lock() + it.bindingRoute(null, point) + naviMutex.unlock() + } + } + } } } -// fun naviTestFlow(): Flow = flow { -// -// while (true) { -// emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) -// delay(1000) -// } -// } + fun naviTestFlow(): Flow = flow { + + while (true) { + emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) + delay(1000) + } + } /** * 获取当前任务 @@ -369,55 +366,68 @@ class MainViewModel @Inject constructor( val res = realm.where(TaskBean::class.java).equalTo("id", id).findFirst() if (res != null) { currentTaskBean = realm.copyFromRealm(res) -// planningPath(currentTaskBean!!) } realm.close() } - - private fun planningPath(taskBean: TaskBean) { - if (taskBean.status == FileManager.Companion.FileDownloadStatus.DONE) { -// Toast.makeText(context, "正在计算导航路径", Toast.LENGTH_SHORT).show() - viewModelScope.launch(Dispatchers.Default) { - naviMutex.lock() - naviEngine = NaviEngine( - niMapController = mapController, + /** + * 规划路径 + */ + fun planningPath() { + viewModelScope.launch(Dispatchers.Default) { + naviMutex.lock() + getTaskBean() + if (currentTaskBean != null && currentTaskBean!!.status == FileManager.Companion.FileDownloadStatus.DONE) { + naviEngine = NaviEngine(niMapController = mapController, + realmOperateHelper = realmOperateHelper, callback = object : OnNaviEngineCallbackListener { - override fun planningPathSuccess() { - naviPathSuccess = true - listDataMessage.postValue("导航路径规划完成") + + override fun planningPathStatus(status: NaviStatus) { + when (status) { + NaviStatus.NAVI_STATUS_PATH_PLANNING -> naviEngineStatus = 0 + NaviStatus.NAVI_STATUS_PATH_ERROR_NODE -> naviEngineStatus = 0 + NaviStatus.NAVI_STATUS_PATH_ERROR_DIRECTION -> naviEngineStatus = 0 + NaviStatus.NAVI_STATUS_PATH_ERROR_BLOCKED -> naviEngineStatus = 0 + NaviStatus.NAVI_STATUS_PATH_SUCCESS -> naviEngineStatus = 1 + NaviStatus.NAVI_STATUS_DISTANCE_OFF -> { + } + NaviStatus.NAVI_STATUS_DIRECTION_OFF -> {} + } + liveDataNaviStatus.postValue(status) } - override fun planningPathError(errorCode: Int, errorMessage: String) { - naviPathSuccess = false - listDataMessage.postValue(errorMessage) - } - - override fun bindingResults(list: List) { + override suspend fun bindingResults( + route: NaviRoute?, + list: List + ) { val signList = mutableListOf() for (naviRouteItem in list) { + val signBean = SignBean( iconId = SignUtil.getSignIcon(naviRouteItem.data), iconText = SignUtil.getSignIconText(naviRouteItem.data), linkId = naviRouteItem.linkId, distance = naviRouteItem.distance, name = SignUtil.getSignNameText(naviRouteItem.data), - bottomRightText = SignUtil.getSignBottomRightText(naviRouteItem.data), + bottomRightText = SignUtil.getSignBottomRightText( + naviRouteItem.data + ), renderEntity = naviRouteItem.data, isMoreInfo = SignUtil.isMoreInfo(naviRouteItem.data), index = SignUtil.getRoadInfoIndex(naviRouteItem.data) ) signList.add(signBean) } + if (route != null) { + liveDataRoadName.postValue(route.name) + captureTopSign(route) + } liveDataSignList.postValue(signList) } }) - listDataMessage.postValue("开始导航路径规划") - naviEngine!!.planningPath(taskBean) + naviEngine!!.planningPath(currentTaskBean!!) naviMutex.unlock() } - } else { - listDataMessage.postValue("数据未安装,无法计算导航路径") } } @@ -439,8 +449,7 @@ class MainViewModel @Inject constructor( var list = mutableListOf() val realm = realmOperateHelper.getRealmDefaultInstance() realm.executeTransaction { - val objects = - realmOperateHelper.getRealmTools(QsRecordBean::class.java).findAll() + val objects = realmOperateHelper.getRealmTools(QsRecordBean::class.java).findAll() list = realm.copyFromRealm(objects) } realm.close() @@ -529,8 +538,10 @@ class MainViewModel @Inject constructor( //增加间距判断 if (lastNiLocaion != null) { disance = GeometryTools.getDistance( - location.latitude, location.longitude, - lastNiLocaion!!.latitude, lastNiLocaion!!.longitude + location.latitude, + location.longitude, + lastNiLocaion!!.latitude, + lastNiLocaion!!.longitude ) } //室内整理工具时不能进行轨迹存储,判断轨迹间隔要超过2.5并小于60米 @@ -570,18 +581,17 @@ class MainViewModel @Inject constructor( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val itemList = realmOperateHelper.queryElement( GeometryTools.createPoint( - point.longitude, - point.latitude + point.longitude, point.latitude ), buffer = 2.4, catchAll = false, ) //增加道路线过滤原则 val filterResult = itemList.filter { - if(isHighRoad()){ - mapController.mMapView.mapLevel>=it.zoomMin&&mapController.mMapView.mapLevel<=it.zoomMax - }else{ + if (isHighRoad()) { + mapController.mMapView.mapLevel >= it.zoomMin && mapController.mMapView.mapLevel <= it.zoomMax + } else { //关闭时过滤道路线捕捉s - mapController.mMapView.mapLevel>=it.zoomMin&&mapController.mMapView.mapLevel<=it.zoomMax&&it.code!=DataCodeEnum.OMDB_RD_LINK.code + mapController.mMapView.mapLevel >= it.zoomMin && mapController.mMapView.mapLevel <= it.zoomMax && it.code != DataCodeEnum.OMDB_RD_LINK.code } }.toList() if (filterResult.size == 1) { @@ -592,6 +602,108 @@ class MainViewModel @Inject constructor( } } + /** + * 获取道路属性 + */ + private suspend fun captureTopSign(route: NaviRoute) { + try { + captureLinkState = true + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + //看板数据 + val signList = mutableListOf() + val topSignList = mutableListOf() + mapController.lineHandler.linksLayer.clear() + if (linkIdCache != route.linkId) { + + mapController.lineHandler.showLine(route.pointList) + var elementList = realmOperateHelper.queryLinkByLinkPid(route.linkId) + for (element in elementList) { + + when (element.code) { + DataCodeEnum.OMDB_MULTI_DIGITIZED.code,//上下线分离 + DataCodeEnum.OMDB_CON_ACCESS.code,//全封闭 + -> { + val signBean = SignBean( + iconId = SignUtil.getSignIcon(element), + iconText = SignUtil.getSignIconText(element), + linkId = route.linkId, + name = SignUtil.getSignNameText(element), + bottomRightText = SignUtil.getSignBottomRightText(element), + renderEntity = element, + isMoreInfo = SignUtil.isMoreInfo(element), + index = SignUtil.getRoadInfoIndex(element) + ) + if (signBean.iconText != "") { + topSignList.add( + signBean + ) + } + } + + DataCodeEnum.OMDB_LANE_NUM.code, //车道数 + DataCodeEnum.OMDB_RD_LINK_KIND.code,//种别, + DataCodeEnum.OMDB_RD_LINK_FUNCTION_CLASS.code, // 功能等级, + DataCodeEnum.OMDB_LINK_SPEEDLIMIT.code, //线限速, + DataCodeEnum.OMDB_LINK_DIRECT.code,//道路方向, + DataCodeEnum.OMDB_RAMP.code, //匝道 + DataCodeEnum.OMDB_BRIDGE.code,//桥 + DataCodeEnum.OMDB_TUNNEL.code,//隧道 + DataCodeEnum.OMDB_ROUNDABOUT.code,//环岛 + DataCodeEnum.OMDB_LINK_ATTRIBUTE_MAIN_SIDE_ACCESS.code,//出入口 + DataCodeEnum.OMDB_LINK_ATTRIBUTE_FORNTAGE.code,//辅路 + DataCodeEnum.OMDB_LINK_ATTRIBUTE_SA.code,//SA + DataCodeEnum.OMDB_LINK_ATTRIBUTE_PA.code,//PA + DataCodeEnum.OMDB_LINK_FORM1_1.code, + DataCodeEnum.OMDB_LINK_FORM1_2.code, + DataCodeEnum.OMDB_LINK_FORM1_3.code, + DataCodeEnum.OMDB_LINK_FORM2_1.code, + DataCodeEnum.OMDB_LINK_FORM2_2.code, + DataCodeEnum.OMDB_LINK_FORM2_3.code, + DataCodeEnum.OMDB_LINK_FORM2_4.code, + DataCodeEnum.OMDB_LINK_FORM2_5.code, + DataCodeEnum.OMDB_LINK_FORM2_6.code, + DataCodeEnum.OMDB_LINK_FORM2_7.code, + DataCodeEnum.OMDB_LINK_FORM2_8.code, + DataCodeEnum.OMDB_LINK_FORM2_9.code, + DataCodeEnum.OMDB_LINK_FORM2_10.code, + DataCodeEnum.OMDB_LINK_FORM2_11.code, + DataCodeEnum.OMDB_LINK_FORM2_12.code, + DataCodeEnum.OMDB_LINK_FORM2_13.code, + DataCodeEnum.OMDB_VIADUCT.code, + -> { + val signBean = SignBean( + iconId = SignUtil.getSignIcon(element), + iconText = SignUtil.getSignIconText(element), + linkId = route.linkId, + name = SignUtil.getSignNameText(element), + bottomRightText = SignUtil.getSignBottomRightText(element), + renderEntity = element, + isMoreInfo = SignUtil.isMoreInfo(element), + index = SignUtil.getRoadInfoIndex(element) + ) + topSignList.add( + signBean + ) + } + } + } + + liveDataTopSignList.postValue(topSignList.distinctBy { it.name } + .sortedBy { it.index }) + + val speechText = SignUtil.getRoadSpeechText(topSignList) + withContext(Dispatchers.Main) { + speakMode?.speakText(speechText) + } + linkIdCache = route.linkId ?: "" + } + } + } catch (e: Exception) { + + } + } + /** * 捕获道路和面板 */ @@ -616,22 +728,18 @@ class MainViewModel @Inject constructor( var hisRoadName = false if (linkList.isNotEmpty()) { + val link = linkList[0] + val linkId = link.properties[RenderEntity.Companion.LinkTable.linkPid] //看板数据 val signList = mutableListOf() val topSignList = mutableListOf() mapController.lineHandler.linksLayer.clear() - - val link = linkList[0] - - val linkId = link.properties[RenderEntity.Companion.LinkTable.linkPid] - if (linkIdCache != linkId) { mapController.lineHandler.showLine(link.geometry) linkId?.let { var elementList = realmOperateHelper.queryLinkByLinkPid(it) for (element in elementList) { - if (element.code == DataCodeEnum.OMDB_LINK_NAME.code) { hisRoadName = true liveDataRoadName.postValue(element) @@ -693,7 +801,6 @@ class MainViewModel @Inject constructor( -> topSignList.add( signBean ) - DataCodeEnum.OMDB_SPEEDLIMIT.code,//常规点限速 DataCodeEnum.OMDB_SPEEDLIMIT_COND.code,//条件点限速 DataCodeEnum.OMDB_SPEEDLIMIT_VAR.code,//可变点限速 @@ -702,40 +809,34 @@ class MainViewModel @Inject constructor( DataCodeEnum.OMDB_LANEINFO.code,//车信 DataCodeEnum.OMDB_WARNINGSIGN.code,//危险信息 DataCodeEnum.OMDB_TOLLGATE.code,//收费站 - -> signList.add( - signBean - ) + -> { + signList.add( + signBean + ) + } } } val realm = realmOperateHelper.getSelectTaskRealmInstance() - val entityList = - realmOperateHelper.getSelectTaskRealmTools( - RenderEntity::class.java, - true - ) - .and() - .equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name) - .and() - .equalTo( - "properties['linkIn']", it - ).findAll() + val entityList = realmOperateHelper.getSelectTaskRealmTools( + RenderEntity::class.java, true + ).and().equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name).and() + .equalTo( + "properties['linkIn']", it + ).findAll() if (entityList.isNotEmpty()) { val outList = entityList.distinct() for (i in outList.indices) { val outLink = outList[i].properties["linkOut"] - val linkOutEntity = - realmOperateHelper.getSelectTaskRealmTools( - RenderEntity::class.java, - true - ) - .equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() - .equalTo( - "properties['${RenderEntity.Companion.LinkTable.linkPid}']", - outLink - ).findFirst() + val linkOutEntity = realmOperateHelper.getSelectTaskRealmTools( + RenderEntity::class.java, true + ).equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() + .equalTo( + "properties['${RenderEntity.Companion.LinkTable.linkPid}']", + outLink + ).findFirst() if (linkOutEntity != null) { mapController.lineHandler.linksLayer.addLine( linkOutEntity.geometry, 0x7DFF0000 @@ -743,8 +844,7 @@ class MainViewModel @Inject constructor( } } mapController.lineHandler.linksLayer.addLine( - link.geometry, - Color.BLUE + link.geometry, Color.BLUE ) realm.close() } @@ -785,7 +885,6 @@ class MainViewModel @Inject constructor( mapPosition.setBearing(0f) // 锁定角度,自动将地图旋转到正北方向 mapController.mMapView.vtmMap.setMapPosition(mapPosition) mapController.locationLayerHandler.animateToCurrentPosition() - planningPath(currentTaskBean!!) } /** @@ -794,7 +893,7 @@ class MainViewModel @Inject constructor( fun onClickMenu() { menuState = !menuState liveDataMenuState.postValue(menuState) - naviEngine!!.bindingRoute(null, mapController.mMapView.vtmMap.mapPosition.geoPoint) +// naviEngine!!.bindingRoute(null, mapController.mMapView.vtmMap.mapPosition.geoPoint) } override fun onCleared() { @@ -955,6 +1054,11 @@ class MainViewModel @Inject constructor( linkIdCache = "" mapController.lineHandler.removeLine() liveDataSignList.value = mutableListOf() + if (bSelectRoad && naviEngineStatus == 1) { + naviEngineStatus = 2 + } else if (naviEngineStatus == 2) { + naviEngineStatus = 1 + } } /** @@ -1044,9 +1148,7 @@ class MainViewModel @Inject constructor( } fun sendServerCommand( - context: Context, - traceVideoBean: TraceVideoBean, - indoorToolsCommand: IndoorToolsCommand + context: Context, traceVideoBean: TraceVideoBean, indoorToolsCommand: IndoorToolsCommand ) { if (TextUtils.isEmpty(Constant.INDOOR_IP)) { @@ -1060,8 +1162,7 @@ class MainViewModel @Inject constructor( val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/${traceVideoBean.command}?" when (val result = networkService.sendServerCommand( - url = url, - traceVideoBean = traceVideoBean + url = url, traceVideoBean = traceVideoBean )) { is NetResult.Success<*> -> { @@ -1074,9 +1175,7 @@ class MainViewModel @Inject constructor( withContext(Dispatchers.Main) { Toast.makeText( - context, - "命令成功。", - Toast.LENGTH_LONG + context, "命令成功。", Toast.LENGTH_LONG ).show() liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS) @@ -1086,8 +1185,7 @@ class MainViewModel @Inject constructor( //启动双向控制服务 if (socketServer != null && socketServer!!.isServerClose) { socketServer!!.connect( - Constant.INDOOR_IP, - this@MainViewModel + Constant.INDOOR_IP, this@MainViewModel ) } @@ -1098,8 +1196,7 @@ class MainViewModel @Inject constructor( context, "命令无效${defaultUserResponse.errmsg}", Toast.LENGTH_SHORT - ) - .show() + ).show() } liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) } @@ -1107,9 +1204,7 @@ class MainViewModel @Inject constructor( } catch (e: IOException) { withContext(Dispatchers.Main) { Toast.makeText( - context, - "${e.message}", - Toast.LENGTH_SHORT + context, "${e.message}", Toast.LENGTH_SHORT ).show() } } @@ -1119,11 +1214,8 @@ class MainViewModel @Inject constructor( is NetResult.Error<*> -> { withContext(Dispatchers.Main) { Toast.makeText( - context, - "${result.exception.message}", - Toast.LENGTH_SHORT - ) - .show() + context, "${result.exception.message}", Toast.LENGTH_SHORT + ).show() } liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) } @@ -1131,11 +1223,8 @@ class MainViewModel @Inject constructor( is NetResult.Failure<*> -> { withContext(Dispatchers.Main) { Toast.makeText( - context, - "${result.code}:${result.msg}", - Toast.LENGTH_SHORT - ) - .show() + context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT + ).show() } liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) } @@ -1158,8 +1247,7 @@ class MainViewModel @Inject constructor( if (niLocation != null) { mapController.markerHandle.addMarker( GeoPoint( - niLocation.latitude, - niLocation.longitude + niLocation.latitude, niLocation.longitude ), traceTag, "", niLocation as java.lang.Object ) } @@ -1197,9 +1285,7 @@ class MainViewModel @Inject constructor( override fun onConnect(success: Boolean) { if (!success && socketServer != null) { BaseToast.makeText( - mapController.mMapView.context, - "轨迹反向控制服务失败,请确认连接是否正常!", - Toast.LENGTH_SHORT + mapController.mMapView.context, "轨迹反向控制服务失败,请确认连接是否正常!", Toast.LENGTH_SHORT ).show() } } @@ -1228,9 +1314,7 @@ class MainViewModel @Inject constructor( Log.e("qj", "反向控制$currentIndexNiLocation") } else { BaseToast.makeText( - mapController.mMapView.context, - "没有找到对应轨迹点!", - Toast.LENGTH_SHORT + mapController.mMapView.context, "没有找到对应轨迹点!", Toast.LENGTH_SHORT ).show() } } @@ -1274,8 +1358,7 @@ class MainViewModel @Inject constructor( startTimer() } } else { - Toast.makeText(mapController.mMapView.context, "无数据了!", Toast.LENGTH_LONG) - .show() + Toast.makeText(mapController.mMapView.context, "无数据了!", Toast.LENGTH_LONG).show() cancelTrace() } } @@ -1292,13 +1375,13 @@ class MainViewModel @Inject constructor( /** * 开启自动定位 */ - fun startAutoLocationTimer(){ + fun startAutoLocationTimer() { if (autoLocationTimer != null) { cancelAutoLocation() } autoLocationTimer = fixedRateTimer("", false, disAutoLocationTime, disAutoLocationTime) { liveDataAutoLocation.postValue(true) - Log.e("qj","自动定位开始执行") + Log.e("qj", "自动定位开始执行") startAutoLocationTimer() } } @@ -1371,9 +1454,7 @@ class MainViewModel @Inject constructor( } else { withContext(Dispatchers.Main) { Toast.makeText( - mapController.mMapView.context, - "未查询到数据", - Toast.LENGTH_SHORT + mapController.mMapView.context, "未查询到数据", Toast.LENGTH_SHORT ).show() } } @@ -1396,9 +1477,7 @@ class MainViewModel @Inject constructor( } else { withContext(Dispatchers.Main) { Toast.makeText( - mapController.mMapView.context, - "未查询到数据", - Toast.LENGTH_SHORT + mapController.mMapView.context, "未查询到数据", Toast.LENGTH_SHORT ).show() } } @@ -1415,9 +1494,7 @@ class MainViewModel @Inject constructor( dialog.dismiss() } else { Toast.makeText( - mapController.mMapView.context, - "输入格式不正确", - Toast.LENGTH_SHORT + mapController.mMapView.context, "输入格式不正确", Toast.LENGTH_SHORT ).show() } } diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt index f8023e57..a12f81a1 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/SignAdapter.kt @@ -79,6 +79,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) : val bd = holder.viewBinding if (item.iconId != 0) { + bd.signMainIconBg.visibility = View.VISIBLE if (item.renderEntity.code == DataCodeEnum.OMDB_WARNINGSIGN.code) { try { var typeCode = "${item.iconId}" @@ -110,6 +111,8 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) : } else { bd.signMainIconBg.setImageResource(item.iconId) } + }else{ + bd.signMainIconBg.visibility = View.INVISIBLE } bd.signMainIcon.text = item.iconText @@ -144,7 +147,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) : val bd = holder.viewBinding bd.signMoreIconsLayout.removeAllViews() bd.signBottomText.text = item.name - bd.signBottomRightText.text = item.distance.toString() + bd.signBottomRightText.text = "${item.distance}米" val list = SignUtil.getLineInfoIcons(item.renderEntity) val lineViewS = View(context) lineViewS.layoutParams = ViewGroup.LayoutParams(24, 80) @@ -216,13 +219,13 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) : holder.tag = item.name + position } - override fun refreshData(newData: List) { - super.refreshData(newData) - for (i in newData.indices) { - if (selectMoreInfoTag == newData[i].name + i) { - return - } - } - } +// override fun refreshData(newData: List) { +// super.refreshData(newData) +//// ?这是要干嘛 for (i in newData.indices) { +//// if (selectMoreInfoTag == newData[i].name + i) { +//// return +//// } +//// } +// } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt index 3467b7f3..ccc564c4 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListAdapter.kt @@ -152,6 +152,7 @@ class TaskListAdapter( if (taskBean.status == FileDownloadStatus.DONE) { binding.taskDownloadBtn.visibility = View.INVISIBLE binding.taskUploadBtn.visibility = View.VISIBLE + } else { binding.taskDownloadBtn.visibility = View.VISIBLE binding.taskUploadBtn.visibility = View.INVISIBLE diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt index ff2d30cd..2c390aef 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/tasklist/TaskListFragment.kt @@ -7,6 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.navinfo.omqs.R @@ -14,6 +15,8 @@ import com.navinfo.omqs.databinding.FragmentTaskListBinding import com.navinfo.omqs.http.taskdownload.TaskDownloadManager import com.navinfo.omqs.http.taskupload.TaskUploadManager import com.navinfo.omqs.tools.FileManager +import com.navinfo.omqs.ui.activity.map.MainActivity +import com.navinfo.omqs.ui.activity.map.MainViewModel import com.navinfo.omqs.ui.fragment.BaseFragment import com.navinfo.omqs.ui.other.shareViewModels import com.yanzhenjie.recyclerview.SwipeMenuCreator @@ -58,9 +61,6 @@ class TaskListFragment : BaseFragment() { Toast.makeText(context, "正在校验", Toast.LENGTH_SHORT).show() viewModel.checkUploadTask(binding.root.context, taskBean) } - else -> { - - } } } } diff --git a/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt index 178c1735..e3e10f4f 100644 --- a/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt +++ b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt @@ -9,43 +9,70 @@ import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.omqs.bean.NaviRoute import com.navinfo.omqs.bean.NaviRouteItem +import com.navinfo.omqs.db.RealmOperateHelper import io.realm.Realm -import io.realm.RealmQuery import org.locationtech.jts.geom.LineString import org.locationtech.jts.geom.Point import org.oscim.core.GeoPoint public interface OnNaviEngineCallbackListener { - fun planningPathSuccess() - fun planningPathError(errorCode: Int, errorMessage: String) - fun bindingResults(list: List) + fun planningPathStatus(code: NaviStatus) + + // fun planningPathError(errorCode: NaviStatus, errorMessage: String) + suspend fun bindingResults(route: NaviRoute?, list: List) +} + +enum class NaviStatus { + NAVI_STATUS_PATH_PLANNING, //路径规划中 + NAVI_STATUS_PATH_ERROR_NODE,//node点缺失 + NAVI_STATUS_PATH_ERROR_DIRECTION,//缺少方向 + NAVI_STATUS_PATH_ERROR_BLOCKED,//路径不通 + NAVI_STATUS_PATH_SUCCESS,//路径规划成功 + NAVI_STATUS_DISTANCE_OFF,//距离偏离 + NAVI_STATUS_DIRECTION_OFF,//方向偏离 } -class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngineCallbackListener) { +class NaviEngine( + private val niMapController: NIMapController, + private val realmOperateHelper: RealmOperateHelper, + val callback: OnNaviEngineCallbackListener +) { - - private val QUERY_KEY_LIST = arrayOf( + /** + * 要查询的要素列表 + */ + private val QUERY_KEY_ITEM_LIST = arrayOf( + DataCodeEnum.OMDB_ELECTRONICEYE.name, DataCodeEnum.OMDB_SPEEDLIMIT.name, DataCodeEnum.OMDB_SPEEDLIMIT_COND.name, DataCodeEnum.OMDB_SPEEDLIMIT_VAR.name, DataCodeEnum.OMDB_TRAFFICLIGHT.name, - DataCodeEnum.OMDB_RESTRICTION.name, +// DataCodeEnum.OMDB_RESTRICTION.name, DataCodeEnum.OMDB_LANEINFO.name, DataCodeEnum.OMDB_TRAFFIC_SIGN.name, DataCodeEnum.OMDB_WARNINGSIGN.name, DataCodeEnum.OMDB_TOLLGATE.name ) + /** + * 要查询的link基本信息列表 + */ + private val QUERY_KEY_LINK_INFO_LIST = arrayOf( + DataCodeEnum.OMDB_RD_LINK.name, + DataCodeEnum.OMDB_LINK_DIRECT.name, + DataCodeEnum.OMDB_LINK_NAME.name, + ) + /** * 偏离距离 单位:米 */ - private val DEVIATION_DISTANCE = 150000 + private val DEVIATION_DISTANCE = 15 /** * 偏离次数上限 */ - private val DEVIATION_COUNT = 3 + private val DEVIATION_COUNT = 5 /** * 局部匹配时,走过的路段还记录100米 @@ -107,6 +134,7 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin */ var tempRoutList = mutableListOf() + /** * 所有路段集合 */ @@ -149,9 +177,9 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin * 计算路径 */ suspend fun planningPath(taskBean: TaskBean) { - + callback.planningPathStatus(NaviStatus.NAVI_STATUS_PATH_PLANNING) val pathList = mutableListOf() - val realm = Realm.getDefaultInstance() + val realm = realmOperateHelper.getSelectTaskRealmInstance() for (link in taskBean.hadLinkDvoList) { //测线不参与导航 if (link.linkStatus == 3) { @@ -162,37 +190,55 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin ) route.pointList = GeometryTools.getGeoPoints(link.geometry) - //查询每条link的snode,enode - val res1 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res1?.let { - val snodePid = it.properties["snodePid"] - if (snodePid != null) { - route.sNode = snodePid - } - val enodePid = it.properties["enodePid"] - if (enodePid != null) { - route.eNode = enodePid + val res = realm.where(RenderEntity::class.java).`in`("table", QUERY_KEY_LINK_INFO_LIST) + .equalTo("properties['linkPid']", link.linkPid).findAll() + var bHasNode = false + var bHasDir = false + var bHasName = false + if (res != null) { + for (entity in res) { + when (entity.code) { + DataCodeEnum.OMDB_RD_LINK.code -> { + bHasNode = true + val snodePid = entity.properties["snodePid"] + if (snodePid != null) { + route.sNode = snodePid + } else { + bHasNode = false + } + val enodePid = entity.properties["enodePid"] + if (enodePid != null) { + route.eNode = enodePid + } else { + bHasNode = false + } + } + DataCodeEnum.OMDB_LINK_DIRECT.code -> { + val direct = entity.properties["direct"] + if (direct != null) { + bHasDir = true + route.direct = direct.toInt() + } + } + DataCodeEnum.OMDB_LINK_NAME.code -> { + bHasName = true + route.name = realm.copyFromRealm(entity) + } + } } } - //查询每条link的方向 - val res2 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_LINK_DIRECT.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res2?.let { - val direct = it.properties["direct"] - if (direct != null) { - route.direct = direct.toInt() - } + if (!bHasNode) { + callback.planningPathStatus( + NaviStatus.NAVI_STATUS_PATH_ERROR_NODE + ) + return } - //查询每条link的名称 - val res3 = realm.where(RenderEntity::class.java) - .equalTo("table", DataCodeEnum.OMDB_LINK_NAME.name).and() - .equalTo("properties['linkPid']", link.linkPid).findFirst() - res3?.let { - route.name = "${it.properties["name"]}" + if (!bHasDir) { + callback.planningPathStatus( + NaviStatus.NAVI_STATUS_PATH_ERROR_DIRECTION + ) + return } pathList.add(route) } @@ -269,7 +315,9 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin } else { if (!bHasLast && !bHasNext) { bBreak = false - callback.planningPathError(1, "路径不连通!") + callback.planningPathStatus( + NaviStatus.NAVI_STATUS_PATH_ERROR_BLOCKED + ) realm.close() return } @@ -279,83 +327,20 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin val itemMap: MutableMap> = mutableMapOf() //查询每根link上的关联要素 for (route in newRouteList) { + itemMap.clear() //常规点限速 - var res = realm.where(RenderEntity::class.java) + val res = realm.where(RenderEntity::class.java) .equalTo("properties['linkPid']", route.linkId).and().`in`( "table", - QUERY_KEY_LIST + QUERY_KEY_ITEM_LIST ).findAll() - if (res != null) { - Log.e("jingo", "道路查询预警要素 ${route.linkId} ${res.size}条数据") + if (res.isNotEmpty()) { +// Log.e("jingo", "道路查询预警要素 ${route.linkId} ${res.size}条数据") for (r in res) { - Log.e("jingo", "道路查询预警要素 ${r.name}") +// Log.e("jingo", "道路查询预警要素 ${r.name}") insertItemToRoute(realm, route, r, itemMap) } } -// //条件点限速 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_SPEEDLIMIT_COND.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //可变点限速 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_SPEEDLIMIT_VAR.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //交通灯 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_TRAFFICLIGHT.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //普通交限 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //车信 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_LANEINFO.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //交通标牌 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_TRAFFIC_SIGN.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //警示信息 -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_WARNINGSIGN.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } -// //OMDB_TOLLGATE -// res = realm.where(RenderEntity::class.java) -// .equalTo("table", DataCodeEnum.OMDB_TOLLGATE.name).and() -// .equalTo("properties['linkPid']", route.linkId).findAll() -// if(res != null){ -// for(r in res) -// insertItemToRoute(realm, route, r, itemMap) -// } //对路径上的要素进行排序 if (itemMap.isNotEmpty()) { route.itemList = mutableListOf() @@ -367,6 +352,7 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin val naviRouteItem = NaviRouteItem(i, item, route.linkId) route.itemList!!.add(naviRouteItem) } + itemMap.remove(point) } } route.itemList!!.sortBy { it.index } @@ -374,8 +360,8 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin } realm.close() routeList = newRouteList - callback.planningPathSuccess() - niMapController.lineHandler.showLine(geometry!!.toText()) + callback.planningPathStatus(NaviStatus.NAVI_STATUS_PATH_SUCCESS) + } /** @@ -399,7 +385,8 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin val point = GeoPoint( footAndDistance.getCoordinate(0).y, footAndDistance.getCoordinate(0).x ) - niMapController.markerHandle.addMarker(point, res.id, res.name) + //测试marker +// niMapController.markerHandle.addMarker(point, res.id, res.name) route.pointList.add(footAndDistance.footIndex + 1, point) if (itemMap.containsKey(point)) { itemMap[point]!!.add(realm.copyFromRealm(res)) @@ -421,7 +408,7 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin /** * 绑定道路 */ - fun bindingRoute(location: NiLocation?, point: GeoPoint) { + suspend fun bindingRoute(location: NiLocation?, point: GeoPoint) { if (geometry != null) { //还没有绑定到路径的时候 if (routeIndex < 0) { @@ -430,33 +417,31 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin //定位点到垂足距离不超过30米 if (pointPairDistance.getMeterDistance() < DEVIATION_DISTANCE) { footIndex = pointPairDistance.footIndex - Log.e( - "jingo", - "当前绑定到了整条路线的第 $footIndex 点 ${pointPairDistance.getMeterDistance()} " - ) +// Log.e( +// "jingo", +// "当前绑定到了整条路线的第 ${footIndex} 点 ${pointPairDistance.getMeterDistance()} " +// ) val lastRouteIndex = routeIndex for (i in routeList.indices) { val route = routeList[i] if (route.startIndexInPath <= footIndex && route.endIndexIntPath >= footIndex) { routeIndex = route.indexInPath - Log.e( - "jingo", - "当前绑定到了整条路线id ${route.linkId} " - ) - niMapController.lineHandler.showLine(route.pointList) +// Log.e( +// "jingo", +// "当前绑定到了整条路线id ${route.linkId} " +// ) +// niMapController.lineHandler.showLine(route.pointList) footPoint = GeoPoint( pointPairDistance.getCoordinate(0).y, pointPairDistance.getCoordinate(0).x ) - val listPoint = mutableListOf(point, footPoint!!) - niMapController.lineHandler.showLine( - listPoint - ) - +// val listPoint = mutableListOf(point, footPoint!!) +// niMapController.lineHandler.showLine( +// listPoint +// ) if (lastRouteIndex != routeIndex) { createTempPath() } - matchingItem() errorCount = 0 break } @@ -470,31 +455,30 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin //定位点到垂足距离不超过30米 if (pointPairDistance.getMeterDistance() < DEVIATION_DISTANCE) { footIndex = pointPairDistance.footIndex + tempRoutList[0].startIndexInPath - Log.e("jingo", "局部 当前绑定到了整条路线的第 $footIndex 点") +// Log.e("jingo", "局部 当前绑定到了整条路线的第 $footIndex 点") val lastRouteIndex = routeIndex for (i in tempRoutList.indices) { val route = tempRoutList[i] if (route.startIndexInPath <= footIndex && route.endIndexIntPath >= footIndex) { routeIndex = route.indexInPath - Log.e( - "jingo", - "局部 当前绑定到了整条路线id ${route.linkId} " - ) - niMapController.lineHandler.showLine(route.pointList) +// Log.e( +// "jingo", +// "局部 当前绑定到了整条路线id ${route.linkId} " +// ) +// niMapController.lineHandler.showLine(route.pointList) footPoint = GeoPoint( pointPairDistance.getCoordinate(0).y, pointPairDistance.getCoordinate(0).x ) - val listPoint = mutableListOf(point, footPoint!!) - niMapController.lineHandler.showLine( - listPoint - ) - +// val listPoint = mutableListOf(point, footPoint!!) +// niMapController.lineHandler.showLine( +// listPoint +// ) + matchingItem() if (lastRouteIndex != routeIndex) { createTempPath() } - matchingItem() errorCount = 0 break } @@ -510,31 +494,43 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin * 匹配要素 * @point:定位点 */ - private fun matchingItem() { + private suspend fun matchingItem() { + if (routeIndex > -1 && tempRoutList.isNotEmpty() && tempGeometry != null) { + Log.e("jingo", "当前${routeIndex} ${tempRoutList[0].startIndexInPath} $footIndex") //道路前方一定距离范围内的要素信息 val bindingItemList = mutableListOf() - //临时局部路径的游标对应整条路径的游标 - val tempFootIndex = footIndex + tempRoutList[0].startIndexInPath //定位点到要素的路径距离 var distance = 0.0 //计算要素路径距离的点集合 val disPoints = mutableListOf(footPoint!!) //下一个要素的起点游标 - var tempIndex = footIndex + 1 - for(route in tempRoutList) { - if( route.indexInPath < routeIndex) + var tempIndex = footIndex - tempRoutList[0].startIndexInPath + 1 + var currentRoute: NaviRoute? = null + for (route in tempRoutList) { +// if (route.itemList != null) { +// Log.e("jingo", "${route.linkId}我有${route.itemList!!.size}个要素 ") +// } + if (route.indexInPath < routeIndex) continue + if (route.indexInPath == routeIndex) { + currentRoute = route + } if (route.itemList != null && route.itemList!!.isNotEmpty()) { for (naviItem in route.itemList!!) { - if (naviItem.index > tempFootIndex) { +// Log.e( +// "jingo", +// "我是:${naviItem.data.name} 我的点位 ${naviItem.index} 垂足点位 $footIndex" +// ) + if (naviItem.index > footIndex) { val rightI = naviItem.index - tempRoutList[0].startIndexInPath + 1 for (i in tempIndex until rightI) { val geo = tempGeometry!!.coordinates[i] disPoints.add(GeoPoint(geo.y, geo.x)) } - tempIndex = rightI + tempIndex = rightI + 1 distance = GeometryTools.getDistance(disPoints) +// Log.e("jingo", "我的距离${distance} 下一个${tempIndex} 位置${rightI}") if (distance < FARTHEST_DISPLAY_DISTANCE && distance > -1) { naviItem.distance = distance.toInt() bindingItemList.add(naviItem) @@ -543,12 +539,12 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin } } } - if(distance >= FARTHEST_DISPLAY_DISTANCE){ + if (distance >= FARTHEST_DISPLAY_DISTANCE) { break } } } - callback.bindingResults(bindingItemList) + callback.bindingResults(currentRoute, bindingItemList) } } @@ -601,6 +597,7 @@ class NaviEngine(val niMapController: NIMapController, val callback: OnNaviEngin private fun deviationUp() { errorCount++ if (errorCount >= DEVIATION_COUNT) { + callback.planningPathStatus(NaviStatus.NAVI_STATUS_DISTANCE_OFF) bindingReset() } } diff --git a/vtm b/vtm index d31e10f1..39b9993b 160000 --- a/vtm +++ b/vtm @@ -1 +1 @@ -Subproject commit d31e10f1483d49ecec361b79497394c9b7983687 +Subproject commit 39b9993b1cc5257d11c872161812ffe890e44bd9 From 2b574da6d40a2239a877e6e24578883d95ef4133 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Wed, 20 Sep 2023 13:41:16 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=E9=9D=A2=E7=BA=B9=E7=90=86=E4=BC=98?= =?UTF-8?q?=E5=8C=96=EF=BC=8C=E6=A0=B9=E6=8D=AE=E5=AE=9E=E9=99=85=E9=95=BF?= =?UTF-8?q?=E5=BA=A6=E8=AE=BE=E7=BD=AE=E7=BA=B9=E7=90=86=E9=87=8D=E5=A4=8D?= =?UTF-8?q?repeat=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/omdb_config.json | 1 + .../omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/omdb_config.json b/app/src/main/assets/omdb_config.json index ed45859f..a037ed16 100644 --- a/app/src/main/assets/omdb_config.json +++ b/app/src/main/assets/omdb_config.json @@ -258,6 +258,7 @@ "code": 3014, "name": "人行横道", "catch":true, + "checkLinkId": false, "zoomMin": 18, "zoomMax": 20 }, diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index c09ca51a..855790d8 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -166,7 +166,7 @@ class PersonalCenterFragment(private var indoorDataListener: ((Boolean) -> Unit? // 定位到指定位置 niMapController.mMapView.vtmMap.animator() // .animateTo(GeoPoint( 40.05108004733645, 116.29187746293708 )) - .animateTo(GeoPoint(40.09848700000006, 116.53088699999999)) + .animateTo(GeoPoint(40.09819324139729,116.53123207733361 )) } R.id.personal_center_menu_open_all_layer -> { From 3dc346f29df5cba89800a10d0108d3124725e61b Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Wed, 20 Sep 2023 15:35:14 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20symbol=E5=A2=9E=E5=8A=A0y=E6=96=B9?= =?UTF-8?q?=E5=90=91=E7=9A=84=E5=81=8F=E7=A7=BB=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt | 5 +++-- collect-library/resources/rendertheme.xsd | 2 ++ collect-library/src/main/assets/editormarker.xml | 2 +- vtm | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt index 9dc13333..0a211e9f 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt @@ -845,8 +845,9 @@ class ImportPreProcess { val listResult = mutableListOf() val coorEnd = Coordinate(pointStart.getX() + dx, pointStart.getY() + dy, pointStart.z) - renderEntity.geometry = - WKTWriter(3).write(GeometryTools.createLineString(arrayOf(pointStart, coorEnd))) + renderEntity.geometry = GeometryTools.createGeometry(GeoPoint(centerPoint!!.y, centerPoint.x)).toString() +// renderEntity.geometry = +// WKTWriter(3).write(GeometryTools.createLineString(arrayOf(pointStart, coorEnd))) val code = renderEntity.properties["signType"] renderEntity.properties["src"] = "assets:omdb/appendix/1105_${code}_0.svg" diff --git a/collect-library/resources/rendertheme.xsd b/collect-library/resources/rendertheme.xsd index 656b3da1..fa7348c9 100644 --- a/collect-library/resources/rendertheme.xsd +++ b/collect-library/resources/rendertheme.xsd @@ -260,6 +260,8 @@ + + diff --git a/collect-library/src/main/assets/editormarker.xml b/collect-library/src/main/assets/editormarker.xml index ba0119c7..b418918f 100644 --- a/collect-library/src/main/assets/editormarker.xml +++ b/collect-library/src/main/assets/editormarker.xml @@ -1568,7 +1568,7 @@ + src="@src" symbol-height="24" symbol-width="24" degree="-90" dy="-30"> diff --git a/vtm b/vtm index f2af87c6..719c44b6 160000 --- a/vtm +++ b/vtm @@ -1 +1 @@ -Subproject commit f2af87c6a012ac41d6f22a77d6b45853b250ed3e +Subproject commit 719c44b65d3ed26d725b24b3a5366b281c9e4fad From 7d29ce2309a6440100e78a4244c634f7e01e544a Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Wed, 20 Sep 2023 16:21:26 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E8=B7=AF=E7=BA=BF=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E8=A6=81=E7=B4=A0=E8=B7=9D=E7=A6=BB=E8=AE=A1?= =?UTF-8?q?=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/omdb_config.json | 3 +- .../omqs/ui/activity/map/MainActivity.kt | 2 +- .../omqs/ui/activity/map/MainViewModel.kt | 25 +++++++--- .../java/com/navinfo/omqs/util/SignUtil.kt | 48 ++++++++++++++++++- .../collect/library/utils/GeometryTools.java | 9 ++++ 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/app/src/main/assets/omdb_config.json b/app/src/main/assets/omdb_config.json index 04357aa9..2859bf52 100644 --- a/app/src/main/assets/omdb_config.json +++ b/app/src/main/assets/omdb_config.json @@ -32,7 +32,8 @@ "name": "道路线", "zoomMin": 15, "zoomMax": 17, - "catch":true + "catch":true, + "checkLinkId": true }, "2002": { "table": "OMDB_RD_LINK_FUNCTION_CLASS", diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt index c8a79efa..5fc097ed 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt @@ -424,7 +424,7 @@ class MainActivity : BaseActivity() { } } - viewModel.listDataMessage.observe(this) { + viewModel.liveDataMessage.observe(this) { Toast.makeText(this, it, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 13dfb3a8..87376f05 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -57,6 +57,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext import org.locationtech.jts.geom.Geometry +import org.locationtech.jts.geom.LineString import org.oscim.core.GeoPoint import org.oscim.core.MapPosition import org.oscim.map.Map @@ -122,7 +123,7 @@ class MainViewModel @Inject constructor( /** * 提示信息 */ - val listDataMessage = MutableLiveData() + val liveDataMessage = MutableLiveData() private var traceTag: String = "TRACE_TAG" @@ -426,8 +427,10 @@ class MainViewModel @Inject constructor( } }) naviEngine!!.planningPath(currentTaskBean!!) - naviMutex.unlock() + } else { + liveDataMessage.postValue("请先安装任务数据") } + naviMutex.unlock() } } @@ -435,8 +438,11 @@ class MainViewModel @Inject constructor( override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { if (key == Constant.SELECT_TASK_ID) { viewModelScope.launch(Dispatchers.IO) { + naviMutex.lock() + naviEngineStatus = 0 getTaskBean() initQsRecordData() + naviMutex.unlock() } } } @@ -680,7 +686,8 @@ class MainViewModel @Inject constructor( bottomRightText = SignUtil.getSignBottomRightText(element), renderEntity = element, isMoreInfo = SignUtil.isMoreInfo(element), - index = SignUtil.getRoadInfoIndex(element) + index = SignUtil.getRoadInfoIndex(element), + ) topSignList.add( signBean @@ -708,10 +715,11 @@ class MainViewModel @Inject constructor( * 捕获道路和面板 */ private suspend fun captureLink(point: GeoPoint) { + if (captureLinkState) { return } - + mapController.markerHandle.addMarker(point, "selectLink") try { captureLinkState = true @@ -731,6 +739,8 @@ class MainViewModel @Inject constructor( if (linkIdCache != linkId) { mapController.lineHandler.showLine(link.geometry) + val lineString:Geometry = GeometryTools.createGeometry(link.geometry) + val footAndDistance = GeometryTools.pointToLineDistance(point,lineString) linkId?.let { var elementList = realmOperateHelper.queryLinkByLinkPid(it) for (element in elementList) { @@ -748,7 +758,8 @@ class MainViewModel @Inject constructor( bottomRightText = SignUtil.getSignBottomRightText(element), renderEntity = element, isMoreInfo = SignUtil.isMoreInfo(element), - index = SignUtil.getRoadInfoIndex(element) + index = SignUtil.getRoadInfoIndex(element), + distance = SignUtil.getDistance(footAndDistance,lineString,element) ) // Log.e("jingo", "捕捉到的数据code ${element.code}") when (element.code) { @@ -829,7 +840,8 @@ class MainViewModel @Inject constructor( RenderEntity::class.java, true ) - .equalTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name).and() + .equalTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name) + .and() .equalTo( "properties['${RenderEntity.Companion.LinkTable.linkPid}']", outLink @@ -1050,6 +1062,7 @@ class MainViewModel @Inject constructor( linkIdCache = "" mapController.lineHandler.removeLine() liveDataSignList.value = mutableListOf() + mapController.markerHandle.removeMarker("selectLink") if (bSelectRoad && naviEngineStatus == 1) { naviEngineStatus = 2 } else if (naviEngineStatus == 2) { diff --git a/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt b/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt index cbda1321..bf77d2ed 100644 --- a/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt +++ b/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt @@ -1,9 +1,10 @@ package com.navinfo.omqs.util -import android.provider.ContactsContract.Data import android.util.Log import com.navinfo.collect.library.data.entity.RenderEntity import com.navinfo.collect.library.enums.DataCodeEnum +import com.navinfo.collect.library.utils.FootAndDistance +import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.omqs.R import com.navinfo.omqs.bean.RoadNameBean import com.navinfo.omqs.bean.SignBean @@ -13,6 +14,10 @@ import com.navinfo.omqs.ui.fragment.signMoreInfo.TwoItemAdapter import com.navinfo.omqs.ui.fragment.signMoreInfo.TwoItemAdapterItem import org.json.JSONArray import org.json.JSONObject +import org.locationtech.jts.geom.Geometry +import org.locationtech.jts.geom.GeometryFactory +import org.locationtech.jts.geom.LineString +import org.oscim.core.Point import java.lang.reflect.Field class SignUtil { @@ -1552,6 +1557,47 @@ class SignUtil { return list } + /** + * 计算捕捉点到 + */ + fun getDistance( + footAndDistance: FootAndDistance, + lineString: Geometry, + element: RenderEntity + ): Int { + footAndDistance.footIndex + val itemGeometry = GeometryTools.createGeoPoint(element.geometry) + if (itemGeometry is Point) { + val itemFoot = GeometryTools.pointToLineDistance(itemGeometry, lineString) + var dis = GeometryTools.getDistance( + footAndDistance.getCoordinate(0).getY(), + footAndDistance.getCoordinate(0).getX(), + itemFoot.getCoordinate(0).getY(), + itemFoot.getCoordinate(0).getX(), + ) + return if (footAndDistance.footIndex > itemFoot.footIndex) { + dis.toInt() + } else { + -dis.toInt() + } + }else if(itemGeometry is LineString){ + val factory = GeometryFactory() + val geo: Geometry = factory.createPoint(lineString.coordinates[0]) + val itemFoot = GeometryTools.pointToLineDistance(itemGeometry, geo) + var dis = GeometryTools.getDistance( + footAndDistance.getCoordinate(0).getY(), + footAndDistance.getCoordinate(0).getX(), + itemFoot.getCoordinate(0).getY(), + itemFoot.getCoordinate(0).getX(), + ) + return if (footAndDistance.footIndex > itemFoot.footIndex) { + dis.toInt() + } else { + -dis.toInt() + } + } + return 0 + } } diff --git a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java index 976ea2bc..003e494a 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java @@ -443,6 +443,15 @@ public class GeometryTools { } + public static double distanceToDouble(Geometry startGeoPoint, Geometry endGeoPoint) { + if (startGeoPoint != null && endGeoPoint != null) { + double d = startGeoPoint.distance(endGeoPoint); + return convertDistanceToDegree(d, startGeoPoint.getCoordinate().y); + } + return 0; + + } + /** * LINESTRING (116.4206899999999933 39.9620999999999995, From 4aac9d1675916852bec7b114b4e089f9cce3db06 Mon Sep 17 00:00:00 2001 From: squallzhjch Date: Thu, 21 Sep 2023 09:46:25 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BA=BF=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E7=9A=84=E9=A2=84=E8=AD=A6=E8=A6=81=E7=B4=A0=E8=B7=9D?= =?UTF-8?q?=E7=A6=BB=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../omqs/ui/activity/map/MainViewModel.kt | 82 ++++++++++++------- .../java/com/navinfo/omqs/util/SignUtil.kt | 53 ++++++------ 2 files changed, 84 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt index 87376f05..93ca83c5 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/map/MainViewModel.kt @@ -336,27 +336,27 @@ class MainViewModel @Inject constructor( MapParamUtils.setTaskConfig(Constant.currentSelectTaskConfig) socketServer = SocketServer(mapController, traceDataBase, sharedPreferences) - viewModelScope.launch(Dispatchers.Default) { - naviTestFlow().collect { point -> - if (naviEngineStatus == 1) { - naviEngine?.let { - naviMutex.lock() - it.bindingRoute(null, point) - naviMutex.unlock() - } - } - } - } +// viewModelScope.launch(Dispatchers.Default) { +// naviTestFlow().collect { point -> +// if (naviEngineStatus == 1) { +// naviEngine?.let { +// naviMutex.lock() +// it.bindingRoute(null, point) +// naviMutex.unlock() +// } +// } +// } +// } } - fun naviTestFlow(): Flow = flow { - - while (true) { - emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) - delay(1000) - } - } +// fun naviTestFlow(): Flow = flow { +// +// while (true) { +// emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) +// delay(1000) +// } +// } /** * 获取当前任务 @@ -561,18 +561,30 @@ class MainViewModel @Inject constructor( } } + + /** + * 导航预警信息 + */ viewModelScope.launch(Dispatchers.Default) { //用于定位点捕捉道路 mapController.locationLayerHandler.niLocationFlow.collectLatest { location -> + if (!isSelectRoad() && !GeometryTools.isCheckError( location.longitude, location.latitude ) ) { - captureLink( - GeoPoint( - location.latitude, location.longitude + if (naviEngine != null && naviEngineStatus == 1) { + naviMutex.lock() + val point = GeoPoint(location.latitude, location.longitude) + naviEngine!!.bindingRoute(location, point) + naviMutex.unlock() + } else { + captureLink( + GeoPoint( + location.latitude, location.longitude + ) ) - ) + } } } } @@ -688,7 +700,7 @@ class MainViewModel @Inject constructor( isMoreInfo = SignUtil.isMoreInfo(element), index = SignUtil.getRoadInfoIndex(element), - ) + ) topSignList.add( signBean ) @@ -719,7 +731,7 @@ class MainViewModel @Inject constructor( if (captureLinkState) { return } - mapController.markerHandle.addMarker(point, "selectLink") + try { captureLinkState = true @@ -737,10 +749,20 @@ class MainViewModel @Inject constructor( val topSignList = mutableListOf() mapController.lineHandler.linksLayer.clear() if (linkIdCache != linkId) { - + if (bSelectRoad) + mapController.markerHandle.addMarker(point, "selectLink") mapController.lineHandler.showLine(link.geometry) - val lineString:Geometry = GeometryTools.createGeometry(link.geometry) - val footAndDistance = GeometryTools.pointToLineDistance(point,lineString) + val lineString: Geometry = GeometryTools.createGeometry(link.geometry) + val footAndDistance = GeometryTools.pointToLineDistance(point, lineString) + val linePoints = GeometryTools.getGeoPoints(link.geometry) + linePoints.add( + footAndDistance.footIndex + 1, + GeoPoint( + footAndDistance.getCoordinate(0).y, + footAndDistance.getCoordinate(0).x + ) + ) + val newLineString = GeometryTools.createLineString(linePoints) linkId?.let { var elementList = realmOperateHelper.queryLinkByLinkPid(it) for (element in elementList) { @@ -759,7 +781,11 @@ class MainViewModel @Inject constructor( renderEntity = element, isMoreInfo = SignUtil.isMoreInfo(element), index = SignUtil.getRoadInfoIndex(element), - distance = SignUtil.getDistance(footAndDistance,lineString,element) + distance = SignUtil.getDistance( + footAndDistance, + newLineString, + element + ) ) // Log.e("jingo", "捕捉到的数据code ${element.code}") when (element.code) { diff --git a/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt b/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt index 2e9d4d0c..12cc49f5 100644 --- a/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt +++ b/app/src/main/java/com/navinfo/omqs/util/SignUtil.kt @@ -15,9 +15,9 @@ import com.navinfo.omqs.ui.fragment.signMoreInfo.TwoItemAdapterItem import org.json.JSONArray import org.json.JSONObject import org.locationtech.jts.geom.Geometry -import org.locationtech.jts.geom.GeometryFactory import org.locationtech.jts.geom.LineString -import org.oscim.core.Point +import org.locationtech.jts.geom.Point +import org.oscim.core.GeoPoint import java.lang.reflect.Field class SignUtil { @@ -813,32 +813,32 @@ class SignUtil { DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> { var color = data.properties["color"] if (color != null) { - when(color){ - "0"->{ - return "颜色:未验证" + when (color) { + "0" -> { + return "颜色:未验证" } - "1"->{ + "1" -> { return "颜色:白色" } - "2"->{ + "2" -> { return "颜色:黄色" } - "3"->{ + "3" -> { return "颜色:红色" } - "5"->{ + "5" -> { return "颜色:棕色" } - "6"->{ + "6" -> { return "颜色:蓝色" } - "7"->{ + "7" -> { return "颜色:绿色" } - "8"->{ + "8" -> { return "颜色:黑色" } - "9"->{ + "9" -> { return "颜色:其他" } } @@ -1070,7 +1070,8 @@ class SignUtil { DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> { var trafsignShape = data.properties["trafsignShape"] if (trafsignShape != null) { - trafsignShape = "icon_${DataCodeEnum.OMDB_TRAFFIC_SIGN.code}_${trafsignShape.lowercase()}" + trafsignShape = + "icon_${DataCodeEnum.OMDB_TRAFFIC_SIGN.code}_${trafsignShape.lowercase()}" return getResId(trafsignShape, R.drawable::class.java) } return 0 @@ -1609,32 +1610,38 @@ class SignUtil { lineString: Geometry, element: RenderEntity ): Int { - footAndDistance.footIndex - val itemGeometry = GeometryTools.createGeoPoint(element.geometry) + + val itemGeometry = GeometryTools.createGeometry(element.geometry) if (itemGeometry is Point) { - val itemFoot = GeometryTools.pointToLineDistance(itemGeometry, lineString) + val itemFoot = GeometryTools.pointToLineDistance( + GeoPoint(itemGeometry.y, itemGeometry.x), + lineString + ) var dis = GeometryTools.getDistance( footAndDistance.getCoordinate(0).getY(), footAndDistance.getCoordinate(0).getX(), itemFoot.getCoordinate(0).getY(), itemFoot.getCoordinate(0).getX(), ) - return if (footAndDistance.footIndex > itemFoot.footIndex) { + return if (footAndDistance.footIndex < itemFoot.footIndex) { dis.toInt() } else { -dis.toInt() } - }else if(itemGeometry is LineString){ - val factory = GeometryFactory() - val geo: Geometry = factory.createPoint(lineString.coordinates[0]) - val itemFoot = GeometryTools.pointToLineDistance(itemGeometry, geo) + } else if (itemGeometry is LineString) { + val itemFoot = GeometryTools.pointToLineDistance( + GeoPoint( + lineString.coordinates[0].y, + lineString.coordinates[0].x + ), lineString + ) var dis = GeometryTools.getDistance( footAndDistance.getCoordinate(0).getY(), footAndDistance.getCoordinate(0).getX(), itemFoot.getCoordinate(0).getY(), itemFoot.getCoordinate(0).getX(), ) - return if (footAndDistance.footIndex > itemFoot.footIndex) { + return if (footAndDistance.footIndex < itemFoot.footIndex) { dis.toInt() } else { -dis.toInt()