Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
p x
SuZhouAvp
Commits
7ea96217
Commit
7ea96217
authored
Nov 29, 2025
by
pxl
Browse files
以车为矩形,求全局路径的焦点
parent
6c616198
Changes
13
Show whitespace changes
Inline
Side-by-side
app/build.gradle.kts
View file @
7ea96217
...
...
@@ -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
...
...
app/src/androidTest/java/com/sd/cavphmi/ExampleInstrumentedTest.kt
View file @
7ea96217
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
calculateTouYing
2
()
{
// 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] + " 米")
}
}
...
...
app/src/main/assets/mock/shiche/CarVehicle_park.txt
View file @
7ea96217
...
...
@@ -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}
...
...
app/src/main/java/com/sd/cavphmi/bean/CarVehicle.kt
View file @
7ea96217
...
...
@@ -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 里面分别是 经度、纬度、航向角
...
...
app/src/main/java/com/sd/cavphmi/ui/MainActivity.kt
View file @
7ea96217
...
...
@@ -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}")
...
...
app/src/main/java/com/sd/cavphmi/utils/GeoRectangleUtils.kt
0 → 100644
View file @
7ea96217
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
app/src/main/java/com/sd/cavphmi/utils/MyGeoTools.kt
0 → 100644
View file @
7ea96217
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
app/src/main/java/com/sd/cavphmi/utils/Proj4jCoord.kt
deleted
100644 → 0
View file @
6c616198
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
app/src/main/java/com/sd/cavphmi/viewmodels/MapOpt.kt
View file @
7ea96217
...
...
@@ -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.
AvpMapUti
ls
import
com.sd.cavphmi.utils.
MyGeoToo
ls
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
(
i
ndex
..
sLatLngs
!!
.
lastIndex
)
var
nPoints
=
sLatLngs
!!
.
sliceArray
(
sliceI
ndex
..
sLatLngs
!!
.
lastIndex
)
sPolyline
=
Polyline
(
nPoints
,
false
)
sPolyline
?.
setStrokeStyle
(
Overlay
.
StrokeStyle
.
solidWithButt
)
sPolyline
?.
setWidth
(
8f
)
...
...
@@ -347,3 +381,7 @@ class MapOpt @Inject constructor(
}
class
CenAreaLock
{
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/viewmodels/MockVM.kt
View file @
7ea96217
...
...
@@ -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
->
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
(
300
0
)
}
}
}
...
...
app/src/test/java/com/sd/cavphmi/CoordinateProjectionUtils.java
deleted
100644 → 0
View file @
6c616198
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
]
+
" 米"
);
}
}
app/src/test/java/com/sd/cavphmi/UnitTest.java
View file @
7ea96217
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] + " 米");
}
...
...
settings.gradle.kts
View file @
7ea96217
...
...
@@ -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
()
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment