Helium314 / SCEE

OpenStreetMap surveyor app for experienced OSM contributors
GNU General Public License v3.0
114 stars 8 forks source link

Maplibre #516

Closed Helium314 closed 2 weeks ago

Helium314 commented 4 months ago

For simple comparison with master, and for discussions.

to do

to do SCEE

upstream blockers


old observations below

Performance regarding icons (symbol layers, mostly about quest pins):

Other things:

westnordost commented 4 months ago

Nice! I do intend to work with you together on this, this week however probably not because I don't have so much time and first should review and give feedback on some ready-to-review PRs (osmfeatures KMP, osmapi KMP).

Next thing I intend to do on this (unless you do it first) is to remove some more commented-out tangram-functionality that has been replaced by or would need to be implemented differently in maplibre anyway because it's easier to compare in diff view if there are not massive amounts of to-be-deleted comments floating around. I am not confident to delete your research-notes though, not sure what is already implemented and what is still relevant. Also, next thing for me would be to try out if defining the layers in the json comes without issues. If there are no issues, consider defining them in the JSON instead (plus probably write a small build script that merges the background map style json with the streetcomplete layers json) and if not, have a look at what would be the best api for moving the layer style definition into the components.

Helium314 commented 4 months ago

I am not confident to delete your research-notes though, not sure what is already implemented and what is still relevant.

I'll go through the comments and try to move them into a comment here (possibly sort of todo list in first post).

plus probably write a small build script that merges the background map style json with the streetcomplete layers json

That should work easily, you probably just need to merge the layers in the json (the Style.Builder uses a json string anyway).

Helium314 commented 4 months ago

Btw the style could use placeholder colors in the json, and replace them with the actual colors before loading the style. This would not require a separate json for night (but on the other hand, you can't conveniently test the style in some other editor)

Helium314 commented 4 months ago

Looks like you made the downloaded area map component work. I set the color to a more bearable transparent black. Not 100% sure, but my impression is that displaying the (not) downloaded area has an effect on performance when zooming.

westnordost commented 4 months ago

Try make it non-transparent. Does it still have this effect?

Helium314 commented 4 months ago

Opacity or color don't have any effect on this.

westnordost commented 4 months ago

I was told that shaders also work with maplibre gl (but differently than in tangram), so the downloaded area stripes could be implemented that way, too. (Or by tiling a graphic that looks like that.)

Helium314 commented 4 months ago

I made a very basic implementation of CustomGeometrySource for quest pins: https://github.com/Helium314/SCEE/compare/maplibre...Helium314:SCEE:custom_geometry_source

It's mostly for testing, but good enough to see how often getFeaturesForBounds is called. I haven't checked anything, it might be better or worse than the current GeoJsonSource or possibly it depends on what the user does...

westnordost commented 4 months ago

Well, good! I think this is the way to go on the mid term. My priority is to get out of the "we are just testing" phase, i.e. solve all those todos and clean up the code.

For this, I deleted the KtMapController, the MapBoxMap is now used directly. The wrapper does not make sense for MapLibre anymore, any adapted/simplified methods can be also implemented with extension functions. So, for now, I put most of the previous functionality into extension functions, most of it could probably be removed in the next step.

westnordost commented 4 months ago

I'll also pull in the layer definitions into the components because I think it makes sense to have the style definitions close to the source definitions and IMO defining them in code is not that verbose after all. (Defining expressions in code is actually better readable).

westnordost commented 4 months ago

Regarding SelectedPinsMapComponent, I think at least without further changes, this is still necessary. Your current (hacky) solution to hide all pins except of one element:

            pinsLayer?.setFilter(eq(get("element_id"), questKey.elementId.toString()))
            pinsDotLayer?.setFilter(eq(get("element_id"), questKey.elementId.toString()))

The filter is not complete because it would also need to include the quest type and element type. But even if it was, since the PinsMapComponent is also used by the EditHistoryPinsManager and there may also be pins not actually referring to any element, this kind of filtering will not work.

So, for now I will make the SelectedPinsMapComponent take care of this again. To change this, maybe the two managers would need to not use the same component for displaying their data. Not sure what would be the best replacement.

westnordost commented 4 months ago

I've ended up changing, fixing and (probably) breaking more things in the process than what is titled in the git commit.

image

(The -600 lines of code have to come from somewhere, right?) :-)

Anyway, I think I will probably not have time to continue to work on this in the next days, so feel free to familiarize yourself with the changes. Some things are not working properly, but I am not sure if I broke them or they have been like this already anyway:

Before I move on with more refactor, I will probably want to look at these. I will write here when I intend to do work on any of this, so that we don't come into conflict each other when we work on things at the same time.

Helium314 commented 4 months ago

I think some of these issues are also in the top post (frequently updated!), at least the bottom 2 are not new and the highlighting was broken after a commit from yesterday. The zoom button should actually work again after https://github.com/Helium314/SCEE/pull/516/commits/8c9a33156ce4262dbc587375cecba2faf4aad160.

I'll have a look at the current issues

Helium314 commented 4 months ago

The -600 lines of code have to come from somewhere, right?

And we didn't even (yet) remove the style yaml files.

Helium314 commented 4 months ago

I guess that's it for me today. Btw we could already test the next MapLibre release: https://github.com/maplibre/maplibre-native/releases/tag/android-v11.0.0-pre0 [Edit: the downloadable .aar file apparently doesn't contain Feature and related classes, so the app doesn't compile]

westnordost commented 4 months ago

[Edit: the downloadable .aar file apparently doesn't contain Feature and related classes, so the app doesn't compile]

Better report a bug. If they didn't notice this on releasing the alpha, who knows when they will notice themselves.

And we didn't even (yet) remove the style yaml files.

Oh! Begone!

Helium314 commented 3 months ago

Do you think it would make sense to create the map style json in SC instead of copying the json files? If it's slow it could be done only on version upgrade. Advantage would be that we could just take the road colors for the most likely necessary fix for

left/right strokes in overlays extend towards the center of an intersection, which is fugly (the same issue existed for tangram implementation, which is why "transparent" was rendered as mimicking the background map style)

(I might do it anyway for SCEE as it allows customizing map colors)

westnordost commented 3 months ago

It's probably not slow but the Kotlin code in the linked map style is more of a "my quick script" quality and I don't really want to introduce a layer on top of MapLibre just to have a nicer API for defining styles. The few number of lines of code that needs to be duplicated for the invisible roads to look like the ones in the background map is really not worth it defining the whole style in code in the app, IMO.

westnordost commented 3 months ago

some maplibre warnings/errors that certain layer property definitions may not be expressions (but must be literal values)

Will look at this now.

westnordost commented 3 months ago

Looking into why darken and addTransparency doesn't work now.

westnordost commented 3 months ago

Btw we could already test the next MapLibre release: https://github.com/maplibre/maplibre-native/releases/tag/android-v11.0.0-pre0 [Edit: the downloadable .aar file apparently doesn't contain Feature and related classes, so the app doesn't compile]

The geojson stuff is a transitive dependency. See gradle dependencies

+--- org.maplibre.gl:android-sdk:10.0.2
|    +--- org.maplibre.gl:android-sdk-geojson:5.9.0
|    |    \--- com.google.code.gson:gson:2.8.6
|    +--- com.mapbox.mapboxsdk:mapbox-android-gestures:0.7.0
|    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20 -> 1.9.0 (*)
westnordost commented 3 months ago

left/right strokes in overlays extend towards the center of an intersection, which is fugly (the same issue existed for tangram implementation, which is why "transparent" was rendered as mimicking the background map style)

I will look at this now.

westnordost commented 3 months ago

Wow, that was... a lot of work. In the end, I solved it by just rendering the left and right side behind the road(s) layer. This required to make sure that for roads on bridges, the left-and-right side highlighting is also rendered on top of other roads. I also fixed all the widths, so that, well, it should be like on master now.

Helium314 commented 3 months ago

@westnordost could you put some minimla style json on your server? I would like to work on the offline part, see https://github.com/Helium314/SCEE/blob/ae53926512a65fb18c67632188b539d7b6a4e903/app/src/main/java/de/westnordost/streetcomplete/data/maptiles/MapTilesDownloader.kt I'm not sure what actually needs to be in the style, other than the tile URL. But the commented version in MapTilesDownloader did work when I put it in my home network (onyl api key needs to be changed).

westnordost commented 3 months ago

Put what where?

westnordost commented 3 months ago

If the style definition does not have to be the exact same as available locally, you could use the one on https://streetcomplete.app/map-jawg/streetcomplete.json (for now)

(The difference is the API key used)

Helium314 commented 3 months ago

If the style definition does not have to be the exact same as available locally, you could use the one on https://streetcomplete.app/map-jawg/streetcomplete.json (for now)

(The difference is the API key used)

Thanks! API key should not be an issue I hope.

westnordost commented 3 months ago

By the way, the json is from this:

https://community.openstreetmap.org/t/minutely-updated-vector-tiles-demo/110121/26

I created a shortbread version of the map style to check out the upcoming openstreetmap-hosted vector tiles, compared it with Jawg. Looks ok, though geometry simplification and compression are missing or lacking. (Test tiles are 65 times the size of jawg tiles or when compared uncompressed, still 15 times the size of jawg tiles)

Helium314 commented 3 months ago

(The difference is the API key used)

Looks like it is an issue. The tiles are now twice in the offline database, once with online API key, once with offline API key. Is it ok if I change the API key in the locale styles to match the one from https://streetcomplete.app/map-jawg/streetcomplete.json?

westnordost commented 3 months ago

During development, that's okay, sure

Helium314 commented 3 months ago

MapTilesDownloader is now working, but needs some more adjustments.

I did not find a way to set database path (it's in internal files, so not in cache). So Android clearing the cache does not affect downloaded tiles. Downloaded tiles can be in an "offline region". They will not be removed as long as they are in such an offline region. Deleting the offline region does not delete the tiles automatically, but only if the cache size is too large (now the tiles behave like the ones downloaded when panning the map).

So there are two ways of managing offline regions:

When downloading, I did not find a way to log how many tiles are re-used. Only way I found is checking the logs for MapLibre download messages.

westnordost commented 3 months ago

Cool, keep it up! I've had a short look at the changes, but I blanked out after reading too many todos and notes about things that should be tested / checked, TBH ^^

Cache not in cache directory

That's fine. Downloaded map data does also not go into the cache. Anyway, IMO a valid feature request at maplibre.

Offline cache only deleted when cache size is exceeded

That's also fine.

delete them immediatly after downlad: should result in same behavior as with tangram

I don't understand. In Tangram, tiles were not deleted immediately after download, that would make no sense. In Tangram, tiles in the http cache were considered stale after 12 hours, but stale does not mean deleted, it just means that it intends to get a newer tile if possible.

westnordost commented 3 months ago

By the way, I posted the bug with the halo here: https://github.com/maplibre/maplibre-native/issues/2175

It looks like this is an issue with the so-called "legacy renderer". They are in the process of replacing the renderer with a "modularized renderer", so not sure if this bug is going to be fixed. However, if I understand correctly, the new android pre-release already makes use of the latter, and since they ask for feedback/bug reports, I think we should change to using the pre-release rather sooner than later: https://github.com/maplibre/maplibre-native/issues/1608

The pre-release is available on maven rep, so need to deal with transitive dependencies manually: https://mvnrepository.com/artifact/org.maplibre.gl/android-sdk/11.0.0-pre4

Maybe I will work on using that version soon, but ofc I will write it here before I start working on it.

westnordost commented 3 months ago

I will look into that the not-downloaded area gets back this hatching pattern, I don't like this darkened map

Helium314 commented 3 months ago

I don't understand. In Tangram, tiles were not deleted immediately after download, that would make no sense

Deleting is only referring to the regions. When a region is deleted, the containing tiles still stay in cache. But now they might be deleted when maximum cache size is exceeded due to subsequent downloads.

I will look into that the not-downloaded area gets back this hatching pattern, I don't like this darkened map

The current state was only a quick thing to at least have something. There is a way to set a pattern image for fill layers iirc.

Helium314 commented 3 months ago

Maybe I will work on using that version soon, but ofc I will write it here before I start working on it.

Switching would be great! Aside from the Feature thing, basically only replacing the imports is required, plus MapBox -> MapLibre.

westnordost commented 3 months ago

That was easier than I though. Though, I now get the most interesting display, looks cool though. Pretty sure it has nothing to do with my changes, so maybe the bug only exists on the Android 14 emulator I just added :-)

image

westnordost commented 3 months ago

Alright, I will do this now @ maplibre 11 pre

Helium314 commented 3 months ago

I like the surface quest icon ^^

Maybe it just goes away with the new maplibre version...

westnordost commented 3 months ago

Is the track color for you also just black?

Helium314 commented 3 months ago

Not sure what is wrong, the error text is pretty useless for me:

19:32:42.633 libc                     A  Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8 in tid 32277 (GLThread 3086), pid 32229 (mplete.ml.debug)
19:32:43.117 DEBUG                    A  pid: 32229, tid: 32277, name: GLThread 3086  >>> de.westnordost.streetcomplete.ml.debug <<<
19:32:43.205 DEBUG                    A      #21 pc 00622405  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.205 DEBUG                    A      #22 pc 0063909d  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.205 DEBUG                    A      #23 pc 00637eff  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.205 DEBUG                    A      #24 pc 004a79e9  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.205 DEBUG                    A      #25 pc 004a67c7  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.205 DEBUG                    A      #26 pc 004b7595  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.206 DEBUG                    A      #27 pc 004c9483  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.206 DEBUG                    A      #28 pc 004c8817  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so
19:32:43.206 DEBUG                    A      #29 pc 0037333f  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so (mbgl::android::MapRenderer::render(_JNIEnv&)+194)
19:32:43.206 DEBUG                    A      #30 pc 003751a9  /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/lib/arm/libmapbox-gl.so (_ZZN3jni16MakeNativeMethodIZNS_17NativeMethodMakerIMZNS_30NativePeerMemberFunctionMethodIMN4mbgl7android11MapRendererEFvR7_JNIEnvEXadL_ZNS5_6renderES7_EEEclIS5_S5_vEEDaRKNS_5FieldIT0_xEEEUlS7_RNS_6ObjectIS5_EEE_KFvS7_SJ_EJEEclISK_EEDaPKcRKT_EUlPS6_PNS_7jobjectEE_EEDaSQ_SQ_ST_PNSt6__ndk19enable_ifIXsr3std8is_classISR_EE5valueEvE4typeEENUlSU_DpT_E_8__invokeIJSW_EEEDaSU_S14_+28)
19:32:43.206 DEBUG                    A      #39 pc 0056e994  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/base.apk (deleted) (org.maplibre.android.maps.renderer.MapRenderer.onDrawFrame+12)
19:32:43.206 DEBUG                    A      #45 pc 0056f8a0  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/base.apk (deleted) (org.maplibre.android.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer.onDrawFrame)
19:32:43.207 DEBUG                    A      #51 pc 00570406  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/base.apk (deleted) (org.maplibre.android.maps.renderer.glsurfaceview.MapLibreGLSurfaceView$GLThread.guardedRun+994)
19:32:43.207 DEBUG                    A      #57 pc 00570960  /dev/ashmem/dalvik-classes.dex extracted in memory from /data/app/de.westnordost.streetcomplete.ml.debug-X6eOgc-FLo8RJAY1-LJMlw==/base.apk (deleted) (org.maplibre.android.maps.renderer.glsurfaceview.MapLibreGLSurfaceView$GLThread.run+48)
westnordost commented 3 months ago

Does that happen on your device? On startup or when you do something? Since using v11 of the sdk?

Is your smartphone OpenGL ES 3.0 capable? Check with

context.getSystemService<ActivityManager>().getDeviceConfigurationInfo().getGlEsVersion()
westnordost commented 3 months ago

I'm looking into loading the style etc. now (SceneMapComponent, large parts of MapFragment, some MainMapFragment)

westnordost commented 3 months ago

Next I'll look into reimplementing that overlays can modify?/hide other layers while active (e.g. housenumber overlay should hide the housenumbers from the background map).

Also, look into how the crass overlapping of text+icons in e.g. the shops overlay can be handled better.

Also, maybe a few color adjustements should be made for dark mode(?) E.g. text should maybe be white with black halo rather than the other way around?

westnordost commented 3 months ago

Regarding clustering, I'm all for it. I think it should actually replace the dots, as the dots were only added to mitigate the "pin forest" on lower zooms with tangram. Clustering sounds like a solution for that.

Helium314 commented 3 months ago

Does that happen on your device? On startup or when you do something? Since using v11 of the sdk?

Is your smartphone OpenGL ES 3.0 capable? Check with

context.getSystemService<ActivityManager>().getDeviceConfigurationInfo().getGlEsVersion()

Happens on startup, after onMapReady and before tiles are shown. I opened an issue.

westnordost commented 3 months ago

The issue is https://github.com/maplibre/maplibre-native/issues/2206

In case it will not be resolved very quickly and a new pre5 with a fix will be released, feel free to downgrade to v10 for now. Reverting the commit will not work without conflicts, but you can copy & replace the imports and very few class names, it will only take 5-10 minutes or so.

westnordost commented 3 months ago

Also, look into how the crass overlapping of text+icons in e.g. the shops overlay can be handled better.

Found something. On that note, is there a good reason why you put the labels (for markers and in the overlays) to the right of the icons instead of below it, what would be the default? Because, if we keep it that way, the text should probably appear to the left of the icon if the user's locale is a RTL language (Arabic, Persian, Hebrew, ...), i.e. more complexity.

westnordost commented 3 months ago

I found a (slight) performance issue that delays the initialization of the main fragment by about half a second on my device, certainly longer on yours: The preset bitmaps and pin bitmaps are created on the UI thread. To compare, to initialize everything else in that fragment takes less than that, so it is rather major.

You can measure how long it takes on your phone by measuring the time difference between the start of onMapReady till the comment with "MapLibre stuff" and then perhaps subtract 50ms from that because the rest doesn't take long (34ms on my device).

Unfortunately, it is not that easy to elegantly fix. Most elegantly would mean that we must use ViewModels (=> bitmaps are only created once, not every time the view is re-created) and that we probably need to merge MapFragment, LocationAwareMapFragment and MainFragment all into one and do the map initialization properly the kotlin-way, with coroutines instead of callbacks (onMapReady etc.). Reason for the latter being that map initialization should only continue if both map style has been loaded (asynchronously) and the icon bitmaps have been created (asynchronously). This can be done with ease with coroutines.

Helium314 commented 3 months ago

is there a good reason why you put the labels (for markers and in the overlays) to the right of the icons instead of below it, what would be the default?

On my device labels for overlays appear on the right without this PR, so I tried to reprodice this.