Skip to content

Commit

Permalink
fix display of multipolygons (fixes #4689)
Browse files Browse the repository at this point in the history
  • Loading branch information
westnordost committed Dec 30, 2022
1 parent dcb101e commit 66b8725
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ package de.westnordost.streetcomplete.screens.main.map.components
import android.content.res.Resources
import android.graphics.drawable.BitmapDrawable
import androidx.annotation.DrawableRes
import com.mapzen.tangram.geometry.Polygon
import com.mapzen.tangram.geometry.Polyline
import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry
import de.westnordost.streetcomplete.data.osm.geometry.ElementPointGeometry
import de.westnordost.streetcomplete.data.osm.geometry.ElementPolygonsGeometry
import de.westnordost.streetcomplete.data.osm.geometry.ElementPolylinesGeometry
import de.westnordost.streetcomplete.data.osm.mapdata.LatLon
import de.westnordost.streetcomplete.screens.main.map.tangram.KtMapController
import de.westnordost.streetcomplete.screens.main.map.tangram.Marker
import de.westnordost.streetcomplete.screens.main.map.tangram.toLngLat
import de.westnordost.streetcomplete.screens.main.map.tangram.toTangramGeometry
import de.westnordost.streetcomplete.util.ktx.getBitmapDrawable
import de.westnordost.streetcomplete.util.math.centerPointOfPolyline

/** Manages putting some generic geometry markers with an optional drawable on the map. I.e. to
* show the geometry of elements surrounding the selected quest */
Expand Down Expand Up @@ -90,31 +89,31 @@ class GeometryMarkersMapComponent(private val resources: Resources, private val

// polygon / polylines marker(s)
if (geometry is ElementPolygonsGeometry || geometry is ElementPolylinesGeometry) {
val positions = when (geometry) {
is ElementPolygonsGeometry -> geometry.polygons
is ElementPolylinesGeometry -> geometry.polylines
else -> throw IllegalStateException()
}

if (geometry is ElementPolygonsGeometry) {
val marker = ctrl.addMarker()
marker.setStylingFromString("""
{
style: 'geometry-polygons',
color: '$areaColor',
order: 2000,
collide: false
for (polygon in geometry.toTangramGeometry()) {
val marker = ctrl.addMarker()
marker.setStylingFromString("""
{
style: 'geometry-polygons',
color: '$areaColor',
order: 2000,
collide: false
}
""".trimIndent())
marker.setPolygon(polygon)
markers.add(marker)
}
""".trimIndent())
marker.setPolygon(Polygon(
positions.map { polygon -> polygon.map { it.toLngLat() } }, null
))
markers.add(marker)
}

/* Polygons should be styled to have a more opaque outline. Due to a technical
* limitation in tangram-es, these have to be actually two markers then. */
for (polyline in positions) {
val polylines: ElementPolylinesGeometry = when (geometry) {
is ElementPolygonsGeometry -> ElementPolylinesGeometry(geometry.polygons, geometry.polygons.first().centerPointOfPolyline())
is ElementPolylinesGeometry -> geometry
else -> throw IllegalStateException()
}
for (polyline in polylines.toTangramGeometry()) {
val marker = ctrl.addMarker()
marker.setStylingFromString("""
{
Expand All @@ -127,7 +126,7 @@ class GeometryMarkersMapComponent(private val resources: Resources, private val
join: round
}
""".trimIndent())
marker.setPolyline(Polyline(polyline.map { it.toLngLat() }, null))
marker.setPolyline(polyline)
markers.add(marker)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,46 @@ import de.westnordost.streetcomplete.util.math.isRingDefinedClockwise
import de.westnordost.streetcomplete.util.math.measuredArea

fun ElementGeometry.toTangramGeometry(properties: Map<String, String> = emptyMap()): List<Geometry> = when (this) {
is ElementPolylinesGeometry -> {
polylines.map { polyline ->
Polyline(polyline.map { it.toLngLat() }, properties + ("type" to "line"))
}
is ElementPolylinesGeometry -> toTangramGeometry(properties)
is ElementPolygonsGeometry -> toTangramGeometry(properties)
is ElementPointGeometry -> toTangramGeometry(properties)
}

fun ElementPointGeometry.toTangramGeometry(properties: Map<String, String> = emptyMap()): List<Point> {
return listOf(Point(center.toLngLat(), properties + ("type" to "point")))
}

fun ElementPolylinesGeometry.toTangramGeometry(properties: Map<String, String> = emptyMap()): List<Polyline> {
return polylines.map { polyline ->
Polyline(polyline.map { it.toLngLat() }, properties + ("type" to "line"))
}
is ElementPolygonsGeometry -> {
val outerRings = mutableListOf<List<LatLon>>()
val innerRings = mutableListOf<List<LatLon>>()
if (polygons.size == 1) {
outerRings.add(polygons.first())
} else {
polygons.forEach {
if (it.isRingDefinedClockwise()) innerRings.add(it) else outerRings.add(it)
}
}

fun ElementPolygonsGeometry.toTangramGeometry(properties: Map<String, String> = emptyMap()): List<Polygon> {
val outerRings = mutableListOf<List<LatLon>>()
val innerRings = mutableListOf<List<LatLon>>()
if (polygons.size == 1) {
outerRings.add(polygons.first())
} else {
polygons.forEach {
if (it.isRingDefinedClockwise()) innerRings.add(it) else outerRings.add(it)
}
}

// outerRings must be sorted size ascending to correctly handle outer rings within holes
// of larger polygons.
outerRings.sortBy { it.measuredArea() }
// outerRings must be sorted size ascending to correctly handle outer rings within holes
// of larger polygons.
outerRings.sortBy { it.measuredArea() }

outerRings.map { outerRing ->
val rings = mutableListOf<List<LngLat>>()
rings.add(outerRing.map { it.toLngLat() })
for (innerRing in innerRings.toList()) {
if (innerRing[0].isInPolygon(outerRing)) {
innerRings.remove(innerRing)
rings.add(innerRing.map { it.toLngLat() })
}
return outerRings.map { outerRing ->
val rings = mutableListOf<List<LngLat>>()
rings.add(outerRing.map { it.toLngLat() })
for (innerRing in innerRings.toList()) {
if (innerRing[0].isInPolygon(outerRing)) {
innerRings.remove(innerRing)
rings.add(innerRing.map { it.toLngLat() })
}
Polygon(rings, properties + ("type" to "poly"))
}
}
is ElementPointGeometry -> {
listOf(Point(center.toLngLat(), properties + ("type" to "point")))
Polygon(rings, properties + ("type" to "poly"))
}
}

Expand Down

0 comments on commit 66b8725

Please sign in to comment.