Conflicts:
	app/src/main/java/com/navinfo/omqs/util/SignUtil.kt
This commit is contained in:
qiji4215
2023-09-21 10:01:21 +08:00
23 changed files with 1291 additions and 552 deletions

View File

@@ -34,7 +34,8 @@
"name": "道路线", "name": "道路线",
"zoomMin": 15, "zoomMin": 15,
"zoomMax": 17, "zoomMax": 17,
"catch":true "catch":true,
"checkLinkId": true
}, },
"2002": { "2002": {
"table": "OMDB_RD_LINK_FUNCTION_CLASS", "table": "OMDB_RD_LINK_FUNCTION_CLASS",
@@ -262,6 +263,7 @@
"code": 3014, "code": 3014,
"name": "人行横道", "name": "人行横道",
"catch":true, "catch":true,
"checkLinkId": false,
"zoomMin": 18, "zoomMin": 18,
"zoomMax": 20 "zoomMax": 20
}, },

View File

@@ -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: RenderEntity? = null,
//路段总长
var length: Double = 0.0,
//当前link在整段路径中的起点
var startIndexInPath: Int = -1,
//当前link在整段路径中的终点
var endIndexIntPath: Int = -1,
var itemList: MutableList<NaviRouteItem>? = null
) {
var pointList: MutableList<GeoPoint> = 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
)

View File

@@ -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<GeoPoint> = mutableListOf()
get() {
return field
}
set(value) {
length = GeometryTools.getDistance(value)
field = value
}
}

View File

@@ -201,7 +201,7 @@ class RealmOperateHelper() {
var link: RenderEntity? = null var link: RenderEntity? = null
val realm = getSelectTaskRealmInstance() val realm = getSelectTaskRealmInstance()
val realmR = val realmR =
getSelectTaskRealmTools(RenderEntity::class.java, true).equalTo("table", "OMDB_RD_LINK_KIND") realm.where(RenderEntity::class.java).equalTo("table", "OMDB_RD_LINK_KIND")
.equalTo("properties['${LinkTable.linkPid}']", linkPid).findFirst() .equalTo("properties['${LinkTable.linkPid}']", linkPid).findFirst()
if (realmR != null) { if (realmR != null) {
link = realm.copyFromRealm(realmR) link = realm.copyFromRealm(realmR)
@@ -288,14 +288,14 @@ class RealmOperateHelper() {
.findAll() .findAll()
} else { } else {
// 查询realm中对应tile号的数据 // 查询realm中对应tile号的数据
if(Constant.CATCH_ALL){ if (Constant.CATCH_ALL) {
realmList = getSelectTaskRealmTools(RenderEntity::class.java, false) realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.greaterThanOrEqualTo("tileX", xStart) .greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd) .lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart) .greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd) .lessThanOrEqualTo("tileY", yEnd)
.findAll() .findAll()
}else{ } else {
realmList = getSelectTaskRealmTools(RenderEntity::class.java, false) realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.greaterThanOrEqualTo("tileX", xStart) .greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd) .lessThanOrEqualTo("tileX", xEnd)

View File

@@ -27,6 +27,7 @@ import com.blankj.utilcode.util.ClipboardUtils
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.navinfo.collect.library.data.entity.RenderEntity 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.NIMapController
import com.navinfo.collect.library.map.handler.MeasureLayerHandler import com.navinfo.collect.library.map.handler.MeasureLayerHandler
import com.navinfo.omqs.Constant 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.http.offlinemapdownload.OfflineMapDownloadManager
import com.navinfo.omqs.tools.LayerConfigUtils import com.navinfo.omqs.tools.LayerConfigUtils
import com.navinfo.omqs.ui.activity.BaseActivity 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.console.ConsoleFragment
import com.navinfo.omqs.ui.fragment.itemlist.ItemListFragment import com.navinfo.omqs.ui.fragment.itemlist.ItemListFragment
import com.navinfo.omqs.ui.fragment.offlinemap.OfflineMapFragment 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.other.BaseToast
import com.navinfo.omqs.ui.widget.RecyclerViewSpacesItemDecoration import com.navinfo.omqs.ui.widget.RecyclerViewSpacesItemDecoration
import com.navinfo.omqs.util.FlowEventBus import com.navinfo.omqs.util.FlowEventBus
import com.navinfo.omqs.util.NaviStatus
import com.navinfo.omqs.util.SignUtil import com.navinfo.omqs.util.SignUtil
import com.navinfo.omqs.util.SpeakMode import com.navinfo.omqs.util.SpeakMode
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@@ -66,6 +69,12 @@ class MainActivity : BaseActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private val viewModel by viewModels<MainViewModel>() private val viewModel by viewModels<MainViewModel>()
private val loadingDialog by lazy {
MaterialAlertDialogBuilder(
this,
com.google.android.material.R.style.MaterialAlertDialog_Material3_Animation
).setMessage("正在计算路线中...").setCancelable(false).show()
}
/** /**
* 左侧fragment * 左侧fragment
@@ -280,11 +289,10 @@ class MainActivity : BaseActivity() {
//道路绑定,名称变化 //道路绑定,名称变化
viewModel.liveDataRoadName.observe(this) { viewModel.liveDataRoadName.observe(this) {
if (it != null) { if (it != null) {
binding.mainActivityRoadName.text = it.properties["name"]
binding.mainActivityRoadName.visibility = View.VISIBLE binding.mainActivityRoadName.visibility = View.VISIBLE
binding.mainActivityRoadName.text = it.properties["name"]
} else { } else {
binding.mainActivityRoadName.text = " " binding.mainActivityRoadName.visibility = View.INVISIBLE
binding.mainActivityRoadName.visibility = View.GONE
} }
} }
@@ -327,7 +335,7 @@ class MainActivity : BaseActivity() {
7, RoundingMode.HALF_UP 7, RoundingMode.HALF_UP
) )
},${BigDecimal(it.latitude).setScale(7, RoundingMode.HALF_UP)}" },${BigDecimal(it.latitude).setScale(7, RoundingMode.HALF_UP)}"
if(Constant.AUTO_LOCATION){ if (Constant.AUTO_LOCATION) {
viewModel.startAutoLocationTimer() viewModel.startAutoLocationTimer()
} }
binding.mainActivityLocation.setImageResource(R.drawable.icon_location) binding.mainActivityLocation.setImageResource(R.drawable.icon_location)
@@ -336,8 +344,8 @@ class MainActivity : BaseActivity() {
Log.e("qj", "异常 $e") Log.e("qj", "异常 $e")
} }
} }
viewModel.liveDataAutoLocation.observe(this){ viewModel.liveDataAutoLocation.observe(this) {
if(it==true){ if (it == true) {
onClickLocation() onClickLocation()
} }
} }
@@ -416,8 +424,59 @@ class MainActivity : BaseActivity() {
} }
} }
viewModel.liveDataMessage.observe(this) {
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 -> {
}
}
}
viewModel.liveDataItemList.observe(this) { viewModel.liveDataItemList.observe(this) {
if(it.isNotEmpty()) { if (it.isNotEmpty()) {
if (leftFragment == null || leftFragment !is ItemListFragment) { if (leftFragment == null || leftFragment !is ItemListFragment) {
leftFragment = ItemListFragment { leftFragment = ItemListFragment {
binding.mainActivityLeftFragment.visibility = View.GONE binding.mainActivityLeftFragment.visibility = View.GONE
@@ -1101,7 +1160,7 @@ class MainActivity : BaseActivity() {
* 路径规划 * 路径规划
*/ */
fun onClickRouteFragment() { fun onClickRouteFragment() {
Toast.makeText(this, "功能开发中", Toast.LENGTH_SHORT).show() viewModel.planningPath()
} }
/** /**

View File

@@ -57,6 +57,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.locationtech.jts.geom.Geometry import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.LineString
import org.oscim.core.GeoPoint import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition import org.oscim.core.MapPosition
import org.oscim.map.Map import org.oscim.map.Map
@@ -86,7 +87,7 @@ class MainViewModel @Inject constructor(
private var mCameraDialog: CommonDialog? = null private var mCameraDialog: CommonDialog? = null
//路径计算 //路径计算
val liveDataPlanningPathStatus = MutableLiveData<Int>() val liveDataNaviStatus = MutableLiveData<NaviStatus>()
//地图点击捕捉到的质检数据ID列表 //地图点击捕捉到的质检数据ID列表
val liveDataQsRecordIdList = MutableLiveData<List<String>>() val liveDataQsRecordIdList = MutableLiveData<List<String>>()
@@ -119,6 +120,12 @@ class MainViewModel @Inject constructor(
*/ */
val liveDataItemList = MutableLiveData<List<RenderEntity>>() val liveDataItemList = MutableLiveData<List<RenderEntity>>()
/**
* 提示信息
*/
val liveDataMessage = MutableLiveData<String>()
private var traceTag: String = "TRACE_TAG" private var traceTag: String = "TRACE_TAG"
/** /**
@@ -196,9 +203,11 @@ class MainViewModel @Inject constructor(
/** /**
* 测量类型 * 测量类型
*/ */
var measuringType: MeasureLayerHandler.MEASURE_TYPE = var measuringType: MeasureLayerHandler.MEASURE_TYPE = MeasureLayerHandler.MEASURE_TYPE.DISTANCE
MeasureLayerHandler.MEASURE_TYPE.DISTANCE
/**
* 捕捉到的上一条link
*/
var linkIdCache = "" var linkIdCache = ""
private var lastNiLocaion: NiLocation? = null private var lastNiLocaion: NiLocation? = null
@@ -223,20 +232,19 @@ class MainViewModel @Inject constructor(
private var currentMapZoomLevel: Int = 0 private var currentMapZoomLevel: Int = 0
//导航信息 //导航信息
private var naviEngine: NaviEngine = NaviEngine() private var naviEngine: NaviEngine? = null
// 0:不导航 1导航 2暂停
private var naviEngineStatus = 0
// 定义一个互斥锁 // 定义一个互斥锁
private val naviMutex = Mutex() private val naviMutex = Mutex()
init { init {
mapController.mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition -> mapController.mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition ->
when (e) { when (e) {
Map.SCALE_EVENT, Map.MOVE_EVENT, Map.ROTATE_EVENT -> liveDataCenterPoint.value = Map.SCALE_EVENT, Map.MOVE_EVENT, Map.ROTATE_EVENT -> liveDataCenterPoint.value =
mapPosition mapPosition
//Map.CLEAR_EVENT->startAutoLocationTimer()
} }
currentMapZoomLevel = mapController.mMapView.vtmMap.mapPosition.zoomLevel currentMapZoomLevel = mapController.mMapView.vtmMap.mapPosition.zoomLevel
@@ -253,8 +261,7 @@ class MainViewModel @Inject constructor(
/** /**
* 处理点击道路捕捉回调功能 * 处理点击道路捕捉回调功能
*/ */
mapController.mMapView.addOnNIMapClickListener( mapController.mMapView.addOnNIMapClickListener(TAG,
TAG,
//处理地图点击操作 //处理地图点击操作
object : OnGeoPointClickListener { object : OnGeoPointClickListener {
override fun onMapClick(tag: String, point: GeoPoint) { override fun onMapClick(tag: String, point: GeoPoint) {
@@ -279,8 +286,7 @@ class MainViewModel @Inject constructor(
*/ */
object : OnQsRecordItemClickListener { object : OnQsRecordItemClickListener {
override fun onQsRecordList(tag: String, list: MutableList<String>) { override fun onQsRecordList(tag: String, list: MutableList<String>) {
if (tag == TAG) if (tag == TAG) liveDataQsRecordIdList.value = list
liveDataQsRecordIdList.value = list
} }
}, },
/** /**
@@ -288,8 +294,7 @@ class MainViewModel @Inject constructor(
*/ */
object : OnTaskLinkItemClickListener { object : OnTaskLinkItemClickListener {
override fun onTaskLink(tag: String, taskLinkId: String) { override fun onTaskLink(tag: String, taskLinkId: String) {
if (tag == TAG) if (tag == TAG) liveDataTaskLink.value = taskLinkId
liveDataTaskLink.value = taskLinkId
} }
}, },
/** /**
@@ -297,8 +302,7 @@ class MainViewModel @Inject constructor(
*/ */
object : ONNoteItemClickListener { object : ONNoteItemClickListener {
override fun onNote(tag: String, noteId: String) { override fun onNote(tag: String, noteId: String) {
if (tag == TAG) if (tag == TAG) liveDataNoteId.value = noteId
liveDataNoteId.value = noteId
} }
}, },
@@ -307,11 +311,9 @@ class MainViewModel @Inject constructor(
*/ */
object : OnNiLocationItemListener { object : OnNiLocationItemListener {
override fun onNiLocation(tag: String, index: Int, it: NiLocation) { override fun onNiLocation(tag: String, index: Int, it: NiLocation) {
if (tag == TAG) if (tag == TAG) liveDataNILocationList.value = it
liveDataNILocationList.value = it
} }
} })
)
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
getTaskBean() getTaskBean()
@@ -335,43 +337,26 @@ class MainViewModel @Inject constructor(
socketServer = SocketServer(mapController, traceDataBase, sharedPreferences) socketServer = SocketServer(mapController, traceDataBase, sharedPreferences)
// viewModelScope.launch(Dispatchers.Default) { // viewModelScope.launch(Dispatchers.Default) {
// naviTestFlow().collect { // naviTestFlow().collect { point ->
// naviMutex.lock() // if (naviEngineStatus == 1) {
// if (naviEngine.geometry != null) { // naviEngine?.let {
// //定义垂线 // naviMutex.lock()
// val pointPairDistance = PointPairDistance() // it.bindingRoute(null, point)
// val coordinate = Coordinate(it.longitude, it.latitude) // naviMutex.unlock()
// 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<GeoPoint> = flow { // fun naviTestFlow(): Flow<GeoPoint> = flow {
//
while (true) { // while (true) {
emit(mapController.mMapView.vtmMap.mapPosition.geoPoint) // emit(mapController.mMapView.vtmMap.mapPosition.geoPoint)
delay(1000) // delay(1000)
} // }
} // }
/** /**
* 获取当前任务 * 获取当前任务
@@ -382,147 +367,70 @@ class MainViewModel @Inject constructor(
val res = realm.where(TaskBean::class.java).equalTo("id", id).findFirst() val res = realm.where(TaskBean::class.java).equalTo("id", id).findFirst()
if (res != null) { if (res != null) {
currentTaskBean = realm.copyFromRealm(res) currentTaskBean = realm.copyFromRealm(res)
//planningPath(currentTaskBean!!)
} }
realm.close() realm.close()
} }
/**
* 规划路径
*/
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 {
private fun planningPath(taskBean: TaskBean) { override fun planningPathStatus(status: NaviStatus) {
if (taskBean.status == FileManager.Companion.FileDownloadStatus.DONE) { when (status) {
// Toast.makeText(context, "正在计算导航路径", Toast.LENGTH_SHORT).show() NaviStatus.NAVI_STATUS_PATH_PLANNING -> naviEngineStatus = 0
viewModelScope.launch(Dispatchers.Default) { NaviStatus.NAVI_STATUS_PATH_ERROR_NODE -> naviEngineStatus = 0
naviMutex.lock() NaviStatus.NAVI_STATUS_PATH_ERROR_DIRECTION -> naviEngineStatus = 0
naviEngine = NaviEngine() NaviStatus.NAVI_STATUS_PATH_ERROR_BLOCKED -> naviEngineStatus = 0
val pathList = mutableListOf<Route>() NaviStatus.NAVI_STATUS_PATH_SUCCESS -> naviEngineStatus = 1
val realm = realmOperateHelper.getSelectTaskRealmInstance() NaviStatus.NAVI_STATUS_DISTANCE_OFF -> {
for (link in taskBean.hadLinkDvoList) { }
//测线不参与导航 NaviStatus.NAVI_STATUS_DIRECTION_OFF -> {}
if (link.linkStatus == 3) { }
continue liveDataNaviStatus.postValue(status)
} }
val route = Route(
linkId = link.linkPid,
)
route.pointList = GeometryTools.getGeoPoints(link.geometry)
//查询每条link的snodeenode
val res1 = realm.where(RenderEntity::class.java)
.equalTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name).and()
.equalTo("properties['linkPid']", link.linkPid).findFirst()
res1?.let {
val snodePid = it.properties["snodePid"] override suspend fun bindingResults(
if (snodePid != null) { route: NaviRoute?,
route.sNode = snodePid list: List<NaviRouteItem>
} ) {
val enodePid = it.properties["enodePid"] val signList = mutableListOf<SignBean>()
if (enodePid != null) { for (naviRouteItem in list) {
route.eNode = enodePid
} val signBean = SignBean(
} iconId = SignUtil.getSignIcon(naviRouteItem.data),
//查询每条link的方向 iconText = SignUtil.getSignIconText(naviRouteItem.data),
val res2 = realm.where(RenderEntity::class.java) linkId = naviRouteItem.linkId,
.equalTo("table", DataCodeEnum.OMDB_LINK_DIRECT.name).and() distance = naviRouteItem.distance,
.equalTo("properties['linkPid']", link.linkPid).findFirst() name = SignUtil.getSignNameText(naviRouteItem.data),
res2?.let { bottomRightText = SignUtil.getSignBottomRightText(
val direct = it.properties["direct"] naviRouteItem.data
if (direct != null) { ),
route.direct = direct.toInt() renderEntity = naviRouteItem.data,
} isMoreInfo = SignUtil.isMoreInfo(naviRouteItem.data),
} index = SignUtil.getRoadInfoIndex(naviRouteItem.data)
//查询每条link的名称 )
val res3 = realm.where(RenderEntity::class.java) signList.add(signBean)
.equalTo("table", DataCodeEnum.OMDB_LINK_NAME.name).and()
.equalTo("properties['linkPid']", link.linkPid).findFirst()
res3?.let {
route.name = "${it.properties["name"]}"
}
pathList.add(route)
}
realm.close()
//用来存储最终的导航路径
val newRouteList = mutableListOf<Route>()
//比对路径排序用的
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 = ""
//如果snodeenode是顺方向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
} }
} if (route != null) {
//先找其实link的起始link liveDataRoadName.postValue(route.name)
var bHasLast = false captureTopSign(route)
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
} }
liveDataSignList.postValue(signList)
} }
if (tempRouteList.size == 0) { })
bBreak = false naviEngine!!.planningPath(currentTaskBean!!)
} else { } else {
if (!bHasLast && !bHasNext) { liveDataMessage.postValue("请先安装任务数据")
bBreak = false
//TODO 处理错误,路径不完整
}
}
}
}
naviEngine.routeList = newRouteList
naviMutex.unlock()
} }
} else { naviMutex.unlock()
// Toast.makeText(context, "数据未安装,无法计算导航路径", Toast.LENGTH_SHORT).show()
} }
} }
@@ -530,8 +438,11 @@ class MainViewModel @Inject constructor(
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
if (key == Constant.SELECT_TASK_ID) { if (key == Constant.SELECT_TASK_ID) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
naviMutex.lock()
naviEngineStatus = 0
getTaskBean() getTaskBean()
initQsRecordData() initQsRecordData()
naviMutex.unlock()
} }
} }
} }
@@ -544,8 +455,7 @@ class MainViewModel @Inject constructor(
var list = mutableListOf<QsRecordBean>() var list = mutableListOf<QsRecordBean>()
val realm = realmOperateHelper.getRealmDefaultInstance() val realm = realmOperateHelper.getRealmDefaultInstance()
realm.executeTransaction { realm.executeTransaction {
val objects = val objects = realmOperateHelper.getRealmTools(QsRecordBean::class.java).findAll()
realmOperateHelper.getRealmTools(QsRecordBean::class.java).findAll()
list = realm.copyFromRealm(objects) list = realm.copyFromRealm(objects)
} }
realm.close() realm.close()
@@ -634,8 +544,10 @@ class MainViewModel @Inject constructor(
//增加间距判断 //增加间距判断
if (lastNiLocaion != null) { if (lastNiLocaion != null) {
disance = GeometryTools.getDistance( disance = GeometryTools.getDistance(
location.latitude, location.longitude, location.latitude,
lastNiLocaion!!.latitude, lastNiLocaion!!.longitude location.longitude,
lastNiLocaion!!.latitude,
lastNiLocaion!!.longitude
) )
} }
//室内整理工具时不能进行轨迹存储判断轨迹间隔要超过2.5并小于60米 //室内整理工具时不能进行轨迹存储判断轨迹间隔要超过2.5并小于60米
@@ -649,18 +561,30 @@ class MainViewModel @Inject constructor(
} }
} }
/**
* 导航预警信息
*/
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
//用于定位点捕捉道路 //用于定位点捕捉道路
mapController.locationLayerHandler.niLocationFlow.collectLatest { location -> mapController.locationLayerHandler.niLocationFlow.collectLatest { location ->
if (!isSelectRoad() && !GeometryTools.isCheckError( if (!isSelectRoad() && !GeometryTools.isCheckError(
location.longitude, location.latitude location.longitude, location.latitude
) )
) { ) {
captureLink( if (naviEngine != null && naviEngineStatus == 1) {
GeoPoint( naviMutex.lock()
location.latitude, location.longitude val point = GeoPoint(location.latitude, location.longitude)
naviEngine!!.bindingRoute(location, point)
naviMutex.unlock()
} else {
captureLink(
GeoPoint(
location.latitude, location.longitude
)
) )
) }
} }
} }
} }
@@ -675,18 +599,17 @@ class MainViewModel @Inject constructor(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val itemList = realmOperateHelper.queryElement( val itemList = realmOperateHelper.queryElement(
GeometryTools.createPoint( GeometryTools.createPoint(
point.longitude, point.longitude, point.latitude
point.latitude
), ),
buffer = 3.2, catchAll = false, buffer = 3.2, catchAll = false,
) )
//增加道路线过滤原则 //增加道路线过滤原则
val filterResult = itemList.filter { val filterResult = itemList.filter {
if(isHighRoad()){ if (isHighRoad()) {
mapController.mMapView.mapLevel>=it.zoomMin&&mapController.mMapView.mapLevel<=it.zoomMax mapController.mMapView.mapLevel >= it.zoomMin && mapController.mMapView.mapLevel <= it.zoomMax
}else{ } else {
//关闭时过滤道路线捕捉s //关闭时过滤道路线捕捉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() }.toList()
if (filterResult.size == 1) { if (filterResult.size == 1) {
@@ -697,10 +620,114 @@ 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<SignBean>()
val topSignList = mutableListOf<SignBean>()
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) {
}
}
/** /**
* 捕获道路和面板 * 捕获道路和面板
*/ */
private suspend fun captureLink(point: GeoPoint) { private suspend fun captureLink(point: GeoPoint) {
if (captureLinkState) { if (captureLinkState) {
return return
} }
@@ -715,44 +742,52 @@ class MainViewModel @Inject constructor(
var hisRoadName = false var hisRoadName = false
if (linkList.isNotEmpty()) { if (linkList.isNotEmpty()) {
val link = linkList[0]
val linkId = link.properties[RenderEntity.Companion.LinkTable.linkPid]
//看板数据 //看板数据
val signList = mutableListOf<SignBean>() val signList = mutableListOf<SignBean>()
val topSignList = mutableListOf<SignBean>() val topSignList = mutableListOf<SignBean>()
mapController.lineHandler.linksLayer.clear() mapController.lineHandler.linksLayer.clear()
val link = linkList[0]
val linkId = link.properties[RenderEntity.Companion.LinkTable.linkPid]
if (linkIdCache != linkId) { if (linkIdCache != linkId) {
if (bSelectRoad)
mapController.markerHandle.addMarker(point, "selectLink")
mapController.lineHandler.showLine(link.geometry) mapController.lineHandler.showLine(link.geometry)
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 { linkId?.let {
var elementList = realmOperateHelper.queryLinkByLinkPid(it) var elementList = realmOperateHelper.queryLinkByLinkPid(it)
for (element in elementList) { for (element in elementList) {
if (element.code == DataCodeEnum.OMDB_LINK_NAME.code) { if (element.code == DataCodeEnum.OMDB_LINK_NAME.code) {
hisRoadName = true hisRoadName = true
liveDataRoadName.postValue(element) liveDataRoadName.postValue(element)
continue continue
} }
val distance = GeometryTools.distanceToDouble(
point, GeometryTools.createGeoPoint(element.geometry)
)
val signBean = SignBean( val signBean = SignBean(
iconId = SignUtil.getSignIcon(element), iconId = SignUtil.getSignIcon(element),
iconText = SignUtil.getSignIconText(element), iconText = SignUtil.getSignIconText(element),
distance = distance.toInt(),
linkId = linkId, linkId = linkId,
name = SignUtil.getSignNameText(element), name = SignUtil.getSignNameText(element),
bottomRightText = SignUtil.getSignBottomRightText(element), bottomRightText = SignUtil.getSignBottomRightText(element),
renderEntity = element, renderEntity = element,
isMoreInfo = SignUtil.isMoreInfo(element), isMoreInfo = SignUtil.isMoreInfo(element),
index = SignUtil.getRoadInfoIndex(element) index = SignUtil.getRoadInfoIndex(element),
distance = SignUtil.getDistance(
footAndDistance,
newLineString,
element
)
) )
Log.e("jingo", "捕捉到的数据code ${element.code}") // Log.e("jingo", "捕捉到的数据code ${element.code}")
when (element.code) { when (element.code) {
DataCodeEnum.OMDB_MULTI_DIGITIZED.code,//上下线分离 DataCodeEnum.OMDB_MULTI_DIGITIZED.code,//上下线分离
DataCodeEnum.OMDB_CON_ACCESS.code,//全封闭 DataCodeEnum.OMDB_CON_ACCESS.code,//全封闭
@@ -797,7 +832,6 @@ class MainViewModel @Inject constructor(
-> topSignList.add( -> topSignList.add(
signBean signBean
) )
DataCodeEnum.OMDB_SPEEDLIMIT.code,//常规点限速 DataCodeEnum.OMDB_SPEEDLIMIT.code,//常规点限速
DataCodeEnum.OMDB_SPEEDLIMIT_COND.code,//条件点限速 DataCodeEnum.OMDB_SPEEDLIMIT_COND.code,//条件点限速
DataCodeEnum.OMDB_SPEEDLIMIT_VAR.code,//可变点限速 DataCodeEnum.OMDB_SPEEDLIMIT_VAR.code,//可变点限速
@@ -806,26 +840,23 @@ class MainViewModel @Inject constructor(
DataCodeEnum.OMDB_LANEINFO.code,//车信 DataCodeEnum.OMDB_LANEINFO.code,//车信
DataCodeEnum.OMDB_WARNINGSIGN.code,//危险信息 DataCodeEnum.OMDB_WARNINGSIGN.code,//危险信息
DataCodeEnum.OMDB_TOLLGATE.code,//收费站 DataCodeEnum.OMDB_TOLLGATE.code,//收费站
-> signList.add( -> {
signBean signList.add(
) signBean
)
}
} }
} }
val realm = realmOperateHelper.getSelectTaskRealmInstance() val realm = realmOperateHelper.getSelectTaskRealmInstance()
val entityList = val entityList = realmOperateHelper.getSelectTaskRealmTools(
realmOperateHelper.getSelectTaskRealmTools( RenderEntity::class.java, true
RenderEntity::class.java, ).and().equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name).and()
true .equalTo(
) "properties['linkIn']", it
.and() ).findAll()
.equalTo("table", DataCodeEnum.OMDB_RESTRICTION.name)
.and()
.equalTo(
"properties['linkIn']", it
).findAll()
if (entityList.isNotEmpty()) { if (entityList.isNotEmpty()) {
val outList = entityList.distinct() val outList = entityList.distinct()
for (i in outList.indices) { for (i in outList.indices) {
@@ -835,7 +866,8 @@ class MainViewModel @Inject constructor(
RenderEntity::class.java, RenderEntity::class.java,
true true
) )
.equalTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name).and() .equalTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name)
.and()
.equalTo( .equalTo(
"properties['${RenderEntity.Companion.LinkTable.linkPid}']", "properties['${RenderEntity.Companion.LinkTable.linkPid}']",
outLink outLink
@@ -847,8 +879,7 @@ class MainViewModel @Inject constructor(
} }
} }
mapController.lineHandler.linksLayer.addLine( mapController.lineHandler.linksLayer.addLine(
link.geometry, link.geometry, Color.BLUE
Color.BLUE
) )
realm.close() realm.close()
} }
@@ -1029,7 +1060,7 @@ class MainViewModel @Inject constructor(
* */ * */
fun refreshOMDBLayer(layerConfigList: List<ImportConfig>) { fun refreshOMDBLayer(layerConfigList: List<ImportConfig>) {
// 根据获取到的配置信息,筛选未勾选的图层名称 // 根据获取到的配置信息,筛选未勾选的图层名称
if (layerConfigList != null && !layerConfigList.isEmpty()) { if (layerConfigList != null && layerConfigList.isNotEmpty()) {
val omdbVisibleList = mutableListOf<String>() val omdbVisibleList = mutableListOf<String>()
layerConfigList.forEach { layerConfigList.forEach {
omdbVisibleList.addAll(it.tableMap.filter { entry -> omdbVisibleList.addAll(it.tableMap.filter { entry ->
@@ -1057,6 +1088,12 @@ class MainViewModel @Inject constructor(
linkIdCache = "" linkIdCache = ""
mapController.lineHandler.removeLine() mapController.lineHandler.removeLine()
liveDataSignList.value = mutableListOf() liveDataSignList.value = mutableListOf()
mapController.markerHandle.removeMarker("selectLink")
if (bSelectRoad && naviEngineStatus == 1) {
naviEngineStatus = 2
} else if (naviEngineStatus == 2) {
naviEngineStatus = 1
}
} }
/** /**
@@ -1146,9 +1183,7 @@ class MainViewModel @Inject constructor(
} }
fun sendServerCommand( fun sendServerCommand(
context: Context, context: Context, traceVideoBean: TraceVideoBean, indoorToolsCommand: IndoorToolsCommand
traceVideoBean: TraceVideoBean,
indoorToolsCommand: IndoorToolsCommand
) { ) {
if (TextUtils.isEmpty(Constant.INDOOR_IP)) { if (TextUtils.isEmpty(Constant.INDOOR_IP)) {
@@ -1162,8 +1197,7 @@ class MainViewModel @Inject constructor(
val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/${traceVideoBean.command}?" val url = "http://${Constant.INDOOR_IP}:8080/sensor/service/${traceVideoBean.command}?"
when (val result = networkService.sendServerCommand( when (val result = networkService.sendServerCommand(
url = url, url = url, traceVideoBean = traceVideoBean
traceVideoBean = traceVideoBean
)) { )) {
is NetResult.Success<*> -> { is NetResult.Success<*> -> {
@@ -1176,9 +1210,7 @@ class MainViewModel @Inject constructor(
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
context, context, "命令成功。", Toast.LENGTH_LONG
"命令成功。",
Toast.LENGTH_LONG
).show() ).show()
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS) liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_SUCCESS)
@@ -1188,8 +1220,7 @@ class MainViewModel @Inject constructor(
//启动双向控制服务 //启动双向控制服务
if (socketServer != null && socketServer!!.isServerClose) { if (socketServer != null && socketServer!!.isServerClose) {
socketServer!!.connect( socketServer!!.connect(
Constant.INDOOR_IP, Constant.INDOOR_IP, this@MainViewModel
this@MainViewModel
) )
} }
@@ -1200,8 +1231,7 @@ class MainViewModel @Inject constructor(
context, context,
"命令无效${defaultUserResponse.errmsg}", "命令无效${defaultUserResponse.errmsg}",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
) ).show()
.show()
} }
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
} }
@@ -1209,9 +1239,7 @@ class MainViewModel @Inject constructor(
} catch (e: IOException) { } catch (e: IOException) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
context, context, "${e.message}", Toast.LENGTH_SHORT
"${e.message}",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
@@ -1221,11 +1249,8 @@ class MainViewModel @Inject constructor(
is NetResult.Error<*> -> { is NetResult.Error<*> -> {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
context, context, "${result.exception.message}", Toast.LENGTH_SHORT
"${result.exception.message}", ).show()
Toast.LENGTH_SHORT
)
.show()
} }
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
} }
@@ -1233,11 +1258,8 @@ class MainViewModel @Inject constructor(
is NetResult.Failure<*> -> { is NetResult.Failure<*> -> {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
context, context, "${result.code}:${result.msg}", Toast.LENGTH_SHORT
"${result.code}:${result.msg}", ).show()
Toast.LENGTH_SHORT
)
.show()
} }
liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE) liveIndoorToolsResp.postValue(IndoorToolsResp.QR_CODE_STATUS_UPDATE_VIDEO_INFO_FAILURE)
} }
@@ -1260,8 +1282,7 @@ class MainViewModel @Inject constructor(
if (niLocation != null) { if (niLocation != null) {
mapController.markerHandle.addMarker( mapController.markerHandle.addMarker(
GeoPoint( GeoPoint(
niLocation.latitude, niLocation.latitude, niLocation.longitude
niLocation.longitude
), traceTag, "", niLocation as java.lang.Object ), traceTag, "", niLocation as java.lang.Object
) )
} }
@@ -1299,9 +1320,7 @@ class MainViewModel @Inject constructor(
override fun onConnect(success: Boolean) { override fun onConnect(success: Boolean) {
if (!success && socketServer != null) { if (!success && socketServer != null) {
BaseToast.makeText( BaseToast.makeText(
mapController.mMapView.context, mapController.mMapView.context, "轨迹反向控制服务失败,请确认连接是否正常!", Toast.LENGTH_SHORT
"轨迹反向控制服务失败,请确认连接是否正常!",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
@@ -1330,9 +1349,7 @@ class MainViewModel @Inject constructor(
Log.e("qj", "反向控制$currentIndexNiLocation") Log.e("qj", "反向控制$currentIndexNiLocation")
} else { } else {
BaseToast.makeText( BaseToast.makeText(
mapController.mMapView.context, mapController.mMapView.context, "没有找到对应轨迹点!", Toast.LENGTH_SHORT
"没有找到对应轨迹点!",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
@@ -1376,8 +1393,7 @@ class MainViewModel @Inject constructor(
startTimer() startTimer()
} }
} else { } else {
Toast.makeText(mapController.mMapView.context, "无数据了!", Toast.LENGTH_LONG) Toast.makeText(mapController.mMapView.context, "无数据了!", Toast.LENGTH_LONG).show()
.show()
cancelTrace() cancelTrace()
} }
} }
@@ -1394,13 +1410,13 @@ class MainViewModel @Inject constructor(
/** /**
* 开启自动定位 * 开启自动定位
*/ */
fun startAutoLocationTimer(){ fun startAutoLocationTimer() {
if (autoLocationTimer != null) { if (autoLocationTimer != null) {
cancelAutoLocation() cancelAutoLocation()
} }
autoLocationTimer = fixedRateTimer("", false, disAutoLocationTime, disAutoLocationTime) { autoLocationTimer = fixedRateTimer("", false, disAutoLocationTime, disAutoLocationTime) {
liveDataAutoLocation.postValue(true) liveDataAutoLocation.postValue(true)
Log.e("qj","自动定位开始执行") Log.e("qj", "自动定位开始执行")
startAutoLocationTimer() startAutoLocationTimer()
} }
} }
@@ -1473,9 +1489,7 @@ class MainViewModel @Inject constructor(
} else { } else {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
mapController.mMapView.context, mapController.mMapView.context, "未查询到数据", Toast.LENGTH_SHORT
"未查询到数据",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
@@ -1498,9 +1512,7 @@ class MainViewModel @Inject constructor(
} else { } else {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
Toast.makeText( Toast.makeText(
mapController.mMapView.context, mapController.mMapView.context, "未查询到数据", Toast.LENGTH_SHORT
"未查询到数据",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }
@@ -1517,9 +1529,7 @@ class MainViewModel @Inject constructor(
dialog.dismiss() dialog.dismiss()
} else { } else {
Toast.makeText( Toast.makeText(
mapController.mMapView.context, mapController.mMapView.context, "输入格式不正确", Toast.LENGTH_SHORT
"输入格式不正确",
Toast.LENGTH_SHORT
).show() ).show()
} }
} }

View File

@@ -79,6 +79,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
val bd = holder.viewBinding val bd = holder.viewBinding
if (item.iconId != 0) { if (item.iconId != 0) {
bd.signMainIconBg.visibility = View.VISIBLE
if (item.renderEntity.code == DataCodeEnum.OMDB_WARNINGSIGN.code) { if (item.renderEntity.code == DataCodeEnum.OMDB_WARNINGSIGN.code) {
try { try {
var typeCode = "${item.iconId}" var typeCode = "${item.iconId}"
@@ -110,6 +111,8 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
} else { } else {
bd.signMainIconBg.setImageResource(item.iconId) bd.signMainIconBg.setImageResource(item.iconId)
} }
}else{
bd.signMainIconBg.visibility = View.INVISIBLE
} }
bd.signMainIcon.text = item.iconText bd.signMainIcon.text = item.iconText
@@ -128,6 +131,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
} else { } else {
bd.signMainInfo.visibility = View.GONE bd.signMainInfo.visibility = View.GONE
} }
bd.signDistanceText.text = "${item.distance}"
bd.signSecondIcon.text = "" bd.signSecondIcon.text = ""
if (item.renderEntity.code == DataCodeEnum.OMDB_SPEEDLIMIT.code) { if (item.renderEntity.code == DataCodeEnum.OMDB_SPEEDLIMIT.code) {
val minSpeed = SignUtil.getSpeedLimitMinText(item.renderEntity) val minSpeed = SignUtil.getSpeedLimitMinText(item.renderEntity)
@@ -143,7 +147,7 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
val bd = holder.viewBinding val bd = holder.viewBinding
bd.signMoreIconsLayout.removeAllViews() bd.signMoreIconsLayout.removeAllViews()
bd.signBottomText.text = item.name bd.signBottomText.text = item.name
bd.signBottomRightText.text = item.distance.toString() bd.signBottomRightText.text = "${item.distance}"
val list = SignUtil.getLineInfoIcons(item.renderEntity) val list = SignUtil.getLineInfoIcons(item.renderEntity)
val lineViewS = View(context) val lineViewS = View(context)
lineViewS.layoutParams = ViewGroup.LayoutParams(24, 80) lineViewS.layoutParams = ViewGroup.LayoutParams(24, 80)
@@ -215,13 +219,13 @@ class SignAdapter(private var listener: OnSignAdapterClickListener?) :
holder.tag = item.name + position holder.tag = item.name + position
} }
override fun refreshData(newData: List<SignBean>) { // override fun refreshData(newData: List<SignBean>) {
super.refreshData(newData) // super.refreshData(newData)
for (i in newData.indices) { //// ?这是要干嘛 for (i in newData.indices) {
if (selectMoreInfoTag == newData[i].name + i) { //// if (selectMoreInfoTag == newData[i].name + i) {
return //// return
} //// }
} //// }
} // }
} }

View File

@@ -166,7 +166,7 @@ class PersonalCenterFragment(private var indoorDataListener: ((Boolean) -> Unit?
// 定位到指定位置 // 定位到指定位置
niMapController.mMapView.vtmMap.animator() niMapController.mMapView.vtmMap.animator()
// .animateTo(GeoPoint( 40.05108004733645, 116.29187746293708 )) // .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 -> { R.id.personal_center_menu_open_all_layer -> {

View File

@@ -152,6 +152,7 @@ class TaskListAdapter(
if (taskBean.status == FileDownloadStatus.DONE) { if (taskBean.status == FileDownloadStatus.DONE) {
binding.taskDownloadBtn.visibility = View.INVISIBLE binding.taskDownloadBtn.visibility = View.INVISIBLE
binding.taskUploadBtn.visibility = View.VISIBLE binding.taskUploadBtn.visibility = View.VISIBLE
} else { } else {
binding.taskDownloadBtn.visibility = View.VISIBLE binding.taskDownloadBtn.visibility = View.VISIBLE
binding.taskUploadBtn.visibility = View.INVISIBLE binding.taskUploadBtn.visibility = View.INVISIBLE

View File

@@ -7,6 +7,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.navinfo.omqs.R 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.taskdownload.TaskDownloadManager
import com.navinfo.omqs.http.taskupload.TaskUploadManager import com.navinfo.omqs.http.taskupload.TaskUploadManager
import com.navinfo.omqs.tools.FileManager 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.fragment.BaseFragment
import com.navinfo.omqs.ui.other.shareViewModels import com.navinfo.omqs.ui.other.shareViewModels
import com.yanzhenjie.recyclerview.SwipeMenuCreator import com.yanzhenjie.recyclerview.SwipeMenuCreator
@@ -58,9 +61,6 @@ class TaskListFragment : BaseFragment() {
Toast.makeText(context, "正在校验", Toast.LENGTH_SHORT).show() Toast.makeText(context, "正在校验", Toast.LENGTH_SHORT).show()
viewModel.checkUploadTask(binding.root.context, taskBean) viewModel.checkUploadTask(binding.root.context, taskBean)
} }
else -> {
}
} }
} }
} }

View File

@@ -12,18 +12,15 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.navinfo.collect.library.data.dao.impl.TraceDataBase import com.navinfo.collect.library.data.dao.impl.TraceDataBase
import com.navinfo.collect.library.data.entity.* 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.NIMapController
import com.navinfo.collect.library.map.OnGeoPointClickListener import com.navinfo.collect.library.map.OnGeoPointClickListener
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.MapParamUtils import com.navinfo.collect.library.utils.MapParamUtils
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
import com.navinfo.omqs.bean.Route
import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.db.RealmOperateHelper
import com.navinfo.omqs.http.NetResult import com.navinfo.omqs.http.NetResult
import com.navinfo.omqs.http.NetworkService import com.navinfo.omqs.http.NetworkService
import com.navinfo.omqs.tools.FileManager 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.ui.dialog.FirstDialog
import com.navinfo.omqs.util.DateTimeUtil import com.navinfo.omqs.util.DateTimeUtil
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel

View File

@@ -1,25 +1,623 @@
package com.navinfo.omqs.util 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.collect.library.utils.GeometryTools
import com.navinfo.omqs.bean.Route import com.navinfo.omqs.bean.NaviRoute
import com.navinfo.omqs.bean.NaviRouteItem
import com.navinfo.omqs.db.RealmOperateHelper
import io.realm.Realm
import org.locationtech.jts.geom.LineString import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Point
import org.oscim.core.GeoPoint import org.oscim.core.GeoPoint
class NaviEngine { public interface OnNaviEngineCallbackListener {
fun planningPathStatus(code: NaviStatus)
// fun planningPathError(errorCode: NaviStatus, errorMessage: String)
suspend fun bindingResults(route: NaviRoute?, list: List<NaviRouteItem>)
}
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(
private val niMapController: NIMapController,
private val realmOperateHelper: RealmOperateHelper,
val callback: OnNaviEngineCallbackListener
) {
/**
* 要查询的要素列表
*/
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_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 = 15
/**
* 偏离次数上限
*/
private val DEVIATION_COUNT = 5
/**
* 局部匹配时走过的路段还记录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 geometry: LineString? = null
var routeList = mutableListOf<Route>()
/**
* 临时路径
*/
var tempGeometry: LineString? = null
/**
* 定位点集合
*/
private var locationList: MutableList<NiLocation> = mutableListOf()
/**
* 局部匹配时的路段
*/
var tempRoutList = mutableListOf<NaviRoute>()
/**
* 所有路段集合
*/
var routeList = mutableListOf<NaviRoute>()
get() { get() {
return field return field
} }
set(value) { set(value) {
val list = mutableListOf<GeoPoint>() val list = mutableListOf<GeoPoint>()
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) { 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) list2.removeAt(0)
list.addAll(list2) list.addAll(list2)
} }
geometry = GeometryTools.createLineString(list) geometry = GeometryTools.createLineString(list)
field = value field = value
} }
/**
* 计算路径
*/
suspend fun planningPath(taskBean: TaskBean) {
callback.planningPathStatus(NaviStatus.NAVI_STATUS_PATH_PLANNING)
val pathList = mutableListOf<NaviRoute>()
val realm = realmOperateHelper.getSelectTaskRealmInstance()
for (link in taskBean.hadLinkDvoList) {
//测线不参与导航
if (link.linkStatus == 3) {
continue
}
val route = NaviRoute(
linkId = link.linkPid,
)
route.pointList = GeometryTools.getGeoPoints(link.geometry)
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)
}
}
}
}
if (!bHasNode) {
callback.planningPathStatus(
NaviStatus.NAVI_STATUS_PATH_ERROR_NODE
)
return
}
if (!bHasDir) {
callback.planningPathStatus(
NaviStatus.NAVI_STATUS_PATH_ERROR_DIRECTION
)
return
}
pathList.add(route)
}
//用来存储最终的导航路径
val newRouteList = mutableListOf<NaviRoute>()
//比对路径排序用的
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 = ""
//如果sNodeeNode是顺方向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.planningPathStatus(
NaviStatus.NAVI_STATUS_PATH_ERROR_BLOCKED
)
realm.close()
return
}
}
}
}
val itemMap: MutableMap<GeoPoint, MutableList<RenderEntity>> = mutableMapOf()
//查询每根link上的关联要素
for (route in newRouteList) {
itemMap.clear()
//常规点限速
val res = realm.where(RenderEntity::class.java)
.equalTo("properties['linkPid']", route.linkId).and().`in`(
"table",
QUERY_KEY_ITEM_LIST
).findAll()
if (res.isNotEmpty()) {
// Log.e("jingo", "道路查询预警要素 ${route.linkId} ${res.size}条数据")
for (r in res) {
// Log.e("jingo", "道路查询预警要素 ${r.name}")
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)
}
itemMap.remove(point)
}
}
route.itemList!!.sortBy { it.index }
}
}
realm.close()
routeList = newRouteList
callback.planningPathStatus(NaviStatus.NAVI_STATUS_PATH_SUCCESS)
}
/**
* 将要素绑定到路径上
*/
private fun insertItemToRoute(
realm: Realm,
route: NaviRoute,
res: RenderEntity?,
itemMap: MutableMap<GeoPoint, MutableList<RenderEntity>>
) {
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
)
//测试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))
} 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))
}
}
}
}
/**
* 绑定道路
*/
suspend 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()
}
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
// )
matchingItem()
if (lastRouteIndex != routeIndex) {
createTempPath()
}
errorCount = 0
break
}
}
} else {
deviationUp()
}
}
}
}
/**
* 匹配要素
* @point:定位点
*/
private suspend fun matchingItem() {
if (routeIndex > -1 && tempRoutList.isNotEmpty() && tempGeometry != null) {
Log.e("jingo", "当前${routeIndex} ${tempRoutList[0].startIndexInPath} $footIndex")
//道路前方一定距离范围内的要素信息
val bindingItemList = mutableListOf<NaviRouteItem>()
//定位点到要素的路径距离
var distance = 0.0
//计算要素路径距离的点集合
val disPoints = mutableListOf(footPoint!!)
//下一个要素的起点游标
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!!) {
// 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 + 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)
} else {
break
}
}
}
if (distance >= FARTHEST_DISPLAY_DISTANCE) {
break
}
}
}
callback.bindingResults(currentRoute, 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<GeoPoint>()
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) {
callback.planningPathStatus(NaviStatus.NAVI_STATUS_DISTANCE_OFF)
bindingReset()
}
}
/**
* 绑定重置
*/
private fun bindingReset() {
//绑定失败次数
errorCount = 0
//当前邦定的那段route
routeIndex = -1
//当前绑定的link上哪个point
footIndex = -1
//上一次定位绑到路线的距离
lastDistance = -1
//垂足坐标
footPoint = null
//定位点集合
locationList.clear()
}
} }

