feat: 重构地图

This commit is contained in:
2025-06-13 21:03:42 +08:00
parent b384446fc6
commit 9889efc754
27 changed files with 1672 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
}
android {
@@ -23,6 +24,9 @@ android {
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
buildFeatures {
viewBinding = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
@@ -38,7 +42,12 @@ dependencies {
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(project(":maps-view"))
implementation(project(":math"))
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.kotlinx.serialization.json)
// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation("com.google.code.gson:gson:2.13.1")
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

View File

@@ -11,6 +11,16 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Maps"
tools:targetApi="31" />
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,113 @@
package com.icegps.maps
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.icegps.maps.databinding.ActivityMainBinding
import com.icegps.maps.ktx.TAG
import com.icegps.maps.layer.BucketTips
import com.icegps.maps.model.MapMode
import com.icegps.math.geometry.Vector3D
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.CompositeDecoder
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.modules.SerializersModule
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
val json = Json {
serializersModule = SerializersModule {
contextual(
Vector3D::class,
Vector3DSerializer
)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val mapView = binding.mapView
val gridLayer = mapView.createGridLayer()
mapView.addLayer(gridLayer)
val boundaryLayer = mapView.createBoundaryLayer()
mapView.addLayer(boundaryLayer)
val bucketLayer = mapView.createBucketLayer()
mapView.addLayer(bucketLayer)
mapView.mapMode = MapMode.NorthUp
lifecycleScope.launch {
val points = json.decodeFromStream<List<Triple<Vector3D, Vector3D, Vector3D>>>(assets.open("BucketData_1749810551032.json"))
var index = 0
while (isActive) {
val triple = points[index++ % points.size]
bucketLayer.updateTipPositions(
BucketTips(
left = triple.first,
center = triple.second,
right = triple.third
)
)
Log.d(TAG, "updateTipPositions: ${triple}")
delay(1000)
}
}
}
}
object Vector3DSerializer : KSerializer<Vector3D> {
// 描述序列化结构
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("Vector3D") {
element<Double>("x")
element<Double>("y")
element<Double>("z")
}
// 序列化(对象 → JSON
override fun serialize(encoder: Encoder, value: Vector3D) {
encoder.beginStructure(descriptor).run {
encodeDoubleElement(descriptor, 0, value.x)
encodeDoubleElement(descriptor, 1, value.y)
encodeDoubleElement(descriptor, 2, value.z)
endStructure(descriptor)
}
}
// 反序列化JSON → 对象)
override fun deserialize(decoder: Decoder): Vector3D {
return decoder.beginStructure(descriptor).run {
var x = 0.0
var y = 0.0
var z = 0.0
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> x = decodeDoubleElement(descriptor, 0)
1 -> y = decodeDoubleElement(descriptor, 1)
2 -> z = decodeDoubleElement(descriptor, 2)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
endStructure(descriptor)
Vector3D(x, y, z)
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.icegps.maps.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<!-- Base application theme. -->
<style name="Theme.Maps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.Maps" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>

View File

@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Maps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.Maps" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>