Skip to content

Fix for reprojecting opaque tile sources #4628

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

Merged
merged 1 commit into from
Jan 12, 2016

Conversation

petrsloup
Copy link
Member

The tile sources that are marked as 'opaque' (to benefit from rendering optimizations) are sometimes rendered incorrectly when reprojected -- the resulting reprojected tiles are not always opaque (e.g. projection boundaries, deformations, ...) and tiles from other zoom levels "bleed-through".

This PR changes getOpaque to return false when reprojecting.

@@ -365,7 +365,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
/** @type {Array.<number>} */
var zs = Object.keys(tilesToDrawByZ).map(Number);
zs.sort(ol.array.numberSafeCompareFunction);
var opaque = tileSource.getOpaque();
var opaque = tileSource.getOpaque(projection);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source.getOpaque(projection) method is now a bit hard to explain. And the opaque value is deceptive. Why not move the projection equivalence check here? Maybe something like:

var opaqueAndNotReprojecting = ol.ENABLE_RASTER_REPROJECTION ?
    ol.proj.equivalent(tileSource.getProjection(), projection) : tileSource.getOpaque();

And then use opaqueAndNotReprojecting below. Cumbersome name, but at least it describes what it is.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far, most of the tile reprojection handling is in ol.source.TileImage so I added it there to keep it in all one place.
The renderer has no special handling related to reprojection and the opaqueAndNotReprojecting would make sense only for ol.source.TileImage (not for other subclasses of ol.source.Tile).

Alternatively, we could rename getOpaque to getOpaqueForProjection (or keep getOpaque unchanged and add getOpaqueForProjection) to make it more clear (and consistent with getTileGridForProjection and getTileCacheForProjection methods).

I have no strong opinion on this, so I'm not opposed to moving the projection equivalence check to the canvastilelayerrenderer.js if others also think it would be better. Opinions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main concern that I have is that I can't make any sense of source.getOpaque(projection) (or getOpaqueForProjection). How would you explain what that method means? Opacity and projection are unrelated. So it suggests to me that "opacity" is being overloaded in a bad way (how many additional meanings should be packed into the same word?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reading your original description, it sounds like you are talking about the reprojection resulting in non-opaque pixels being rendered.

Can you provide a screenshot to help illustrate the issue?

@fredj fredj added this to the v3.13.0 milestone Jan 7, 2016
@petrsloup
Copy link
Member Author

@tschaub Sorry the problem description was not clear. I'll try to explain it better this time.

Some sources are marked as "opaque", which the canvastilelayerrenderer uses as a hint to perform certain optimizations (it skips clearRect calls since the content is to be fully overwritten anyway).

When reprojecting for example MapQuest source to some projections, the new tiles (created by the reprojection) can be partially transparent although the original tiles are always opaque:
opaque-reprojection-error
(example from current master)
The error on the bottom is caused by limited extent of the target projection, while the error on the top is caused by limited extent of the source projection (and tile grid).
In both cases, the canvastilelayerrenderer expects the tiles to be fully opaque (as hinted by getOpaque) and does not clear the old content in the canvas (when zooming for example) -- the opaque hint makes sense only for the original "data" projection and is not reliable when reprojecting.

@tschaub
Copy link
Member

tschaub commented Jan 8, 2016

Thanks for the clarified description and illustration of the problem @petrsloup.

So ideally the canvas renderer could know source.getOpaque(extent, projection). But I know that would be a more involved change for potentially little gain.

I agree it is nice to contain the concerns about reprojecting. So I think this makes sense to merge as it is.

Given your screenshot above, this looks like a great place for a rendering test. I'm not sure how sensitive the assertions would be to changes in the reprojection implementation, so I don't have a sense for how hard these would be to maintain (or create in the first place).

@petrsloup petrsloup force-pushed the opaque-reprojection-fix branch 2 times, most recently from 42767de to 7555b1b Compare January 11, 2016 09:37
@petrsloup
Copy link
Member Author

@tschaub I tried to create the rendering test for this, but it proved to be quite complicated. The issue is only visible under certain conditions (after interaction -- at least zooming), so the test needs to have several "steps" and a lot of trial and error is required to get the test constants right.

I'm afraid I don't have enough time to look at the test now, so (unless there are other comments or notes) I think we should merge this as it is to have the fix in v3.13.0.

@tschaub
Copy link
Member

tschaub commented Jan 11, 2016

@petrsloup I agree this should be merged. Thanks for the fix and for the additional explanation.

@petrsloup petrsloup force-pushed the opaque-reprojection-fix branch from 7555b1b to 08b52f3 Compare January 12, 2016 07:50
@petrsloup petrsloup force-pushed the opaque-reprojection-fix branch from 08b52f3 to 2c3ed38 Compare January 12, 2016 07:58
petrsloup added a commit that referenced this pull request Jan 12, 2016
Fix for reprojecting opaque tile sources
@petrsloup petrsloup merged commit 11bd31c into openlayers:master Jan 12, 2016
@petrsloup
Copy link
Member Author

Thanks @tschaub

@petrsloup petrsloup deleted the opaque-reprojection-fix branch January 12, 2016 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants