mapbox-maps-android icon indicating copy to clipboard operation
mapbox-maps-android copied to clipboard

Layer Ordering and Polygon Overlap with Buildings

Open vidalbenjoe opened this issue 1 year ago • 4 comments

Environment

  • Android OS version: Android 14
  • Devices affected: Android Pixel 9 pro
  • Maps SDK Version: 11.8.1

Observed behavior and steps to reproduce

I'm encountering an issue with Mapbox (specifically on Android, using the Maps SDK for Android with Jetpack Compose) where polygons I'm adding to the map are being rendered underneath the building layer when zooming-in.

Steps to reproduce:

  1. Implement a Mapbox map in an Android app using Jetpack Compose and the Maps SDK for Android.
  2. Load a Mapbox style .
  3. Add a GeoJSON fill layer to the map's style.

Expected behavior

The polygon should be consistently rendered above the building layer. The polygon should be fully visible and not obscured by building geometry.

Notes / preliminary analysis

I've tried inspecting the style's layers at runtime, but I'm unsure if I'm correctly identifying the building layer in all cases. It's also possible there's an issue with how layer ordering interacts with the asynchronous style loading in Compose.

Screenshot 2025-01-07 184838

vidalbenjoe avatar Jan 07 '25 11:01 vidalbenjoe

@vidalbenjoe could you please provide code with a minimum reproducible example? Thank you!

jush avatar Jan 15 '25 12:01 jush

Hello @jush Thanks for replying. Here's my setup

