ThinkGeo.com    |     Documentation    |     Premium Support

When zoomed in point symbols don't get re-drawn

This can easily be seen on the how Do I sample for iOS. Using the sqlite layer selection start zooming in on a point using pinch zoom it will redraw to the proper size until you get in extremely close at which point it no longer gets redrawn. At that point it looks like the display is simply sczooming in on the image as opposed to redrawing. Its easily seen if you adjust the minimumScale to something extremely low – say around 50 or so. By the way you have to use pinch zoom as the + on the zoom control grays out at the point where it starts zooming in.

Unfortunately in our application we do have a need to have the scale set extremely low and we are having issues with the way this is working currently.

By default, a map has 20 zoomlevels, and a stretched image is used for any scale between. You can create a customized zoomlevelset with over 20 zoomlevels like following.

   // Set the custom zoomlevelset to the map. 
   mapView.ZoomLevelSet = GetCustomZoomLevelSet();

    ZoomLevelSet GetCustomZoomLevelSet()
    {
        ZoomLevelSet zoomLevelSet = new ZoomLevelSet();
        double topScale = zoomLevelSet.ZoomLevel01.Scale;
        for (int i = 0; i < 22; i++)
        {
            zoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(topScale / Math.Pow(2, i)));
        }
        return zoomLevelSet;
    }

Hopefully it helps.
Ben

I misunderstood how this works – I thought the zoom level set on the layer itself controlled when it would get drawn.

The way we tried this is we set it to 23 zoom levels instead of 22 as you show – unfortunately with the bing map overlays this resulted in image not available tiles being display and the application crashed while panning at the most zoomed in stage. I was able to duplicate this with the howDoISample with the following code.

For our case we are likely going to alter our minimum zoom in order to avoid that issue, but thought you might want to know about the crash. Modified code for howDoiSample follows – just pinch/zoom as far as you can and start panning and you will see the crash.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThinkGeo.Core;
using ThinkGeo.UI.XamarinForms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace ThinkGeo.UI.XamarinForms.HowDoI
{
///


/// Learn how to display a SQLite Layer on the map
///

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class SQLiteLayerSample : ContentPage
{
public SQLiteLayerSample()
{
InitializeComponent();
}

    /// <summary>
    /// Setup the map with the ThinkGeo Cloud Maps overlay. Also, add the SQLite layer to the map
    /// </summary>
    protected override void OnAppearing()
    {
        base.OnAppearing();
        // It is important to set the map unit first to either feet, meters or decimal degrees.
        mapView.MapUnit = GeographyUnit.Meter;

        // Create the background world maps using vector tiles requested from the ThinkGeo Cloud Service and add it to the map.
        //ThinkGeoCloudVectorMapsOverlay thinkGeoCloudVectorMapsOverlay = new ThinkGeoCloudVectorMapsOverlay("9ap16imkD_V7fsvDW9I8r8ULxgAB50BX_BnafMEBcKg~", "vtVao9zAcOj00UlGcK7U-efLANfeJKzlPuDB9nw7Bp4K4UxU_PdRDg~~", ThinkGeoCloudVectorMapsMapType.Light);
        //           thinkGeoCloudVectorMapsOverlay.VectorTileCache = new FileVectorTileCache(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "cache"), "CloudMapsVector");
        //         mapView.Overlays.Add(thinkGeoCloudVectorMapsOverlay);
        BingMapsOverlay lo = new BingMapsOverlay();
        lo.ApplicationId = "ReplaceMe";
        lo.Name = "BingMapsOverlay";
        lo.MapStyle = BingMapsMapType.AerialWithLabels;
        mapView.Overlays.Add(lo);

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

        // Create the new layer and set the projection as the data is in srid 2276 as our background is srid 3857 (spherical mercator).
        string restaurantPath = (Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Data/SQLite/frisco-restaurants.sqlite"));
        SqliteFeatureLayer restaurantsLayer = new SqliteFeatureLayer($"Data Source={restaurantPath};", "restaurants", "id", "geometry");
        restaurantsLayer.FeatureSource.ProjectionConverter = new ProjectionConverter(2276, 3857);

        // Add the layer to the overlay we created earlier.
        restaurantsOverlay.Layers.Add("Frisco Restaurants", restaurantsLayer);
        // Set a point style and the above text style to zoom level 1 and then apply it to all zoom levels up to 20.
        {
            restaurantsLayer.Open();
            RectangleShape rectOverlay = restaurantsLayer.GetBoundingBox();
            var curScale = MapUtil.GetScale(rectOverlay, (float)mapView.Width, GeographyUnit.Meter);

            mapView.CurrentExtent = rectOverlay;
            double InitialMapScale = curScale * 1.1;
            mapView.MinimumScale = 50;
            double dStart = InitialMapScale / 50;
            double scaleFactor = Math.Pow(dStart, 1.0 / 19.0);
            mapView.MaximumScale = InitialMapScale;


            var defps = new PointStyle(PointSymbolType.Circle, 12, GeoBrushes.Green, new GeoPen(GeoColors.White, 2));
            for (int i = 0; i < 20; i++)
            {
                double resolution = InitialMapScale / Math.Pow(scaleFactor, i);
                ZoomLevel zl = new ZoomLevel(resolution);
                if( i >=15)
                {
                    defps = new PointStyle((PointSymbolType)(PointSymbolType.Circle + i - 14), 12, GeoBrushes.Red, new GeoPen(GeoColors.White, 2));
                }
                zl.CustomStyles.Add(defps);
                restaurantsLayer.ZoomLevelSet.CustomZoomLevels.Add(zl);
            }
            // Set the map view current extent to a bounding box that shows just a few restaurants.
            mapView.CurrentExtent = rectOverlay;
            mapView.ZoomLevelSet = GetCustomZoomLevelSet();

            // Refresh the map.
            mapView.Refresh();
        }
    }


    ZoomLevelSet GetCustomZoomLevelSet()
    {
        ZoomLevelSet zoomLevelSet = new ZoomLevelSet();
        double topScale = mapView.ZoomLevelSet.ZoomLevel01.Scale;
        for (int i = 0; i < 23; i++)
        {
            zoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(topScale / Math.Pow(2, i)));
        }
        return zoomLevelSet;
    }

}

}

