ThinkGeo.com    |     Documentation    |     Premium Support

Applying styles to a range of zooms

We want to be able to only display features on a layer at a specific range of zoom scales (say from 1:1 to 1:1,000,000). We are setting up a set of 6 CustomZoomLevels for the layer. The zoomed out to one more than the maximum are set to null Maximum and minimum are set to the style we want, and 1 less than the minimum to 1.0 are again set to null.

When we run this we expect that if we set the zoom to a scale inside the min/max range we see it (and this currently works as expected), but if we set the scale to any value outside that range, we see nothing. However, it still seems to use the range style for values higher.

Example, if we set the Maximum to say 1,000,000, the layer will still show the style all the way up to say 1,400,000.

Here is an example of the “Range” setting for the Layer ZoomLevels

Is there something like snapping going on here, something I need to ensure gets set? This did work in an other application verbatim to what I am trying here, except it is an older version of ThinkGeo (it had CustomZoomLevels in the ZoomLevelSet), but the ZoomLevelSet is now deprecated in the maps zoom settings (still there for layers).

        ZoomLevelSet zoomLevels = new ZoomLevelSet();
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(100000000.0));    // All the way zoomed out (off)
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(maximum + 0.1));  // Turn layer off (maybe all the way out), no styles
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(maximum));             // Display the layer using these styles
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(minimum));             // Again, same style as above
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(minimum - 0.1)); // And nothing
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(0.0));           // And nothing

Hi Chris,

The ZoomLevelSet is too heavy for a MapView . A ZoomLevelSet contains multiple zoom levels, and each zoom level includes one or more styles. This design makes sense for a FeatureLayer , but not for a MapView . That’s why in newer versions we replaced MapView.CustomZoomLevelSet with a simpler Collection<double> .

The MapView.ZoomScales is used only for snapping when double-clicking or wheel zooming. In practice, though, the map can stop at any scale. You can programmatically zoom to an exact scale, and if you pan during a zoom animation, the ongoing zoom will be canceled immediately and the map will stop at the current scale.

If your code worked with the old MapView.CustomZoomLevelSet , it can also work with MapView.ZoomScales . You can additionally enforce limits by setting MapView.MaximumScale and MapView.MinimumScale .

Let me know if you run into any issues.

Thanks,
Ben

Okay, tested this further.

Looks like the map zooms to any scale, but still seems to Snap to the zoom levels of the map prior to determining which style is applied to that layer.

In a test we do the following:

We make our own set of Map zoom levels (although this still does funny things with the default)

        mapView.ZoomScales = new Collection<double>
            // These are the zoom levels we use in the dropdown, they are not all used in the map
            // but we want to show them all so users can select them.
            // Note: These are in reverse order of how they appear in the dropdown.
            //       The first one is the highest zoom level, and the last one is the lowest zoom level.
            {
                100000000,50000000,20000000,10000000,5000000,2000000,1000000,500000,200000,100000,50000,
                25000,10000,5000,2000,1000,500,200,100
            };

We add the base map and a source file (just some areas from your how do I samples)

        var baseOverlay = new ThinkGeoCloudVectorMapsOverlay("USlbIyO5uIMja2y0qoM21RRM6NBXUad4hjK3NBD6pD0~",
            "f6OJsvCDDzmccnevX55nL7nXpPDXXKANe5cN6czVjCH0s8jhpCH-2A~~", ThinkGeoCloudVectorMapsMapType.Light);
        // Set up the tile cache for the base overlay, passing in the location and an ID to distinguish the cache. 
        baseOverlay.TileCache = new FileRasterTileCache(@".\cache", "basemap");
        mapView.Overlays.Add(baseOverlay);

        // Create a new overlay that will hold our new layer and add it to the map.
        var fileGeoDatabaseOverlay = new LayerOverlay();
        mapView.Overlays.Add("overlay", fileGeoDatabaseOverlay);

        // Create the new layer and set the projection as the data is in srid 2276 and our background is srid 3857 (spherical mercator).
        var fileGeoDatabaseFeatureLayer = new FileGeoDatabaseFeatureLayer(@"C:\ProgramData\GeoCarta\UserMap\zoning.gdb")
        {
            FeatureSource =
            {
                ProjectionConverter = new ProjectionConverter(2276, 3857)
            },
            ActiveLayer = "zoning"
        };

        // Add the layer to the overlay we created earlier.
        fileGeoDatabaseOverlay.Layers.Add("Zoning", fileGeoDatabaseFeatureLayer);

We then set that layer to have styles only for a range of values:

        SetLayerStyles(fileGeoDatabaseFeatureLayer, _minimumZoomLevel, _maximumZoomLevel);

