Open hpinkos opened 7 years ago
I suspect the SSE computation isn't just taking into account the height in 2D.
The SSE computation for Mercator projection depends on the latitude, here.
You can easily see that this is the reason by temporarily assigning a constant to latitudeFactor
variable (for example, 1.0
).
So without fully understanding the getLevelWithMaximumTexelSpacing code, is the issue simply the case the test for a GeographicTilingScheme has a ! surrounding the brackets?
function getLevelWithMaximumTexelSpacing(layer, texelSpacing, latitudeClosestToEquator) { // PERFORMANCE_IDEA: factor out the stuff that doesn't change. var imageryProvider = layer._imageryProvider; var tilingScheme = imageryProvider.tilingScheme; var ellipsoid = tilingScheme.ellipsoid; var latitudeFactor = !(layer._imageryProvider.tilingScheme instanceof GeographicTilingScheme) ? Math.cos(latitudeClosestToEquator) : 1.0;
var tilingSchemeRectangle = tilingScheme.rectangle;
var levelZeroMaximumTexelSpacing = ellipsoid.maximumRadius * tilingSchemeRectangle.width * latitudeFactor / (imageryProvider.tileWidth * tilingScheme.getNumberOfXTilesAtLevel(0));
var twoToTheLevelPower = levelZeroMaximumTexelSpacing / texelSpacing;
var level = Math.log(twoToTheLevelPower) / Math.log(2);
var rounded = Math.round(level);
return rounded| 0;
}
In my case I have the OSM layer which is a WebMercartorTilingScheme which evaluates to true due to the !. So now my WebMercartorTilingScheme is setting the latitudeFactor using the math.cos function instead of setting it to 1.0;
Anyway I found changing this and also setting the default from 1.0 to 0.5 means my map now matches OSM at the same scales.
so the final change is simply:
var latitudeFactor = (layer._imageryProvider.tilingScheme instanceof GeographicTilingScheme) ? Math.cos(latitudeClosestToEquator) : 0.5;
Again, happy to be corrected.
No, that's not correct. It will produce incorrect results with an imagery layer using GeographicTilingScheme
.
Actually, this is tricky. The original code is correct in 3D, just not in 2D. In 3D, the real world space of a given tile of imagery in the Web Mercator projection gets smaller near the poles. In 2D, this is not the case.
The ideal solution is to separate selection of terrain and imagery tiles. Currently a set of imagery tiles is selected just once for each terrain tile and used from then on. That's a lot of work though.
An easier but not as good solution is to select imagery tiles based on the current scene mode, and when the scene mode changes, redo that computation. This is still pretty tricky. The basic approach is to clear out the imagery list for each loaded terrain tile, and then recreate it by calling that _createTileImagerySkeletons
to recreate them according to the rules of the new scene mode. Some issues I can think of:
processStateMachine
at least once (is once enough? I think so) on each new TileImagery
created by _createTileImagerySkeletons
so that they can discover they're already loaded (if they are) or select a parent tile to use instead (if they're not).ok Kevin, no dramas. I was hoping it was as the 2D map seemed heaps better. This is holding us back from going to Prod :( Canberra streets are completely unreadable
As a workaround, just set latitudeFactor
to 1.0. In 2D it'll look ok, in 3D it'll load more tiles and go slower, but it shouldn't look terrible, at least.
Or, if I can shamelessly plug my own work, take a look at TerriaJS which uses Leaflet for 2D (still Cesium for 3D). Developed in Australia, too.
Reported on the forum: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/1eIeTqEqgsA
Eventually you'll see France/Switzerland tiles from level 5 and Germany/UK will be tiles from level 4. This persists for several scroll wheel clicks for me.
I know this is expected behavior in 3D, but in 2D I would expect all tiles to be from the same level.