Incorrect rendering for layer with transparent tiles - WPF

Jun 28, 2013 at 7:58 AM
Hello Paul,

I have two WMS layers:
  • Base map – tiles are requested through WMS with no transparency
  • Flood zones – layer above the first one and is requested through WMS with "TRANSPARENT"="True"
I can see some incorrect rendering for the second layer which occurs in certain scenarios. Once I left-click into the MapControl or manually call Refresh() the layer is correctly rendered. I am sure that it is not problem of missing tiles, because even if I wait for realy long time (for all tiles to download - if they are missing in cache) the scene is not rerendered automatically.

Please see print-screens:

Before-1
After-1

Before-2
After-2

Only base layer

Actions that evoke the state of incorrect rendering:
  • Displaying the second layer for the first time (setting Enabled=true) on layer – happens always
  • Zooming out – happens sometimes
  • Panning – happens sometimes
When I download tiles from WMS without transparency the problem never happens.


Note: I utileze FileCache for both layers.

I am using the latest version (build from source) - 44e7f35560c0
Sep 25, 2013 at 11:52 AM
mapsui renders multiple zoom-Levels at once, until the current Level is completely loaded. Not sure if that's your only problem in this case, but we had that effect too.
We solved the problem by modifiying two places in the mapsui code.
We added a OnlySingleLevel property to TileLayer and FetchStrategy, indicating this is a transparent map and should only render one Level at the time.

We modified the GetRecursive method in TileLayer class to optionally render only a single Level.
public static void GetRecursive(IDictionary<TileIndex, IFeature> resultTiles, ITileSchema schema, MemoryCache<Feature> cache, Extent extent, int level, ref int tilesRendered, ref int tilesRequired, bool onlySingleLevel = false)
{
    if (level < 0) return;
            
    var tiles = schema.GetTilesInView(extent, level);
    tilesRequired += tiles.Count();

    foreach (TileInfo tileInfo in tiles)
    {
        var feature = cache.Find(tileInfo.Index);
                
        if (feature == null)
        {
            if (onlySingleLevel) continue;

            GetRecursive(resultTiles, schema, cache, tileInfo.Extent.Intersect(extent), level - 1);
        }
        else
        {
            tilesRendered++;
            resultTiles[tileInfo.Index] = feature;
            if (!onlySingleLevel && !IsFullyShown(feature))
            {
                GetRecursive(resultTiles, schema, cache, tileInfo.Extent.Intersect(extent), level - 1);
            }
        }
    }
}
We did the same in the GetTilesWanted of the FetchStrategy class
public IList<TileInfo> GetTilesWanted(ITileSchema schema, Extent extent, int level)
{
    //line below only works properly of this instance is always called with the the resolutions. Think of something better
    if (preFetchLayers == null) preFetchLayers = GetPreFetchLevels(0, schema.Resolutions.Count - 1);

    IList<TileInfo> infos = new List<TileInfo>();
    // Iterating through all levels from current to zero. If lower levels are
    // not availeble the renderer can fall back on higher level tiles. 
    while (level >= 0)
    {
        ////////if (!preFetchLayers.Contains(level)) continue;
        var infosOfLevel = schema.GetTilesInView(extent, level);
        infosOfLevel = PrioritizeTiles(infosOfLevel, extent.CenterX, extent.CenterY);

        foreach (TileInfo info in infosOfLevel)
        {
            if ((info.Index.Row >= 0) && (info.Index.Col >= 0)) infos.Add(info);
        }
        level--;
        if (OnlySingleLevel && infos.Count != 0) break;
    }

    return infos;
}
It worked for us.
Coordinator
Sep 29, 2013 at 1:18 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Sep 29, 2013 at 1:22 PM
Thanks philjay for helping out.

R_Cervenec I created an issue for this: [url:https://mapsui.codeplex.com/workitem/9197]

The way it is supposed to work is that during a short 'animation' of opacity (0 to 1) you should see the layer below, but after that animation the layer below should be invisible. Somehow the redraw after the animation is not triggered.
Nov 26, 2013 at 12:17 PM
To philjay: Thank you very much - it works!