Here is that function:

    private static void SetLayerStyles(FeatureLayer layer, double minimum, double maximum)
    {
        // Create the Custom Zoom Level Set
        layer.ZoomLevelSet.CustomZoomLevels.Clear();
        ZoomLevel defaultZoomLevel = layer.ZoomLevelSet.ZoomLevel01;
        defaultZoomLevel.DefaultAreaStyle = null;
        defaultZoomLevel.DefaultLineStyle = null;
        defaultZoomLevel.DefaultPointStyle = null;
        defaultZoomLevel.DefaultTextStyle = null;

        ZoomLevelSet zoomLevels = new ZoomLevelSet();
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(100000000.0));     // All the way zoomed out (off)
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(maximum + 0.1));  // Turn layer off (maybe all the way out), no styles
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(maximum));             // Display the layer using these styles
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(minimum));             // Again, same style as above
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(minimum - 0.1)); // And nothing
        zoomLevels.CustomZoomLevels.Add(new ZoomLevel(0.0));           // And nothing

        // Initialize the levels
        foreach (ZoomLevel level in zoomLevels.CustomZoomLevels)
        {
            level.DefaultAreaStyle = null;
            level.DefaultLineStyle = null;
            level.DefaultPointStyle = null;
            level.DefaultTextStyle = null;
        }

        // Grab the 2 levels (the range) so I can set them
        layer.ZoomLevelSet = zoomLevels;
        ZoomLevel maximumLevel = layer.ZoomLevelSet.CustomZoomLevels[2];
        ZoomLevel minimumLevel = layer.ZoomLevelSet.CustomZoomLevels[3];

        // Create an Area style on zoom level 1 and then apply it to all zoom levels up to 20.
        AreaStyle style = new AreaStyle(GeoPens.Black, new GeoSolidBrush(new GeoColor(50, GeoColors.Blue)));
        minimumLevel.DefaultAreaStyle = style;
        maximumLevel.DefaultAreaStyle = style;
    }

We set the minimum to 1.0 and maximum to 1,000,000

If we zoom to 1,000,000 the layer shows on the map, zoom to 2,000,000 it does not show. But when we set the scale to say 1,000,100 one would expect the layer not to show, but it does, and it does all the way up to in the 1,450,000 range. We need the layer to show at and above the minimum and below or at the maximum, this is not the case.

Any pearls of wisdom you can share would help, or is there more I need to do.

Hi Chris,

I couldn’t reproduce the issue on my side. Here’s what I tried:

  1. Copied your code into HowDoI → DisplayFileGeoDatabase.xaml.cs .
  2. Added a Label in XAML and bound it to MapView.CurrentScale so I could see the current scale while zooming in/out:
   <Grid>
       <thinkGeoUi:MapView x:Name="MapView" Loaded="MapView_Loaded"></thinkGeoUi:MapView>
       <Label Width="200" Height="40" FontSize="20"   VerticalAlignment="Bottom" Content="{Binding ElementName=MapView, Path=CurrentScale }"/>
   </Grid>
  1. Added 1000010 to the custom ZoomScales , so I could zoom exactly to scale 1000010 using the mouse wheel or the scale bar:
  MapView.ZoomScales = new Collection<double>
  {
       ....., 2000000, 1000010, 1000000,
   };

In my test, the layer renders at scale 1000000 and stops rendering at 1000010 , which is as expected.

I’m using the latest beta. Could you try the steps above and let me know which version you’re on, and whether you see the same results?

Also, please note: if you insert 100001 and zoom from 100000 to 100001, it may appear not to work because we intentionally skip rendering when the scale change is too small, as an optimization.

Thanks,
Ben

First, I am using the latest version 14.3.2

I tried your test, and if I set the 1000010 in the On_Loaded function, then I am on at 1,000,000 and off at the zoomscale of 1,000,010. The issue is the user could set any scale for the map, and thus we don’t know the scales. If I try to change the zoomscales “On The Fly” in the CurrentScaleChanging event and insert the “Current Scale” as a scale, this does not turn off as I expect.

It is almost like it only sets this up at initialization, and not later.

I do note that the “Inserted” scale does become a zoom stop and scrolling with the mouse, but this is not what we are after.

I only added the 1000010 scale to the ZoomScales list to make testing easier — you don’t need to do that in your project. Let’s forget about inserting that scale and add a button and a textbox instead:

  <Button Content="Zoom To Scale" Click="ZoomToScale_Click">
  <TextBox x:Name="ZoomScale" />

        private void ZoomToScale_Click(object sender, RoutedEventArgs e)
        {
            _ = MapView.ZoomToAsync(Convert.ToDouble(ZoomScale.Text));
        }

This way, you can enter any scale and zoom to it directly.

In my test, the layer shows correctly when zoomed to scale 1,000,000 and disappears at 1,000,010 . You mentioned that when setting the scale to 1,000,100 you still see the layer, even up to around 1,450,000. can you share how you’re running that test?