`

LaunchedEffect(params.drawnGeoJsonData) { areaFillSourceState.data = params.drawnGeoJsonData.areaPolygon areaValidSidesSourceState.data = params.drawnGeoJsonData.areaValidSides areaInvalidSidesSourceState.data = params.drawnGeoJsonData.areaInvalidSides areaClosingSideSourceState.data = params.drawnGeoJsonData.areaClosingSides } FillLayer( layerId = AreaDrawingPlugin.FILL_LAYER_ID, sourceState = areaFillSourceState, fillLayerState = FillLayerState().apply { fillColor = ColorValue(MaterialTheme.customColorsPalette.blue) fillOpacity = DoubleValue(0.5) } )

        LineLayer(
            layerId = AreaDrawingPlugin.VALID_SIDE_LAYER_ID,
            sourceState = areaValidSidesSourceState,
            lineLayerState = LineLayerState().apply {
                lineWidth = DoubleValue(6.0)
                lineColor = ColorValue(MaterialTheme.customColorsPalette.blue)
                lineBorderColor = ColorValue(Color.White)
                lineBorderWidth = DoubleValue(1.0)
            }
        )

        LineLayer(
            layerId = AreaDrawingPlugin.INVALID_SIDE_LAYER_ID,
            sourceState = areaInvalidSidesSourceState,
            lineLayerState = LineLayerState().apply {
                lineWidth = DoubleValue(4.0)
                lineColor = ColorValue(Color.Red)
                lineDasharray = DoubleListValue(listOf(dashLength, dashLength / 2))
            }
        )

        LineLayer(
            layerId = AreaDrawingPlugin.CLOSING_SIDE_LAYER_ID,
            sourceState = areaClosingSideSourceState,
            lineLayerState = LineLayerState().apply {
                lineWidth = DoubleValue(6.0)
                linePattern = ImageValue(
                    imageId = AreaDrawingPlugin.LINE_PATTERN
                )
            }
        )
    }

    PointAnnotationGroup(
        annotations = params.drawnGeoJsonData.areaPoints.mapIndexed { index, areaPoint ->
            val areaPointData = JsonObject()
            areaPointData.add(
                AreaDrawingPlugin.FEATURE_POINT_INDEX,
                JsonPrimitive(index)
            )
            PointAnnotationOptions()
                .withPoint(areaPoint)
                .withIconImage(AreaDrawingPlugin.AREA_POINT_IMAGE_ID)
                .withDraggable(true)
                .withData(areaPointData)
        },
        annotationConfig = AnnotationConfig(
            layerId = AreaDrawingPlugin.POINT_LAYER_ID,
        ),
        pointAnnotationGroupState = PointAnnotationGroupState().apply {
            interactionsState =
                PointAnnotationGroupInteractionsState().onClicked { pointAnnotation ->
                    val data = pointAnnotation.getData()?.asJsonObject
                    if (data != null && data.has(AreaDrawingPlugin.FEATURE_POINT_INDEX)) {
                        val pointIndex =
                            data.getAsJsonPrimitive(AreaDrawingPlugin.FEATURE_POINT_INDEX)
                        if (!pointIndex.isNumber) return@onClicked false

                        params.onEvent(
                            MapScreenEvent.OnAreaDrawingClickPoint(
                                pointIndex = pointIndex.asInt
                            )
                        )
                        return@onClicked true
                    }
                    return@onClicked false
                }.onDragged { draggedPoint ->
                    val updatedPoints =
                        params.drawnGeoJsonData.areaPoints.mapIndexed { index, areaPoint ->
                            if (index == draggedPoint.getData()?.asJsonObject
                                    ?.getAsJsonPrimitive(AreaDrawingPlugin.FEATURE_POINT_INDEX)?.asInt
                            ) {
                                draggedPoint.point
                            } else {
                                areaPoint
                            }
                        }
                    val closedPoints = if (updatedPoints.first() != updatedPoints.last()) {
                        updatedPoints + updatedPoints.first()
                    } else {
                        updatedPoints
                    }

                    val polygon = Polygon.fromLngLats(listOf(closedPoints))
                    val updatedGeoJsonData = GeoJSONData(listOf(Feature.fromGeometry(polygon)))

                    // Update the GeoJSON data
                    params.drawnGeoJsonData = params.drawnGeoJsonData.copy(
                        areaPoints = updatedPoints,
                        areaPolygon = updatedGeoJsonData,
                        areaValidSides = updatedGeoJsonData,
                        areaInvalidSides = GeoJSONData(
                            listOf(
                                Feature.fromGeometry(
                                    Polygon.fromLngLats(listOf(listOf(draggedPoint.point)))
                                )
                            )
                        ),
                        areaClosingSides = updatedGeoJsonData
                    )

                    areaFillSourceState.data = params.drawnGeoJsonData.areaPolygon
                    areaValidSidesSourceState.data = params.drawnGeoJsonData.areaValidSides
                    areaInvalidSidesSourceState.data = params.drawnGeoJsonData.areaInvalidSides
                    areaClosingSideSourceState.data = params.drawnGeoJsonData.areaClosingSides
                }.onDragFinished { draggedPointAnnotation ->
                    onPointDrag(params, draggedPointAnnotation)
                }
        }
    )

    SymbolLayer(
        sourceState = drawnWaypointSource,
        layerId = WaypointDrawingPlugin.WAYPOINT_DRAWING_LAYER_ID,
        symbolLayerState = SymbolLayerState().apply {
            iconImage = ImageValue(WaypointDrawingPlugin.DRAWN_WAYPOINT_MARKER_IMAGE_ID)
            iconAnchor = IconAnchorValue.BOTTOM
            iconColor = ColorValue(draftWaypoint.tintForTagIcon.toColor())
        },
    )`

vidalbenjoe avatar Jan 20 '25 13:01 vidalbenjoe

Also getting the same thing when creating a line.

lineDepthOcclusionFactor = DoubleValue(0.0) Doesn't seem to work on 3D buildings. lineZOffset = DoubleValue(1000.0) seems to be very buggy and is unusable for us. Lots of graphical gitches (line moving around the map, flickering in and out, overlapping) when zooming in and out.

Image

splendidbits avatar Mar 08 '25 23:03 splendidbits

We are also facing the same problem where the layer is overlapping with the buildings in 3d

Image Image

AkshatDubey10 avatar Jun 12 '25 12:06 AkshatDubey10