Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The map is lagged when the polyline consists of a large number of points #1107

Closed
Tracked by #1165
Vafin84 opened this issue Dec 22, 2021 · 43 comments
Closed
Tracked by #1165
Labels
bug This issue reports broken functionality or another error

Comments

@Vafin84
Copy link

Vafin84 commented Dec 22, 2021

Hi guys! I am experiencing performance problems when a polyline consists of a large number of points (for example, more than 7000 points), the map starts lagging and the FPS drops. Is there a way to increase productivity? For example, it would be possible to render only what is visible on the screen.

@JaffaKetchup
Copy link
Member

Hi there,
Unfortunately this is a well known issue (although previously known for markers, the same issues apply).
At the moment, you can try enabling: polylineCulling: true in PolygonLayerOptions but it is not guaranteed to fix your issue. Hope it works!

@Vafin84
Copy link
Author

Vafin84 commented Dec 22, 2021

Hi there, Unfortunately this is a well known issue (although previously known for markers, the same issues apply). At the moment, you can try enabling: polylineCulling: true in PolygonLayerOptions but it is not guaranteed to fix your issue. Hope it works!

Thanks for the answer. I've tried toggling polylineCulling on / off, but unfortunately it doesn't help much. I see the following steps in solving this problem:

  1. Render only the part of the polyline that is visible on the screen.
  2. Remove some points from the list of points of the polyline when zooming out

@ibrierley
Copy link
Collaborator

