Optimized heights parsing

This commit is contained in:
Alexey 2025-09-24 16:20:10 +03:00
commit c7b22f012b
2 changed files with 68 additions and 48 deletions

View file

@ -88,30 +88,35 @@ class KhmParser {
dis.use { dis.use {
val header = readHeader(dis) val header = readHeader(dis)
val glist: Array<Pair<Pair<Float, Float>, Int>> = Array(coords.size) { i -> val glist: MutableMap<Pair<Float, Float>, Int> = mutableMapOf()
val x = ((coords[i].first - header.minLon) / header.lonPerValue).toInt()
val y = ((coords[i].second - header.minLat) / header.latPerValue).toInt() for (coord in coords) {
val x = ((coord.first - header.minLon) / header.lonPerValue).toInt()
val y = ((coord.second - header.minLat) / header.latPerValue).toInt()
val offset = getOffset(header, x, y) val offset = getOffset(header, x, y)
Pair(coords[i], offset) glist.put(coord, offset)
}
glist.sortBy {
it.second
} }
val sortedGlist = glist.toList().sortedBy { (_, v) -> v }.toMap()
val glistKeys = sortedGlist.keys.toTypedArray()
coords.sortBy { oit -> val cutOffsets = IntArray(glist.size) {-1}
glist.find { it.first == oit }!!.second if (inBounds(header, coords[0].first, coords[0].second)) {
val key = glistKeys[0]
cutOffsets[0] = sortedGlist.getOrDefault(key, 0)
} }
for (i in 1 until sortedGlist.size) {
val cutOffsets = IntArray(glist.size) if (inBounds(header, coords[i].first, coords[i].second) && cutOffsets[i-1] >= 0) {
cutOffsets[0] = glist[0].second val prevKey = glistKeys[i-1]
for (i in 1 until glist.size) { val key = glistKeys[i]
cutOffsets[i] = glist[i].second - glist[i-1].second - 2 cutOffsets[i] = sortedGlist.getOrDefault(key, 0) - sortedGlist.getOrDefault(prevKey, 0) - 2
assert(cutOffsets[i] >= 0) } else break
} }
return Pair(UShortArray(coords.size) { i -> return Pair(UShortArray(coords.size) { i ->
if (cutOffsets[i] > 0) {
dis.skipBytes(cutOffsets[i]) dis.skipBytes(cutOffsets[i])
dis.readUnsignedShort().toUShort() dis.readUnsignedShort().toUShort()
} else 0u
}, coords) }, coords)
} }
} }

View file

@ -5,6 +5,8 @@ import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -46,12 +48,21 @@ fun MapCanvas(
var pointRequested by rememberSaveable { viewModel.pointRequested } var pointRequested by rememberSaveable { viewModel.pointRequested }
var pointLat by rememberSaveable { viewModel.rememberedPointLat } var pointLat by rememberSaveable { viewModel.rememberedPointLat }
var pointLon by rememberSaveable { viewModel.rememberedPointLon } var pointLon by rememberSaveable { viewModel.rememberedPointLon }
var invokeHeightCalc by remember { mutableStateOf(false) }
Canvas( Canvas(
modifier = modifier.fillMaxSize() modifier = modifier.fillMaxSize()
.pointerInput(Unit) { .pointerInput(Unit) {
detectDragGestures { _, distance -> detectDragGestures (
onDragEnd = {
invokeHeightCalc = true
},
onDragCancel = {
invokeHeightCalc = true
}
) { _, distance ->
offsetX -= distance.x offsetX -= distance.x
offsetY -= distance.y offsetY -= distance.y
invokeHeightCalc = false
} }
} }
) { ) {
@ -186,6 +197,7 @@ fun MapCanvas(
end = Offset(halvedX, halvedY) end = Offset(halvedX, halvedY)
) )
val startHeight = KhmParser.getHeight(pointLon, pointLat, ctx) val startHeight = KhmParser.getHeight(pointLon, pointLat, ctx)
if (pointOffsetX >= 0 && pointOffsetY >= 0 && pointOffsetX < size.width && pointOffsetY < size.height)
drawText( drawText(
textMeasurer = textMeasurer, textMeasurer = textMeasurer,
text = buildAnnotatedString { withStyle(SpanStyle(color = Color.White)) { text = buildAnnotatedString { withStyle(SpanStyle(color = Color.White)) {
@ -193,6 +205,7 @@ fun MapCanvas(
} }, } },
topLeft = Offset(pointOffsetX, pointOffsetY - 32) topLeft = Offset(pointOffsetX, pointOffsetY - 32)
) )
if (invokeHeightCalc) {
val latPV = KhmParser.getLatPerValue() val latPV = KhmParser.getLatPerValue()
val lonPV = KhmParser.getLonPerValue() val lonPV = KhmParser.getLonPerValue()
val valueDistance = sqrt(latPV.pow(2) + lonPV.pow(2)) val valueDistance = sqrt(latPV.pow(2) + lonPV.pow(2))
@ -206,12 +219,13 @@ fun MapCanvas(
} }
val heightPair = KhmParser.getHeightsMul(ctx, array) val heightPair = KhmParser.getHeightsMul(ctx, array)
val heights = heightPair.first val heights = heightPair.first
val coords = heightPair.second val coords = heightPair.second.reversed()
for (step in 0 until coords.size) { for (step in 0 until coords.size) {
val stepLat = coords[step].second val stepLat = coords[step].second
val stepLon = coords[step].first val stepLon = coords[step].first
val stepOffsetX = SphereMercator.mercateLon(stepLon.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetX val stepOffsetX = SphereMercator.mercateLon(stepLon.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetX
val stepOffsetY = SphereMercator.mercateLat(stepLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY val stepOffsetY = SphereMercator.mercateLat(stepLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY
if (stepOffsetX >= 0 && stepOffsetY >= 0 && stepOffsetX < size.width && stepOffsetY < size.height)
drawRect( drawRect(
color = if (heights[step] > startHeight) Color.Red else Color.Green, color = if (heights[step] > startHeight) Color.Red else Color.Green,
size = Size(8F, 8F), size = Size(8F, 8F),
@ -219,6 +233,7 @@ fun MapCanvas(
) )
} }
} }
}
// Cursor path // Cursor path
val path = Path() val path = Path()