Generalize feature draw logic
This commit is contained in:
parent
5b95adc649
commit
8a94438dfd
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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)))
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user