I can't remember how the polyline culling works just off the top of my head, but if you have one polyline with 7000 points, that's quite a lot....maybe it would be more optimal to have the poly broken into multiple lines so it can cull differently (this would only working depending how the cull code works). You could also look at line simplifcation at certain zooms or something (I think there's some line simplification code floating about somewhere).

@Vafin84
Copy link
Author

Vafin84 commented Dec 22, 2021

I can't remember how the polyline culling works just off the top of my head, but if you have one polyline with 7000 points, that's quite a lot....maybe it would be more optimal to have the poly broken into multiple lines so it can cull differently (this would only working depending how the cull code works). You could also look at line simplifcation at certain zooms or something (I think there's some line simplification code floating about somewhere).

Thank you. I will try to break the polyline into parts to test this.

@mohammedX6
Copy link

@Vafin84 Hi, do you come up with a solution, i have the same proplem.

@JaffaKetchup
Copy link
Member

#958 may also help here?

@mohammedX6
Copy link

@JaffaKetchup i mean the solution about breaking polyline into parts.

@JaffaKetchup
Copy link
Member

@mohammedX6 Not sure, but if search Google for chunked list in dart, you'll probably get an algorithm that splits a list into smaller parts through 2D lists. You can then use the .map method to map to a polyline.

@ibrierley
Copy link
Collaborator

I'd be interested if someone has a test data set and widget that's causing problems. Nothing like real world examples to look at.

@Vafin84
Copy link
Author

Vafin84 commented Jan 7, 2022

@Vafin84 Hi, do you come up with a solution, i have the same proplem.
Yes, I found a solution, but I don't know how good it is. I create a polyline only from those points that enter the boundaries of the phone screen. I get the borders of the screen through the map controller.

@mohammedX6
Copy link

@Vafin84 Can you share the code?

@Vafin84
Copy link
Author

Vafin84 commented Jan 7, 2022

@Vafin84 Can you share the code?

Unfortunately, I do not have the right to distribute the code, because I signed an agreement with my employer.

@Vafin84
Copy link
Author

Vafin84 commented Jan 7, 2022

@Vafin84 Can you share the code?

Just create a condition for a list of all polyline points. If the point is included in the borders of the screen, then we add it to a separate list from which a polyline is formed in the future. Every time the borders of the screen change, it is necessary to recalculate the polyline.

@ibrierley
Copy link
Collaborator

ibrierley commented Jan 7, 2022

I assume that would be a relatively straightforward map over every point and previous, see if they are within bounds eg map.pixelBounds.containsPartialBounds(x,y) ?, if so add to the new polyline list ? or is it more complex than that ?

Edit: Sorry, beat me to it.

@Vafin84
Copy link
Author

Vafin84 commented Jan 7, 2022

I assume that would be a relatively straightforward map over every point and previous, see if they are within bounds eg map.pixelBounds.containsPartialBounds(x,y) ?, if so add to the new polyline list ? or is it more complex than that ?

Edit: Sorry, beat me to it.

Yes, it is exactly as you said. In addition, I made an additional optimization as follows. It is necessary to recalculate the polyline only after the animation or actions on the map are finished (for example, changing the zoom or moving around the map). Additionally, I recommend simplifying the list of points depending on the zoom, so when the zoom is reduced, good detail is not needed.

@mohammedX6
Copy link

@ibrierley Thank you very much

@mohammedX6
Copy link

@Vafin84 Thanks for explaining, little question how do I know the animation is finished for flutter maps?

@Vafin84
Copy link
Author

Vafin84 commented Jan 8, 2022

It is necessary to listen to the changes of the map controller, so you will know when the animation has stopped.

@mohammedX6
Copy link

@Vafin84 thank you

@mohammedX6
Copy link

@ibrierley @Vafin84 Hi, can i use widget.map.bounds.contains(point) instead of map.pixelBounds.containsPartialBounds(x,y) because i don't know how to use it.
Thanks.

@Vafin84
Copy link
Author

Vafin84 commented Jan 10, 2022

@ibrierley @Vafin84 Hi, can i use widget.map.bounds.contains(point) instead of map.pixelBounds.containsPartialBounds(x,y) because i don't know how to use it. Thanks.

I use _mapController.bounds

@mohammedX6
Copy link

Thank you I did what you said earlier, I don't know if you faced this problem but when I drag the map the lines keep disappearing, please see the video for better understanding.

final_61dc7a5338b43100459a0e41_483235.mp4

@Vafin84
Copy link
Author

Vafin84 commented Jan 10, 2022

I think you need to expand the boundaries so that the end of the polyline disappears behind the scenes.

@akeblom
Copy link

akeblom commented Feb 3, 2022

@JaffaKetchup Do you now what is causing the performance problem with polylines? Just for fun i tried to paint the same amount of polylines using the mapgbox gl packages. And with that package the map was very responsive even though I painted a large amount och polylines.

@ibrierley
Copy link
Collaborator

What type of volume of polylines, and typically how many points ?

@JaffaKetchup
Copy link
Member

@akeblom Sorry, I don't have a clue. Maybe the maths is wrong, I wouldn't even know where to start. Perhaps the Mapbox packages use platform views or something like that?

@ibrierley
Copy link
Collaborator

Ultimately Mapbox can using OpenGL and have years of optimisations working on it and many people. Some Canvas solutions do have performance limitations at times, and there sometimes needs to be some creative solutions to get around them.

I do have some ideas around some of that stuff and would be interested to see some data that flutter_map struggles with to test if any of those ideas would help. I'd also be interested to see any videos of the performance issues, as it's hard to know without seeing anything if that performance is expected or not (from the amount of polys and styling being used).

@akeblom
Copy link

akeblom commented Feb 5, 2022

We are talking about thousands for points. Does it matter if I chunk them and create a polyline object for every chunk? I think I tried that earlier without noticing a big difference.

@akeblom
Copy link

akeblom commented Feb 5, 2022

Ok, so we are plotting gps-positions of hunting dogs. I have a main Polyline which shows the movement of the dog. On top on that I am plotting multiple polylines that shows where on the track the dog did bark. Seems like it is the amount of "bark" polyline objects that is causing the performance to drop. If I only show the main track the map flows quite nice.

@ibrierley
Copy link
Collaborator

Typically for performance I would suggest trying to batch together as many draw calls into one superpath as possible (i.e one per style if order of depth not important). This may not quite work easily if you are using normal default Polylines as flutter_map takes care of that for you and you don't have a lot of control, but you may be able to hack one into a modified plugin.

Obviously, if you can reduce points, it can help and would probably be the biggest impact. Example https://pub.dev/packages/simplify/install you could possibly run that as your polys get bigger.

If you can make your strokeWidth < 1.0 you will probably find it a LOT faster than a thicker line than > 1.0 (even if just temp when pinch-zooming) as it uses a faster algorithm to calculate pixels to display.

Just for anyone interested, I'm also working on a geojson vector tile slicer https://github.com/ibrierley/geojson-vt-dart (it kinda works, but it's a long way off from being ready). Which slices up Polys or sets of points that would typically be in a geojson structure (or list of points) into tiles to display. I'm not sure that would help much in your case anyway, as I expect most of your use case to be at quite a high zoom level all focused around a specific location. But mentioning it in case someone else stumbles upon this thread, and I'll chat more about it at some point.

@akeblom
Copy link

akeblom commented Feb 7, 2022

Could you just give me a quick example on how I should use your vector tile slicer?

@ibrierley
Copy link
Collaborator

There's an example hacked from the mapController test page at https://github.com/ibrierley/geojson-vt-dart/blob/master/test/test_flutter_map_map_controller.dart (all of that needs tidying up, but I'm not going to get chance for about 2 weeks). If you drag over the the U.S, you should see the polylines there. You should be able to tweak "tolerance" on line 512 to adjust line simplification (eg try 5). There's quite a lot missing, like removal of old cache and stuff like that, so it's not production ready though. Feel free to post any issues on that repo though, and I will take a look when I get chance.

