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