View File

@@ -1,9 +1,10 @@
package com.navinfo.omqs.util package com.navinfo.omqs.util
import android.provider.ContactsContract.Data
import android.util.Log import android.util.Log
import com.navinfo.collect.library.data.entity.RenderEntity import com.navinfo.collect.library.data.entity.RenderEntity
import com.navinfo.collect.library.enums.DataCodeEnum 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.R
import com.navinfo.omqs.bean.RoadNameBean import com.navinfo.omqs.bean.RoadNameBean
import com.navinfo.omqs.bean.SignBean 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 com.navinfo.omqs.ui.fragment.signMoreInfo.TwoItemAdapterItem
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Point
import org.oscim.core.GeoPoint
import java.lang.reflect.Field import java.lang.reflect.Field
class SignUtil { class SignUtil {
@@ -808,32 +813,32 @@ class SignUtil {
DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> { DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> {
var color = data.properties["color"] var color = data.properties["color"]
if (color != null) { if (color != null) {
when(color){ when (color) {
"0"->{ "0" -> {
return "颜色:未验证" return "颜色:未验证"
} }
"1"->{ "1" -> {
return "颜色:白色" return "颜色:白色"
} }
"2"->{ "2" -> {
return "颜色:黄色" return "颜色:黄色"
} }
"3"->{ "3" -> {
return "颜色:红色" return "颜色:红色"
} }
"5"->{ "5" -> {
return "颜色:棕色" return "颜色:棕色"
} }
"6"->{ "6" -> {
return "颜色:蓝色" return "颜色:蓝色"
} }
"7"->{ "7" -> {
return "颜色:绿色" return "颜色:绿色"
} }
"8"->{ "8" -> {
return "颜色:黑色" return "颜色:黑色"
} }
"9"->{ "9" -> {
return "颜色:其他" return "颜色:其他"
} }
} }
@@ -1065,7 +1070,8 @@ class SignUtil {
DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> { DataCodeEnum.OMDB_TRAFFIC_SIGN.code -> {
var trafsignShape = data.properties["trafsignShape"] var trafsignShape = data.properties["trafsignShape"]
if (trafsignShape != null) { 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 getResId(trafsignShape, R.drawable::class.java)
} }
return 0 return 0
@@ -1645,5 +1651,54 @@ class SignUtil {
return list return list
} }
/**
* 计算捕捉点到
*/
fun getDistance(
footAndDistance: FootAndDistance,
lineString: Geometry,
element: RenderEntity
): Int {
val itemGeometry = GeometryTools.createGeometry(element.geometry)
if (itemGeometry is Point) {
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) {
dis.toInt()
} else {
-dis.toInt()
}
} 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) {
dis.toInt()
} else {
-dis.toInt()
}
}
return 0
}
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -29,16 +29,29 @@
android:textColor="#2F2F2F" android:textColor="#2F2F2F"
android:textSize="16sp" /> android:textSize="16sp" />
<TextView
android:id="@+id/sign_distance_text"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignRight="@id/sign_main_bg"
android:layout_marginTop="4dp"
android:layout_marginRight="19dp"
android:gravity="center"
android:text="范围外"
android:textColor="#3736DB"
android:textSize="16sp" />
<TextView <TextView
android:id="@+id/sign_second_icon" android:id="@+id/sign_second_icon"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:gravity="center"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_toRightOf="@id/sign_main_icon" android:layout_toRightOf="@id/sign_main_icon"
android:gravity="center"
android:text="" android:text=""
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16sp" /> android:textSize="16sp" />
<TextView <TextView
android:id="@+id/sign_bottom_text" android:id="@+id/sign_bottom_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -69,8 +82,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignBottom="@id/sign_main_bg" android:layout_alignBottom="@id/sign_main_bg"
android:layout_marginLeft="2dp" android:layout_marginLeft="2dp"
android:padding="4dp"
android:layout_toRightOf="@id/sign_main_bg" android:layout_toRightOf="@id/sign_main_bg"
android:padding="4dp"
android:src="@drawable/icon_sign_info" android:src="@drawable/icon_sign_info"
android:visibility="gone" /> android:visibility="gone" />
@@ -81,7 +94,7 @@
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginLeft="172dp" android:layout_marginLeft="172dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:visibility="gone" android:background="@drawable/icon_evaluation"
android:background="@drawable/icon_evaluation" /> android:visibility="gone" />
</RelativeLayout> </RelativeLayout>

View File

@@ -260,6 +260,8 @@
<xs:attribute name="gland" default="true" type="xs:boolean" use="optional"/> <xs:attribute name="gland" default="true" type="xs:boolean" use="optional"/>
<!-- 原图标旋转角度默认情况下应该使用以X轴为正方向的图标此处可设置原图标的旋转角度在渲染时自动对图标进行旋转仅支持线要素 --> <!-- 原图标旋转角度默认情况下应该使用以X轴为正方向的图标此处可设置原图标的旋转角度在渲染时自动对图标进行旋转仅支持线要素 -->
<xs:attribute name="degree" default="0" type="xs:float" use="optional"/> <xs:attribute name="degree" default="0" type="xs:float" use="optional"/>
<!-- 图标在y轴方向上的偏移量 -->
<xs:attribute name="dy" default="0" type="xs:float" use="optional"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="extrusion"> <xs:complexType name="extrusion">

View File

@@ -1568,7 +1568,7 @@
<!-- 交通标牌 --> <!-- 交通标牌 -->
<m v="OMDB_TRAFFIC_SIGN"> <m v="OMDB_TRAFFIC_SIGN">
<symbol repeat="false" repeat-gap="2000" repeat-start="0" rotate="true" <symbol repeat="false" repeat-gap="2000" repeat-start="0" rotate="true"
src="@src" symbol-height="24" symbol-width="24" degree="-90"></symbol> src="@src" symbol-height="24" symbol-width="24" degree="-90" dy="-30"></symbol>
</m> </m>
<m v="OMDB_AREA"> <m v="OMDB_AREA">

View File

@@ -10,7 +10,7 @@ abstract class BaseHandler(context: AppCompatActivity, mapView: NIMapView) {
protected val mMapView: NIMapView = mapView protected val mMapView: NIMapView = mapView
fun addLayer(layer: Layer, groupType: NIMapView.LAYER_GROUPS) { fun addLayer(layer: Layer, groupType: NIMapView.LAYER_GROUPS) {
Log.e("jingo", "增加了图层 ${layer.toString()}") // Log.e("jingo", "增加了图层 ${layer.toString()}")
mMapView.vtmMap.layers().add( mMapView.vtmMap.layers().add(
layer, layer,
groupType.groupIndex groupType.groupIndex

View File

@@ -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.map.layers.OmdbTaskLinkLayer
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import org.oscim.android.canvas.AndroidBitmap import org.oscim.android.canvas.AndroidBitmap
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.ItemizedLayer import org.oscim.layers.marker.ItemizedLayer
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface import org.oscim.layers.marker.MarkerInterface
@@ -112,6 +113,18 @@ class LineHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(
layer layer
} }
/**
* 高亮一条线
*/
fun showLine(list:List<GeoPoint>) {
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(
} }
} }
/** /**
* 取消高亮线 * 取消高亮线
*/ */

View File

@@ -77,7 +77,7 @@ public class OMDBDataDecoder extends TileDecoder {
properties.putAll(renderEntity.getProperties()); properties.putAll(renderEntity.getProperties());
parseGeometry(renderEntity.getTable(), renderEntity.getWkt(), properties); parseGeometry(renderEntity.getTable(), renderEntity.getWkt(), properties);
}else{ }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());
} }
} }
}); });

