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: 14 additions & 0 deletions api/android-for-openmobilemaps.api
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,12 @@ public final class com.mapconductor.openmobilemaps.OpenMobileMapsGroundImageOver
}
public final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers {
public static final int DESIGN_INDEX;
public static final int RASTER_INDEX_FIRST;
public static final int BELOW_INDEX_FIRST;
public static final int GROUND_IMAGE_INDEX_FIRST;
public static final int FIXED_INDEX_FIRST;
public static final int MARKER_TILE_INDEX_FIRST;
public static final int ICON_INDEX;
public com.mapconductor.openmobilemaps.OpenMobileMapsLayers();
public final io.openmobilemaps.mapscore.shared.map.layers.polygon.PolygonLayerInterface getPolygonFillLayer();
public final io.openmobilemaps.mapscore.shared.map.layers.line.LineLayerInterface getPolygonOutlineLayer();
Expand All @@ -133,9 +137,19 @@ public final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers {
public final void attachTo(io.openmobilemaps.mapscore.shared.map.MapInterface);
public final void setDesignLayer(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface);
public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertBelowOverlays(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface);
public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertGroundImage(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface);
public final io.openmobilemaps.mapscore.shared.map.LayerInterface insertMarkerTile(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface);
public final void remove(io.openmobilemaps.mapscore.shared.map.MapInterface, io.openmobilemaps.mapscore.shared.map.LayerInterface);
public final void clearAll();
}
final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers$Band {
public final int getFirst();
public final int getEnd();
public final java.util.TreeSet<java.lang.Integer> getFree();
public final int getNext();
public final void setNext(int);
public final int take();
}
final class com.mapconductor.openmobilemaps.OpenMobileMapsLayers$Companion {
}
public interface com.mapconductor.openmobilemaps.OpenMobileMapsMapDesignTypeInterface extends com.mapconductor.core.map.MapDesignTypeInterface<java.lang.String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import io.openmobilemaps.mapscore.shared.map.layers.polygon.PolygonLayerInterfac
* → 円の塗り → 円の輪郭 → ポリライン → マーカー
* ```
*
* すべてのプロバイダ共通の決まり([com.mapconductor.core.controller.OverlayStacking])。
* ラスターとグラウンドイメージ、マーカーのタイルは数が変わるので、帯ごとに索引の区間を分けて
* 割り当てる(以前はラスターとグラウンドイメージが同じ区間を空き番号から使い回していたため、
* 追加・送り直しの順で上下が入れ替わった)。
*
* 他プロバイダのクリックのカスケード(marker → circle → groundImage → polyline →
* polygon → map)と**上下が逆に見える**が、これは正しい。カスケードは「上にあるものから
* 順に当たり判定する」ので、描画の重ね順を上から読むとカスケード順に一致する。
Expand Down Expand Up @@ -56,18 +61,30 @@ class OpenMobileMapsLayers {
/** 地図デザインとオーバーレイ群の間に入っているレイヤ(ラスター / グラウンドイメージ)と、その索引。 */
private val belowOverlayIndices = mutableMapOf<LayerInterface, Int>()

/** 外したレイヤの索引。使い回さないと、タイルの張り替えを繰り返すうちに索引が尽きる。 */
private val freeBelowIndices = sortedSetOf<Int>()
private var nextBelowIndex = BELOW_INDEX_FIRST
/** 帯ごとの索引の割り当て。外したレイヤの索引は使い回す(張り替えを繰り返すうちに尽きないよう)。 */
private class Band(
val first: Int,
val end: Int,
) {
val free = sortedSetOf<Int>()
var next = first

fun take(): Int = free.pollFirst() ?: next++.also { check(it < end) { "layer index band exhausted" } }
}

private val rasterBand = Band(RASTER_INDEX_FIRST, GROUND_IMAGE_INDEX_FIRST)
private val groundImageBand = Band(GROUND_IMAGE_INDEX_FIRST, FIXED_INDEX_FIRST)
private val markerTileBand = Band(MARKER_TILE_INDEX_FIRST, ICON_INDEX)
private val bandOfLayer = mutableMapOf<LayerInterface, Band>()

private val fixedLayers: List<LayerInterface> by lazy {
private val fixedLayers: List<Pair<LayerInterface, Int>> by lazy {
listOf(
polygonFillLayer.asLayerInterface(),
polygonOutlineLayer.asLayerInterface(),
circleFillLayer.asLayerInterface(),
circleOutlineLayer.asLayerInterface(),
polylineLayer.asLayerInterface(),
iconLayer.asLayerInterface(),
polygonFillLayer.asLayerInterface() to FIXED_INDEX_FIRST,
polygonOutlineLayer.asLayerInterface() to FIXED_INDEX_FIRST + 1,
circleFillLayer.asLayerInterface() to FIXED_INDEX_FIRST + 2,
circleOutlineLayer.asLayerInterface() to FIXED_INDEX_FIRST + 3,
polylineLayer.asLayerInterface() to FIXED_INDEX_FIRST + 4,
iconLayer.asLayerInterface() to ICON_INDEX,
)
}

Expand All @@ -90,8 +107,8 @@ class OpenMobileMapsLayers {
polylineLayer.setLayerClickable(false)
iconLayer.setLayerClickable(false)

fixedLayers.forEachIndexed { offset, layer ->
map.insertLayerAt(layer, FIXED_INDEX_FIRST + offset)
fixedLayers.forEach { (layer, index) ->
map.insertLayerAt(layer, index)
}
}

Expand All @@ -114,9 +131,28 @@ class OpenMobileMapsLayers {
fun insertBelowOverlays(
map: MapInterface,
layer: LayerInterface,
): LayerInterface = insertInBand(map, layer, rasterBand)

/** グラウンドイメージ: ラスターレイヤの上、ポリゴンの下。 */
fun insertGroundImage(
map: MapInterface,
layer: LayerInterface,
): LayerInterface = insertInBand(map, layer, groundImageBand)

/** マーカーのタイル: ポリラインの上、マーカー(アイコン)の下。 */
fun insertMarkerTile(
map: MapInterface,
layer: LayerInterface,
): LayerInterface = insertInBand(map, layer, markerTileBand)

private fun insertInBand(
map: MapInterface,
layer: LayerInterface,
band: Band,
): LayerInterface {
val index = freeBelowIndices.pollFirst() ?: nextBelowIndex++
val index = band.take()
belowOverlayIndices[layer] = index
bandOfLayer[layer] = band
map.insertLayerAt(layer, index)
return layer
}
Expand All @@ -125,7 +161,9 @@ class OpenMobileMapsLayers {
map: MapInterface,
layer: LayerInterface,
) {
belowOverlayIndices.remove(layer)?.let { freeBelowIndices.add(it) }
val index = belowOverlayIndices.remove(layer)
val band = bandOfLayer.remove(layer)
if (index != null && band != null) band.free.add(index)
map.removeLayer(layer)
}

Expand All @@ -142,10 +180,23 @@ class OpenMobileMapsLayers {
/** 地図デザイン。一番下。 */
const val DESIGN_INDEX = 0

/** ラスターレイヤ・グラウンドイメージ。地図デザインとオーバーレイ群の間。 */
const val BELOW_INDEX_FIRST = 1
/** ラスターレイヤ。地図デザインの上。 */
const val RASTER_INDEX_FIRST = 1

/** 以前の名前(ラスターとグラウンドイメージが共用していた区間の先頭)。 */
@Suppress("unused")
const val BELOW_INDEX_FIRST = RASTER_INDEX_FIRST

/** グラウンドイメージ。ラスターの上、ポリゴンの下。 */
const val GROUND_IMAGE_INDEX_FIRST = 500

/** 固定のオーバーレイ 6 種。下の枠を使い切らないよう十分離す。 */
const val FIXED_INDEX_FIRST = 1_000

/** マーカーのタイル。ポリラインの上、マーカーの下。 */
const val MARKER_TILE_INDEX_FIRST = 1_100

/** マーカー(アイコン)。一番上。 */
const val ICON_INDEX = 2_000
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,10 @@ class OpenMobileMapsPolylineOverlayRenderer(
override suspend fun removePolyline(entity: PolylineEntityInterface<OpenMobileMapsActualPolyline>) = Unit

override suspend fun onPostProcess() {
lineLayer.setLines(polylineManager.allEntities().flatMapTo(ArrayList()) { it.polyline.orEmpty() })
// 帯の中は zIndex の順(同じなら渡された順)。
lineLayer.setLines(
polylineManager.allEntities().sortedBy { it.state.zIndex }.flatMapTo(ArrayList()) { it.polyline.orEmpty() },
)
}
}

Expand Down Expand Up @@ -475,7 +478,8 @@ class OpenMobileMapsPolygonOverlayRenderer(
override suspend fun removePolygon(entity: PolygonEntityInterface<OpenMobileMapsActualPolygon>) = Unit

override suspend fun onPostProcess() {
val entities = polygonManager.allEntities()
// 帯の中は zIndex の順(同じなら渡された順)。
val entities = polygonManager.allEntities().sortedBy { it.state.zIndex }
// add / addAll ではなく setPolygons を使うこと。4.0 の PolygonLayer は
// 原点(第 2 引数)を持つようになっていて、setPolygons を一度も通っていない
// レイヤに add すると**何も描かれない**(例外も警告も出ない)。
Expand Down Expand Up @@ -530,7 +534,7 @@ class OpenMobileMapsCircleOverlayRenderer(
override suspend fun removeCircle(entity: CircleEntityInterface<OpenMobileMapsActualCircle>) = Unit

override suspend fun onPostProcess() {
val entities = circleManager.allEntities()
val entities = circleManager.allEntities().sortedBy { it.state.zIndex ?: 0 }
fillLayer.setPolygons(entities.flatMapTo(ArrayList()) { it.circle.fills }, RENDER_ORIGIN)
outlineLayer.setLines(entities.flatMapTo(ArrayList()) { it.circle.outlines })
}
Expand Down Expand Up @@ -583,7 +587,7 @@ class OpenMobileMapsGroundImageOverlayRenderer(

return OpenMobileMapsActualGroundImage(
layer = layer,
layerInterface = layers.insertBelowOverlays(holder.map, layer.asLayerInterface()),
layerInterface = layers.insertGroundImage(holder.map, layer.asLayerInterface()),
)
}

Expand Down Expand Up @@ -685,7 +689,13 @@ class OpenMobileMapsRasterLayerOverlayRenderer(
}
return OpenMobileMapsActualRasterLayer(
layer = layer,
layerInterface = layers.insertBelowOverlays(holder.map, layer.asLayerInterface()),
layerInterface =
if (state.id.startsWith("marker-tile-")) {
// マーカーのタイルはマーカーの帯(ポリラインの上)。
layers.insertMarkerTile(holder.map, layer.asLayerInterface())
} else {
layers.insertBelowOverlays(holder.map, layer.asLayerInterface())
},
)
}
}
Expand Down
Loading