-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Batch polygon and circle fills and strokes #5196
Conversation
e33d467
to
a6fd547
Compare
Opened for discussion: The problem with batching fills and strokes is that overlapping polygons and circles with transparency won't have increased opacity. See #5179 (comment). Maybe there is a way to achieve fill overlap when applying a fill to a path that has overlaps, but I haven't found one. One way to deal with this would be to make rendering behaviour configurable, so users can decide whether they want increased performance and no increased opacity on overlapping features with transparency, or features with true visual overlap at the cost of poorer performance. Ideas? |
How about this: when creating the replay, we check if there is any opacity. If so, we do not batch. Otherwise we do. I can update the pull request easily for a proof of concept. |
5391a0d
to
81498bf
Compare
I think this is a nice approach. Ready for review. |
3407ceb
to
59d6066
Compare
While I agree this approach is a nice default that works, I would find an option to force the batching always on useful in cases where I don't care about the opacity-correctness. |
@@ -1440,13 +1484,20 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle | |||
var fillStyleColor = fillStyle.getColor(); | |||
state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ? | |||
fillStyleColor : ol.render.canvas.defaultFillStyle); | |||
if (!this.transparency && ol.color.isRgba(state.fillStyle)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since ol.color.isRgba()
is only used to test if alpha is not 1
, it would be simpler just to have ol.color.isOpaque()
or something (rather than first testing if it is RGBA and then creating an array and then testing the alpha value).
I don't want to rain on the parade, but I'm dubious about the effort to batch fills and strokes in this way. Here is a picture with batched fills and strokes: I don't think this is what people want. I'm also curious about how this affects what is reported in #4232, since I think that with the changes here, things are not being batched (because |
I can imagine we could gain performance when there is no fill or no stroke. In those cases, we could defer stroking or filling (respectively) until the end. We could also delay stroking or filling until a fill or stroke is encountered (no need to stroke until you are going to fill and no need to fill until you are going to stroke). But these performance gains would be limited to pretty narrow cases. |
Thanks @tschaub and @bjornharrtell for the valuable feedback. Based on that, I got rid of the opacity guessing game and introduced a new |
695484d
to
259b601
Compare
Looks good to me. I like the note on which kind of data this works on, another argument for my mission to convince people to work with non-overlapping topological data. |
var pendingFill = 0; | ||
var pendingStroke = 0; | ||
var batchSize = | ||
this.instructions != instructions || this.overlaps ? 0 : 200; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious about the 200
here. Did you find that performance is degraded if the batch size gets too big? It might be nice to document the justification for this default on its own line.
This sounds like a nice solution @ahocevar. It looks like your tests may cover it, but it would be even clearer to see rendering tests for |
259b601
to
5dc2043
Compare
Thanks for the review @tschaub. I have addressed your comments. Can you take another look please? |
5dc2043
to
232f9e3
Compare
Is this good to merge now @tschaub? |
0b56136
to
b521675
Compare
Instead of deciding whether to batch fills and strokes by looking at the opacity of the style, we now rely on user input.
f50dfc1
to
1b6eea6
Compare
Rebased one more time. |
@@ -4416,6 +4417,17 @@ olx.source.VectorTileOptions.prototype.logo; | |||
|
|||
|
|||
/** | |||
* This source may have overlapping geometries. Default is `true`. Setting this | |||
* to `false` (e.g. for sources with polygons that represent adminstrative |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
administrative
LGTM @ahocevar |
1b6eea6
to
6daf7b2
Compare
6daf7b2
to
395793b
Compare
sorry for being late, but shouldn't this addition to the API be documented in the release notes? |
Changes like this can be added to the release notes by the release manager when the release is created. |
the performance boost with this change is amazing !! |
This says the issue #4232 is closed by this issue, I but still have terrible performance issue using IE (11 or Edge) - FF is a bit better, but not much. I use OL 3.19 version. Is there any progress on this? |
@mstrop Have you configured your source with |
@mstrop Looks like your source does not have topological data, so you cannot use the |
@ahocevar ups, it's not a good message. Is there a chance this issue will be solved in future? |
@mstrop The only two places where I see additional potential for library side performance optimization is text and regular shape (including circle) rendering. In your case, however, I suspect that you could optimize the style functions for your vector layers on the application level. |
@ahocevar thanks a lot. |
@ahocevar sry, one more question - I was thinking about your comment "I suspect that you could optimize the style functions for your vector layers on the application level". What is relation between a styling function and forEachFeatureAtPixel method? I use forEachFeatureAtPixel inside pointer move event as I need to change cursor in case it hovers above a feature. So the styling function is not called as the map is not being redrawn. Or am I missing anything? |
Even if you are only using |
@ahocevar thanks a lot for your very prompt response. I am really sorry, but I don't agree with you - I just made a quick test - I placed console.log(new Date().getTime()); as the first row of my styling function - sure, it overloads my console when I move the map, but there is no single record when the map is static and I just move the cursor above it. |
My mistake @mstrop. The style function is called when creating the replay, not when replaying. And during mousemoves, it is only replayed. However, without seeing your code, it is hard to guess what could be the culprit. Does your vector source use a spatial index? Have you tried with a smaller |
Fixes #4232.
Better solution than the reverted one from #5149.