Thanks Richard,
You don’t need the maxscale. Here is the full code

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThinkGeo.Core;
using ThinkGeo.UI.XamarinForms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;


namespace ThinkGeo.UI.XamarinForms.HowDoI
{
    /// <summary>
    /// Learn how to display a SQLite Layer on the map
    /// </summary>
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class SQLiteLayerSample : ContentPage
    {
        public SQLiteLayerSample()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Setup the map with the ThinkGeo Cloud Maps overlay. Also, add the SQLite layer to the map
        /// </summary>
        protected override void OnAppearing()
        {
            base.OnAppearing();
            // It is important to set the map unit first to either feet, meters or decimal degrees.
            mapView.MapUnit = GeographyUnit.Meter;

            mapView.ZoomLevelSet = GetCustomZoomLevelSet();
            BingMapsOverlay lo = new BingMapsOverlay();
            lo.ApplicationId = "Your ID";
            lo.Name = "BingMapsOverlay";
            lo.MapStyle = BingMapsMapType.AerialWithLabels;
            mapView.Overlays.Add(lo);
            mapView.MinimumScale = 0;
            // Create a new overlay that will hold our new layer and add it to the map.
            LayerOverlay restaurantsOverlay = new LayerOverlay();
            mapView.Overlays.Add(restaurantsOverlay);

            // Create the new layer and set the projection as the data is in srid 2276 as our background is srid 3857 (spherical mercator).
            string restaurantPath = (Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Data/SQLite/frisco-restaurants.sqlite"));
            SqliteFeatureLayer restaurantsLayer = new SqliteFeatureLayer($"Data Source={restaurantPath};", "restaurants", "id", "geometry");
            restaurantsLayer.FeatureSource.ProjectionConverter = new ProjectionConverter(2276, 3857);
  
            // Add the layer to the overlay we created earlier.
            restaurantsOverlay.Layers.Add("Frisco Restaurants", restaurantsLayer);
            // Set a point style and the above text style to zoom level 1 and then apply it to all zoom levels up to 20.
            //{
            restaurantsLayer.Open();
            RectangleShape rectOverlay = restaurantsLayer.GetBoundingBox();
            var curScale = MapUtil.GetScale(rectOverlay, (float)mapView.Width, GeographyUnit.Meter);

            mapView.CurrentExtent = rectOverlay;

            var defps = new PointStyle(PointSymbolType.Circle, 12, GeoBrushes.Green, new GeoPen(GeoColors.White, 2));
            restaurantsLayer.ZoomLevelSet.CustomZoomLevels.Clear();
            for (int i = 0; i < 23; i++)
            {
                ZoomLevel zl = mapView.ZoomLevelSet.CustomZoomLevels[i];
                if (i >= 15)
                {
                    defps = new PointStyle(PointSymbolType.Circle, 12, GeoBrushes.Red, new GeoPen(GeoColors.White, 2));
                }
                if (i >= 20)
                {
                    defps = new PointStyle(PointSymbolType.Circle, 12, GeoBrushes.Yellow, new GeoPen(GeoColors.White, 2));
                }
                zl.CustomStyles.Add(defps);
                restaurantsLayer.ZoomLevelSet.CustomZoomLevels.Add(zl);
            }
                mapView.Refresh();
        }


        ZoomLevelSet GetCustomZoomLevelSet()
        {
            ZoomLevelSet zoomLevelSet = new ZoomLevelSet();
            double topScale = mapView.ZoomLevelSet.ZoomLevel01.Scale;
            for (int i = 0; i < 23; i++)
            {
                zoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(topScale / Math.Pow(2, i)));
            }
            return zoomLevelSet;
        }
    }
}

Thanks

Frank

The intent of supplying the code was to make you aware of a problem in Thinkgeo that is causing a crash – This is not the code that we are using.

As for the maxScale – that does work in WPF – at least in version 10, haven’t tried in version 12. It has never worked to my knowledege in iOS or android in the same fashion as WPF – We ended up using our implementation of the max scale for ios/android.

Thanks let us know this issue.
We have created a internal ticket to look into the maxScale issue.

Thanks

Frank