Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions api/android-for-mapbox.api
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,29 @@ public interface com.mapconductor.mapbox.IMapboxPaddingsInterface extends com.ma
public abstract com.mapbox.maps.EdgeInsets toEdgeInsects();
}
public final class com.mapconductor.mapbox.MapCameraPositionKt {
public static final double MAPBOX_VERTICAL_FOV;
public static final com.mapbox.maps.EdgeInsets toMapboxEdgeInsets(com.mapconductor.core.map.MapPaddingsInterface, float);
public static final com.mapconductor.core.map.MapPaddings toMapPaddings(com.mapbox.maps.EdgeInsets, float);
public static final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition(com.mapbox.maps.CameraChanged);
public static final com.mapbox.maps.CameraOptions toCameraOptions(com.mapconductor.core.map.MapCameraPosition);
public static final com.mapbox.maps.CameraOptions toCameraOptions(com.mapconductor.core.map.MapCameraPosition, java.lang.Float);
public static final com.mapbox.maps.CameraState toCameraState(com.mapconductor.core.map.MapCameraPosition);
public static final com.mapconductor.core.map.MapCameraPosition from(com.mapconductor.core.map.MapCameraPosition$Companion, com.mapconductor.core.map.MapCameraPositionInterface);
public static final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition(com.mapbox.maps.CameraOptions);
public static final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition(com.mapbox.maps.CameraState);
public static final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition(com.mapbox.maps.CameraState, java.lang.Double);
public static final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition(com.mapbox.maps.CameraState, java.lang.Double, java.lang.Float);
}
public final class com.mapconductor.mapbox.MapboxCameraStateSnapshot {
public com.mapconductor.mapbox.MapboxCameraStateSnapshot(com.mapbox.maps.CameraState, java.lang.Double);
public com.mapconductor.mapbox.MapboxCameraStateSnapshot(com.mapbox.maps.CameraState, java.lang.Double, java.lang.Float);
public com.mapconductor.mapbox.MapboxCameraStateSnapshot(com.mapbox.maps.CameraState, java.lang.Double, java.lang.Float, int, kotlin.jvm.internal.DefaultConstructorMarker);
public final com.mapbox.maps.CameraState getCameraState();
public final java.lang.Double getLogicalTiltHint();
public final java.lang.Float getDensity();
public final com.mapconductor.core.map.MapCameraPosition toMapCameraPosition();
public final com.mapbox.maps.CameraState component1();
public final java.lang.Double component2();
public final com.mapconductor.mapbox.MapboxCameraStateSnapshot copy(com.mapbox.maps.CameraState, java.lang.Double);
public final java.lang.Float component3();
public final com.mapconductor.mapbox.MapboxCameraStateSnapshot copy(com.mapbox.maps.CameraState, java.lang.Double, java.lang.Float);
public java.lang.String toString();
public int hashCode();
public boolean equals(java.lang.Object);
Expand Down Expand Up @@ -151,6 +158,7 @@ public final class com.mapconductor.mapbox.MapboxMapViewController extends com.m
public final class com.mapconductor.mapbox.MapboxMapViewControllerCameraKt {
public static final com.mapconductor.core.map.MapCameraPosition getMapCameraPosition(com.mapconductor.mapbox.MapboxMapViewController);
public static final com.mapconductor.core.map.MapCameraPosition readLogicalCameraPosition(com.mapconductor.mapbox.MapboxMapViewController);
public static final float density(com.mapconductor.mapbox.MapboxMapViewController);
public static final java.lang.Object getMapCameraPositionAsync(com.mapconductor.mapbox.MapboxMapViewController, kotlin.coroutines.Continuation<? super com.mapconductor.core.map.MapCameraPosition>);
public static final void handleMoveCamera(com.mapconductor.mapbox.MapboxMapViewController, com.mapconductor.core.map.MapCameraPosition);
public static final void handleAnimateCamera(com.mapconductor.mapbox.MapboxMapViewController, com.mapconductor.core.map.MapCameraPosition, long);
Expand Down
56 changes: 42 additions & 14 deletions src/main/java/com/mapconductor/mapbox/MapCameraPosition.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.mapconductor.core.features.GeoPointInterface
import com.mapconductor.core.map.CameraBearing
import com.mapconductor.core.map.MapCameraPosition
import com.mapconductor.core.map.MapCameraPositionInterface
import com.mapconductor.core.map.MapPaddings
import com.mapconductor.core.map.MapPaddingsInterface
import com.mapconductor.core.map.VisibleRegion
import com.mapconductor.core.spherical.Spherical
Expand All @@ -19,21 +20,42 @@ import kotlin.math.tan

private val converter = ZoomAltitudeConverter()

/**
* Mapbox のカメラの縦方向の視野角(度)。Mapbox Maps の既定値で、地図の大きさに
* よらず一定(焦点距離 = 地図の高さ × 1.5)。TB520FU で 36.9° を実測。
*/
internal const val MAPBOX_VERTICAL_FOV = 36.87

/** dp のパディング → Mapbox の px のパディング。 */
internal fun MapPaddingsInterface.toMapboxEdgeInsets(density: Float): EdgeInsets =
EdgeInsets(top * density, left * density, bottom * density, right * density)

/** Mapbox の px のパディング → dp のパディング。 */
internal fun EdgeInsets.toMapPaddings(density: Float): MapPaddings =
MapPaddings(top = top / density, left = left / density, bottom = bottom / density, right = right / density)

fun CameraChanged.toMapCameraPosition() =
cameraState
.toMapCameraPosition()
.copy(paddings = cameraState.padding.toPaddings())

fun MapCameraPosition.toCameraOptions(): CameraOptions {
fun MapCameraPosition.toCameraOptions(): CameraOptions = toCameraOptions(density = null)

/**
* [density] があれば [MapCameraPosition.paddings] を Mapbox のパディングとして渡す。
* Mapbox はパディングを除いた領域の中央にカメラの中心を置き、tilt の遠近もエンジンが解く。
* パディングは次に変えるまで残るので、null(未指定)のときは渡さない。
*/
internal fun MapCameraPosition.toCameraOptions(density: Float?): CameraOptions {
val padding = if (density != null) paddings?.toMapboxEdgeInsets(density) else null
if (this.tilt >= 0) {
return CameraOptions
.Builder()
.center(GeoPoint.from(position).toPoint())
.zoom(ZoomAltitudeConverter.googleZoomToMapboxZoom(zoom))
.pitch(tilt)
.bearing(CameraBearing.toNativeHeading(bearing))
// TODO:
// .padding(paddings?.toEdgeInsects())
.padding(padding)
.build()
} else {
// tilt < 0: Mapbox cannot represent an upward pitch directly.
Expand All @@ -53,8 +75,7 @@ fun MapCameraPosition.toCameraOptions(): CameraOptions {
.zoom(mapboxZoom)
.pitch(tiltAbsDeg)
.bearing(CameraBearing.toNativeHeading(bearing))
// TODO:
// .padding(paddings?.toEdgeInsects())
.padding(padding)
.build()
}
}
Expand All @@ -79,6 +100,7 @@ fun MapCameraPosition.Companion.from(cameraPosition: MapCameraPositionInterface)
tilt = cameraPosition.tilt,
paddings = MapboxPaddings.from(cameraPosition.paddings),
visibleRegion = cameraPosition.visibleRegion,
fov = cameraPosition.fov,
)
}

Expand All @@ -101,20 +123,24 @@ fun CameraState.toMapCameraPosition() =
logicalTiltHint = null,
)

internal fun CameraState.toMapCameraPosition(logicalTiltHint: Double?) =
toMapCameraPosition(
center = center.toGeoPoint(),
mapboxZoom = zoom,
bearing = bearing,
pitch = pitch,
logicalTiltHint = logicalTiltHint,
)
internal fun CameraState.toMapCameraPosition(
logicalTiltHint: Double?,
density: Float? = null,
) = toMapCameraPosition(
center = center.toGeoPoint(),
mapboxZoom = zoom,
bearing = bearing,
pitch = pitch,
paddings = density?.let { padding.toMapPaddings(it) },
logicalTiltHint = logicalTiltHint,
)

internal data class MapboxCameraStateSnapshot(
val cameraState: CameraState,
val logicalTiltHint: Double?,
val density: Float? = null,
) {
fun toMapCameraPosition(): MapCameraPosition = cameraState.toMapCameraPosition(logicalTiltHint)
fun toMapCameraPosition(): MapCameraPosition = cameraState.toMapCameraPosition(logicalTiltHint, density)
}

private fun toMapCameraPosition(
Expand All @@ -135,6 +161,7 @@ private fun toMapCameraPosition(
tilt = pitch,
paddings = paddings,
visibleRegion = visibleRegion,
fov = MAPBOX_VERTICAL_FOV,
)
}

Expand All @@ -153,5 +180,6 @@ private fun toMapCameraPosition(
tilt = -pitchAbsDeg,
paddings = paddings,
visibleRegion = visibleRegion,
fov = MAPBOX_VERTICAL_FOV,
)
}
2 changes: 1 addition & 1 deletion src/main/java/com/mapconductor/mapbox/MapboxMapView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ fun MapboxMapView(
modifier = modifier,
viewProvider = {
val cameraOptions =
state.cameraPosition.toCameraOptions()
state.cameraPosition.toCameraOptions(context.resources.displayMetrics.density)

val styleUri = state.mapDesignType.getValue()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ internal fun MapboxMapViewController.readLogicalCameraPosition(): MapCameraPosit
MapboxCameraStateSnapshot(
cameraState = holder.map.cameraState,
logicalTiltHint = lastLogicalCameraPosition?.tilt,
density = density(),
).toMapCameraPosition()

internal fun MapboxMapViewController.density(): Float = holder.mapView.resources.displayMetrics.density

/**
* Async version of getMapCameraPosition that can be called from background threads.
* Uses withContext to ensure Mapbox SDK calls run on the main thread.
Expand All @@ -43,7 +46,7 @@ internal suspend fun MapboxMapViewController.getMapCameraPositionAsync(): MapCam
}

internal fun MapboxMapViewController.handleMoveCamera(position: MapCameraPosition) {
val cameraOptions = position.toCameraOptions()
val cameraOptions = position.toCameraOptions(density())
lastLogicalCameraPosition = position
mainCoroutine.launch {
holder.map.setCamera(cameraOptions)
Expand All @@ -54,7 +57,7 @@ internal fun MapboxMapViewController.handleAnimateCamera(
position: MapCameraPosition,
duration: Long,
) {
val targetCamera = position.toCameraOptions()
val targetCamera = position.toCameraOptions(density())
lastLogicalCameraPosition = position

val animationOptions =
Expand Down
Loading