@JaffaKetchup JaffaKetchup added bug This issue reports broken functionality or another error non-fatal labels Feb 8, 2022
@tupats
Copy link

tupats commented Feb 9, 2022

I have just noticed another thing, if I use a very long polyline consisting of a single line (by long, i mean 1000km long), when I am zoomed out, everything is fine, no lags. If I zoom in to about zoom level 15-16, it starts getting very laggy. Even if the line is off screen.
Maybe its something related.

@JaffaKetchup
Copy link
Member

@tupats That's kind of interesting. Maybe indicates the painting is too slow, as was considered before?

@tupats
Copy link

tupats commented Feb 9, 2022

@JaffaKetchup I'm not sure, did not have any issues before, just noticed this one on my app by accident today.
Is it possible that when zoomed out, the single line is painted, for example, 400pixels wide, but when zoomed in, its getting painted 400 squared by zoomfactor pixels wide? Even though all of it is off screen. Idk just brainstorming

@ibrierley
Copy link
Collaborator

If it's offscreen, it shouldn't affect it (unless there's a bug, and assuming polylineCulling: true). Proof of the pudding is always testing though. If you can create a minimal example, I'm sure someone can test, just to check they experience the same problem and can have a poke about to check if its still being rendered offscreen.

@tupats
Copy link

tupats commented Feb 10, 2022

@ibrierley Oh I am very sorry, my bad, I implied polylineCulling is true by default. Everything is OK now.

@ibrierley
Copy link
Collaborator

Great stuff, thanks for the feedback

@JaffaKetchup
Copy link
Member

Is this OK to close now then?

@Vafin84
Copy link
Author

Vafin84 commented Feb 18, 2022

Is this OK to close now then?

I don't think the problem has been solved definitively, but I solved this issue for myself by the workarounds that I described earlier, which significantly improved performance.

@JaffaKetchup
Copy link
Member

Ok, in that case, I will close it for now. If it needs to be re-opened later, I can. Thanks!

@aitinsan
Copy link

@JaffaKetchup Do you now what is causing the performance problem with polylines? Just for fun i tried to paint the same amount of polylines using the mapgbox gl packages. And with that package the map was very responsive even though I painted a large amount och polylines.

In mapbox_gl used native languages to draw polilines and poligons. That's how I think makes it faster

@JaffaKetchup
Copy link
Member

@aitinsan That's an interesting point. Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue reports broken functionality or another error
Projects
None yet
Development

No branches or pull requests

7 participants