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

View File

@ -20,7 +20,10 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import mu.KotlinLogging import mu.KotlinLogging
import org.jetbrains.skia.Paint 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 { private fun Color.toPaint(): Paint = Paint().apply {
@ -57,7 +60,7 @@ public actual fun MapView(
// Load tiles asynchronously // Load tiles asynchronously
LaunchedEffect(viewPoint, canvasSize) { LaunchedEffect(viewPoint, canvasSize) {
with(mapTileProvider) { 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 left = centerCoordinates.x - canvasSize.width.value / 2 / tileScale
val right = 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 (j in verticalIndices) {
for (i in horizontalIndices) { 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 //ensure that failed tiles do not fail the application
supervisorScope { supervisorScope {
//start all //start all

View File

@ -26,12 +26,12 @@ public object WebMercatorProjection {
/** /**
* https://en.wikipedia.org/wiki/Web_Mercator_projection#Formulas * 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" } 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( return WebMercatorCoordinates(
zoom = floor(zoom).toInt(), zoom = zoom,
x = scaleFactor * (gmc.longitude.radians.value + PI), x = scaleFactor * (gmc.longitude.radians.value + PI),
y = scaleFactor * (PI - ln(tan(PI / 4 + gmc.latitude.radians.value / 2))) y = scaleFactor * (PI - ln(tan(PI / 4 + gmc.latitude.radians.value / 2)))
) )