diff --git a/app/build.gradle b/app/build.gradle index b02d1782..826f37ee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,6 @@ android { } - dependencies { api project(':collect-library') implementation project(path: ':vtm-android') diff --git a/app/src/main/java/com/navinfo/omqs/bean/Route.kt b/app/src/main/java/com/navinfo/omqs/bean/Route.kt new file mode 100644 index 00000000..e57ec794 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/bean/Route.kt @@ -0,0 +1,24 @@ +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/db/ImportOMDBHelper.kt b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt index f1c962cc..15c5b7f8 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt @@ -439,187 +439,192 @@ class ImportOMDBHelper @AssistedInject constructor( // 对renderEntity做预处理后再保存 - val resultEntity = - importConfig.transformProperties(renderEntity) + try { + val resultEntity = + importConfig.transformProperties(renderEntity) - if (resultEntity != null) { - if (currentConfig.catch) { - renderEntity.catchEnable = 0 - } else { - renderEntity.catchEnable = 1 - } - - //对code编码需要特殊处理 存在多个属性值时,渲染优先级:SA>PA,存在多个属性值时,渲染优先级:FRONTAGE>MAIN_SIDE_A CCESS - if (renderEntity.code == DataCodeEnum.OMDB_LINK_ATTRIBUTE.code) { - - Log.e("qj", "道路属性===0") - - var type = renderEntity.properties["sa"] - - if (type != null && type == "1") { - renderEntity.code = - DataCodeEnum.OMDB_LINK_ATTRIBUTE_SA.code - Log.e("qj", "道路属性===1") + if (resultEntity != null) { + if (currentConfig.catch) { + renderEntity.catchEnable = 0 } else { - type = renderEntity.properties["pa"] + renderEntity.catchEnable = 1 + } + + //对code编码需要特殊处理 存在多个属性值时,渲染优先级:SA>PA,存在多个属性值时,渲染优先级:FRONTAGE>MAIN_SIDE_A CCESS + if (renderEntity.code == DataCodeEnum.OMDB_LINK_ATTRIBUTE.code) { + + Log.e("qj", "道路属性===0") + + var type = renderEntity.properties["sa"] + if (type != null && type == "1") { renderEntity.code = - DataCodeEnum.OMDB_LINK_ATTRIBUTE_PA.code - Log.e("qj", "道路属性===2") + DataCodeEnum.OMDB_LINK_ATTRIBUTE_SA.code + Log.e("qj", "道路属性===1") } else { - type = renderEntity.properties["frontage"] + type = renderEntity.properties["pa"] if (type != null && type == "1") { renderEntity.code = - DataCodeEnum.OMDB_LINK_ATTRIBUTE_FORNTAGE.code - Log.e("qj", "道路属性===3") + DataCodeEnum.OMDB_LINK_ATTRIBUTE_PA.code + Log.e("qj", "道路属性===2") } else { - type = - renderEntity.properties["mainSideAccess"] + type = renderEntity.properties["frontage"] if (type != null && type == "1") { renderEntity.code = - DataCodeEnum.OMDB_LINK_ATTRIBUTE_MAIN_SIDE_ACCESS.code - Log.e("qj", "道路属性===4") + DataCodeEnum.OMDB_LINK_ATTRIBUTE_FORNTAGE.code + Log.e("qj", "道路属性===3") } else { - renderEntity.enable = 0 - Log.e( - "qj", - "过滤不显示数据${renderEntity.table}" - ) - Log.e("qj", "道路属性===5") - continue + type = + renderEntity.properties["mainSideAccess"] + if (type != null && type == "1") { + renderEntity.code = + DataCodeEnum.OMDB_LINK_ATTRIBUTE_MAIN_SIDE_ACCESS.code + Log.e("qj", "道路属性===4") + } else { + renderEntity.enable = 0 + Log.e( + "qj", + "过滤不显示数据${renderEntity.table}" + ) + Log.e("qj", "道路属性===5") + continue + } } } } - } - } else if (renderEntity.code == DataCodeEnum.OMDB_RAMP.code) { - /*匝道*/ - var formWay = renderEntity.properties["formOfWay"] - if (formWay != null) { - when (formWay) { - "93" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_1.code + } else if (renderEntity.code == DataCodeEnum.OMDB_RAMP.code) { + /*匝道*/ + var formWay = renderEntity.properties["formOfWay"] + if (formWay != null) { + when (formWay) { + "93" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_1.code - "98" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_2.code + "98" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_2.code - "99" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_3.code + "99" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_3.code - "100" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_4.code + "100" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_4.code - "102" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_5.code + "102" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_5.code - "103" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_6.code + "103" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_6.code - "104" -> renderEntity.code = - DataCodeEnum.OMDB_RAMP_7.code + "104" -> renderEntity.code = + DataCodeEnum.OMDB_RAMP_7.code + } } - } - } else if (renderEntity.code == DataCodeEnum.OMDB_LINK_FORM1.code) { - /*道路形态1*/ - var formWay = renderEntity.properties["formOfWay"] - if (formWay != null) { - when (formWay) { - "35" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM1_1.code + } else if (renderEntity.code == DataCodeEnum.OMDB_LINK_FORM1.code) { + /*道路形态1*/ + var formWay = renderEntity.properties["formOfWay"] + if (formWay != null) { + when (formWay) { + "35" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM1_1.code - "37" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM1_2.code + "37" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM1_2.code - "38" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM1_3.code + "38" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM1_3.code + } } - } - } else if (renderEntity.code == DataCodeEnum.OMDB_LINK_FORM2.code) { - Log.e( - "qj", - "道路形态2${renderEntity.properties["formOfWay"]}" - ) - /*道路形态2*/ - var formWay = renderEntity.properties["formOfWay"] - if (formWay != null) { - when (formWay) { - "10" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_1.code - - "11" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_2.code - - "17" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_3.code - - "18" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_4.code - - "20" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_5.code - - "22" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_6.code - - "36" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_7.code - - "52" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_8.code - - "53" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_9.code - - "54" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_10.code - - "60" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_11.code - - "84" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_12.code - - "85" -> renderEntity.code = - DataCodeEnum.OMDB_LINK_FORM2_13.code - } - } - } else if (renderEntity.table == DataCodeEnum.OMDB_NODE_FORM.name) {//特殊处理,因为code相同,使用表名判断 - //过滤不需要渲染的要素 - var formOfWay = renderEntity.properties["formOfWay"] - if (formOfWay != null && formOfWay == "30") { - renderEntity.enable = 2 - renderEntity.code = - DataCodeEnum.OMDB_NODE_FORM.code - } else { + } else if (renderEntity.code == DataCodeEnum.OMDB_LINK_FORM2.code) { Log.e( "qj", - "过滤不显示数据${renderEntity.table}" + "道路形态2${renderEntity.properties["formOfWay"]}" ) - continue - } - } else if (renderEntity.table == DataCodeEnum.OMDB_NODE_PA.name) {//特殊处理,因为code相同,使用表名判断 - //过滤不需要渲染的要素 - var attributeType = - renderEntity.properties["attributeType"] - if (attributeType != null && attributeType == "30") { - renderEntity.enable = 2 - renderEntity.code = - DataCodeEnum.OMDB_NODE_PA.code - } else { - Log.e( - "qj", - "过滤不显示数据${renderEntity.table}" - ) - continue - } - } else if (renderEntity.code == DataCodeEnum.OMDB_LANE_CONSTRUCTION.code) { - //特殊处理空数据,渲染原则使用 - var startTime = renderEntity.properties["startTime"] - if (startTime == null || startTime == "") { - renderEntity.properties["startTime"] = "null" + /*道路形态2*/ + var formWay = renderEntity.properties["formOfWay"] + if (formWay != null) { + when (formWay) { + "10" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_1.code + + "11" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_2.code + + "17" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_3.code + + "18" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_4.code + + "20" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_5.code + + "22" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_6.code + + "36" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_7.code + + "52" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_8.code + + "53" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_9.code + + "54" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_10.code + + "60" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_11.code + + "84" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_12.code + + "85" -> renderEntity.code = + DataCodeEnum.OMDB_LINK_FORM2_13.code + } + } + } else if (renderEntity.table == DataCodeEnum.OMDB_NODE_FORM.name) {//特殊处理,因为code相同,使用表名判断 + //过滤不需要渲染的要素 + var formOfWay = renderEntity.properties["formOfWay"] + if (formOfWay != null && formOfWay == "30") { + renderEntity.enable = 2 + renderEntity.code = + DataCodeEnum.OMDB_NODE_FORM.code + } else { + Log.e( + "qj", + "过滤不显示数据${renderEntity.table}" + ) + continue + } + } else if (renderEntity.table == DataCodeEnum.OMDB_NODE_PA.name) {//特殊处理,因为code相同,使用表名判断 + //过滤不需要渲染的要素 + var attributeType = + renderEntity.properties["attributeType"] + if (attributeType != null && attributeType == "30") { + renderEntity.enable = 2 + renderEntity.code = + DataCodeEnum.OMDB_NODE_PA.code + } else { + Log.e( + "qj", + "过滤不显示数据${renderEntity.table}" + ) + continue + } + } else if (renderEntity.code == DataCodeEnum.OMDB_LANE_CONSTRUCTION.code) { + //特殊处理空数据,渲染原则使用 + var startTime = renderEntity.properties["startTime"] + if (startTime == null || startTime == "") { + renderEntity.properties["startTime"] = "null" + } } + listResult.add(renderEntity) } - listResult.add(renderEntity) + }catch ( e:Exception){ + } + } } } 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 180b7289..173cec11 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt @@ -18,7 +18,7 @@ class ImportPreProcess { val code2NameMap = Code2NameMap() lateinit var cacheRdLink: Map val defaultTranslateDistance = 3.0 - val testFlag:Boolean = true + val testFlag:Boolean = false fun checkCircleRoad(renderEntity: RenderEntity): Boolean { val linkInId = renderEntity.properties["linkIn"] val linkOutId = renderEntity.properties["linkOut"] 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 3fab9a26..db33d350 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 @@ -279,11 +279,8 @@ class MainActivity : BaseActivity() { viewModel.liveDataRoadName.observe(this) { if (it != null) { binding.mainActivityRoadName.text = it.properties["name"] - if (binding.mainActivityRoadName.visibility != View.VISIBLE) binding.mainActivityRoadName.visibility = - View.VISIBLE } else { - if (binding.mainActivityRoadName.visibility != View.GONE) binding.mainActivityRoadName.visibility = - View.GONE + binding.mainActivityRoadName.text = " " } } 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 0359e291..69af8dad 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 @@ -30,33 +30,36 @@ import com.navinfo.collect.library.garminvirbxe.HostBean import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.OnGeoPointClickListener import com.navinfo.collect.library.map.handler.* +import com.navinfo.collect.library.utils.DistanceUtil import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryToolsKt import com.navinfo.collect.library.utils.MapParamUtils import com.navinfo.omqs.Constant import com.navinfo.omqs.R -import com.navinfo.omqs.bean.ImportConfig -import com.navinfo.omqs.bean.QRCodeBean -import com.navinfo.omqs.bean.SignBean -import com.navinfo.omqs.bean.TraceVideoBean +import com.navinfo.omqs.bean.* 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.dialog.CommonDialog import com.navinfo.omqs.ui.manager.TakePhotoManager import com.navinfo.omqs.ui.other.BaseToast -import com.navinfo.omqs.util.SignUtil -import com.navinfo.omqs.util.DateTimeUtil -import com.navinfo.omqs.util.ShareUtil -import com.navinfo.omqs.util.SoundMeter -import com.navinfo.omqs.util.SpeakMode +import com.navinfo.omqs.util.* import dagger.hilt.android.lifecycle.HiltViewModel import io.realm.Realm import io.realm.RealmSet import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext +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.oscim.core.GeoPoint import org.oscim.core.MapPosition @@ -86,6 +89,9 @@ class MainViewModel @Inject constructor( private var mCameraDialog: CommonDialog? = null + //路径计算 + val liveDataPlanningPathStatus = MutableLiveData() + //地图点击捕捉到的质检数据ID列表 val liveDataQsRecordIdList = MutableLiveData>() @@ -210,16 +216,22 @@ class MainViewModel @Inject constructor( private var currentMapZoomLevel: Int = 0 + //导航信息 + private var naviEngine: NaviEngine = NaviEngine() + + // 定义一个互斥锁 + 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 = mapPosition } - if (mapController.mMapView.vtmMap.mapPosition.zoomLevel >= 16) { - } currentMapZoomLevel = mapController.mMapView.vtmMap.mapPosition.zoomLevel }) @@ -304,9 +316,46 @@ class MainViewModel @Inject constructor( sharedPreferences.registerOnSharedPreferenceChangeListener(this) 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()) + } + } + naviMutex.unlock() + } + } } + fun naviTestFlow(): Flow = flow { + + while (true) { + emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) + delay(1000) + } + } + /** * 获取当前任务 */ @@ -316,6 +365,146 @@ class MainViewModel @Inject constructor( val res = realm.where(TaskBean::class.java).equalTo("id", id).findFirst() if (res != null) { currentTaskBean = realm.copyFromRealm(res) + planningPath(currentTaskBean!!) + } + } + + + 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() + 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 { + + 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: 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 + } + } + //先找其实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 = pathList + mapController.lineHandler.showLine(naviEngine.geometry!!.toText()) + naviMutex.unlock() + } + } else { +// Toast.makeText(context, "数据未安装,无法计算导航路径", Toast.LENGTH_SHORT).show() } } @@ -360,7 +549,6 @@ class MainViewModel @Inject constructor( } - for (item in list) { mapController.markerHandle.addOrUpdateNoteMark(item) } @@ -619,13 +807,18 @@ class MainViewModel @Inject constructor( "properties['linkIn']", it ).findAll() if (entityList.isNotEmpty()) { - val outList = entityList.distinct() - for(i in outList.indices){ + val outList = entityList.distinct() + for (i in outList.indices) { val outLink = outList[i].properties["linkOut"] val linkOutEntity = - realmOperateHelper.getRealmTools(RenderEntity::class.java, true) + realmOperateHelper.getRealmTools( + RenderEntity::class.java, + true + ) .equalTo("table", DataCodeEnum.OMDB_RD_LINK.name).and() - .equalTo("properties['${RenderEntity.Companion.LinkTable.linkPid}']",outLink + .equalTo( + "properties['${RenderEntity.Companion.LinkTable.linkPid}']", + outLink ).findFirst() if (linkOutEntity != null) { mapController.lineHandler.linksLayer.addLine( @@ -633,7 +826,10 @@ class MainViewModel @Inject constructor( ) } } - mapController.lineHandler.linksLayer.addLine(link.geometry, Color.BLUE) + mapController.lineHandler.linksLayer.addLine( + link.geometry, + Color.BLUE + ) } } 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 c318a621..d9773ef2 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 @@ -11,15 +11,14 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.navinfo.collect.library.data.dao.impl.TraceDataBase -import com.navinfo.collect.library.data.entity.HadLinkDvoBean -import com.navinfo.collect.library.data.entity.NiLocation -import com.navinfo.collect.library.data.entity.QsRecordBean -import com.navinfo.collect.library.data.entity.TaskBean +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 @@ -146,7 +145,7 @@ class TaskViewModel @Inject constructor( } } } - }else { + } else { viewModelScope.launch(Dispatchers.IO) { val links = realmOperateHelper.queryLink( point = point, @@ -183,7 +182,7 @@ class TaskViewModel @Inject constructor( /** * 获取任务列表 */ - fun loadNetTaskList(context: Context){ + fun loadNetTaskList(context: Context) { viewModelScope.launch(Dispatchers.IO) { when (val result = networkService.getTaskList(Constant.USER_ID)) { is NetResult.Success -> { @@ -239,12 +238,12 @@ class TaskViewModel @Inject constructor( } is NetResult.Loading -> {} + else -> {} } } } - /** * 获取任务列表 */ @@ -281,7 +280,7 @@ class TaskViewModel @Inject constructor( * 设置当前选择的任务,并高亮当前任务的所有link */ - fun setSelectTaskBean(taskBean: TaskBean) { + fun setSelectTaskBean( taskBean: TaskBean) { sharedPreferences.edit().putInt(Constant.SELECT_TASK_ID, taskBean.id).apply() @@ -292,9 +291,10 @@ class TaskViewModel @Inject constructor( MapParamUtils.setTaskId(taskBean.id) mapController.layerManagerHandler.updateOMDBVectorTileLayer() mapController.mMapView.updateMap(true) - } + + private fun showTaskLinks(taskBean: TaskBean) { mapController.lineHandler.removeAllTaskLine() diff --git a/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt new file mode 100644 index 00000000..863ed36c --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/util/NaviEngine.kt @@ -0,0 +1,25 @@ +package com.navinfo.omqs.util + +import com.navinfo.collect.library.utils.GeometryTools +import com.navinfo.omqs.bean.Route +import org.locationtech.jts.geom.LineString +import org.oscim.core.GeoPoint + +class NaviEngine { + var geometry: LineString? = null + var routeList = mutableListOf() + get() { + return field + } + set(value) { + val list = mutableListOf() + list.addAll(value[0].pointList) + for (i in 1 until value.size) { + val list2 = value[i].pointList + list2.removeAt(0) + list.addAll(list2) + } + geometry = GeometryTools.createLineString(list) + field = value + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17a22bdf..81439ebf 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -102,7 +102,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginRight="@dimen/top_right_drawer_btns_mr" - app:constraint_referenced_ids="main_activity_note,main_activity_task_line,main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_distance,main_activity_menu" + app:constraint_referenced_ids="main_activity_add_new,main_activity_task_line,main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_distance,main_activity_menu" app:flow_horizontalGap="6dp" app:flow_wrapMode="aligned" app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment" @@ -113,7 +113,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" - app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_note,main_activity_task_line,main_activity_calc_distance" /> + app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_add_new,main_activity_task_line,main_activity_calc_distance" /> + android:onClick="@{()->mainActivity.voiceOnclick()}" + android:src="@drawable/icon_add_data" /> @@ -291,11 +290,11 @@ app:layout_constraintRight_toRightOf="@id/main_activity_map_update" /> @@ -305,8 +304,8 @@ android:layout_marginBottom="12dp" android:onClick="@{()->mainActivity.voiceOnclick()}" android:src="@drawable/icon_add_voice" - app:layout_constraintBottom_toTopOf="@id/main_activity_add_new" - app:layout_constraintRight_toRightOf="@id/main_activity_add_new" /> + app:layout_constraintBottom_toTopOf="@id/main_activity_note" + app:layout_constraintRight_toRightOf="@id/main_activity_note" /> + app:constraint_referenced_ids="main_activity_close_line,main_activity_select_line,main_activity_voice,main_activity_note" /> + app:constraint_referenced_ids="main_activity_close_line,main_activity_select_line,main_activity_voice,main_activity_note,main_activity_map_update,main_activity_zoom_in,main_activity_zoom_out,main_activity_geometry,main_activity_location" /> mContext.lifecycleScope.launch { @@ -212,6 +215,7 @@ private class MyLocationListener(callback: (BDLocation) -> Unit) : BDAbstractLoc val call = callback; override fun onReceiveLocation(location: BDLocation) { call(location) + Log.e("jingo", "定位结果:速度=" + location.speed +" 方向=" + location.direction) } } 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 02d1e1ff..4ac644d2 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 @@ -1,7 +1,12 @@ package com.navinfo.collect.library.utils; 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; @@ -14,6 +19,7 @@ import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.operation.linemerge.LineMerger; import org.oscim.core.GeoPoint; import org.oscim.map.Map; + import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; @@ -416,7 +422,7 @@ public class GeometryTools { Geometry startGeo = createGeometry(startGeoPoint); Geometry endGeo = createGeometry(endGeoPoint); double d = startGeo.distance(endGeo); - return convertDistanceToDegree(d,startGeoPoint.getLatitude()); + return convertDistanceToDegree(d, startGeoPoint.getLatitude()); } return 0; @@ -589,6 +595,21 @@ public class GeometryTools { return list; } + public static List getGeoPoints(Geometry geometry) { + List list = null; + if (geometry != null) { + Coordinate[] coordinates = geometry.getCoordinates(); + if (coordinates != null && coordinates.length > 0) { + list = new ArrayList(); + for (Coordinate coor : coordinates) { + list.add(new GeoPoint(coor.y, coor.x)); + } + } + } + return list; + } + + public static Coordinate[] getCoordinates(String str) { Coordinate[] coordinates = null; if (Check.isEmpty(str)) @@ -1294,6 +1315,8 @@ public class GeometryTools { } + + public enum SNAP_TYPE { /** * 像素 @@ -1327,7 +1350,7 @@ public class GeometryTools { } public static boolean isCheckError(double lon, double lat) { - if(lon==0||lat==0){ + if (lon == 0 || lat == 0) { return true; } @@ -1377,8 +1400,10 @@ public class GeometryTools { static class Check { public static boolean isEmpty(String str) { - if (str == null || str.isEmpty()) { - return true; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + if (str == null || str.isEmpty()) { + return true; + } } return false; } @@ -1446,7 +1471,7 @@ public class GeometryTools { switch (unit) { case SNAP_PIXEL: org.oscim.core.Point p = new org.oscim.core.Point(); - fMap.viewport().toScreenPoint(gp,false, p); + fMap.viewport().toScreenPoint(gp, false, p); GeoPoint gPLq = fMap.viewport().fromScreenPoint((float) p.x, (float) p.y); org.oscim.core.Point pL = new org.oscim.core.Point((p.x - distance), (p.y - distance)); @@ -1521,6 +1546,7 @@ public class GeometryTools { /** * 计算距离 + * * @param list * @return */ @@ -1573,10 +1599,68 @@ public class GeometryTools { * @return 对应的地理坐标系中的距离(单位:度) */ private static final double EARTH_RADIUS = 6371000.0; + public static double convertDistanceToDegree(double distance, double latitude) { double radianDistance = distance / EARTH_RADIUS; double radianLatitude = Math.toRadians(latitude); + double radianDegree = 2 * Math.asin(Math.sin(radianDistance / 2) / Math.cos(radianLatitude)); return Math.toDegrees(radianDegree); } + + /** + * 经纬度转墨卡托 + */ + public static Coordinate geoPointToMercator(GeoPoint point) { + Coordinate coordinate = new Coordinate(); + + double x = point.getLongitude() * 20037508.34 / 180; + double y = Math.log(Math.tan((90 + point.getLatitude()) * Math.PI / 360)) / (Math.PI / 180); + + y = y * 20037508.34 / 180; + + coordinate.x = x; + coordinate.y = y; + + return coordinate; + } + + /** + * 墨卡托转经纬度 + */ + public static GeoPoint mercatorToGeoPoint(Coordinate coordinate) { + GeoPoint point = null; + double x = coordinate.x / 20037508.34 * 180; + double y = coordinate.y / 20037508.34 * 180; + + y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2); + + point = new GeoPoint(y, x); + return point; + } + + public static List pointToLineDistance(GeoPoint point, List pointList) { + + Coordinate coordinate = geoPointToMercator(point); + Coordinate[] cs = new Coordinate[pointList.size()]; + + 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; + } } diff --git a/vtm b/vtm index facb2419..96981d22 160000 --- a/vtm +++ b/vtm @@ -1 +1 @@ -Subproject commit facb2419b710ea272eb9b06ebce2acf373ef6e73 +Subproject commit 96981d227d68df5cf4e6de000be5e9011557f69a