Closed Helium314 closed 2 weeks 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.
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).
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)
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.
Try make it non-transparent. Does it still have this effect?
Opacity or color don't have any effect on this.
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.)
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...
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.
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).
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.
I've ended up changing, fixing and (probably) breaking more things in the process than what is titled in the git commit.
(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.
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
The -600 lines of code have to come from somewhere, right?
And we didn't even (yet) remove the style yaml files.
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]
[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!
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)
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.
some maplibre warnings/errors that certain layer property definitions may not be expressions (but must be literal values)
Will look at this now.
Looking into why darken and addTransparency doesn't work now.
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 (*)
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.
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.
@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).
Put what where?
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)
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.
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)
(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?
During development, that's okay, sure
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.
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.
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.
I will look into that the not-downloaded area gets back this hatching pattern, I don't like this darkened map
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.
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.
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 :-)
Alright, I will do this now @ maplibre 11 pre
I like the surface quest icon ^^
Maybe it just goes away with the new maplibre version...
Is the track color for you also just black?
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)
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()
I'm looking into loading the style etc. now (SceneMapComponent, large parts of MapFragment, some MainMapFragment)
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?
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.
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.
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.
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.
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.
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.
For simple comparison with master, and for discussions.
to do
CustomGeometrySource
(draft started by @Helium314)~ blocked by at least maplibre-native#2262 and not strictly necessaryto do SCEE
upstream blockers
old observations below
Performance regarding icons (symbol layers, mostly about quest pins):
Other things:
This request was cancelled (https://api.jawg.io/glyphs/Roboto%20Regular%2cNoto%20Regular/0-255.pbf). This is expected for tiles that were being prefetched but are no longer needed for the map to render.
. It's not horrible, but downloading the same thing on every start seems like a waste of bandwidth and resources.