diff --git a/src/main/java/com/mapconductor/tomtom/polygon/TomTomPolygonOverlayRenderer.kt b/src/main/java/com/mapconductor/tomtom/polygon/TomTomPolygonOverlayRenderer.kt index 80de850..c0c3152 100644 --- a/src/main/java/com/mapconductor/tomtom/polygon/TomTomPolygonOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/tomtom/polygon/TomTomPolygonOverlayRenderer.kt @@ -3,13 +3,13 @@ package com.mapconductor.tomtom.polygon import androidx.compose.ui.graphics.toArgb import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.features.GeoPointInterface +import com.mapconductor.core.geometry.densifyPolygonRing import com.mapconductor.core.polygon.AbstractPolygonOverlayRenderer import com.mapconductor.core.polygon.PolygonEntityInterface import com.mapconductor.core.polygon.PolygonState import com.mapconductor.core.polygon.bridgeHolesIntoSingleRing import com.mapconductor.core.polygon.unionHoles import com.mapconductor.core.projection.Earth -import com.mapconductor.core.spherical.WGS84Geodesic import com.mapconductor.tomtom.TomTomActualPolygon import com.mapconductor.tomtom.TomTomMapViewHolder import com.mapconductor.tomtom.toTomTomGeoPoint @@ -42,13 +42,7 @@ class TomTomPolygonOverlayRenderer( points: List, geodesic: Boolean, ): List { - // 非 geodesic は補間せず生の頂点を使う(HERE と同じ)。geodesic のみ補間する。 - val geoPoints = - if (geodesic) { - WGS84Geodesic.createInterpolatePoints(points, maxSegmentLength = maxSegmentLengthMeters()) - } else { - points - } + val geoPoints = densify(points, geodesic) var ring = geoPoints.map { GeoPoint.from(it).toTomTomGeoPoint() } // 末尾の重複始点を除く(開いたリング)。 if (ring.size >= 2 && ring.first() == ring.last()) { @@ -78,16 +72,28 @@ class TomTomPolygonOverlayRenderer( points: List, geodesic: Boolean, ): List { - val geoPoints = - if (geodesic) { - WGS84Geodesic.createInterpolatePoints(points, maxSegmentLength = maxSegmentLengthMeters()) - } else { - points - } - val ring = geoPoints.map { GeoPoint.from(it) } + val ring = densify(points, geodesic).map { GeoPoint.from(it) } return if (ring.size >= 2 && ring.first() == ring.last()) ring.dropLast(1) else ring } + /** + * 閉じる辺(末尾 → 先頭)も含めてリングを密度化する(塗りと輪郭が同じネイティブポリゴン)。 + * geodesic は大圏、geodesic=false は緯度経度の線形補間(ポリラインの false と同じ線)。 + * + * 線形補間は [MAX_GEODESIC_SEGMENT_METERS] 刻みと粗くする。世界マスク級のリングを 10 km 刻みで + * 補間すると過密になり TomTom の描画が失敗する(以前はこのため false を補間していなかった)。 + * 緯度経度の直線は 200 km 刻みでもメルカトル上の曲がりを十分に表せる。 + */ + private fun densify( + points: List, + geodesic: Boolean, + ): List = + densifyPolygonRing( + points, + geodesic, + maxSegmentLength = if (geodesic) maxSegmentLengthMeters() else MAX_GEODESIC_SEGMENT_METERS, + ) + private fun maxSegmentLengthMeters(): Double { val zoom = holder.map.cameraPosition.zoom val metersPerPixel = Earth.CIRCUMFERENCE_METERS / (256.0 * 2.0.pow(zoom))