Compare commits
7 commits
47cd68fcfe
...
f089879d1b
| Author | SHA1 | Date | |
|---|---|---|---|
| f089879d1b | |||
| 7a83286681 | |||
| 2937f17a69 | |||
| 8bdbe3dc69 | |||
| 6c69440b4d | |||
| 3f2b3eec45 | |||
| 8a530d9d48 |
7 changed files with 288 additions and 63 deletions
4
.idea/deploymentTargetSelector.xml
generated
4
.idea/deploymentTargetSelector.xml
generated
|
|
@ -4,10 +4,10 @@
|
|||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-08-08T10:50:02.571721922Z">
|
||||
<DropdownSelection timestamp="2025-08-26T11:06:03.805342749Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/secondbeam/.android/avd/Pixel_3.avd" />
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/secondbeam/.config/.android/avd/Virtual_Pixel_3.avd" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
|
|
|||
|
|
@ -3,33 +3,47 @@ package com.mirenkov.ktheightmap
|
|||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.toUpperCase
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
|
@ -72,7 +86,7 @@ class MainActivity : ComponentActivity() {
|
|||
|
||||
@Composable
|
||||
fun Main(vm: TileViewModel = viewModel()) {
|
||||
val sliderValue = rememberSaveable { mutableFloatStateOf(1F) }
|
||||
var scale by rememberSaveable { vm.scale }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val tileContainer = TileContainer(vm, coroutineScope)
|
||||
KtHeightMapTheme {
|
||||
|
|
@ -81,14 +95,14 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
modifier = Modifier.fillMaxSize()
|
||||
.safeDrawingPadding()
|
||||
.align(Alignment.Center),
|
||||
floatingActionButton = { ToolButton() }
|
||||
floatingActionButton = { ToolButton(vm) }
|
||||
) { innerPadding ->
|
||||
MapCanvas(
|
||||
viewModel = vm,
|
||||
gridColor = colorScheme.primary,
|
||||
backColor = colorScheme.background,
|
||||
scale = sliderValue,
|
||||
tileContainer = tileContainer,
|
||||
modifier = Modifier.padding(innerPadding),
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
Box(modifier = Modifier.safeDrawingPadding()
|
||||
|
|
@ -98,8 +112,8 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
.offset(0.dp, 60.dp)
|
||||
) {
|
||||
Slider(
|
||||
value = sliderValue.floatValue,
|
||||
onValueChange = { sliderValue.floatValue = it },
|
||||
value = scale,
|
||||
onValueChange = { scale = it },
|
||||
valueRange = 1F..14F,
|
||||
modifier = Modifier.align(Alignment.CenterStart)
|
||||
)
|
||||
|
|
@ -109,33 +123,97 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun ToolButton() {
|
||||
fun ToolButton(viewModel: TileViewModel) {
|
||||
val context = LocalContext.current
|
||||
var expanded by rememberSaveable{ mutableStateOf(false) }
|
||||
var debug by rememberSaveable{ viewModel.debug }
|
||||
var logRequested by remember{ viewModel.logRequested }
|
||||
val dialogShown = rememberSaveable{ mutableStateOf(false) }
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
expanded = !expanded
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Filled.Build, contentDescription = "Tools")
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Toggle debug") },
|
||||
onClick = {
|
||||
debug = !debug
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Log") },
|
||||
onClick = {
|
||||
logRequested = true
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Set location") },
|
||||
onClick = {
|
||||
dialogShown.value = true
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Settings") },
|
||||
onClick = {
|
||||
expanded = false
|
||||
val intent = Intent(context, SettingsActivity::class.java)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
) { Icon(Icons.Filled.Build, contentDescription = "Tools") }
|
||||
)
|
||||
SetLocationDialog(viewModel, dialogShown)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun MainPreview() {
|
||||
KtHeightMapTheme {
|
||||
Scaffold(
|
||||
modifier = Modifier.safeDrawingPadding(),
|
||||
floatingActionButton = { ToolButton() }
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = "Gryadki"
|
||||
fun SetLocationDialog(vm: TileViewModel, dialogShown: MutableState<Boolean>) {
|
||||
var showLocationDialog by dialogShown
|
||||
if (showLocationDialog) {
|
||||
var latitudeText by remember { vm.latitudeText }
|
||||
var longitudeText by remember { vm.longitudeText }
|
||||
AlertDialog (
|
||||
onDismissRequest = { showLocationDialog = false },
|
||||
title = { Text("Input coordinates") },
|
||||
text = {
|
||||
Column {
|
||||
TextField(
|
||||
value = latitudeText,
|
||||
onValueChange = { newValue ->
|
||||
latitudeText = newValue
|
||||
},
|
||||
label = { Text("Latitude") },
|
||||
placeholder = { Text("60.086763") },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
|
||||
)
|
||||
TextField(
|
||||
value = longitudeText,
|
||||
onValueChange = { newValue ->
|
||||
longitudeText = newValue
|
||||
},
|
||||
label = { Text("Longitude") },
|
||||
placeholder = { Text("30.014658") },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = { TextButton(onClick = {
|
||||
val latitude = latitudeText.text.toDoubleOrNull() ?: 0.0
|
||||
val longitude = longitudeText.text.toDoubleOrNull() ?: 0.0
|
||||
Log.i(TAG, "Lat: %.6f, Lon: %.6f".format(latitude, longitude))
|
||||
Log.i(TAG, "X = %.6f".format(SphereMercator.mercateLon(longitude, vm.scale.floatValue.toInt(), -TILE_SIZE.toDouble())))
|
||||
}) {
|
||||
Text("Confirm".uppercase())
|
||||
} },
|
||||
dismissButton = { TextButton(onClick = { showLocationDialog = false }) {
|
||||
Text("Cancel".uppercase())
|
||||
} }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,21 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableFloatState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
|
|
@ -25,52 +30,71 @@ import kotlin.math.absoluteValue
|
|||
|
||||
@Composable
|
||||
fun MapCanvas(
|
||||
viewModel: TileViewModel,
|
||||
backColor: Color,
|
||||
gridColor: Color,
|
||||
scale: MutableFloatState,
|
||||
tileContainer: TileContainer,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val offsetX = rememberSaveable { mutableFloatStateOf(-TILE_SIZE) }
|
||||
val offsetY = rememberSaveable { mutableFloatStateOf(-TILE_SIZE) }
|
||||
var offsetX by rememberSaveable { viewModel.mapOffsetX }
|
||||
var offsetY by rememberSaveable { viewModel.mapOffsetY }
|
||||
val scale by rememberSaveable { viewModel.scale }
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val debug by rememberSaveable { viewModel.debug }
|
||||
var logRequested by rememberSaveable { viewModel.logRequested }
|
||||
Canvas(
|
||||
modifier = modifier.fillMaxSize()
|
||||
.pointerInput(Unit) {
|
||||
detectDragGestures { _, distance ->
|
||||
offsetX.floatValue -= distance.x
|
||||
offsetY.floatValue -= distance.y
|
||||
offsetX -= distance.x
|
||||
offsetY -= distance.y
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (viewModel.halvedOffsetX == null) {
|
||||
viewModel.halvedOffsetX = size.width / 2
|
||||
viewModel.halvedOffsetY = size.height / 2
|
||||
}
|
||||
val halvedX = viewModel.halvedOffsetX!!
|
||||
val halvedY = viewModel.halvedOffsetY!!
|
||||
|
||||
drawRect(
|
||||
color = backColor,
|
||||
size = size
|
||||
)
|
||||
|
||||
if (logRequested) {
|
||||
Log.i(TAG, "Offset: %.6f, %.6f".format(offsetX, offsetY))
|
||||
logRequested = false
|
||||
}
|
||||
|
||||
val oldLevel = tileContainer.getLevel()
|
||||
val level = scale.floatValue.toInt()
|
||||
val level = scale.toInt()
|
||||
val levelDiff = level - oldLevel
|
||||
|
||||
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
|
||||
offsetX -= halvedX + TILE_SIZE
|
||||
offsetY -= halvedY + TILE_SIZE
|
||||
offsetX /= 2F
|
||||
offsetY /= 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
|
||||
offsetX *= 2F
|
||||
offsetY *= 2F
|
||||
offsetX += halvedX + TILE_SIZE
|
||||
offsetY += halvedY + TILE_SIZE
|
||||
}
|
||||
}
|
||||
val tileOffsetX = (offsetX.floatValue / TILE_SIZE).toInt()
|
||||
val tileOffsetY = (offsetY.floatValue / TILE_SIZE).toInt()
|
||||
val tileOffsetX = (offsetX / TILE_SIZE).toInt()
|
||||
val tileOffsetY = (offsetY / TILE_SIZE).toInt()
|
||||
|
||||
val strippedOffsetX = offsetX.floatValue % TILE_SIZE
|
||||
val strippedOffsetY = offsetY.floatValue % TILE_SIZE
|
||||
val centerTileX = (1 + (offsetX + halvedX) / TILE_SIZE).toDouble()
|
||||
val centerTileY = (1 + (offsetY + halvedY) / TILE_SIZE).toDouble()
|
||||
|
||||
val strippedOffsetX = offsetX % TILE_SIZE
|
||||
val strippedOffsetY = offsetY % TILE_SIZE
|
||||
|
||||
val offset = Offset(strippedOffsetX, strippedOffsetY)
|
||||
|
||||
|
|
@ -81,6 +105,12 @@ fun MapCanvas(
|
|||
|
||||
val tiles = tileContainer.getTiles(tileOffsetX, tileOffsetY, tileOffsetX + gridWidth + 2, tileOffsetY + gridHeight + 2, level)
|
||||
|
||||
val crossRadius = 24F
|
||||
|
||||
val additionalSize = if (debug) 96F else 0F
|
||||
val latLonSize = Size(216F, 96F + additionalSize)
|
||||
val latLonOffset = Offset(16F, 16F)
|
||||
|
||||
for (cellX in 0 .. gridWidth + 2) {
|
||||
val tileX = tileOffsetX + cellX
|
||||
val localOffsetX = TILE_SIZE * (cellX - 1)
|
||||
|
|
@ -88,20 +118,23 @@ 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 }?.toBitmap()
|
||||
val tile = tiles.find { it.x == tileX && it.y == tileY && it.level == level }!!
|
||||
val bitmap = tile.toBitmap()
|
||||
val totalOffset = Offset(localOffsetX, localOffsetY) - offset
|
||||
|
||||
bitmap?.let {
|
||||
val imageBitmap = bitmap.asImageBitmap()
|
||||
drawImage(
|
||||
image = imageBitmap,
|
||||
topLeft = Offset(localOffsetX, localOffsetY) - offset
|
||||
topLeft = totalOffset
|
||||
)
|
||||
}
|
||||
/*
|
||||
|
||||
if (debug) {
|
||||
drawRect(
|
||||
color = gridColor,
|
||||
size = Size(TILE_SIZE, TILE_SIZE),
|
||||
topLeft = Offset(localOffsetX, localOffsetY) - offset,
|
||||
topLeft = totalOffset,
|
||||
style = Stroke(width = 4F)
|
||||
)
|
||||
|
||||
|
|
@ -110,14 +143,53 @@ fun MapCanvas(
|
|||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
append("x:%d, y:%d".format(tileX, tileY))
|
||||
val mercX = tile.mercateX()
|
||||
val mercY = tile.mercateY()
|
||||
append("%.6f, %.6f,\n%d, %d".format(mercX, mercY, tileX, tileY))
|
||||
}
|
||||
}
|
||||
},
|
||||
topLeft = Offset(localOffsetX, localOffsetY) - offset,
|
||||
topLeft = totalOffset,
|
||||
size = Size(TILE_SIZE, TILE_SIZE)
|
||||
)
|
||||
*/
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
drawPath(
|
||||
path,
|
||||
Color.White,
|
||||
style = Stroke(width = 6F)
|
||||
)
|
||||
|
||||
drawRect(
|
||||
color = backColor,
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
val lon = SphereMercator.mercateX(centerTileX, level)
|
||||
val lat = SphereMercator.mercateY(centerTileY, level)
|
||||
append("%.6f\n%.6f".format(lon, lat))
|
||||
if (debug) {
|
||||
append("\n%.0f\n%.0f".format(offsetX, offsetY))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
app/src/main/java/com/mirenkov/ktheightmap/SphereMercator.kt
Normal file
58
app/src/main/java/com/mirenkov/ktheightmap/SphereMercator.kt
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import java.lang.Math.toRadians
|
||||
import java.lang.Math.toDegrees
|
||||
import kotlin.math.atan
|
||||
import kotlin.math.exp
|
||||
import kotlin.math.ln
|
||||
import kotlin.math.tan
|
||||
import kotlin.math.PI
|
||||
|
||||
class SphereMercator {
|
||||
companion object {
|
||||
const val RADIUS = 6378137
|
||||
const val METERS_PER_PIXEL = 156543.0339
|
||||
|
||||
fun x2lon(x: Double): Double {
|
||||
return toDegrees(x / RADIUS)
|
||||
}
|
||||
|
||||
fun y2lat(y: Double): Double {
|
||||
return toDegrees(atan(exp(y / RADIUS / 2)) * 2 - PI / 2)
|
||||
}
|
||||
|
||||
fun lon2x(longitude: Double): Double {
|
||||
return toRadians(longitude) * RADIUS
|
||||
}
|
||||
|
||||
fun lat2y(latitude: Double): Double {
|
||||
return ln(tan(PI / 4 + toRadians(latitude) / 2)) * RADIUS
|
||||
}
|
||||
|
||||
fun scaledMetersPerPixel(level: Int): Double {
|
||||
return METERS_PER_PIXEL / ( 1 shl (level - 1) )
|
||||
}
|
||||
|
||||
fun sx2lon(x: Double, level: Int): Double {
|
||||
return x2lon(x * scaledMetersPerPixel(level))
|
||||
}
|
||||
|
||||
fun sy2lat(y: Double, level: Int): Double {
|
||||
return y2lat( y * scaledMetersPerPixel(level))
|
||||
}
|
||||
|
||||
fun lon2sx(longitude: Double, level: Int) : Double {
|
||||
return lon2x(longitude) / scaledMetersPerPixel(level)
|
||||
}
|
||||
|
||||
fun lat2sy(latitude: Double, level: Int): Double {
|
||||
return lat2y(latitude) / scaledMetersPerPixel(level)
|
||||
}
|
||||
|
||||
fun mercateX(x: Double, level: Int): Double = sx2lon((x * TILE_SIZE), level) - 180.0
|
||||
|
||||
fun mercateY(y: Double, level: Int): Double = -sy2lat((y - ((1 shl (level - 1)).toDouble() / 2.0)) * TILE_SIZE, level - 1)
|
||||
|
||||
fun mercateLon(longitude: Double, level: Int, offset: Double): Double = lon2sx(longitude + 180.0, level) + offset
|
||||
}
|
||||
}
|
||||
|
|
@ -46,4 +46,8 @@ class Tile {
|
|||
bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.size)
|
||||
return bitmap
|
||||
}
|
||||
|
||||
fun mercateX(): Double = SphereMercator.mercateX(x.toDouble(), level)
|
||||
|
||||
fun mercateY(): Double = SphereMercator.mercateY(y.toDouble(), level)
|
||||
}
|
||||
|
|
@ -12,14 +12,12 @@ class TileRepository(private val tileDao: TileDao) {
|
|||
fun pushTile(tile: Tile) {
|
||||
coroutineScope.launch(Dispatchers.IO) { tileDao.pushTile(tile) }
|
||||
}
|
||||
|
||||
fun getTile(x: Int, y: Int, level: Int): Tile? {
|
||||
val tileFuture = coroutineScope.future(Dispatchers.IO) {
|
||||
tileDao.getTile(x, y, level)
|
||||
}
|
||||
return tileFuture.join()
|
||||
}
|
||||
|
||||
fun clearTiles() {
|
||||
coroutineScope.launch(Dispatchers.IO) { tileDao.clearTiles() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,27 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import android.app.Application
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class TileViewModel(application: Application): ViewModel() {
|
||||
val repository: TileRepository
|
||||
|
||||
var debug = mutableStateOf(false)
|
||||
var logRequested = mutableStateOf(false)
|
||||
|
||||
var latitudeText = mutableStateOf(TextFieldValue(""))
|
||||
var longitudeText = mutableStateOf(TextFieldValue(""))
|
||||
|
||||
val mapOffsetX = mutableFloatStateOf(-646.65625F)
|
||||
val mapOffsetY = mutableFloatStateOf(-1157.2814F)
|
||||
val scale = mutableFloatStateOf(1F)
|
||||
|
||||
var halvedOffsetX: Float? = null
|
||||
var halvedOffsetY: Float? = null
|
||||
|
||||
init {
|
||||
val tileDb = TileDB.getInstance(application)
|
||||
val tileDao = tileDb.tileDao()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue