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
6 changes: 6 additions & 0 deletions api/android-for-longdo.api
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public final class com.mapconductor.longdo.LongdoMapViewControllerRasterKt {
public static final java.lang.String rasterSourceSpec(com.mapconductor.longdo.LongdoMapViewController, com.mapconductor.core.raster.RasterLayerSource);
public static final java.lang.String rasterLayerSpec(com.mapconductor.longdo.LongdoMapViewController, java.lang.String, java.lang.String, float, boolean);
public static final java.lang.String addRasterJs(com.mapconductor.longdo.LongdoMapViewController, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
public static final java.lang.String addRasterJs(com.mapconductor.longdo.LongdoMapViewController, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
public static final java.lang.String readdRastersAfterStyleSwapJs(com.mapconductor.longdo.LongdoMapViewController, java.util.List<com.mapconductor.core.raster.RasterLayerState>);
public static final java.lang.String removeRasterJs(com.mapconductor.longdo.LongdoMapViewController, java.lang.String);
public static final java.lang.String setRasterOpacityJs(com.mapconductor.longdo.LongdoMapViewController, java.lang.String, float);
Expand Down Expand Up @@ -190,6 +191,11 @@ final class com.mapconductor.longdo.LongdoMapViewSaver$Companion {
public final class com.mapconductor.longdo.LongdoMapViewScope extends com.mapconductor.compose.MapViewScope {
public com.mapconductor.longdo.LongdoMapViewScope();
}
public final class com.mapconductor.longdo.LongdoOverlayStacking {
public static final com.mapconductor.longdo.LongdoOverlayStacking INSTANCE;
public final java.lang.String addLayerJs(java.lang.String, com.mapconductor.core.controller.OverlayKind, int);
public final java.lang.String addMarkerTileLayerJs(java.lang.String);
}
public final class com.mapconductor.longdo.LongdoOverlayState {
public com.mapconductor.longdo.LongdoOverlayState();
public final androidx.compose.runtime.snapshots.SnapshotStateMap<java.lang.String, androidx.compose.ui.geometry.Offset> getRenderPx();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ internal fun LongdoMapViewController.applyMarkerTileRaster(state: RasterLayerSta
val prev = markerTileState
val layerSpec = rasterLayerSpec(layerId, srcId, state.opacity, state.visible)
when {
prev == null -> runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec))
// マーカーのタイルはマーカーの帯(ポリライン等より上)。
prev == null ->
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec, LongdoOverlayStacking.addMarkerTileLayerJs(layerSpec)))
prev.source != state.source -> {
runRasterJs(removeRasterJs(state.id))
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec))
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec, LongdoOverlayStacking.addMarkerTileLayerJs(layerSpec)))
}
}
markerTileState = state
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mapconductor.longdo

