From 9a396805e2fb6147324c4587c67e5311231b1849 Mon Sep 17 00:00:00 2001 From: masashi Date: Tue, 1 Sep 2026 11:40:23 +0900 Subject: [PATCH 1/3] Make bearing a clockwise map rotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bearing を「値を増やすと地図が時計回りに回る」向きに統一し、ネイティブ SDK との変換をコアの CameraBearing に集約する。 --- .../OpenMobileMapsMapViewController.kt | 21 ++++++++++--------- .../OpenMobileMapsTiltEmulation.kt | 5 +++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt index 3985ce3..0265712 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsMapViewController.kt @@ -4,6 +4,7 @@ import com.mapconductor.core.controller.BaseMapViewController import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.features.GeoPointInterface import com.mapconductor.core.features.GeoRectBounds +import com.mapconductor.core.map.CameraBearing import com.mapconductor.core.map.MapCameraPosition import com.mapconductor.core.map.MapCapabilityStatus import com.mapconductor.core.map.MapUISettings @@ -475,20 +476,20 @@ class OpenMobileMapsMapViewController( companion object { /** - * 方位の符号。**SDK は MapConductor と逆回りである。** + * 方位の符号。**SDK の `setRotation` は MapConductor の bearing と同じ向き** + * (どちらも「地図を時計回りに回す量」)なので、変換は恒等になる。 * - * MapConductor の bearing は Google 準拠で「カメラが向いている方位を北から時計回りに測る」。 - * SDK の `setRotation` は地図を反時計回りに回す量なので、符号を反転する。 - * 反転を忘れると bearing 270 の地図が 90 として描かれ、**ちょうど 180 度ずれる** - * (tilt ページを MapLibre と並べて気づいた。単独で見ると「回っている」ので正しく見える)。 + * ここは机上ではなく端末で決めた値である。基準は「MapLibre と並べて同じ向きに + * 描かれること」で、MapLibre 側が heading 系(bearing の符号反転)に変わったのに + * 合わせてこちらも反転させてある。**符号を触ったら必ず tilt ページを MapLibre と + * 並べて確認すること。** 単独で見ると「回っている」ので正しく見えてしまう。 */ - internal fun nativeRotationFromBearing(bearing: Double): Float = (-bearing).toFloat() + internal fun nativeRotationFromBearing(bearing: Double): Float = + CameraBearing.toNativeRotation(bearing).toFloat() /** SDK の回転角 → MapConductor の bearing(0 以上 360 未満)。 */ - internal fun bearingFromNativeRotation(rotation: Float): Double { - val bearing = -rotation.toDouble() % 360.0 - return if (bearing < 0) bearing + 360.0 else bearing - } + internal fun bearingFromNativeRotation(rotation: Float): Double = + CameraBearing.bearingFromNativeRotation(rotation.toDouble()) /** * ズームの往復換算。 diff --git a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsTiltEmulation.kt b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsTiltEmulation.kt index 497bf18..a430217 100644 --- a/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsTiltEmulation.kt +++ b/src/main/java/com/mapconductor/openmobilemaps/OpenMobileMapsTiltEmulation.kt @@ -2,6 +2,7 @@ package com.mapconductor.openmobilemaps import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.features.GeoPointInterface +import com.mapconductor.core.map.CameraBearing import com.mapconductor.core.map.MapCameraPosition import com.mapconductor.core.spherical.Spherical import com.mapconductor.core.zoom.AbstractZoomAltitudeConverter @@ -53,7 +54,7 @@ internal object OpenMobileMapsTiltEmulation { val tiltAbsRad = Math.toRadians(tiltAbsDeg) val altitude = altitudeFor(position.zoom, position.position.latitude) val distanceForward = altitude * cos(tiltAbsRad) * tan(tiltAbsRad) * TARGET_DISTANCE_SCALE - val target = Spherical.computeOffset(position.position, distanceForward, position.bearing) + val target = Spherical.computeOffset(position.position, distanceForward, CameraBearing.toNativeHeading(position.bearing)) return target to zoom } @@ -71,7 +72,7 @@ internal object OpenMobileMapsTiltEmulation { val tiltAbsRad = Math.toRadians(tiltAbsDeg) val altitude = altitudeFor(originalZoom, center.latitude) val distanceBackward = altitude * cos(tiltAbsRad) * tan(tiltAbsRad) * TARGET_DISTANCE_SCALE - val originalPosition: GeoPoint = Spherical.computeOffset(center, distanceBackward, bearing + 180.0) + val originalPosition: GeoPoint = Spherical.computeOffset(center, distanceBackward, CameraBearing.toNativeHeading(bearing) + 180.0) return originalPosition to originalZoom } From 1cfc20e7b072efda5d5c5da8a5a32c17885254ab Mon Sep 17 00:00:00 2001 From: masashi Date: Thu, 3 Sep 2026 17:12:59 +0900 Subject: [PATCH 2/3] ci: build the core module from the matching branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit コアの未マージ/未リリースな変更に追随する PR を、コアが先に取り込まれるのを待たずに検証できるようにする。同名ブランチが無ければ従来どおり既定のコアを使う。 --- .github/workflows/build.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79f872f..f0d3bb0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,8 +38,29 @@ jobs: cache: 'gradle' - name: Build core and compose locally + env: + HEAD_REF: ${{ github.head_ref }} run: | - git clone --depth 1 https://github.com/MapConductor/android-sdk-core.git _core + # コア側に PR と同名のブランチがあるなら、そちらを組む。 + # + # ここを default ブランチ固定にしていると、**コアの未マージな変更に追随する + # PR は永久に赤いまま**になる。実際 CameraBearing をコアへ足したとき、 + # プロバイダ側の PR が 10 本まとめて Unresolved reference で落ちた。 + # コアが先にマージされるまで待つ、という運用は取り込み順の事故を呼ぶので、 + # 同名ブランチがあれば拾う形にしてある(無ければ従来どおり default)。 + clone_matching() { + repo="$1"; dir="$2" + url="https://github.com/MapConductor/$repo.git" + if [ -n "$HEAD_REF" ] && git ls-remote --exit-code --heads "$url" "$HEAD_REF" >/dev/null 2>&1; then + echo "$repo: matching branch $HEAD_REF" + git clone --depth 1 --branch "$HEAD_REF" "$url" "$dir" + else + echo "$repo: default branch" + git clone --depth 1 "$url" "$dir" + fi + } + + clone_matching android-sdk-core _core cd _core ./gradlew --no-daemon publishToMavenLocal cd .. @@ -53,7 +74,7 @@ jobs: } EOF - git clone --depth 1 https://github.com/MapConductor/android-sdk-compose.git _compose + clone_matching android-sdk-compose _compose cd _compose ./gradlew --no-daemon publishToMavenLocal cd .. From c7f1b5d52060488fc62898493e3d8cc44298c36d Mon Sep 17 00:00:00 2001 From: masashi Date: Thu, 3 Sep 2026 20:01:49 +0900 Subject: [PATCH 3/3] fix: point material3 at its own version line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit material3 は compose-ui とは別のバージョン系列で、composeLibs(1.7.8)を流用すると存在しない material3:1.7.8 を要求して sample-app のクラスパスごと解決に失敗する。集約ビルド(android-sdk)の catalog と同じ 1.4.0 に合わせる。 --- gradle/libs.versions.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 583b54c..ec9fe40 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,8 @@ [versions] composeLibs = "1.7.8" +# material3 は compose-ui とは別のバージョン系列。composeLibs(ui 系)を流用すると +# 存在しない material3:1.7.8 を要求してクラスパスごと解決に失敗する。 +material3 = "1.4.0" openmobilemaps = "4.0.0" coroutines = "1.9.0" agp = "9.2.1" @@ -37,7 +40,7 @@ play-services-maps = { module = "com.google.android.gms:play-services-maps", ver # Sample app androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } -androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "composeLibs" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "composeLibs" } # Test