View File

@@ -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<Coordinate> {
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)
}
}
}

View File

@@ -4,9 +4,6 @@ import android.graphics.Point;
import android.os.Build; import android.os.Build;
import android.util.Log; 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.Coordinate;
import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.GeometryFactory;
@@ -446,148 +443,15 @@ public class GeometryTools {
} }
public static GeoPoint getLineStringCenter(String lineString) { public static double distanceToDouble(Geometry startGeoPoint, Geometry endGeoPoint) {
List<GeoPoint> points = getGeoPoints(lineString); if (startGeoPoint != null && endGeoPoint != null) {
return getLineStringCenter(points); double d = startGeoPoint.distance(endGeoPoint);
return convertDistanceToDegree(d, startGeoPoint.getCoordinate().y);
}
return 0;
} }
public static GeoPoint getLineStringCenter(List<GeoPoint> 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<Double> dList = new ArrayList<Double>();
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<GeoPoint> 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<Double> dList = new ArrayList<Double>();
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, * LINESTRING (116.4206899999999933 39.9620999999999995,
@@ -1160,39 +1024,6 @@ public class GeometryTools {
return null; return null;
} }
/**
* 点与几何最近点位置
*
* @param list
* @param geoPoint
* @return geopoint
* @author qiji
*/
public static GeoPoint getZuijinGeoPoint(List<GeoPoint> 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) { public static String GeometryFormatDouble5(String geometry) {
try { try {
@@ -1333,8 +1164,6 @@ public class GeometryTools {
} }
public enum SNAP_TYPE { public enum SNAP_TYPE {
/** /**
* 像素 * 像素
@@ -1570,7 +1399,7 @@ public class GeometryTools {
*/ */
public static double getDistance(List<GeoPoint> list) { public static double getDistance(List<GeoPoint> list) {
if (list.size() < 2) { if (list.size() < 2) {
return 0; return -1;
} }
double dis = 0; double dis = 0;
for (int i = 0; i < list.size() - 1; i++) { for (int i = 0; i < list.size() - 1; i++) {
@@ -1618,6 +1447,12 @@ public class GeometryTools {
*/ */
private static final double EARTH_RADIUS = 6371000.0; private static final double EARTH_RADIUS = 6371000.0;
/**
* 距离转米
* @param distance
* @param latitude
* @return
*/
public static double convertDistanceToDegree(double distance, double latitude) { public static double convertDistanceToDegree(double distance, double latitude) {
double radianDistance = distance / EARTH_RADIUS; double radianDistance = distance / EARTH_RADIUS;
double radianLatitude = Math.toRadians(latitude); double radianLatitude = Math.toRadians(latitude);
@@ -1669,28 +1504,13 @@ public class GeometryTools {
return point; return point;
} }
public static List<GeoPoint> pointToLineDistance(GeoPoint point, List<GeoPoint> pointList) {
Coordinate coordinate = geoPointToMercator(point); public static FootAndDistance pointToLineDistance(GeoPoint point, Geometry geometry) {
Coordinate[] cs = new Coordinate[pointList.size()]; //定义垂线
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++) { return pointPairDistance;
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<GeoPoint>();
for (int i = 0; i < pointPairDistance.getCoordinates().length; i++) {
newPoints.add(mercatorToGeoPoint(pointPairDistance.getCoordinate(i)));
}
return newPoints;
} }
} }

2
vtm

Submodule vtm updated: 3d9400fb6a...719c44b65d