import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.raster.RasterHeaderRuleSet
import com.mapconductor.core.raster.RasterLayerSource
import com.mapconductor.core.raster.RasterLayerState
Expand All @@ -23,10 +24,10 @@ internal fun LongdoMapViewController.applyRaster(state: RasterLayerState) {
val layerSpec = rasterLayerSpec(layerId, srcId, state.opacity, state.visible)
when {
prev == null ->
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec))
prev.source != state.source -> {
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec, rasterAddLayerJs(layerSpec, state)))
prev.source != state.source || prev.zIndex != state.zIndex -> {
runRasterJs(removeRasterJs(state.id))
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec))
runRasterJs(addRasterJs(srcId, layerId, spec, layerSpec, rasterAddLayerJs(layerSpec, state)))
}
else -> {
if (prev.opacity != state.opacity) runRasterJs(setRasterOpacityJs(layerId, state.opacity))
Expand All @@ -36,6 +37,11 @@ internal fun LongdoMapViewController.applyRaster(state: RasterLayerState) {
appliedRasters[state.id] = state
}

private fun rasterAddLayerJs(
layerSpec: String,
state: RasterLayerState,
): String = LongdoOverlayStacking.addLayerJs(layerSpec, OverlayKind.RasterLayer, state.zIndex)

internal fun LongdoMapViewController.runRasterJs(js: String) {
runCatching { longdoMap.run(js) {} }
}
Expand Down Expand Up @@ -79,14 +85,23 @@ internal fun LongdoMapViewController.addRasterJs(
layerId: String,
sourceSpec: String,
layerSpec: String,
): String = addRasterJs(sourceId, layerId, sourceSpec, layerSpec, LongdoOverlayStacking.addLayerJs(layerSpec, OverlayKind.RasterLayer))

/** [addLayer] は帯の順で層を足す JS([LongdoOverlayStacking.addLayerJs])。 */
internal fun LongdoMapViewController.addRasterJs(
sourceId: String,
layerId: String,
sourceSpec: String,
layerSpec: String,
addLayer: String,
): String =
"""
(function(){var m=map.Renderer; if(!m)return;
var tries=0;
function apply(){
try{
if(!m.getSource('$sourceId'))m.addSource('$sourceId',$sourceSpec);
if(!m.getLayer('$layerId'))m.addLayer($layerSpec);
if(!m.getLayer('$layerId'))$addLayer
}catch(e){ if(tries++<30)setTimeout(apply,150); }
}
apply();
Expand All @@ -107,8 +122,14 @@ internal fun LongdoMapViewController.readdRastersAfterStyleSwapJs(rasters: List<
val srcId = rasterSourceId(state.id)
val layerId = rasterLayerId(state.id)
val layerSpec = rasterLayerSpec(layerId, srcId, state.opacity, state.visible)
val addLayer =
if (state.id == markerTileState?.id) {
LongdoOverlayStacking.addMarkerTileLayerJs(layerSpec)
} else {
LongdoOverlayStacking.addLayerJs(layerSpec, OverlayKind.RasterLayer, state.zIndex)
}
"try{if(!m.getSource('$srcId'))m.addSource('$srcId',$spec);" +
"if(!m.getLayer('$layerId'))m.addLayer($layerSpec);}catch(e){}"
"if(!m.getLayer('$layerId'))$addLayer}catch(e){}"
}.joinToString("")
return "(function(){var m=map.Renderer;if(!m)return;function re(){$adds}" +
"m.once('style.load',function(){setTimeout(re,0);});setTimeout(re,1500);})()"
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/com/mapconductor/longdo/LongdoOverlayStacking.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.mapconductor.longdo

import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.controller.OverlayStacking

/**
* 重なり順([OverlayStacking]: ラスター < GroundImage < ポリゴン < サークル < ポリライン < マーカー)。
*
* Longdo の地図は WebView の中の MapLibre GL JS(`map.Renderer`)で、レイヤーは
* `addLayer` した順に上へ積まれていた(追加・送り直し・スタイル差し替えの順に左右される)。
* ここで作る JS は、足す層の帯と zIndex を `m.__mcStack` に記録し、今のスタイルの並びから
* 「鍵が自分より大きい一番下の SDK の層」を beforeId に選んで `addLayer` する。
* ラスターだけはベースマップのラベル(SDK の層でない最初の symbol 層)の下に入れる。
*/
internal object LongdoOverlayStacking {
private const val FN =
"function(m,s,b,z){var K=m.__mcStack||(m.__mcStack={});K[s.id]=[b,z];" +
"if(m.getLayer(s.id))return;var L=m.getStyle().layers,i,k,bi=-1;" +
"for(i=0;i<L.length;i++){k=K[L[i].id];if(k&&(k[0]>b||(k[0]==b&&k[1]>z))){bi=i;break;}}" +
"if(b==0){for(i=0;i<L.length;i++){if(L[i].type=='symbol'&&!K[L[i].id]){if(bi<0||i<bi)bi=i;break;}}}" +
"m.addLayer(s,bi<0?undefined:L[bi].id);}"

/**
* `m`(MapLibre GL JS の地図)へ [layerSpec] を帯の順で足す JS 文。
* 既に同じ id の層があれば何もしない。
*/
fun addLayerJs(
layerSpec: String,
kind: OverlayKind,
zIndex: Int = 0,
): String = "($FN)(m,$layerSpec,${OverlayStacking.band(kind)},$zIndex);"

/** マーカーのタイル: マーカーの帯の一番下。 */
fun addMarkerTileLayerJs(layerSpec: String): String = addLayerJs(layerSpec, OverlayKind.Marker, Int.MIN_VALUE)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import com.longdo.sdk3.LongdoMap
import com.mapconductor.core.circle.CircleEntityInterface
import com.mapconductor.core.circle.CircleOverlayRendererInterface
import com.mapconductor.core.circle.CircleState
import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.geometry.OverlayGeoJson
import com.mapconductor.core.geometry.circleToRing
import com.mapconductor.longdo.LongdoOverlayStacking
import org.json.JSONObject

/**
Expand Down Expand Up @@ -55,8 +57,12 @@ class LongdoCircleOverlayRenderer(
handles.forEach { runJs(addJs(it)) }
}

/** 層の id → zIndex(帯の中の順)。 */
private val zIndexByLayer = java.util.concurrent.ConcurrentHashMap<String, Int>()

private fun addCircle(state: CircleState): LongdoCircleHandle? {
val feature = buildGeoJson(state) ?: return null
zIndexByLayer["circle-fill-${state.id}"] = state.zIndex ?: 0
val fillArgb = state.fillColor.toArgb()
val strokeArgb = state.strokeColor.toArgb()
val handle =
Expand Down Expand Up @@ -137,15 +143,18 @@ class LongdoCircleOverlayRenderer(
.put("line-opacity", handle.strokeOpacity)
.put("line-width", handle.strokeWidth),
).toString()
// サークルの帯。輪郭は塗りの直後。
val fillAdd = LongdoOverlayStacking.addLayerJs(fillSpec, OverlayKind.Circle, zIndexByLayer[handle.fillLayerId] ?: 0)
val lineAdd = LongdoOverlayStacking.addLayerJs(lineSpec, OverlayKind.Circle, zIndexByLayer[handle.fillLayerId] ?: 0)
return """
(function(){var m=map.Renderer; if(!m)return;
var tries=0;
function apply(){
try{
if(!m.getSource('${handle.sourceId}'))
m.addSource('${handle.sourceId}',{type:'geojson',data:${handle.featureJson}});
if(!m.getLayer('${handle.fillLayerId}'))m.addLayer($fillSpec);
if(!m.getLayer('${handle.lineLayerId}'))m.addLayer($lineSpec);
if(!m.getLayer('${handle.fillLayerId}'))$fillAdd
if(!m.getLayer('${handle.lineLayerId}'))$lineAdd
}catch(e){ if(tries++<30)setTimeout(apply,150); }
}
apply();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.mapconductor.longdo.groundimage

import com.longdo.sdk3.LongdoMap
import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.features.GeoRectBounds
import com.mapconductor.core.groundimage.GroundImageEntityInterface
import com.mapconductor.core.groundimage.GroundImageOverlayRendererInterface
import com.mapconductor.core.groundimage.GroundImageState
import com.mapconductor.longdo.LongdoOverlayStacking
import org.json.JSONObject
import java.io.ByteArrayOutputStream
import android.graphics.Bitmap
Expand Down Expand Up @@ -146,6 +148,8 @@ class LongdoGroundImageOverlayRenderer(
.put("paint", JSONObject().put("raster-opacity", handle.opacity))
.put("layout", JSONObject().put("visibility", "visible"))
.toString()
// GroundImage の帯(ラスターの上、ポリゴンの下)。
val layerAdd = LongdoOverlayStacking.addLayerJs(layerSpec, OverlayKind.GroundImage)
return """
(function(){var m=map.Renderer; if(!m)return;
var tries=0;
Expand All @@ -154,7 +158,7 @@ class LongdoGroundImageOverlayRenderer(
if(!m.getSource('${handle.sourceId}'))
m.addSource('${handle.sourceId}',
{type:'image',url:'${handle.imageUrl}',coordinates:${handle.coordinatesJson}});
if(!m.getLayer('${handle.layerId}'))m.addLayer($layerSpec);
if(!m.getLayer('${handle.layerId}'))$layerAdd
}catch(e){ if(tries++<30)setTimeout(apply,150); }
}
apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package com.mapconductor.longdo.polygon

import androidx.compose.ui.graphics.toArgb
import com.longdo.sdk3.LongdoMap
import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.geometry.OverlayGeoJson
import com.mapconductor.core.geometry.buildUnwrappedPolygonRings
import com.mapconductor.core.polygon.PolygonEntityInterface
import com.mapconductor.core.polygon.PolygonOverlayRendererInterface
import com.mapconductor.core.polygon.PolygonState
import com.mapconductor.core.polygon.unionHoles
import com.mapconductor.longdo.LongdoOverlayStacking
import org.json.JSONObject

/**
Expand Down Expand Up @@ -56,8 +58,12 @@ class LongdoPolygonOverlayRenderer(
handles.forEach { runJs(addPolygonJs(it)) }
}

/** 層の id → zIndex(帯の中の順)。handle は公開型なので持たせずここで覚える。 */
private val zIndexByLayer = java.util.concurrent.ConcurrentHashMap<String, Int>()

private fun addPolygon(state: PolygonState): LongdoPolygonHandle? {
val feature = buildGeoJson(state) ?: return null
zIndexByLayer["polygon-fill-${state.id}"] = state.zIndex
val fillArgb = state.fillColor.toArgb()
val strokeArgb = state.strokeColor.toArgb()
val handle =
Expand Down Expand Up @@ -140,15 +146,19 @@ class LongdoPolygonOverlayRenderer(
.put("line-opacity", handle.strokeOpacity)
.put("line-width", handle.strokeWidth),
).toString()
// ポリゴンの帯。帯の中は zIndex の順、輪郭は塗りの直後。
val z = zIndexByLayer[handle.fillLayerId] ?: 0
val fillAdd = LongdoOverlayStacking.addLayerJs(fillSpec, OverlayKind.Polygon, z)
val lineAdd = LongdoOverlayStacking.addLayerJs(lineSpec, OverlayKind.Polygon, z)
return """
(function(){var m=map.Renderer; if(!m)return;
var tries=0;
function apply(){
try{
if(!m.getSource('${handle.sourceId}'))
m.addSource('${handle.sourceId}',{type:'geojson',data:${handle.featureJson}});
if(!m.getLayer('${handle.fillLayerId}'))m.addLayer($fillSpec);
if(!m.getLayer('${handle.lineLayerId}'))m.addLayer($lineSpec);
if(!m.getLayer('${handle.fillLayerId}'))$fillAdd
if(!m.getLayer('${handle.lineLayerId}'))$lineAdd
}catch(e){ if(tries++<30)setTimeout(apply,150); }
}
apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.mapconductor.longdo.polyline

import androidx.compose.ui.graphics.toArgb
import com.longdo.sdk3.LongdoMap
import com.mapconductor.core.controller.OverlayKind
import com.mapconductor.core.geometry.OverlayGeoJson
import com.mapconductor.core.geometry.buildUnwrappedPolylinePath
import com.mapconductor.core.polyline.PolylineEntityInterface
import com.mapconductor.core.polyline.PolylineOverlayRendererInterface
import com.mapconductor.core.polyline.PolylineState
import com.mapconductor.longdo.LongdoOverlayStacking
import org.json.JSONObject

/**
Expand Down Expand Up @@ -52,8 +54,12 @@ class LongdoPolylineOverlayRenderer(
handles.forEach { runJs(addLineJs(it)) }
}

/** 層の id → zIndex(帯の中の順)。 */
private val zIndexByLayer = java.util.concurrent.ConcurrentHashMap<String, Int>()

private fun addLine(state: PolylineState): LongdoPolylineHandle? {
val feature = buildGeoJson(state) ?: return null
zIndexByLayer["polyline-layer-${state.id}"] = state.zIndex
val argb = state.strokeColor.toArgb()
val handle =
LongdoPolylineHandle(
Expand Down Expand Up @@ -122,14 +128,16 @@ class LongdoPolylineOverlayRenderer(
.put("line-opacity", handle.opacity)
.put("line-width", handle.width),
).toString()
// ポリラインの帯。
val layerAdd = LongdoOverlayStacking.addLayerJs(layerSpec, OverlayKind.Polyline, zIndexByLayer[handle.layerId] ?: 0)
return """
(function(){var m=map.Renderer; if(!m)return;
var tries=0;
function apply(){
try{
if(!m.getSource('${handle.sourceId}'))
m.addSource('${handle.sourceId}',{type:'geojson',data:${handle.featureJson}});
if(!m.getLayer('${handle.layerId}'))m.addLayer($layerSpec);
if(!m.getLayer('${handle.layerId}'))$layerAdd
}catch(e){ if(tries++<30)setTimeout(apply,150); }
}
apply();
Expand Down
Loading