diff --git a/api/android-for-longdo.api b/api/android-for-longdo.api index 90efe1f..99ecfa1 100644 --- a/api/android-for-longdo.api +++ b/api/android-for-longdo.api @@ -141,7 +141,7 @@ public final class com.mapconductor.longdo.LongdoMapViewControllerMarkerTilesKt public static final void renderTiledMarkers(com.mapconductor.longdo.LongdoMapViewController, java.util.List); public static final void applyMarkerTileRaster(com.mapconductor.longdo.LongdoMapViewController, com.mapconductor.core.raster.RasterLayerState); public static final void removeMarkerTileRaster(com.mapconductor.longdo.LongdoMapViewController); - public static final boolean handleMarkerTap(com.mapconductor.longdo.LongdoMapViewController, com.mapconductor.core.features.GeoPoint, double); + public static final boolean handleMarkerTap(com.mapconductor.longdo.LongdoMapViewController, com.mapconductor.core.features.GeoPoint); } public final class com.mapconductor.longdo.LongdoMapViewControllerRasterKt { public static final void applyRaster(com.mapconductor.longdo.LongdoMapViewController, com.mapconductor.core.raster.RasterLayerState); @@ -339,6 +339,7 @@ public final class com.mapconductor.longdo.marker.LongdoMarkerTileRenderer { public final com.mapconductor.core.raster.RasterLayerState render(java.util.List); public final java.lang.String getRasterLayerId(); public final void clear(); + public final com.mapconductor.core.marker.MarkerState findMarkerAt(com.mapconductor.core.features.GeoPointInterface, kotlin.jvm.functions.Function1); public final com.mapconductor.core.marker.MarkerState findMarkerAt(com.mapconductor.core.features.GeoPointInterface, double); } final class com.mapconductor.longdo.marker.LongdoMarkerTileRenderer$Companion { diff --git a/src/main/java/com/mapconductor/longdo/LongdoMapView.kt b/src/main/java/com/mapconductor/longdo/LongdoMapView.kt index d32b4ed..a4c4195 100644 --- a/src/main/java/com/mapconductor/longdo/LongdoMapView.kt +++ b/src/main/java/com/mapconductor/longdo/LongdoMapView.kt @@ -291,12 +291,12 @@ fun LongdoMapSurface( pushTargets() onLoaded?.invoke(currentState) } - bridge.onMapClick = { point, zoom -> + bridge.onMapClick = { point, _ -> // marker → circle → groundImage → polyline → polygon → map のカスケード。 // **必ずどれか 1 つだけ**が配送される(他プロバイダと同じ)。 // 順序と先勝ちはコアの dispatchOverlayTap が持つ。マーカーだけは Longdo の // タイルレンダラでヒットテストするのでここで先に見る。 - if (!controller.handleMarkerTap(point, zoom) && !controller.dispatchOverlayTap(point)) { + if (!controller.handleMarkerTap(point) && !controller.dispatchOverlayTap(point)) { onClick?.invoke(point) } } diff --git a/src/main/java/com/mapconductor/longdo/LongdoMapViewControllerMarkerTiles.kt b/src/main/java/com/mapconductor/longdo/LongdoMapViewControllerMarkerTiles.kt index 28b8758..05e9187 100644 --- a/src/main/java/com/mapconductor/longdo/LongdoMapViewControllerMarkerTiles.kt +++ b/src/main/java/com/mapconductor/longdo/LongdoMapViewControllerMarkerTiles.kt @@ -92,14 +92,12 @@ internal fun LongdoMapViewController.removeMarkerTileRaster() { * 流さない(他プロバイダと同じ)。 * * @param point タップ座標。 - * @param nativeZoom Longdo ネイティブ(MapLibre)ズーム。 * @return マーカーがタップを消費したら true。 */ internal fun LongdoMapViewController.handleMarkerTap( point: com.mapconductor.core.features.GeoPoint, - nativeZoom: Double, ): Boolean { - val state = markerTileRenderer?.findMarkerAt(point, nativeZoom) ?: return false + val state = markerTileRenderer?.findMarkerAt(point, holder::toScreenOffset) ?: return false // clickable = false のマーカーは透過させる(コアの clickableOnly と同じ方針)。 if (!state.clickable) return false state.onClick?.invoke(state) diff --git a/src/main/java/com/mapconductor/longdo/marker/LongdoMarkerTileRenderer.kt b/src/main/java/com/mapconductor/longdo/marker/LongdoMarkerTileRenderer.kt index 290d669..f302a6a 100644 --- a/src/main/java/com/mapconductor/longdo/marker/LongdoMarkerTileRenderer.kt +++ b/src/main/java/com/mapconductor/longdo/marker/LongdoMarkerTileRenderer.kt @@ -1,5 +1,8 @@ package com.mapconductor.longdo.marker +import com.mapconductor.core.InternalMapConductorApi +import com.mapconductor.core.marker.MarkerHitPick +import androidx.compose.ui.geometry.Offset import com.mapconductor.core.features.GeoPointInterface import com.mapconductor.core.marker.MarkerEntity import com.mapconductor.core.marker.MarkerManager @@ -10,10 +13,10 @@ import com.mapconductor.core.raster.RasterLayerSource import com.mapconductor.core.raster.RasterLayerState import com.mapconductor.core.raster.TileScheme import com.mapconductor.core.tileserver.TileServerRegistry -import java.util.UUID import kotlin.math.cos import kotlin.math.pow import kotlin.math.sqrt +import java.util.UUID /** * 大量マーカー(「Bunch of Markers」等)を、他モジュール(maplibre / maptiler 等)と同じ方式= @@ -95,8 +98,31 @@ class LongdoMarkerTileRenderer( } /** - * タップ座標付近のマーカーを返す(クリック用の簡易ヒットテスト)。 + * タップ座標に当たるマーカーを返す。選び方はコアの [MarkerHitPick.pick] と同じで、 + * 指の下にアイコンかラベルが描かれているマーカーが、先端の近い別のマーカーより優先する。 + * + * @param project 地理座標をビューの画面座標へ投影する(holder の toScreenOffset)。 + */ + @OptIn(InternalMapConductorApi::class) + fun findMarkerAt( + tap: GeoPointInterface, + project: (GeoPointInterface) -> Offset?, + ): MarkerState? { + if (markers.isEmpty()) return null + val touchScreen = project(tap) ?: return null + val bounds = MarkerHitPick.searchBounds(tap, touchScreen, project) ?: return null + val candidates = markers.filter { bounds.contains(it.position) } + return MarkerHitPick.pickBy(touchScreen, candidates, { it }, project) + } + + /** + * 旧来の判定(先端からの距離だけを見る)。ラベルやアイコンの大きさを見ないので、 + * 指の下に描かれているマーカーより先端の近い別のマーカーを選ぶことがある。 */ + @Deprecated( + "先端からの距離だけで選ぶ旧来の判定。findMarkerAt(tap, project) を使う。", + ReplaceWith("findMarkerAt(tap, project)"), + ) fun findMarkerAt( tap: GeoPointInterface, nativeZoom: Double,