Commit 7ea96217 authored by pxl's avatar pxl
Browse files

以车为矩形,求全局路径的焦点

parent 6c616198
......@@ -20,7 +20,7 @@ android {
ndk {
// abiFilters.addAll(listOf("x86_64", "arm64-v8a"))
abiFilters.addAll(listOf("arm64-v8a"))
abiFilters.addAll(listOf("arm64-v8a","x86_64"))
}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
......@@ -50,6 +50,21 @@ android {
abortOnError = false
checkReleaseBuilds = false
}
packaging {
jniLibs {
excludes.add("META-INF/*******")
excludes.add("plugin.xml")
}
resources {
excludes.addAll(
listOf(
"META-INF/*******",
"META-INF/INDEX.LIST",
"META-INF/io.netty.versions.properties"
)
)
}
}
applicationVariants.all {
outputs.all {
if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
......@@ -84,11 +99,18 @@ dependencies {
//屏幕适配
implementation("com.github.JessYanCoding:AndroidAutoSize:v1.2.1")
//用于坐标重投影的Proj.4库的Java端口
implementation("org.locationtech.proj4j:proj4j:1.4.1")
// https://mvnrepository.com/artifact/org.locationtech.proj4j/proj4j-epsg
implementation("org.locationtech.proj4j:proj4j-epsg:1.3.0")// 包含EPSG定义
// implementation("org.locationtech.proj4j:proj4j:1.4.1")
// // https://mvnrepository.com/artifact/org.locationtech.proj4j/proj4j-epsg
// implementation("org.locationtech.proj4j:proj4j-epsg:1.3.0")// 包含EPSG定义
//sm4 加密
implementation("org.bouncycastle:bcprov-jdk15on:1.70")
// GeoTools
implementation("org.geotools:gt-main:33.1"){
exclude("org.eclipse.emf", "*")
}
// implementation("org.geotools:gt-referencing:21.1") {
// exclude("org.eclipse.emf", "*")
// }
implementation("com.google.protobuf:protobuf-java:4.31.1")
// implementation("com.google.protobuf:protobuf-javalite:4.31.1")CRSFactory
......
package com.sd.cavphmi
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.gson.Gson
import com.minedata.minenavi.mapdal.LatLng
import com.minedata.minenavi.util.Tools
import com.sd.cavphmi.bean.AvpStatuBean
import com.sd.cavphmi.bean.CarVehicle
import com.sd.cavphmi.bean.mock.MRoutes
import com.sd.cavphmi.utils.FileIoUtils
import com.sd.cavphmi.utils.Proj4jCoord
import com.sd.cavphmi.utils.SM4CryptoHelper
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
......@@ -37,49 +41,38 @@ class ExampleInstrumentedTest {
}
@Test
fun calculateTouYing() {
fun calculateTouYing2() {
// 02runTest
TestScope(UnconfinedTestDispatcher()).launch {
var gson = Gson()
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
var str =
FileIoUtils.getAsset(appContext, "mock/Car_fangzhen.txt") //Qgis里取的点和四维取得点混合
val mRoutes = gson.fromJson<MRoutes>(str, MRoutes::class.java)
//获取全局路径
var avpDatas = mutableListOf<String>()
FileIoUtils.getAssetMock(appContext.applicationContext, "mock/shiche/avp_status_call.txt", avpDatas)
var str = avpDatas.first()
val statu = gson.fromJson<AvpStatuBean>(str, AvpStatuBean::class.java)
//转换小弟提路径点
var sLatLngs = statu.drivenDecision.trajectory.points.map {
Tools.latLngToPoint(LatLng(it.latitude, it.longitude))
}.toTypedArray()
println("-------------sLatLngs = ${sLatLngs}")
//点传线段
val testPoint = mutableListOf<List<Double>>()
// val testPoint = doubleArrayOf(116.38810256578773, 39.92848759523565) // 北海公园
val testPoint = mutableListOf<DoubleArray>()
//车辆位姿
var carDatas = mutableListOf<String>()
FileIoUtils.getAssetMock(appContext, "mock/shiche/CarVehicle_Call.txt", carDatas)
// 坐标点串 (02坐标系)
val coordinateSeries = mutableListOf<DoubleArray>()
mRoutes.rs.forEachIndexed { index, it ->
var tLng = it[0]
var tLag = it[1]
if (index in 0..50) {
tLng = tLng + 0.00001 * index
tLag = tLag + 0.00001 * index
coordinateSeries.add(doubleArrayOf(tLng, tLag))
} else {
tLng = tLng + 0.000001 * index
tLag = tLag - 0.000001 * index
coordinateSeries.add(doubleArrayOf(tLng, tLag))
carDatas.forEach { str ->
val cCar = gson.fromJson<CarVehicle>(str, CarVehicle::class.java)
if (cCar.vehiclePos != null) {
delay(300)
}
// coordinateSeries.add(doubleArrayOf(tLng, tLag))
testPoint.add(doubleArrayOf(it[0], it[1]))
}
// coordinateSeries.add(doubleArrayOf(116.38811674159075, 39.93087909844135))
// coordinateSeries.add(doubleArrayOf(116.38513982313117, 39.928482159906224))
// coordinateSeries.add(doubleArrayOf(116.38808130208565, 39.928291923094065))
// coordinateSeries.add(doubleArrayOf(116.39202682873122, 39.92837661180238))
// val testPoint = doubleArrayOf(116.38810256578773, 39.92848759523565) // 北海公园
// val testPoint = mutableListOf<DoubleArray>()
// 计算投影
// double[] result = CoordinateProjectionUtils.calculatePointProjection(testPoint, coordinateSeries);
testPoint.forEachIndexed { index, it ->
// val result = Proj4jCoord.calculatePointProjection(it, coordinateSeries)
// println("车当前下标: (" + index + ") " + "车当前位置:" + it[0] + " " + it[1] + " 最近线段索引: " + result[2].toInt())
// println("投影点坐标: (" + result[0] + ", " + result[1] + ")")
// println("最近线段索引: " + result[2].toInt())
// println("最小距离: " + result[3] + " 米")
}
}
......
......@@ -157,7 +157,6 @@
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502479,39.809175,57.94189453125],"routing":[],"progress":17.851668803740097}
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502482,39.809176,58.11767578125],"routing":[],"progress":17.851668803740097}
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502485,39.809178,58.16162109375],"routing":[],"progress":17.851668803740097}
[{"deviceId":"DW15-XJQJ-001-045","intersectionCode":"yz-15","reportTime":1764212754158,"accessTime":1764212754762,"receiveTime":0,"participants":[{"ptcId":"12073","ptcType":"car","longitude":116.50280352244955,"latitude":39.80892902993889,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12199","ptcType":"car","longitude":116.5026728354027,"latitude":39.808972912673745,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11543","ptcType":"car","longitude":116.50263454240961,"latitude":39.80914144000592,"heading":57.64426040649414,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11741","ptcType":"car","longitude":116.5027574321414,"latitude":39.808986960319004,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11542","ptcType":"car","longitude":116.50256069044845,"latitude":39.80891867788518,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13444","ptcType":"car","longitude":116.50266949043878,"latitude":39.80878400788523,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13846","ptcType":"car","longitude":116.50261907167797,"latitude":39.809160796296396,"heading":58.7477912902832,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11540","ptcType":"car","longitude":116.50291121904414,"latitude":39.80879379404847,"heading":59.078330993652344,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11547","ptcType":"car","longitude":116.50266902894238,"latitude":39.80899359999985,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11545","ptcType":"car","longitude":116.50264929240828,"latitude":39.809122890005916,"heading":57.64426040649414,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11544","ptcType":"car","longitude":116.50259100044575,"latitude":39.80888115788519,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12831","ptcType":"car","longitude":116.50275042281662,"latitude":39.80917998352133,"heading":239.0422821044922,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13842","ptcType":"car","longitude":116.50283001217039,"latitude":39.809081234361564,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11748","ptcType":"car","longitude":116.50263792075117,"latitude":39.80882307750339,"heading":57.98255920410156,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11902","ptcType":"car","longitude":116.50295271248211,"latitude":39.80892897397477,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11548","ptcType":"car","longitude":116.50268014246065,"latitude":39.80908411993883,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13729","ptcType":"car","longitude":116.50287553187466,"latitude":39.80902475474727,"heading":239.0604705810547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11550","ptcType":"car","longitude":116.50269536214698,"latitude":39.80906499031898,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11670","ptcType":"car","longitude":116.50291936247787,"latitude":39.808987603974806,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11553","ptcType":"car","longitude":116.50270404509297,"latitude":39.80893375305483,"heading":237.6903533935547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11552","ptcType":"car","longitude":116.50271170183275,"latitude":39.80904445069962,"heading":57.633811950683594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11673","ptcType":"car","longitude":116.50283382244685,"latitude":39.808890929938904,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11557","ptcType":"car","longitude":116.50273472540826,"latitude":39.80889527267371,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11556","ptcType":"car","longitude":116.50274171245512,"latitude":39.80900671993886,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11875","ptcType":"car","longitude":116.50278258216612,"latitude":39.80914008436159,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11555","ptcType":"car","longitude":116.50271926540687,"latitude":39.808914662673715,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11830","ptcType":"car","longitude":116.50266476214972,"latitude":39.80910345031898,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11637","ptcType":"car","longitude":116.50257575044711,"latitude":39.80890003788518,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11559","ptcType":"car","longitude":116.50274986540963,"latitude":39.80887628267371,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11561","ptcType":"car","longitude":116.50278061541238,"latitude":39.80883771267369,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11560","ptcType":"car","longitude":116.50278808245095,"latitude":39.80894842993889,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12775","ptcType":"car","longitude":116.50253081045109,"latitude":39.808955657885164,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13302","ptcType":"car","longitude":116.50265402044015,"latitude":39.808803147885214,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11883","ptcType":"car","longitude":116.50284933244545,"latitude":39.808871439938905,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11965","ptcType":"car","longitude":116.50259531044398,"latitude":39.808856487885194,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11569","ptcType":"car","longitude":116.50277288276477,"latitude":39.80896753955845,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11800","ptcType":"car","longitude":116.50286065217314,"latitude":39.80904321436156,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11921","ptcType":"car","longitude":116.50293650217856,"latitude":39.80896867436153,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11887","ptcType":"car","longitude":116.50290049221708,"latitude":39.809010770096634,"heading":51.22670364379883,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13785","ptcType":"car","longitude":116.50284529217177,"latitude":39.809062274361565,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11568","ptcType":"car","longitude":116.50298282218414,"latitude":39.8088916143615,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11842","ptcType":"car","longitude":116.50286455275652,"latitude":39.808852299558495,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11567","ptcType":"car","longitude":116.50294889248053,"latitude":39.80895075397479,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11885","ptcType":"car","longitude":116.50272715276887,"latitude":39.809025009558425,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11922","ptcType":"car","longitude":116.50296815218282,"latitude":39.8089098343615,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11807","ptcType":"car","longitude":116.5027958651012,"latitude":39.80881858305479,"heading":237.6903533935547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11770","ptcType":"car","longitude":116.50276508541099,"latitude":39.8088571926737,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11532","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11774","ptcType":"car","longitude":116.502814592169,"latitude":39.80910037436157,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12068","ptcType":"car","longitude":116.50260985044267,"latitude":39.80883826788521,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11536","ptcType":"car","longitude":116.50282752863292,"latitude":39.80877926326007,"heading":237.9940185546875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11535","ptcType":"car","longitude":116.50281140541513,"latitude":39.80879908267367,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11534","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11533","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11775","ptcType":"car","longitude":116.50279852246823,"latitude":39.80912031397485,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11539","ptcType":"car","longitude":116.50289659570291,"latitude":39.80881243644724,"heading":58.447410583496094,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11538","ptcType":"car","longitude":116.50288008213037,"latitude":39.808832790319094,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11537","ptcType":"car","longitude":116.50284161976174,"latitude":39.80876134465391,"heading":238.91062927246094,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11619","ptcType":"car","longitude":116.50281863244821,"latitude":39.808910029938886,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0}],"statistic":{"bus":0,"heavy_truck":0,"truck":0,"bike":0,"unknown":0,"motorcycle":0,"car":59,"suv":0,"police_car":0,"midibus":0,"electric_bicycle":0,"conical_barrel":0,"micro_truck":0,"spillage":0,"small_truck":0,"engine_emergency":0,"pickup":0,"ambulance":0,"tank_truck":0,"large_truck":0,"mpv":0,"fire_truck":0,"concrete_mixer":0,"minibus":0,"pedestrian":0,"tricycle":0}}]
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502488,39.809179,58.238525390625],"routing":[],"progress":18.08269849953993}
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502491,39.80918,58.392333984375],"routing":[],"progress":18.410517400177167}
{"businessStatus":"PARKING","spaceName":"B002","vehiclePos":[116.502493,39.809182,58.414306640625],"routing":[],"progress":18.494778231282748}
......@@ -943,7 +942,6 @@
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.502461,39.809118,115.982666015625],"routing":[],"progress":null}
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.502463,39.809117,116.861572265625],"routing":[],"progress":null}
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.502465,39.809117,117.630615234375],"routing":[],"progress":null}
[{"deviceId":"DW15-XJQJ-001-045","intersectionCode":"yz-15","reportTime":1764212927417,"accessTime":1764212927774,"receiveTime":0,"participants":[{"ptcId":"12073","ptcType":"car","longitude":116.50280352244955,"latitude":39.80892902993889,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13882","ptcType":"car","longitude":116.50277217,"latitude":39.80916155,"heading":239.05372619628906,"speed":0.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12199","ptcType":"car","longitude":116.5026728354027,"latitude":39.808972912673745,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11543","ptcType":"car","longitude":116.50263454240961,"latitude":39.80914144000592,"heading":57.64426040649414,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11741","ptcType":"car","longitude":116.5027574321414,"latitude":39.808986960319004,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11542","ptcType":"car","longitude":116.50256069044845,"latitude":39.80891867788518,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13444","ptcType":"car","longitude":116.50266949043878,"latitude":39.80878400788523,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13846","ptcType":"car","longitude":116.50261907167797,"latitude":39.809160796296396,"heading":58.7477912902832,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11540","ptcType":"car","longitude":116.50291121904414,"latitude":39.80879379404847,"heading":59.078330993652344,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11547","ptcType":"car","longitude":116.50265825508887,"latitude":39.80899119305486,"heading":237.6903533935547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11545","ptcType":"car","longitude":116.50264929240828,"latitude":39.809122890005916,"heading":57.64426040649414,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11544","ptcType":"car","longitude":116.50259100044575,"latitude":39.80888115788519,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11748","ptcType":"car","longitude":116.50263792075117,"latitude":39.80882307750339,"heading":57.98255920410156,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11902","ptcType":"car","longitude":116.50295271248211,"latitude":39.80892897397477,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11548","ptcType":"car","longitude":116.50268014246065,"latitude":39.80908411993883,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13729","ptcType":"car","longitude":116.50287553187466,"latitude":39.80902475474727,"heading":239.0604705810547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11550","ptcType":"car","longitude":116.50269536214698,"latitude":39.80906499031898,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11670","ptcType":"car","longitude":116.50291936247787,"latitude":39.808987603974806,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11553","ptcType":"car","longitude":116.50270404509297,"latitude":39.80893375305483,"heading":237.6903533935547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11552","ptcType":"car","longitude":116.50271170183275,"latitude":39.80904445069962,"heading":57.633811950683594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11673","ptcType":"car","longitude":116.50283382244685,"latitude":39.808890929938904,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11557","ptcType":"car","longitude":116.50273472540826,"latitude":39.80889527267371,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13896","ptcType":"car","longitude":116.50268856540413,"latitude":39.80895317267374,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11556","ptcType":"car","longitude":116.50274171245512,"latitude":39.80900671993886,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11875","ptcType":"car","longitude":116.50278258216612,"latitude":39.80914008436159,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11555","ptcType":"car","longitude":116.50271926540687,"latitude":39.808914662673715,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11830","ptcType":"car","longitude":116.50266476214972,"latitude":39.80910345031898,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11637","ptcType":"car","longitude":116.50257575044711,"latitude":39.80890003788518,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11559","ptcType":"car","longitude":116.50274986540963,"latitude":39.80887628267371,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11561","ptcType":"car","longitude":116.50278061541238,"latitude":39.80883771267369,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11560","ptcType":"car","longitude":116.50278808245095,"latitude":39.80894842993889,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12775","ptcType":"car","longitude":116.50253081045109,"latitude":39.808955657885164,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13302","ptcType":"car","longitude":116.50265402044015,"latitude":39.808803147885214,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11883","ptcType":"car","longitude":116.50284933244545,"latitude":39.808871439938905,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11965","ptcType":"car","longitude":116.50259531044398,"latitude":39.808856487885194,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11569","ptcType":"car","longitude":116.50277288276477,"latitude":39.80896753955845,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11800","ptcType":"car","longitude":116.50286065217314,"latitude":39.80904321436156,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11921","ptcType":"car","longitude":116.50293650217856,"latitude":39.80896867436153,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11887","ptcType":"car","longitude":116.50290049221708,"latitude":39.809010770096634,"heading":51.22670364379883,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13785","ptcType":"car","longitude":116.50284529217177,"latitude":39.809062274361565,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11568","ptcType":"car","longitude":116.50298282218414,"latitude":39.8088916143615,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11842","ptcType":"car","longitude":116.50286455275652,"latitude":39.808852299558495,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11567","ptcType":"car","longitude":116.50294889248053,"latitude":39.80895075397479,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11885","ptcType":"car","longitude":116.50272715276887,"latitude":39.809025009558425,"heading":57.6510009765625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11922","ptcType":"car","longitude":116.50296815218282,"latitude":39.8089098343615,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11807","ptcType":"car","longitude":116.5027958651012,"latitude":39.80881858305479,"heading":237.6903533935547,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11770","ptcType":"car","longitude":116.50276508541099,"latitude":39.8088571926737,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"13310","ptcType":"pedestrian","longitude":116.50299249,"latitude":39.80901095,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11532","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11774","ptcType":"car","longitude":116.502814592169,"latitude":39.80910037436157,"heading":239.05474853515625,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"12068","ptcType":"car","longitude":116.50260985044267,"latitude":39.80883826788521,"heading":57.976829528808594,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11536","ptcType":"car","longitude":116.50282752863292,"latitude":39.80877926326007,"heading":237.9940185546875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11535","ptcType":"car","longitude":116.50281140541513,"latitude":39.80879908267367,"heading":237.6846160888672,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11534","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11533","ptcType":"car","longitude":116.50168582895532,"latitude":39.80914664999986,"heading":90.0,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11775","ptcType":"car","longitude":116.50279852246823,"latitude":39.80912031397485,"heading":239.04901123046875,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11539","ptcType":"car","longitude":116.50289659570291,"latitude":39.80881243644724,"heading":58.447410583496094,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11538","ptcType":"car","longitude":116.50288008213037,"latitude":39.808832790319094,"heading":57.63954544067383,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11537","ptcType":"car","longitude":116.50284161976174,"latitude":39.80876134465391,"heading":238.91062927246094,"speed":1.0,"elevation":0.0,"gear":0,"color":0},{"ptcId":"11619","ptcType":"car","longitude":116.50281863244821,"latitude":39.808910029938886,"heading":57.64527130126953,"speed":1.0,"elevation":0.0,"gear":0,"color":0}],"statistic":{"bus":0,"heavy_truck":0,"truck":0,"bike":0,"unknown":0,"motorcycle":0,"car":59,"suv":0,"police_car":0,"midibus":0,"electric_bicycle":0,"conical_barrel":0,"micro_truck":0,"spillage":0,"small_truck":0,"engine_emergency":0,"pickup":0,"ambulance":0,"tank_truck":0,"large_truck":0,"mpv":0,"fire_truck":0,"concrete_mixer":0,"minibus":0,"pedestrian":1,"tricycle":0}}]
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.502467,39.809116,118.223876953125],"routing":[],"progress":null}
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.502468,39.809115,118.663330078125],"routing":[],"progress":null}
{"businessStatus":"DRIVING","spaceName":null,"vehiclePos":[116.50247,39.809114,118.992919921875],"routing":[],"progress":null}
......
......@@ -23,8 +23,8 @@ package com.sd.cavphmi.bean
class CarVehicle {
val businessStatus: String = ""
val progress: Any = ""
val routing: List<Any>? = null
// val progress: Any = ""
// val routing: List<Any>? = null
val spaceName: String = ""
//vehiclePos 里面分别是 经度、纬度、航向角
......
......@@ -299,7 +299,7 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
}
//显示车辆位姿UI
private fun showVehicle(car: CarVehicle?) {
private fun showVehicle(car: CarVehicle) {
if (car == null)
return
if (car.vehiclePos == null || car.vehiclePos.count() < 3)
......@@ -313,6 +313,8 @@ class MainActivity : BaseActivity<ActivityMainBinding, MyBaseViewModel>() {
mapOpt.drawSmallCar(car)
//刷新右下角小车位置
mapOpt.showNavingCarPosition(car)
//生成车前方矩形
mapOpt.genFronArea(car)
//刷新右下角小地图路径
mapOpt.upSmallMapLine(car)
// println("----car.heading ${car.heading}")
......
package com.sd.cavphmi.utils
import kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
import kotlin.math.PI
object GeoRectangleUtils {
/**
* 根据中心点、宽度和高度生成矩形(米为单位)
*/
fun createRectangleFromCenter(
centerLng: Double,
centerLat: Double,
widthMeters: Double = 6.0,
heightMeters: Double = 8.0
): List<List<Double>> {
val halfWidth = widthMeters / 2
val halfHeight = heightMeters / 2
// 计算四个角点
val topLeft = calculateDestinationPoint(
centerLng,
centerLat,
315.0,
sqrt(halfWidth * halfWidth + halfHeight * halfHeight)
)
val topRight = calculateDestinationPoint(
centerLng,
centerLat,
45.0,
sqrt(halfWidth * halfWidth + halfHeight * halfHeight)
)
val bottomRight = calculateDestinationPoint(
centerLng,
centerLat,
135.0,
sqrt(halfWidth * halfWidth + halfHeight * halfHeight)
)
val bottomLeft = calculateDestinationPoint(
centerLng,
centerLat,
225.0,
sqrt(halfWidth * halfWidth + halfHeight * halfHeight)
)
return listOf(topLeft, topRight, bottomRight, bottomLeft, topLeft) // 闭合
}
// 矩形尺寸:半宽1000米,半高500米
// 方向:45°(东北方向)
fun generateCenterRect(
centerLng: Double,
centerLat: Double,
direction: Double,
halfWidth: Double = 2.0,
halfHeight: Double = 5.0
): List<List<Double>> {
// 将方向角转换为数学角度(逆时针从x轴正方向)
val angleRad = Math.toRadians(90 - direction)
// 计算四个顶点的偏移量(米)
val offsets = listOf(
// 右上顶点
Pair(
halfWidth * cos(angleRad) - halfHeight * sin(angleRad),
halfWidth * sin(angleRad) + halfHeight * cos(angleRad)
),
// 右下顶点
Pair(
halfWidth * cos(angleRad) + halfHeight * sin(angleRad),
halfWidth * sin(angleRad) - halfHeight * cos(angleRad)
),
// 左下顶点
Pair(
-halfWidth * cos(angleRad) + halfHeight * sin(angleRad),
-halfWidth * sin(angleRad) - halfHeight * cos(angleRad)
),
// 左上顶点
Pair(
-halfWidth * cos(angleRad) - halfHeight * sin(angleRad),
-halfWidth * sin(angleRad) + halfHeight * cos(angleRad)
),
// 右上顶点
Pair(
halfWidth * cos(angleRad) - halfHeight * sin(angleRad),
halfWidth * sin(angleRad) + halfHeight * cos(angleRad)
),
)
// 将米偏移量转换为经纬度坐标
var ps = offsets.map { (dx, dy) ->
metersToGeoPoint(centerLng, centerLat, dx, dy)
}
return ps
}
/**
* 将米单位的偏移量转换为经纬度坐标
*/
private fun metersToGeoPoint(
centerLng: Double,
centerLat: Double, dx: Double, dy: Double
): List<Double> {
// 地球半径(米)
val EARTH_RADIUS = 6378137.0
val latRad = Math.toRadians(centerLat)
// 纬度每度对应的米数
val latPerMeter = 1.0 / (PI * EARTH_RADIUS / 180.0)
// 经度每度对应的米数(随纬度变化)
val lonPerMeter = 1.0 / (PI * EARTH_RADIUS * cos(latRad) / 180.0)
val newLat = centerLat + dy * latPerMeter
val newLon = centerLng + dx * lonPerMeter
return listOf(newLon, newLat)
}
/**
* 根据前方点和方向生成矩形
*/
fun createRectangleInFront(
frontPoint: List<Double>,
bearingDegrees: Double, // 方向角度(0-360,0表示北)
widthMeters: Double = 3.0,
depthMeters: Double = 8.0
): List<List<Double>> {
// 计算矩形中心点(在前方 depthMeters/2 处)
val center = calculateDestinationPoint(
frontPoint[0],
frontPoint[1],
bearingDegrees,
depthMeters / 2
)
// 垂直于方向的宽度
val perpendicularBearing1 = (bearingDegrees + 90) % 360
val perpendicularBearing2 = (bearingDegrees - 90 + 360) % 360
// 前方点
val frontCenter = calculateDestinationPoint(
center[0], center[1], bearingDegrees, depthMeters / 2
)
// 计算四个角点
val frontLeft = calculateDestinationPoint(
frontCenter[0], frontCenter[1], perpendicularBearing1, widthMeters / 2
)
val frontRight = calculateDestinationPoint(
frontCenter[0], frontCenter[1], perpendicularBearing2, widthMeters / 2
)
val backLeft = calculateDestinationPoint(
frontPoint[0], frontCenter[1], perpendicularBearing1, widthMeters / 2
)
val backRight = calculateDestinationPoint(
frontPoint[0], frontCenter[1], perpendicularBearing2, widthMeters / 2
)
return listOf(backLeft, frontLeft, frontRight, backRight, backLeft)
}
/**
* 生成旋转的矩形
*/
fun createRotatedRectangleFromCenter(
centerLon: Double, centerLat: Double,
rotation: Double = 0.0,
widthMeters: Double = 100.0,
heightMeters: Double = 80.0
): List<List<Double>> {
// 地球半径(米)
val EARTH_RADIUS = 6371000.0
// 将米转换为经纬度(近似计算)
val latDelta = (heightMeters / 2) / EARTH_RADIUS * (180 / Math.PI)
val lonDelta =
(widthMeters / 2) / (EARTH_RADIUS * cos(Math.toRadians(centerLat))) * (180 / Math.PI)
var result = mutableListOf<List<Double>>()
// 左上角
result.add(listOf(centerLon - lonDelta, centerLat + latDelta))
// 右上角
result.add(listOf(centerLon + lonDelta, centerLat + latDelta))
// 右下角
result.add(listOf(centerLon + lonDelta, centerLat - latDelta))
// 左下角
result.add(listOf(centerLon - lonDelta, centerLat - latDelta))
result.add(listOf(centerLon - lonDelta, centerLat + latDelta))
return result
}
/**
* 计算目标点(根据起点、方向和距离)
*/
private fun calculateDestinationPoint(
startLng: Double,
startLat: Double,
bearing: Double,
distanceMeters: Double
): List<Double> {
val earthRadius = 6371000.0 // 地球半径(米)
val startLatRad = Math.toRadians(startLat)
val startLngRad = Math.toRadians(startLng)
val bearingRad = Math.toRadians(bearing)
val endLatRad = asin(
sin(startLatRad) * cos(distanceMeters / earthRadius) +
cos(startLatRad) * sin(distanceMeters / earthRadius) * cos(bearingRad)
)
val endLngRad = startLngRad + atan2(
sin(bearingRad) * sin(distanceMeters / earthRadius) * cos(startLatRad),
cos(distanceMeters / earthRadius) - sin(startLatRad) * sin(endLatRad)
)
return listOf(Math.toDegrees(endLngRad), Math.toDegrees(endLatRad))
}
}
\ No newline at end of file
package com.sd.cavphmi.utils
import com.sd.cavphmi.bean.DrivenDecision
import org.locationtech.jts.geom.Coordinate
import org.locationtech.jts.geom.GeometryFactory
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Polygon
object MyGeoTools {
// 创建 GeometryFactory
private var geometryFactory: GeometryFactory = GeometryFactory()
//全局路径生成线段
fun genLine(drivenDecision: DrivenDecision): LineString {
val lines = drivenDecision.trajectory.points.map {
Coordinate(it.longitude, it.latitude)
}.toTypedArray()
var lineString = geometryFactory.createLineString(lines)
return lineString
}
//根据坐标生成前方矩形
fun genFontArea(
lng: Double, lat: Double, heading: Double, length: Double = 10.0,
width: Double = 3.0
): Polygon {
var rectanglePoints = GeoRectangleUtils.createRectangleInFront(listOf(lng, lat), heading)
val coordinates = rectanglePoints.map {
Coordinate(it[0], it[1])
}.toMutableList()
// var one = myRectangle.corners.first()
// coordinates.add(Coordinate(one[0], one[1]))
var polygon = geometryFactory.createPolygon(coordinates.toTypedArray())
return polygon
}
// 生成指定方向的矩形
fun genRectangleFromCenter(
lng: Double, lat: Double, heading: Double, length: Double = 10.0,
width: Double = 3.0
): Polygon {
// var rectanglePoints = GeoRectangleUtils.createRectangleFromCenter(lng,lat)
var rectanglePoints = GeoRectangleUtils.generateCenterRect(lng,lat,heading)
val coordinates = rectanglePoints.map {
Coordinate(it[0], it[1])
}.toMutableList()
// var one = myRectangle.corners.first()
// coordinates.add(Coordinate(one[0], one[1]))
var polygon = geometryFactory.createPolygon(coordinates.toTypedArray())
return polygon
}
//计算线段里的点是否在面里
fun cauLineContainsArea(polygon: Polygon?, lineString: LineString?): Int {
if (polygon == null || lineString == null) {
return 0
}
lineString.coordinates.forEachIndexed { index, cood ->
val sinPoint = geometryFactory.createPoint(cood)
if (polygon.contains(sinPoint)) {
return index
}
}
return 0
// 计算相交部分
// val intersection = polygon.intersection(lineString)
// if (intersection.isEmpty) {
// return emptyList()
// }
//// val coordinates = mutableListOf<Coordinate>()
//
// var crossP = intersection.coordinates
// return listOf(crossP[0].x, crossP[0].y)
}
}
\ No newline at end of file
package com.sd.cavphmi.utils
import org.locationtech.proj4j.CRSFactory
import org.locationtech.proj4j.CoordinateReferenceSystem
import org.locationtech.proj4j.CoordinateTransform
import org.locationtech.proj4j.CoordinateTransformFactory
import org.locationtech.proj4j.Proj4jException
import org.locationtech.proj4j.ProjCoordinate
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sin
import kotlin.math.sqrt
class CoordResultBean {
//最近点
var nearPoi: ProjCoordinate? = null
//线段下标
var nearIndex: Int = 0
var distance = 0
}
/**坐标投影转换工具***/
object Proj4jCoord {
private val crsFactory: CRSFactory = CRSFactory()
private var transformFactory: CoordinateTransformFactory = CoordinateTransformFactory()
// 定义 WGS84 (经纬度) 和 Web墨卡托 (用于计算) 坐标系
var wgs84: CoordinateReferenceSystem = crsFactory.createFromName("epsg:4326") // 经纬度源坐标
// var webMercator: CoordinateReferenceSystem = crsFactory.createFromName("epsg:3857") // 投影目标坐标
var webMercator: CoordinateReferenceSystem = crsFactory.createFromName("EPSG:32650") // 投影目标坐标
// 创建转换器
var wgsToMercator: CoordinateTransform = transformFactory.createTransform(wgs84, webMercator)
// 创建逆转换器 (墨卡托 -> WGS84)
var mercatorToWgs: CoordinateTransform = transformFactory.createTransform(webMercator, wgs84)
//返回结果
private val resultBean = CoordResultBean()
// private val resultArray = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
// 定义坐标系参数
private const val WGS84_PARAMS = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
private const val CGCS2000_PARAMS =
"+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"
const val CGCS2000_BEIJING_3_DEGREE_ZONE_39: String =
"+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"
/**
* 计算点到坐标点串的投影距离
* @param point 待投影点 [经度, 纬度]
* @param coordinateSeries 坐标点串 [[经度1, 纬度1], [经度2, 纬度2], ...]
* @return 投影结果数组 [投影点经度, 投影点纬度, 最近点索引, 最小距离]
*/
suspend fun calculatePointProjection(
point: DoubleArray,
coordinateSeries: MutableList<DoubleArray>
): CoordResultBean {
try {
// 转换点到投影坐标
val pointWgs = ProjCoordinate(point[0], point[1]) // 你的点经纬度
val pointMercator = ProjCoordinate()
wgsToMercator.transform(pointWgs, pointMercator)
// val projectedPoint = doubleArrayOf(pointMercator.x, pointMercator.y)
// //直接使用02坐标系
// val dstCoord = ProjCoordinate(point[0], point[1])
// val projectedPoint = doubleArrayOf(dstCoord.x, dstCoord.y)
// 转换坐标点串到CGCS2000坐标系
// var projectedSeries = mutableListOf<DoubleArray>()
// for (coord in coordinateSeries) {
// projectedSeries.add(doubleArrayOf(coord[0], coord[1]))
// }
// 计算点到线串的最短距离和投影点
return findNearestProjection(pointMercator, coordinateSeries)
} catch (e: Proj4jException) {
e.printStackTrace()
return CoordResultBean()
}
}
/**
* 在投影后的坐标系中查找最近投影点
*/
private fun findNearestProjection(
point: ProjCoordinate,
series: MutableList<DoubleArray>
): CoordResultBean {
var minDistance = Double.Companion.MAX_VALUE
var nearestIndex = -1
var nearPoi: ProjCoordinate? = null
// 遍历所有线段计算投影
for (i in 0..<series.size - 1) {
val start = series.get(i)
val end = series.get(i + 1)
// 同样转换线段的两个端点
val lineStartWgs = ProjCoordinate(start[0], start[1])
val lineEndWgs = ProjCoordinate(end[0], end[1])
val lineStartMercator = ProjCoordinate()
val lineEndMercator = ProjCoordinate()
wgsToMercator.transform(lineStartWgs, lineStartMercator)
wgsToMercator.transform(lineEndWgs, lineEndMercator)
// val currentProjection: DoubleArray = projectPointToLine(point, start, end)
// val currentProjection: DoubleArray = series.get(i)
var closestPointWgs = closestPointOnSegment(point, lineStartMercator, lineEndMercator)
// 转换最近点回 WGS84
nearPoi = ProjCoordinate()
mercatorToWgs.transform(closestPointWgs, nearPoi)
//计算点距离
val distance: Double = calculateDistance(point, closestPointWgs)
// println("-------nearPoi = ${nearPoi.x} ${nearPoi.y} i = ${i}")
// println("---------------distance = ${distance} i = ${i}")
if (distance < minDistance) {
minDistance = distance
nearestIndex = i
}
}
resultBean.nearPoi = nearPoi
return resultBean
}
//在投影坐标下,使用向量投影法计算点到线段的最近点
fun closestPointOnSegment(
point: ProjCoordinate,
lineStart: ProjCoordinate,
lineEnd: ProjCoordinate
): ProjCoordinate {
// 计算方向向量 d = lineEnd - lineStart
val dx = lineEnd.x - lineStart.x
val dy = lineEnd.y - lineStart.y
// 如果线段退化为一个点,直接返回起点
if (dx == 0.0 && dy == 0.0) {
return ProjCoordinate(lineStart.x, lineStart.y)
}
// 计算向量 AP = point - lineStart
val apx = point.x - lineStart.x
val apy = point.x - lineStart.y
// 计算投影参数 t = (AP · d) / (d · d)
// 点积公式: ap dot d = apx * dx + apy * dy
val dot = apx * dx + apy * dy
val lenSq = dx * dx + dy * dy
val t = dot / lenSq
// val t = if (lenSq != 0.0) max(0.0, min(1.0, dot / lenSq)) else 0.0
// 检查最近点是否在线段范围内
if (t < 0.0) {
return ProjCoordinate(lineStart.x, lineStart.y) // 最近点是起点
} else if (t > 1.0) {
return ProjCoordinate(lineEnd.x, lineEnd.y) // 最近点是终点
} else {
// 最近点在线段上: lineStart + t * d
val closestX = lineStart.x + t * dx
val closestY = lineStart.y + t * dy
return ProjCoordinate(closestX, closestY)
}
}
/**
* 计算点到线段的投影
*/
private fun projectPointToLine(
point: DoubleArray,
lineStart: DoubleArray,
lineEnd: DoubleArray
): DoubleArray {
val ax = point[0] - lineStart[0]
val ay = point[1] - lineStart[1]
val bx = lineEnd[0] - lineStart[0]
val by = lineEnd[1] - lineStart[1]
val dot = ax * bx + ay * by
val lenSq = bx * bx + by * by
val t = if (lenSq != 0.0) max(0.0, min(1.0, dot / lenSq)) else 0.0
return doubleArrayOf(
lineStart[0] + t * bx,
lineStart[1] + t * by
)
}
// 地球半径(米),WGS84/CGCS2000 椭球近似半径
private const val EARTH_RADIUS: Double = 6371008.8
/**
* 计算两点间距离
*/
private fun calculateDistance(p1: ProjCoordinate, p2: ProjCoordinate): Double {
val dx: Double = p2.x - p1.y
val dy: Double = p2.y - p1.y
return sqrt(dx * dx + dy * dy)
// 角度转弧度
/* val radLat1 = Math.toRadians(p1[1])
val radLon1 = Math.toRadians(p1[0])
val radLat2 = Math.toRadians(p2[1])
val radLon2 = Math.toRadians(p2[0])
// 纬度差、经度差
val deltaLat = radLat2 - radLat1
val deltaLon = radLon2 - radLon1
// Haversine 公式
val a = (sin(deltaLat / 2) * sin(deltaLat / 2)
+ cos(radLat1) * cos(radLat2) * sin(deltaLon / 2) * sin(deltaLon / 2))
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
// 距离 = 地球半径 × 圆心角
return EARTH_RADIUS * c*/
}
}
\ No newline at end of file
......@@ -23,13 +23,16 @@ import com.sd.cavphmi.highmap.AllLine
import com.sd.cavphmi.highmap.HighMapApi
import com.sd.cavphmi.highmap.ReverCar
import com.sd.cavphmi.utils.AvpContants
import com.sd.cavphmi.utils.AvpMapUtils
import com.sd.cavphmi.utils.MyGeoTools
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Polygon
import javax.inject.Inject
//地图操作类
@HiltViewModel
class MapOpt @Inject constructor(
......@@ -47,6 +50,18 @@ class MapOpt @Inject constructor(
//小地图路径点坐标集合
private var sLatLngs: Array<Point>? = null
//路径点的下标
private var sliceIndex = 0
//小地图线段
private var lineString: LineString? = null
//车前方矩形
private var fontArea: Polygon? = null
//锁
// private var cenAreaLock = CenAreaLock()
// 小地图路径坐标点串 (02坐标系)
// private var coordinateSeries = ArrayList<DoubleArray>()
private var sPolyline: Polyline? = null
......@@ -165,6 +180,9 @@ class MapOpt @Inject constructor(
sLatLngs = drivenDecision.trajectory.points.map {
Tools.latLngToPoint(LatLng(it.latitude, it.longitude))
}.toTypedArray()
//生成小地图线段
lineString = MyGeoTools.genLine(drivenDecision)
//生成DoubleArray
// sLatLngs?.forEach {
// var ll = Tools.pointToLatLng(it)
......@@ -174,25 +192,41 @@ class MapOpt @Inject constructor(
}
}
//车前方生成矩形
fun genFronArea(car: CarVehicle) {
// synchronized(NativeEnv.SyncObject) {
var vehiclePos = car.vehiclePos!!
fontArea =
MyGeoTools.genRectangleFromCenter(vehiclePos[0], vehiclePos[1], vehiclePos[2])
// }
}
//更新小地图路径
fun upSmallMapLine(carVehicle: CarVehicle) {
if (sLatLngs != null && (sLatLngs?.count() ?: 0) > 0) {
//当前车辆位置
var latlng = LatLng(carVehicle.vehiclePos!!.get(1), carVehicle.vehiclePos.get(0))
//投影计算结果
// var result = Proj4jCoord.calculatePointProjection(
// doubleArrayOf(latlng.longitude, latlng.latitude),
// coordinateSeries
// )
viewModelScope.launch(Dispatchers.Default) {
var index = AvpMapUtils.findNearPointIndex(latlng, sLatLngs!!.toList())
// var index = AvpMapUtils.findNearPointIndex(latlng, sLatLngs!!.toList())
// println("-----------前方矩形 fontArea = ${fontArea} 全局路径 = ${lineString}")
// var crossIndex = 0
// if (crossIndex > 0) {
// sliceIndex = crossIndex
// }
// println("----最近线段索引: " + index)
// var index = result.nearIndex
// var sliceIndex = if ((crossIndex-1)<0) 0 else (crossIndex-1)
//删除线
deleteSmapLine()
synchronized(NativeEnv.SyncObject) {
var crossIndex = MyGeoTools.cauLineContainsArea(fontArea, lineString)
println("-----------相交线段下标 crossIndex = ${crossIndex}")
if (sliceIndex < crossIndex) {
sliceIndex = crossIndex
}
//截取线段
var nPoints = sLatLngs!!.sliceArray(index..sLatLngs!!.lastIndex)
var nPoints = sLatLngs!!.sliceArray(sliceIndex..sLatLngs!!.lastIndex)
sPolyline = Polyline(nPoints, false)
sPolyline?.setStrokeStyle(Overlay.StrokeStyle.solidWithButt)
sPolyline?.setWidth(8f)
......@@ -346,4 +380,8 @@ class MapOpt @Inject constructor(
}
}
class CenAreaLock {
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.minedata.minenavi.map.Marker
import com.minedata.minenavi.map.MarkerOptions
import com.minedata.minenavi.map.MineMap
......@@ -238,12 +239,18 @@ class MockVM @Inject constructor(
var gson = Gson()
var datas = mutableListOf<String>()
FileIoUtils.getAssetMock(context, "mock/shiche/CarVehicle.txt", datas)
var temp=""
datas.forEach { str ->
val cCar = gson.fromJson<CarVehicle>(str, CarVehicle::class.java)
if (cCar.vehiclePos != null) {
carLiveData.value = cCar
try {
temp=str
val cCar = gson.fromJson<CarVehicle>(str, CarVehicle::class.java)
if (cCar.vehiclePos != null) {
carLiveData.value = cCar
// carLiveData.postValue(cCar)
delay(300)
delay(200)
}
} catch (e: JsonSyntaxException) {
e.printStackTrace()
}
}
}
......@@ -440,12 +447,12 @@ class MockVM @Inject constructor(
viewModelScope.launch {
var gson = Gson()
var datas = mutableListOf<String>()
FileIoUtils.getAssetMock(context, "mock/shiche/avp_status_call.txt", datas)
FileIoUtils.getAssetMock(context, "mock/shiche/avp_status_park.txt", datas)
var str = datas.first()
val statu = gson.fromJson<AvpStatuBean>(str, AvpStatuBean::class.java)
for (i in 0..10000) {
flow.emit(statu)
delay(300)
delay(3000)
}
}
}
......
package com.sd.cavphmi;
import com.sd.cavphmi.utils.MyMapUtils;
import org.locationtech.proj4j.*;
import java.util.ArrayList;
import java.util.List;
public class CoordinateProjectionUtils {
private static final CRSFactory crsFactory = new CRSFactory();
// 定义坐标系参数
private static final String WGS84_PARAMS = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
private static final String CGCS2000_PARAMS = "+proj=tmerc +lat_0=0 +lon_0=116 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
// 北京主要使用的3度分带投影
public static final String CGCS2000_BEIJING_3_DEGREE_ZONE_39 =
"+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
// CGCS2000 常用投影参数
public static final String CGCS2000_GEOGRAPHIC = "+proj=longlat +ellps=GRS80 +no_defs";
public static final String CGCS2000_3_DEGREE_ZONE_37 = "+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
public static final String CGCS2000_3_DEGREE_ZONE_38 = "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=38500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
public static final String CGCS2000_3_DEGREE_ZONE_39 = "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=39500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
public static final String CGCS2000_3_DEGREE_ZONE_40 = "+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=40500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
// 6度带投影参数
public static final String CGCS2000_6_DEGREE_ZONE_13 = "+proj=tmerc +lat_0=0 +lon_0=75 +k=1 +x_0=13500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
public static final String CGCS2000_6_DEGREE_ZONE_20 = "+proj=tmerc +lat_0=0 +lon_0=117 +k=1 +x_0=20500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
public static final String CGCS2000_6_DEGREE_ZONE_21 = "+proj=tmerc +lat_0=0 +lon_0=123 +k=1 +x_0=21500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
/**
* 计算点到坐标点串的投影距离
* @param point 待投影点 [经度, 纬度]
* @param coordinateSeries 坐标点串 [[经度1, 纬度1], [经度2, 纬度2], ...]
* @return 投影结果数组 [投影点经度, 投影点纬度, 最近点索引, 最小距离]
*/
public static double[] calculatePointProjection(double[] point, List<double[]> coordinateSeries) {
try {
// 创建坐标系
CoordinateReferenceSystem wgs84 = crsFactory.createFromParameters("WGS84", WGS84_PARAMS);
CoordinateReferenceSystem cgcs2000 = crsFactory.createFromParameters("CGCS2000", CGCS2000_BEIJING_3_DEGREE_ZONE_39);
CoordinateTransform transform = new CoordinateTransformFactory().createTransform(wgs84, cgcs2000);
// 转换待投影点到CGCS2000坐标系
// ProjCoordinate srcCoord = new ProjCoordinate(point[0], point[1]);
// ProjCoordinate dstCoord = new ProjCoordinate();
// transform.transform(srcCoord, dstCoord);
// double[] projectedPoint = {dstCoord.x, dstCoord.y};
//直接使用02坐标系
ProjCoordinate dstCoord = new ProjCoordinate(point[0], point[1]);
double[] projectedPoint = {dstCoord.x, dstCoord.y};
// 转换坐标点串到CGCS2000坐标系
List<double[]> projectedSeries = new ArrayList<>();
for (double[] coord : coordinateSeries) {
// ProjCoordinate src = new ProjCoordinate(coord[0], coord[1]);
// ProjCoordinate dst = new ProjCoordinate();
// transform.transform(src, dst);
// projectedSeries.add(new double[]{dst.x, dst.y});
projectedSeries.add(new double[]{coord[0], coord[1]});
}
// 计算点到线串的最短距离和投影点
return findNearestProjection(projectedPoint, projectedSeries);
} catch (Proj4jException e) {
e.printStackTrace();
return new double[]{0, 0, -1, -1};
}
}
/**
* 在投影后的坐标系中查找最近投影点
*/
private static double[] findNearestProjection(double[] point, List<double[]> series) {
double minDistance = Double.MAX_VALUE;
int nearestIndex = -1;
double[] projectionPoint = new double[2];
// 遍历所有线段计算投影
for (int i = 0; i < series.size() - 1; i++) {
double[] start = series.get(i);
double[] end = series.get(i + 1);
double[] currentProjection = projectPointToLine(point, start, end);
double distance = calculateDistance(point, currentProjection);
if (distance < minDistance) {
minDistance = distance;
nearestIndex = i;
projectionPoint = currentProjection;
}
}
return new double[]{
projectionPoint[0],
projectionPoint[1],
nearestIndex,
minDistance
};
}
/**
* 计算点到线段的投影
*/
private static double[] projectPointToLine(double[] point, double[] lineStart, double[] lineEnd) {
double ax = point[0] - lineStart[0];
double ay = point[1] - lineStart[1];
double bx = lineEnd[0] - lineStart[0];
double by = lineEnd[1] - lineStart[1];
double dot = ax * bx + ay * by;
double lenSq = bx * bx + by * by;
double t = (lenSq != 0) ? Math.max(0, Math.min(1, dot / lenSq)) : 0;
return new double[]{
lineStart[0] + t * bx,
lineStart[1] + t * by
};
}
// 地球半径(米),WGS84/CGCS2000 椭球近似半径
private static final double EARTH_RADIUS = 6371008.8;
/**
* 计算两点间距离
*/
private static double calculateDistance(double[] p1, double[] p2) {
// double dx = p1[0] - p2[0];
// double dy = p1[1] - p2[1];
// return Math.sqrt(dx * dx + dy * dy);
// 角度转弧度
double radLat1 = Math.toRadians(p1[1]);
double radLon1 = Math.toRadians(p1[0]);
double radLat2 = Math.toRadians(p2[1]);
double radLon2 = Math.toRadians(p2[0]);
// 纬度差、经度差
double deltaLat = radLat2 - radLat1;
double deltaLon = radLon2 - radLon1;
// Haversine 公式
double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
+ Math.cos(radLat1) * Math.cos(radLat2)
* Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// 距离 = 地球半径 × 圆心角
return EARTH_RADIUS * c;
}
/**
* 示例用法
*/
public static void main(String[] args) {
// 待投影点 (WGS84坐标系)
double[] testPoint = {116.3974, 39.9093}; // 北京天安门
// 坐标点串 (WGS84坐标系)
List<double[]> coordinateSeries = new ArrayList<>();
coordinateSeries.add(new double[]{116.3914, 39.9053});
coordinateSeries.add(new double[]{116.4034, 39.9133});
coordinateSeries.add(new double[]{116.4154, 39.9213});
// 计算投影
double[] result = calculatePointProjection(testPoint, coordinateSeries);
System.out.println("投影点坐标: (" + result[0] + ", " + result[1] + ")");
System.out.println("最近线段索引: " + (int)result[2]);
System.out.println("最小距离: " + result[3] + " 米");
}
}
package com.sd.cavphmi;
import com.sd.cavphmi.utils.Proj4jCoord;
import org.junit.Test;
......@@ -27,11 +27,11 @@ public class UnitTest {
// 计算投影
// double[] result = CoordinateProjectionUtils.calculatePointProjection(testPoint, coordinateSeries);
double[] result = Proj4jCoord.INSTANCE.calculatePointProjection(testPoint, coordinateSeries);
System.out.println("投影点坐标: (" + result[0] + ", " + result[1] + ")");
System.out.println("最近线段索引: " + (int)result[2]);
System.out.println("最小距离: " + result[3] + " 米");
// double[] result = Proj4jCoord.INSTANCE.calculatePointProjection(testPoint, coordinateSeries);
//
// System.out.println("投影点坐标: (" + result[0] + ", " + result[1] + ")");
// System.out.println("最近线段索引: " + (int)result[2]);
// System.out.println("最小距离: " + result[3] + " 米");
}
......
......@@ -6,6 +6,7 @@ pluginManagement {
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
maven { setUrl("https://maven.aliyun.com/repository/public") }
maven { setUrl("https://jitpack.io") }
// maven { setUrl("https://repo.osgeo.org/repository/release/")}
google {
content {
includeGroupByRegex("com\\.android.*")
......@@ -20,12 +21,13 @@ pluginManagement {
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { setUrl("https://jitpack.io") }
maven { setUrl("https://repo.osgeo.org/repository/release/")}
maven { setUrl("https://maven.aliyun.com/repository/central") }
maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
maven { setUrl("https://maven.aliyun.com/repository/google") }
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
maven { setUrl("https://maven.aliyun.com/repository/public") }
maven { setUrl("https://jitpack.io") }
google()
mavenCentral()
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment