Giter Club home page Giter Club logo

Comments (25)

geisterfurz007 avatar geisterfurz007 commented on July 27, 2024 1

@HusseinCopol You'd use that in your dart code like this:

const _themeData = /* { all of this is your json } */;

final mapTheme = ThemeReader().read(_themeData); // You can also supply logger: Logger.console() to the ThemeReader to spot parsing issues with your theme.

Then in your VectorTileLayerOptions, you can provide your theme by setting theme: mapTheme.

ThemeReader needs import 'package:vector_tile_renderer/vector_tile_renderer.dart'; which is a dependency of this library so it should be available.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024 1

@FaFre I couldn't wait - with some profiling I made a few changes inspired by your suggestion greensopinion/dart-vector-tile-renderer@548c0cc

from flutter-vector-map-tiles.

ibrierley avatar ibrierley commented on July 27, 2024 1

I'm just adding a few bits here, after recent thoughts on the removal of raster discussion...some has already been covered I think, so apologies, just getting it out of my head before it pops out again. Some may have already been done! But writing it down in case someone wants to explore (I don't think I've got quite time to dabble atm, but will if I do).

Generally in Flutter, canvas paths are typically very slow to render with strokewidths sub 1px (especially when zoomed) as it uses a different algorithm for linecaps etc. Sometimes there may be a path say at 1.2px...when pinchzooming, could anything between 1-2px be rendered at 0.99px for example (I experimented a bit with this in the renderer, and maybe it helped a little, in some cases, but not sure how the renderer would know if pinchzooming, or if thats better done outside the rendering code and figured before any calls to it)

Generally calls to drawPath should be minimised. Can paths with the same style be grouped into one superpath (with a Move inbetween them), cache that path and draw (may be fiddly if using expressions that change per zoom, but could be done in inbeween zoom level changes). This may be similar to the addPolygon idea, but we can also group multiple lines as well.

TextLayouts are typically expensive, so can that be cached (I know thats been discussed a bit before, not sure where that is currently), I was thinking about a simple storage of a previous frame type cache even. If a labels textlayout (based on latlng point and name for example) was stored in a hash of previous display frame/update, it should be able to be reused (I think!).

I played with the idea of "overZooming" (I think there's another term for it, but it eludes me). So let's say we are at zoom 14. We draw the tiles at zoom 13, which means you only need a quarter of the tiles (some loss of lines maybe, but for tiles that have too much data it can help a bit). (Does this also play into the mapbox tilesize of 512 vs 256, not sure ?)

Instead of drawPath, during a pinchzoom, can Canvas drawPoints with a PointMode of lines/polygon be used ? It may not need to calculate linecaps etc do maybe faster (similar to earlier...if a strokeWidth is < 4 say, do we care about accuracy of joins ? Now, I did try this a year or two ago, and the odd time got an out of mem error, but I think this was referencing GPU memory for point storage, and it may well be all of that is fixed now.

If pinchzooming, could rendering be interrupted if a new zoom level comes in (bit fiddly this one...one may end up with blank tiles, not sure I like this...) ?

Out of interest, is there a way for the rendering code to know that a pinchzoom is taking place ? I couldn't quite tell from the code if that's possible or not...

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

Hi, thanks for the kudos!

Performance is a real problem when it comes to vector tiles. So great to hear that you're interested in contributing.

There are a few things that you can do to tune the codebase as-is:

  1. Check that you're using RenderMode.mixed, which uses raster tiles (rendered from vector data) while zooming, and then renders again with vector tiles when zooming is finished.
  2. Check your tile data to verify that it doesn't include unnecessary information that would render outside of the tile bounds.
  3. Tune your map theme to avoid rendering unnecessary polygons/lines
  4. Check your memory usage - if the app is freezing, it's possible that you are using too much memory and hitting the upper limits.

I've done the above and come up with a decent frame rate while zooming/panning. There is some jitter (i.e. skipped frames) especially in dense regions (e.g. London, UK) however the user experience is still pretty good.

At one point I did experience freezing as you mentioned. I made some changes to the codebase to avoid rendering outside of the tile area for labels on the Canvas, and that made a huge difference. There's potentially more that could be done here (e.g. with polygons/lines) I wonder if your tiles contain shapes outside of the tile rendering area? That could be a good place to start with a contribution.

The Flutter memory view is really helpful to see if you're hitting an upper memory limit.

from flutter-vector-map-tiles.

filipproch avatar filipproch commented on July 27, 2024

Thanks for your fast reply, I will experiment and try to get into the code more. With Memory view didn't see immediate problems - so I started debugging it with the performance view (see below). I will write updates in this issue if I manage to get some improvements.

image

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

I've done some more work in this area since I was noticing jank on iPad.

It's still not perfect, but these two commits make a big difference:

b46c80a
55f3841

Also, I've found that tuning the map style to reduce detail at different zoom levels can help. For example, the style that I'm using has minzoom=14 for road_minor, and minzoom=15 for road_minor_casing. By having casing for minor roads only render at zoom level 15 and above, there's half as much work to do at zoom level < 15.

from flutter-vector-map-tiles.

filipproch avatar filipproch commented on July 27, 2024

Cool, I will try it out. I should get to experiment with it more during the upcoming week

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

from flutter-vector-map-tiles.

HusseinCopol avatar HusseinCopol commented on July 27, 2024

I've done some more work in this area since I was noticing jank on iPad.

It's still not perfect, but these two commits make a big difference:

b46c80a 55f3841

Also, I've found that tuning the map style to reduce detail at different zoom levels can help. For example, the style that I'm using has minzoom=14 for road_minor, and minzoom=15 for road_minor_casing. By having casing for minor roads only render at zoom level 15 and above, there's half as much work to do at zoom level < 15.

Hi.
I have performance issues too , how do i tune my map style to reduce details?
thanks

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

how do i tune my map style to reduce details?

to do that you'll need to edit the map style, which you could do with a text editor but it's easier with something like https://maputnik.github.io

The fewer things showing on a map, the less computationally expensive it is (i.e. the faster it will render.) There are a few ways to achieve fewer things while still having beautiful maps:

  1. Consider rendering finer details only at higher zoom levels. For example, if your style shows buildings, consider having them show up only when the map is zoomed level 14, 15 or higher. That can be achieved with the minzoom property. The same applies for things like trails, alleys, and minor roads.

  2. Consider reducing the level of detail of roads by eliminating borders at lower zoom levels. Most styles that I've seen render roads twice at different widths to give the effect of a border. By eliminating road borders, there's less work in rendering those tiles.

I hope that helps. If it's still not enough, you could use raster rendering which will provide the styling advantages of vector tiles, but without the crisp edges.

from flutter-vector-map-tiles.

HusseinCopol avatar HusseinCopol commented on July 27, 2024

how do i tune my map style to reduce details?

to do that you'll need to edit the map style, which you could do with a text editor but it's easier with something like https://maputnik.github.io

The fewer things showing on a map, the less computationally expensive it is (i.e. the faster it will render.) There are a few ways to achieve fewer things while still having beautiful maps:

1. Consider rendering finer details only at higher zoom levels. For example, if your style shows buildings, consider having them show up only when the map is zoomed level 14, 15 or higher. That can be achieved with the `minzoom` property. The same applies for things like trails, alleys, and minor roads.

2. Consider reducing the level of detail of roads by eliminating borders at lower zoom levels. Most styles that I've seen render roads twice at different widths to give the effect of a border. By eliminating road borders, there's less work in rendering those tiles.

I hope that helps. If it's still not enough, you could use raster rendering which will provide the styling advantages of vector tiles, but without the crisp edges.

thanks.i have one more question! maputnik gave me a JSON file and where do i use it? the map controller didn't have any styling property (like google map controller ) .

from flutter-vector-map-tiles.

geisterfurz007 avatar geisterfurz007 commented on July 27, 2024

I've found that most of the time spent rendering is looping over the theme layers so to increase performance, you can start by throwing out all layers from your theme, that you won't need. For example I built an app with a map scoped in Germany but the default theme from Mapbox includes a theme layer for US highway symbols. After trimming down the layers from a few hundred to just over a dozen which suffice in my case, performance went from 5 FPS went around 50 when zooming, moving and rotating.

Of course if you have layers that should only show at specific zoom levels, using the minzoom/maxzoom properties works as well.

from flutter-vector-map-tiles.

FaFre avatar FaFre commented on July 27, 2024

I read the rendering code today, it was really a pleasure. Great work @greensopinion !

I was also doing some canvas painting, but on top of the standard flutter_map tile layer. In my case I had a big performance improvement when actually adding lines via addPolygon() to the Path. It's a lot faster compared to lineTo()when having larger linestrings. However, I tried it out and couldn't feel a notably difference when applying to this project. Maybe it's a little bit faster, but I haven't done any benchmarking. I think because the tiled linestrings are already very small, so most CPU time is taken by the painting overhead.

When interested, take a look here: FaFre/dart-vector-tile-renderer@f43fffe

But I think having 1-4 long running isolates and distribute the tile rendering jobs to them will bring a huge performance improvement. Downside, isolates are not supported for web.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

I read the rendering code today, it was really a pleasure. Great work @greensopinion !

Thanks @FaFre, great to hear.

I was also doing some canvas painting, but on top of the standard flutter_map tile layer. In my case I had a big performance improvement when actually adding lines via addPolygon() to the Path. It's a lot faster compared to lineTo()when having larger linestrings. However, I tried it out and couldn't feel a notably difference when applying to this project. Maybe it's a little bit faster, but I haven't done any benchmarking. I think because the tiled linestrings are already very small, so most CPU time is taken by the painting overhead.

When interested, take a look here: FaFre/dart-vector-tile-renderer@f43fffe

Feel free to issue a pull request - this is worth adding regardless of performance since it simplifies the code.

But I think having 1-4 long running isolates and distribute the tile rendering jobs to them will bring a huge performance improvement. Downside, isolates are not supported for web.

What do you have in mind for rendering jobs? From what I understand, calls to Canvas can only be done on the UI thread.

from flutter-vector-map-tiles.

filipproch avatar filipproch commented on July 27, 2024

regarding canvas on UI thread, there is a Flutter issue for this FYI
flutter/flutter#75755

from flutter-vector-map-tiles.

FaFre avatar FaFre commented on July 27, 2024

Ohh too bad. I thought through the rasterization it could be also done in an isolate, but it seems like that it's not even possible to instantiate a Canvas inside an isolate. However, with the new release they put a lot of focus on isolates. Hopefully it will be possible soon.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

I've had a run at some performance related changes. There's more work to do, but there are some noticeable improvements in the latest release.

  • eliminated unnecessary re-rendering of tiles while panning
  • reduced CPU overhead of text labels
  • reduced memory overhead
  • improved cache hit rate

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

The latest release has more performance improvements.

Some performance issues remain, clearly showing up as jank with the default theme.

Current recommendations:

  1. Tune your theme:
    • reduce unnecessary map elements (such as buildings, minor roads, labels) at lower zoom levels using minzoom
    • avoid rendering unnecessary polygons/lines
  2. Check that you're using RenderMode.mixed, which uses raster tiles (rendered from vector data) while zooming, and then renders again with vector tiles when zooming is finished.
  3. Check your tile data to verify that it doesn't include unnecessary information that would render outside of the tile bounds.
  4. Check your memory usage and avoid large cache sizes - if the app is freezing, it's possible that you are using too much memory and hitting the upper limits.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

Closing based on recent optimizations including issues #21. Feel free to open a new issue if there continues to be a problem.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

A lot of work has been done to improve performance. There is still room for more improvement, however in testing I've found that RenderMode.mixed is no longer needed for my use-case. See #21 for related discussion.

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

from flutter-vector-map-tiles.

ibrierley avatar ibrierley commented on July 27, 2024

Thinking out loud, I may be barking up the wrong street, so this may not apply! I was thinking about why I didn't really get any major text performance issues later on when experimenting with vector tiles.

When I was doing Vector stuff, in the end, I ended up not using Positioned Widgets (maybe a hybrid is interesting..can't remember if I tried this). I suspect what may be happening is that every zoom change, all the text layouts need to be recalculated, and then readjusted inversely according to the scale (and text layout is very expensive iirc).

However, in reality, we don't need to do any of this at all (unless we are either literally resizing the text to fit in with a road width for example, or curving text along a road). At all times, typically we want the text to be the same size (visually to the human eye). So we don't need to recalculate any of this, one can just reuse the old layout and draw on one none transformed Canvas.

For example...all on one single upper Canvas

///pos = tile position..
matrix = Matrix4.identity();
matrix..translate(pos.point.x.toDouble(), pos.point.y.toDouble())
          ..scale(pos.scale);

...


for (Label label in labels) {

    label.transformedPoint =
            MatrixUtils.transformPoint(matrix, label.point);

         // collision detection, maybe every x frames

         //canvas.save(); // only if map rotated

    canvas.translate(
            transformedPoint.dx, transformedPoint.dy);

         //canvas.rotate(-widgetRotation * 0.0174533); // only if map rotated
         //canvas.restore(); // only if map rotated




Apologies again, if this is a redherring.

from flutter-vector-map-tiles.

serraojoao avatar serraojoao commented on July 27, 2024

Where is this RenderMode being set? could not find it anywhere with latest version of the package

from flutter-vector-map-tiles.

greensopinion avatar greensopinion commented on July 27, 2024

Where is this RenderMode being set? could not find it anywhere with latest version of the package

RenderMode was removed, see discussion on #31 and implementation on #52

from flutter-vector-map-tiles.

ch-muhammad-adil avatar ch-muhammad-adil commented on July 27, 2024

@HusseinCopol You'd use that in your dart code like this:

const _themeData = /* { all of this is your json } */;

final mapTheme = ThemeReader().read(_themeData); // You can also supply logger: Logger.console() to the ThemeReader to spot parsing issues with your theme.

Then in your VectorTileLayerOptions, you can provide your theme by setting theme: mapTheme.

ThemeReader needs import 'package:vector_tile_renderer/vector_tile_renderer.dart'; which is a dependency of this library so it should be available.

With this implementation you have to make sure that chosen theme and map providers are same. In my case I have been using Stadia map provider and picked a theme from GeoApify. I started facing problems because of incompatibilities. Then I switched to GeoApify map provider with the following link inside _urlTemplate()

https://maps.geoapify.com/v1/tile/klokantech-basic/{z}/{x}/{y}.pbf?apiKey=YOUR_API_KEY

I have picked theme style from here

https://maps.geoapify.com/v1/styles/klokantech-basic/style.json?apiKey=YOUR_API_KEY

This has completed my implementation ... rest anyone can pick a theme from the plugin's gallery and can add to application by making sure both providers and theme are from same source.
Also one more important thing here is source for me, which says default and inside this plugin's example app we have openmaptiles, Question is why I am using 'default' source? Because this source is mentioned inside style json file we pick. I have attached few screenshots below.

Screenshot 2023-02-03 at 2 48 40 PM

Screenshot 2023-02-03 at 2 50 51 PM

from flutter-vector-map-tiles.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.