Changed multiple heights parsing

This commit is contained in:
Alexey 2025-09-23 16:39:53 +03:00
commit 71f012dc6b
2 changed files with 50 additions and 6 deletions

View file

@ -2,10 +2,12 @@ package com.mirenkov.ktheightmap
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import java.io.DataInput
import java.io.DataInputStream import java.io.DataInputStream
import java.io.FileInputStream import java.io.FileInputStream
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.sign
private data class HeightInfo( private data class HeightInfo(
val minLon: Float, val minLon: Float,
@ -20,6 +22,7 @@ class KhmParser {
companion object { companion object {
private var header: HeightInfo? = null private var header: HeightInfo? = null
const val HEIGHT_FILE: String = "height.khm" const val HEIGHT_FILE: String = "height.khm"
fun load(filePath: String, ctx: Context) { fun load(filePath: String, ctx: Context) {
if (ctx.getFileStreamPath(HEIGHT_FILE).exists()) { if (ctx.getFileStreamPath(HEIGHT_FILE).exists()) {
return return
@ -77,6 +80,42 @@ class KhmParser {
} }
} }
@OptIn(ExperimentalUnsignedTypes::class)
fun getHeightsMul(ctx: Context, coords: Array<Pair<Float, Float>>): Pair<UShortArray, Array<Pair<Float, Float>>> {
if (coords.isEmpty()) return Pair(ushortArrayOf(), coords)
val dis = DataInputStream(ctx.openFileInput(HEIGHT_FILE))
dis.use {
val header = readHeader(dis)
val glist: Array<Pair<Pair<Float, Float>, Int>> = Array(coords.size) { i ->
val x = ((coords[i].first - header.minLon) / header.lonPerValue).toInt()
val y = ((coords[i].second - header.minLat) / header.latPerValue).toInt()
val offset = getOffset(header, x, y)
Pair(coords[i], offset)
}
glist.sortBy {
it.second
}
coords.sortBy { oit ->
glist.find { it.first == oit }!!.second
}
val cutOffsets = IntArray(glist.size)
cutOffsets[0] = glist[0].second
for (i in 1 until glist.size) {
cutOffsets[i] = glist[i].second - glist[i-1].second - 2
assert(cutOffsets[i] >= 0)
}
return Pair(UShortArray(coords.size) { i ->
dis.skipBytes(cutOffsets[i])
dis.readUnsignedShort().toUShort()
}, coords)
}
}
fun getLonPerValue(): Float { fun getLonPerValue(): Float {
return header?.lonPerValue ?: 0F return header?.lonPerValue ?: 0F
} }

View file

@ -24,11 +24,11 @@ import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.ceil
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
@OptIn(ExperimentalUnsignedTypes::class)
@Composable @Composable
fun MapCanvas( fun MapCanvas(
viewModel: TileViewModel, viewModel: TileViewModel,
@ -200,15 +200,20 @@ fun MapCanvas(
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 = floor(distance / valueDistance).toInt() val valuesCount = floor(distance / valueDistance).toInt()
for (step in 0 .. valuesCount) { val array: Array<Pair<Float, Float>> = Array(valuesCount) { step ->
val interCoef = 1F - step.toFloat() / valuesCount val interCoef = 1F - step.toFloat() / valuesCount
val stepLat = lat - latDiff * interCoef Pair(lon - lonDiff * interCoef, lat - latDiff * interCoef)
val stepLon = lon - lonDiff * interCoef }
val heightPair = KhmParser.getHeightsMul(ctx, array)
val heights = heightPair.first
val coords = heightPair.second
for (step in 0 until coords.size) {
val stepLat = coords[step].second
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
val height = KhmParser.getHeight(stepLon, stepLat, ctx)
drawRect( drawRect(
color = if (height > startHeight) Color.Red else Color.Green, color = if (heights[step] > startHeight) Color.Red else Color.Green,
size = Size(8F, 8F), size = Size(8F, 8F),
topLeft = Offset(stepOffsetX - 4, stepOffsetY - 4) topLeft = Offset(stepOffsetX - 4, stepOffsetY - 4)
) )