Compare commits

...

2 commits

Author SHA1 Message Date
4ecdbb1c48 Improved GetHeightsMul algorithm 2025-11-11 13:04:45 +03:00
7a424db8ab Updated Settings Activity UI 2025-11-11 12:53:15 +03:00
3 changed files with 81 additions and 29 deletions

View file

@ -33,6 +33,7 @@ import com.mirenkov.ktheightmap.Config.Companion.MAP_START_OFFSET_X
import com.mirenkov.ktheightmap.Config.Companion.MAP_START_OFFSET_Y import com.mirenkov.ktheightmap.Config.Companion.MAP_START_OFFSET_Y
import com.mirenkov.ktheightmap.parser.KhmParser import com.mirenkov.ktheightmap.parser.KhmParser
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.ceil
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.min import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
@ -257,7 +258,7 @@ fun DrawScope.drawPointInfo(
val latDiff = lat - pointLat val latDiff = lat - pointLat
val lonDiff = lon - pointLon val lonDiff = lon - pointLon
val distance = sqrt((latDiff).pow(2) + (lonDiff).pow(2)) val distance = sqrt((latDiff).pow(2) + (lonDiff).pow(2))
val valuesCount = min(floor(distance / valueDistance).toInt(),1000) val valuesCount = min(ceil(distance / valueDistance).toInt(), 1000)
val array: Array<Pair<Float, Float>> = Array(valuesCount) { step -> val array: Array<Pair<Float, Float>> = Array(valuesCount) { step ->
val interCoef = 1F - step.toFloat() / valuesCount val interCoef = 1F - step.toFloat() / valuesCount
Pair(lon - lonDiff * interCoef, lat - latDiff * interCoef) Pair(lon - lonDiff * interCoef, lat - latDiff * interCoef)

View file

@ -1,5 +1,6 @@
package com.mirenkov.ktheightmap package com.mirenkov.ktheightmap
import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
@ -8,16 +9,27 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.mirenkov.ktheightmap.parser.KhmParser import com.mirenkov.ktheightmap.parser.KhmParser
@ -49,41 +61,76 @@ class SettingsActivity : ComponentActivity() {
} }
} }
@SuppressLint("ShowToast")
@Composable @Composable
fun SettingsMain(vm: TileViewModel, launcher: ActivityResultLauncher<DocumentFilePickerConfig?>) { fun SettingsMain(vm: TileViewModel, launcher: ActivityResultLauncher<DocumentFilePickerConfig?>) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val filePath by remember { FileLoader.filePath } val filePath by remember { FileLoader.filePath }
val ctx = LocalContext.current val ctx = LocalContext.current
val toast = Toast.makeText(ctx, "File parsed.", Toast.LENGTH_LONG) val loadToast = Toast.makeText(ctx, "File successfully loaded.", Toast.LENGTH_LONG)
val clearTilesToast = Toast.makeText(ctx, "Tiles removed from database.", Toast.LENGTH_LONG)
val clearHeightToast = Toast.makeText(ctx, "Height data removed.", Toast.LENGTH_LONG)
val fileSelectorRow = @Composable () {
Row(Modifier.fillMaxWidth()) {
Button({ launcher.launch(null) }) { Text("Select") }
Text("Selected file: none", Modifier.padding(8.dp, 0.dp).align(Alignment.CenterVertically))
}
}
KtHeightMapTheme { KtHeightMapTheme {
Column(Modifier.fillMaxSize() Scaffold { paddingValues ->
.safeDrawingPadding()) { Column(Modifier.padding(paddingValues)) {
Button({ launcher.launch(null) }) { Text("Select file") } LabeledSection("Select file:", Modifier.padding(24.dp, 8.dp)) {
Button({ fileSelectorRow()
filePath?.let { }
LabeledSection("Load file as...", Modifier.padding(24.dp, 8.dp)) {
Button({ filePath?.let {
coroutineScope.launch(Dispatchers.IO) { coroutineScope.launch(Dispatchers.IO) {
SasSQLiteParser.processZip(it, vm.repository, ctx) SasSQLiteParser.processZip(it, vm.repository, ctx)
coroutineScope.launch(Dispatchers.Main) { toast.show() } coroutineScope.launch(Dispatchers.Main) { loadToast.show() }
} }
} } } }) { Text("SQLite (.zip)") }
) { Text("Load SQLite") } Button({ filePath?.let {
Button({
filePath?.let {
coroutineScope.launch(Dispatchers.IO) { coroutineScope.launch(Dispatchers.IO) {
SasJPEGParser.processZip(it, vm.repository) SasJPEGParser.processZip(it, vm.repository)
coroutineScope.launch(Dispatchers.Main) { toast.show() } coroutineScope.launch(Dispatchers.Main) { loadToast.show() }
} }
} } }) { Text("JPEG (.zip)") }
}, Button({ filePath?.let {
) { Text("Load JPEG") }
Button({
filePath?.let {
KhmParser.load(it, ctx) KhmParser.load(it, ctx)
toast.show() loadToast.show()
} }, } }) { Text("Height data (.khm)") }
) { Text("Load KHM") } }
Button({ coroutineScope.launch { vm.repository.clearTiles() } }) { Text("Clear tiles") } LabeledSection("Clear...", Modifier.padding(24.dp, 8.dp)) {
Button({ KhmParser.clear(ctx) }) { Text("Clear KHM") } Button({ coroutineScope.launch {
vm.repository.clearTiles()
clearTilesToast.show()
} }) { Text("Tile data") }
Button({
KhmParser.clear(ctx)
clearHeightToast.show()
}) { Text("Height data") }
}
}
} }
} }
}
fun labelString(text: String): AnnotatedString {
return buildAnnotatedString {
withStyle(SpanStyle(fontWeight = FontWeight.Bold, fontSize = 24.sp)) {
append(text)
}
}
}
@Composable
fun LabeledSection(text: String, modifier: Modifier = Modifier, content: @Composable () -> Unit) {
Column(modifier) {
Text(labelString(text))
HorizontalDivider()
Column(
modifier = modifier.fillMaxWidth()
) { content() }
}
} }

View file

@ -122,10 +122,14 @@ class KhmParser {
return Pair( return Pair(
UShortArray(coords.size) { i -> UShortArray(coords.size) { i ->
if (cutOffsets[i] > 0) { when {
dis.skipBytes(cutOffsets[i]) (cutOffsets[i] > 0) -> {
dis.readUnsignedShort().toUShort() dis.skipBytes(cutOffsets[i])
} else 0u }, dis.readUnsignedShort().toUShort()
}
(cutOffsets[i] == 0) -> {dis.readUnsignedShort().toUShort()}
else -> 0u
} },
if (reversed) coords else coords.reversed().toTypedArray()) if (reversed) coords else coords.reversed().toTypedArray())
} }
} }