From 2f15a6f6250293d615f0ea1a82e468581ad1da9a Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Fri, 8 Aug 2025 13:27:12 +0300 Subject: [PATCH 1/3] Proper scaling --- .../java/com/mirenkov/ktheightmap/MapCanvas.kt | 17 ++++++++++++++--- .../com/mirenkov/ktheightmap/TileContainer.kt | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt index 593f33f..a78a44f 100644 --- a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt +++ b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt @@ -46,15 +46,26 @@ fun MapCanvas( color = backColor, size = size ) + val oldLevel = tileContainer.getLevel() + val level = scale.floatValue.toInt() + if (oldLevel > level) { + offsetX.floatValue -= size.width / 2F + offsetY.floatValue -= size.height / 2F + offsetX.floatValue /= 2F + offsetY.floatValue /= 2F + } else if (oldLevel < level) { + offsetX.floatValue *= 2F + offsetY.floatValue *= 2F + offsetX.floatValue += size.width / 2F + offsetY.floatValue += size.height / 2F + } val tileOffsetX = (offsetX.floatValue / TILE_SIZE).toInt() val tileOffsetY = (offsetY.floatValue / TILE_SIZE).toInt() val strippedOffsetX = offsetX.floatValue % TILE_SIZE val strippedOffsetY = offsetY.floatValue % TILE_SIZE - val level = scale.floatValue.toInt() - val offset = Offset(strippedOffsetX, strippedOffsetY) val grid = size / TILE_SIZE @@ -62,7 +73,7 @@ fun MapCanvas( val gridWidth = grid.width.toInt() val gridHeight = grid.height.toInt() - val tiles = tileContainer.getTiles(tileOffsetX, tileOffsetY, tileOffsetX + gridWidth, tileOffsetY + gridHeight, level) + val tiles = tileContainer.getTiles(tileOffsetX, tileOffsetY, tileOffsetX + gridWidth + 2, tileOffsetY + gridHeight + 2, level) for (cellX in 0 .. gridWidth + 2) { val tileX = tileOffsetX + cellX diff --git a/app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt b/app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt index 8e257d9..02095ec 100644 --- a/app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt +++ b/app/src/main/java/com/mirenkov/ktheightmap/TileContainer.kt @@ -13,6 +13,8 @@ class TileContainer(private val vm: TileViewModel, private val coroutineScope: C private var level = 1 + fun getLevel(): Int = level + fun getTiles(_startX: Int, _startY: Int, _endX: Int, _endY: Int, _level: Int): List { val newParams = arrayOf( _startX, _startY, _endX, _endY, _level ) val oldParams = arrayOf( startX, startY, endX, endY, level ) From be85e92397fd514d6a7a53571782bcf5dbf546f9 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Mon, 11 Aug 2025 16:56:43 +0300 Subject: [PATCH 2/3] Optimized drawing --- .idea/deploymentTargetSelector.xml | 8 ++++++++ app/src/main/AndroidManifest.xml | 2 +- .../java/com/mirenkov/ktheightmap/MapCanvas.kt | 17 +++++++++-------- .../main/java/com/mirenkov/ktheightmap/Tile.kt | 14 +++++++++----- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..de71baa 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fd10a14..b7c9285 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,13 +12,13 @@ android:supportsRtl="true" android:theme="@style/Theme.KtHeightMap" tools:targetApi="31"> + diff --git a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt index a78a44f..fe951bf 100644 --- a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt +++ b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt @@ -30,8 +30,8 @@ fun MapCanvas( tileContainer: TileContainer, modifier: Modifier = Modifier ) { - val offsetX = rememberSaveable { mutableFloatStateOf(0F) } - val offsetY = rememberSaveable { mutableFloatStateOf(0F) } + val offsetX = rememberSaveable { mutableFloatStateOf(-TILE_SIZE) } + val offsetY = rememberSaveable { mutableFloatStateOf(-TILE_SIZE) } val textMeasurer = rememberTextMeasurer() Canvas( modifier = modifier.fillMaxSize() @@ -50,15 +50,15 @@ fun MapCanvas( val level = scale.floatValue.toInt() if (oldLevel > level) { - offsetX.floatValue -= size.width / 2F - offsetY.floatValue -= size.height / 2F + offsetX.floatValue -= size.width / 2F + TILE_SIZE + offsetY.floatValue -= size.height / 2F + TILE_SIZE offsetX.floatValue /= 2F offsetY.floatValue /= 2F } else if (oldLevel < level) { offsetX.floatValue *= 2F offsetY.floatValue *= 2F - offsetX.floatValue += size.width / 2F - offsetY.floatValue += size.height / 2F + offsetX.floatValue += size.width / 2F + TILE_SIZE + offsetY.floatValue += size.height / 2F + TILE_SIZE } val tileOffsetX = (offsetX.floatValue / TILE_SIZE).toInt() val tileOffsetY = (offsetY.floatValue / TILE_SIZE).toInt() @@ -82,7 +82,7 @@ fun MapCanvas( val tileY = tileOffsetY + cellY val localOffsetY = TILE_SIZE * (cellY - 1) - val bitmap = tiles.find { it.x == tileX && it.y == tileY && it.level == level }?.getBitmap() + val bitmap = tiles.find { it.x == tileX && it.y == tileY && it.level == level }?.toBitmap() bitmap?.let { val imageBitmap = bitmap.asImageBitmap() @@ -91,7 +91,7 @@ fun MapCanvas( topLeft = Offset(localOffsetX, localOffsetY) - offset ) } - + /* drawRect( color = gridColor, size = Size(TILE_SIZE, TILE_SIZE), @@ -111,6 +111,7 @@ fun MapCanvas( topLeft = Offset(localOffsetX, localOffsetY) - offset, size = Size(TILE_SIZE, TILE_SIZE) ) + */ } } } diff --git a/app/src/main/java/com/mirenkov/ktheightmap/Tile.kt b/app/src/main/java/com/mirenkov/ktheightmap/Tile.kt index 4420051..fefd2f9 100644 --- a/app/src/main/java/com/mirenkov/ktheightmap/Tile.kt +++ b/app/src/main/java/com/mirenkov/ktheightmap/Tile.kt @@ -4,6 +4,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import androidx.room.ColumnInfo import androidx.room.Entity +import androidx.room.Ignore import java.util.Base64 @Entity(tableName = "tiles", primaryKeys = [ "x", "y", "level" ]) @@ -20,6 +21,9 @@ class Tile { @ColumnInfo(name = "data") var base64: String? = null + @Ignore + var bitmap: Bitmap? = null + constructor() constructor(x: Int, y: Int, level: Int) { @@ -35,11 +39,11 @@ class Tile { this.base64 = base64 } - fun getBitmap(): Bitmap? { - if (this.base64 == null) - return null + fun toBitmap(): Bitmap? { + if (bitmap != null || base64 == null) + return bitmap val ba = Base64.getDecoder().decode(this.base64) - val bmp = BitmapFactory.decodeByteArray(ba, 0, ba.size) - return bmp + bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.size) + return bitmap } } \ No newline at end of file From 47cd68fcfeef8eaa00273d67c7baf2661c7bf818 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Tue, 12 Aug 2025 15:42:55 +0300 Subject: [PATCH 3/3] Fixed quick scaling --- .../com/mirenkov/ktheightmap/MapCanvas.kt | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt index fe951bf..9e73d6d 100644 --- a/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt +++ b/app/src/main/java/com/mirenkov/ktheightmap/MapCanvas.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.text.drawText import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withStyle +import kotlin.math.absoluteValue @Composable fun MapCanvas( @@ -48,17 +49,22 @@ fun MapCanvas( ) val oldLevel = tileContainer.getLevel() val level = scale.floatValue.toInt() + val levelDiff = level - oldLevel - if (oldLevel > level) { - offsetX.floatValue -= size.width / 2F + TILE_SIZE - offsetY.floatValue -= size.height / 2F + TILE_SIZE - offsetX.floatValue /= 2F - offsetY.floatValue /= 2F - } else if (oldLevel < level) { - offsetX.floatValue *= 2F - offsetY.floatValue *= 2F - offsetX.floatValue += size.width / 2F + TILE_SIZE - offsetY.floatValue += size.height / 2F + TILE_SIZE + if (levelDiff < 0) { + repeat (levelDiff.absoluteValue) { + offsetX.floatValue -= size.width / 2F + TILE_SIZE + offsetY.floatValue -= size.height / 2F + TILE_SIZE + offsetX.floatValue /= 2F + offsetY.floatValue /= 2F + } + } else if (levelDiff > 0) { + repeat (levelDiff) { + offsetX.floatValue *= 2F + offsetY.floatValue *= 2F + offsetX.floatValue += size.width / 2F + TILE_SIZE + offsetY.floatValue += size.height / 2F + TILE_SIZE + } } val tileOffsetX = (offsetX.floatValue / TILE_SIZE).toInt() val tileOffsetY = (offsetY.floatValue / TILE_SIZE).toInt()