Generalize feature draw logic

This commit is contained in:
Alexander Nozik 2022-12-25 11:29:31 +03:00
parent 5b95adc649
commit 8a94438dfd
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
3 changed files with 16 additions and 11 deletions

View File

@ -11,21 +11,23 @@ internal class MapState internal constructor(
config: ViewConfig<Gmc>,
canvasSize: DpSize,
viewPoint: ViewPoint<Gmc>,
public val tileSize: Int,
val tileSize: Int,
) : CoordinateViewState<Gmc>(config, canvasSize, viewPoint) {
override val space: CoordinateSpace<Gmc> get() = GmcCoordinateSpace
public val scaleFactor: Double
get() = WebMercatorProjection.scaleFactor(viewPoint.zoom)
val intZoom: Int get() = floor(zoom).toInt()
public val centerCoordinates: WebMercatorCoordinates
get() = WebMercatorProjection.toMercator(viewPoint.focus, zoom)
get() = WebMercatorProjection.toMercator(viewPoint.focus, intZoom)
internal val tileScale: Double
get() = 2.0.pow(viewPoint.zoom - zoom)
get() = 2.0.pow(viewPoint.zoom - floor(viewPoint.zoom))
private fun DpOffset.toMercator(): WebMercatorCoordinates = WebMercatorCoordinates(
floor(zoom).toInt(),
intZoom,
(x - canvasSize.width / 2).value / tileScale + centerCoordinates.x,
(y - canvasSize.height / 2).value / tileScale + centerCoordinates.y,
)
@ -42,7 +44,7 @@ internal class MapState internal constructor(
)
override fun Gmc.toDpOffset(): DpOffset =
WebMercatorProjection.toMercator(this, zoom).toOffset()
WebMercatorProjection.toMercator(this, intZoom).toOffset()
override fun Rectangle<Gmc>.toDpRect(): DpRect {
val topLeft = topLeft.toDpOffset()

View File

@ -20,7 +20,10 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import mu.KotlinLogging
import org.jetbrains.skia.Paint
import kotlin.math.*
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
private fun Color.toPaint(): Paint = Paint().apply {
@ -57,7 +60,7 @@ public actual fun MapView(
// Load tiles asynchronously
LaunchedEffect(viewPoint, canvasSize) {
with(mapTileProvider) {
val indexRange = 0 until 2.0.pow(zoom).toInt()
val indexRange = 0 until 2.0.pow(intZoom).toInt()
val left = centerCoordinates.x - canvasSize.width.value / 2 / tileScale
val right = centerCoordinates.x + canvasSize.width.value / 2 / tileScale
@ -71,7 +74,7 @@ public actual fun MapView(
for (j in verticalIndices) {
for (i in horizontalIndices) {
val id = TileId(floor(zoom).toInt(), i, j)
val id = TileId(intZoom, i, j)
//ensure that failed tiles do not fail the application
supervisorScope {
//start all

View File

@ -26,12 +26,12 @@ public object WebMercatorProjection {
/**
* https://en.wikipedia.org/wiki/Web_Mercator_projection#Formulas
*/
public fun toMercator(gmc: GeodeticMapCoordinates, zoom: Double): WebMercatorCoordinates {
public fun toMercator(gmc: GeodeticMapCoordinates, zoom: Int): WebMercatorCoordinates {
require(abs(gmc.latitude) <= MercatorProjection.MAXIMUM_LATITUDE) { "Latitude exceeds the maximum latitude for mercator coordinates" }
val scaleFactor = scaleFactor(zoom)
val scaleFactor = scaleFactor(zoom.toDouble())
return WebMercatorCoordinates(
zoom = floor(zoom).toInt(),
zoom = zoom,
x = scaleFactor * (gmc.longitude.radians.value + PI),
y = scaleFactor * (PI - ln(tan(PI / 4 + gmc.latitude.radians.value / 2)))
)