Moved everything out of loop
This commit is contained in:
parent
c7b22f012b
commit
32cfa000c7
2 changed files with 109 additions and 101 deletions
|
|
@ -23,6 +23,9 @@ class KhmParser {
|
|||
private var header: HeightInfo? = null
|
||||
const val HEIGHT_FILE: String = "height.khm"
|
||||
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
var cachedHeights: Pair<UShortArray, Array<Pair<Float, Float>>>? = null
|
||||
|
||||
fun load(filePath: String, ctx: Context) {
|
||||
if (ctx.getFileStreamPath(HEIGHT_FILE).exists()) {
|
||||
return
|
||||
|
|
@ -84,6 +87,7 @@ 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)
|
||||
if (cachedHeights != null) return cachedHeights!!
|
||||
val dis = DataInputStream(ctx.openFileInput(HEIGHT_FILE))
|
||||
dis.use {
|
||||
val header = readHeader(dis)
|
||||
|
|
@ -112,12 +116,13 @@ class KhmParser {
|
|||
} else break
|
||||
}
|
||||
|
||||
return Pair(UShortArray(coords.size) { i ->
|
||||
cachedHeights = Pair(UShortArray(coords.size) { i ->
|
||||
if (cutOffsets[i] > 0) {
|
||||
dis.skipBytes(cutOffsets[i])
|
||||
dis.readUnsignedShort().toUShort()
|
||||
} else 0u
|
||||
}, coords)
|
||||
return cachedHeights!!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
|
|
@ -54,9 +55,11 @@ fun MapCanvas(
|
|||
.pointerInput(Unit) {
|
||||
detectDragGestures (
|
||||
onDragEnd = {
|
||||
KhmParser.cachedHeights = null
|
||||
invokeHeightCalc = true
|
||||
},
|
||||
onDragCancel = {
|
||||
KhmParser.cachedHeights = null
|
||||
invokeHeightCalc = true
|
||||
}
|
||||
) { _, distance ->
|
||||
|
|
@ -137,6 +140,7 @@ fun MapCanvas(
|
|||
size = size
|
||||
)
|
||||
|
||||
// Tiles
|
||||
for (cellX in 0 .. gridWidth + 2) {
|
||||
val tileX = tileOffsetX + cellX
|
||||
val localOffsetX = TILE_SIZE * (cellX - 1)
|
||||
|
|
@ -181,110 +185,109 @@ fun MapCanvas(
|
|||
size = Size(TILE_SIZE, TILE_SIZE)
|
||||
)
|
||||
}
|
||||
|
||||
// Placed point and line to center
|
||||
if (pointLat != 0F) {
|
||||
val pointOffsetX = SphereMercator.mercateLon(pointLon.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetX
|
||||
val pointOffsetY = SphereMercator.mercateLat(pointLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY
|
||||
drawRect(
|
||||
color = gridColor,
|
||||
size = Size(8F, 8F),
|
||||
topLeft = Offset(pointOffsetX - 4, pointOffsetY - 4)
|
||||
)
|
||||
drawLine(
|
||||
color = gridColor,
|
||||
start = Offset(pointOffsetX, pointOffsetY),
|
||||
end = Offset(halvedX, halvedY)
|
||||
)
|
||||
val startHeight = KhmParser.getHeight(pointLon, pointLat, ctx)
|
||||
if (pointOffsetX >= 0 && pointOffsetY >= 0 && pointOffsetX < size.width && pointOffsetY < size.height)
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString { withStyle(SpanStyle(color = Color.White)) {
|
||||
append("${startHeight}m")
|
||||
} },
|
||||
topLeft = Offset(pointOffsetX, pointOffsetY - 32)
|
||||
}
|
||||
}
|
||||
// Placed point and line to center
|
||||
if (pointLat != 0F) {
|
||||
val pointOffsetX = SphereMercator.mercateLon(pointLon.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetX
|
||||
val pointOffsetY = SphereMercator.mercateLat(pointLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY
|
||||
drawRect(
|
||||
color = gridColor,
|
||||
size = Size(8F, 8F),
|
||||
topLeft = Offset(pointOffsetX - 4, pointOffsetY - 4)
|
||||
)
|
||||
drawLine(
|
||||
color = gridColor,
|
||||
start = Offset(pointOffsetX, pointOffsetY),
|
||||
end = Offset(halvedX, halvedY)
|
||||
)
|
||||
val startHeight = KhmParser.getHeight(pointLon, pointLat, ctx)
|
||||
if (pointOffsetX >= 0 && pointOffsetY >= 0 && pointOffsetX < size.width && pointOffsetY < size.height)
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString { withStyle(SpanStyle(color = Color.White)) {
|
||||
append("${startHeight}m")
|
||||
} },
|
||||
topLeft = Offset(pointOffsetX, pointOffsetY - 32)
|
||||
)
|
||||
if (invokeHeightCalc) {
|
||||
val latPV = KhmParser.getLatPerValue()
|
||||
val lonPV = KhmParser.getLonPerValue()
|
||||
val valueDistance = sqrt(latPV.pow(2) + lonPV.pow(2))
|
||||
val latDiff = lat - pointLat
|
||||
val lonDiff = lon - pointLon
|
||||
val distance = sqrt((latDiff).pow(2) + (lonDiff).pow(2))
|
||||
val valuesCount = floor(distance / valueDistance).toInt()
|
||||
val array: Array<Pair<Float, Float>> = Array(valuesCount) { step ->
|
||||
val interCoef = 1F - step.toFloat() / valuesCount
|
||||
Pair(lon - lonDiff * interCoef, lat - latDiff * interCoef)
|
||||
}
|
||||
val heightPair = KhmParser.getHeightsMul(ctx, array)
|
||||
val heights = heightPair.first
|
||||
val coords = heightPair.second.reversed()
|
||||
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 stepOffsetY = SphereMercator.mercateLat(stepLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY
|
||||
if (stepOffsetX >= 0 && stepOffsetY >= 0 && stepOffsetX < size.width && stepOffsetY < size.height)
|
||||
drawRect(
|
||||
color = if (heights[step] > startHeight) Color.Red else Color.Green,
|
||||
size = Size(8F, 8F),
|
||||
topLeft = Offset(stepOffsetX - 4, stepOffsetY - 4)
|
||||
)
|
||||
if (invokeHeightCalc) {
|
||||
val latPV = KhmParser.getLatPerValue()
|
||||
val lonPV = KhmParser.getLonPerValue()
|
||||
val valueDistance = sqrt(latPV.pow(2) + lonPV.pow(2))
|
||||
val latDiff = lat - pointLat
|
||||
val lonDiff = lon - pointLon
|
||||
val distance = sqrt((latDiff).pow(2) + (lonDiff).pow(2))
|
||||
val valuesCount = floor(distance / valueDistance).toInt()
|
||||
val array: Array<Pair<Float, Float>> = Array(valuesCount) { step ->
|
||||
val interCoef = 1F - step.toFloat() / valuesCount
|
||||
Pair(lon - lonDiff * interCoef, lat - latDiff * interCoef)
|
||||
}
|
||||
val heightPair = KhmParser.getHeightsMul(ctx, array)
|
||||
val heights = heightPair.first
|
||||
val coords = heightPair.second.reversed()
|
||||
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 stepOffsetY = SphereMercator.mercateLat(stepLat.toDouble(), level, -TILE_SIZE.toDouble()).toFloat() - offsetY
|
||||
if (stepOffsetX >= 0 && stepOffsetY >= 0 && stepOffsetX < size.width && stepOffsetY < size.height)
|
||||
drawRect(
|
||||
color = if (heights[step] > startHeight) Color.Red else Color.Green,
|
||||
size = Size(8F, 8F),
|
||||
topLeft = Offset(stepOffsetX - 4, stepOffsetY - 4)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cursor path
|
||||
val path = Path()
|
||||
path.moveTo(halvedX - crossRadius, halvedY)
|
||||
path.lineTo(halvedX + crossRadius, halvedY)
|
||||
path.moveTo(halvedX, halvedY - crossRadius)
|
||||
path.lineTo(halvedX, halvedY + crossRadius)
|
||||
path.close()
|
||||
|
||||
// Cursor
|
||||
drawPath(
|
||||
path,
|
||||
Color.White,
|
||||
style = Stroke(width = 6F)
|
||||
)
|
||||
|
||||
// Info box
|
||||
drawRect(
|
||||
color = backColor,
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
// Info box content
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
append("%.6f\n%.6f".format(lat, lon))
|
||||
if (debug) {
|
||||
append("\n%.0f\n%.0f".format(offsetX, offsetY))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
// Cursor path
|
||||
val path = Path()
|
||||
path.moveTo(halvedX - crossRadius, halvedY)
|
||||
path.lineTo(halvedX + crossRadius, halvedY)
|
||||
path.moveTo(halvedX, halvedY - crossRadius)
|
||||
path.lineTo(halvedX, halvedY + crossRadius)
|
||||
path.close()
|
||||
|
||||
// Cursor
|
||||
drawPath(
|
||||
path,
|
||||
Color.White,
|
||||
style = Stroke(width = 6F)
|
||||
)
|
||||
|
||||
// Info box
|
||||
drawRect(
|
||||
color = backColor,
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
// Info box content
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
append("%.6f\n%.6f".format(lat, lon))
|
||||
if (debug) {
|
||||
append("\n%.0f\n%.0f".format(offsetX, offsetY))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
// Height under cursor
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(color = Color.White)) {
|
||||
append("${KhmParser.getHeight(lon, lat, ctx)}m")
|
||||
}
|
||||
},
|
||||
topLeft = Offset(halvedX + crossRadius, halvedY + crossRadius)
|
||||
)
|
||||
}
|
||||
}
|
||||
// Height under cursor
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(color = Color.White)) {
|
||||
append("${KhmParser.getHeight(lon, lat, ctx)}m")
|
||||
}
|
||||
},
|
||||
topLeft = Offset(halvedX + crossRadius, halvedY + crossRadius)
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue