ThinkGeo.com    |     Documentation    |     Premium Support

Zoom in/out based on Image resolution

Hi,


I am new on thinkgeo. I am trying to zoom the map based on image resolution. I am using the following code for getting minimum & maximum zoom scale & current extent.


public static double GetMinZoomScale(RectangleShape currentExtent, float mapActualWidth, GeographyUnit mapUnit, float dpi) {

            try {

                if (mapActualWidth > 0)  {

                    double minScale = ExtentHelper.GetScale(currentExtent, mapActualWidth, mapUnit, dpi);      

                    return minScale;

                }

                else  {

                    throw new Exception("Invalid map width");

                }

            }

            catch (Exception) {

                throw;

            }

        }



        public static double GetMaxZoomScale(RectangleShape currentExtent, float mapActualWidth, GeographyUnit mapUnit)

        {

            try {

                if (mapActualWidth > 0) {

                    double maxScale = ExtentHelper.GetScale(currentExtent, mapActualWidth, mapUnit);

                    return maxScale;

                }

                else {

                    throw new Exception("Invalid map width");

                }

            }

            catch (Exception) {

                throw;

            }

        }


 


  public static RectangleShape GetFitExtent(RectangleShape sourceExtent, double mapScreenWidth, double mapScreenHeight) {

            try {

                double resolution = Math.Min(sourceExtent.Width / mapScreenWidth, sourceExtent.Height / mapScreenHeight) * .5;

                PointShape center = sourceExtent.GetCenterPoint();

                double mapHalfWorldWidth = resolution * mapScreenWidth * .5;

                double mapHalfWorldHeight = resolution * mapScreenHeight * .5;

                double left = center.X - mapHalfWorldWidth;

                double right = center.X + mapHalfWorldWidth;

                double top = center.Y + mapHalfWorldHeight;

                double bottom = center.Y - mapHalfWorldHeight;



                RectangleShape currentExtend = new RectangleShape(left, top, right, bottom);



                return currentExtend;

            }

            catch (Exception)  {

                throw;

            }

        }


 


 map.MapUnit = GeographyUnit.DecimalDegree;


 map.MinimumScale = GetMinZoomScale(map.FullExtend, (float)mapWidth, GeographyUnit.DecimalDegree, 20);

 map.RestrictExtent = map.FullExtend;

 RectangleShape mapExtend = MapExtendUtility.GetFitExtent(map.FullExtend, mapWidth, mapHeight);

 map.MaximumScale = ZoomLevelUtility.GetMaxZoomScale(mapExtend, (float)mapWidth, GeographyUnit.DecimalDegree);

 map.CurrentExtent = mapExtend;


 The prb is when I try to click the middle of the navigation tool, the application  crashes. 


Am I missing something?


Thanks,


Nadia


 


 



Hi Nadia,


Thank you for your code snippet. I modified your code as following, It works (I used WpfDesktopEdition 4.5 for this test).


Map1.MinimumScale = GetMinZoomScale(Map1.MaxExtent, (float)Map1.ActualWidth, GeographyUnit.DecimalDegree, 20);
Map1.RestrictExtent = Map1.MaxExtent;
RectangleShape Map1Extend = GetFitExtent(Map1.MaxExtent, Map1.ActualWidth, Map1.ActualHeight);
Map1.MaximumScale = GetMaxZoomScale(Map1Extend, (float)Map1.ActualHeight, GeographyUnit.DecimalDegree);
Map1.CurrentExtent = Map1Extend;


The link below demonstrates how to customize min/max zoom scale in another way.


gis.thinkgeo.com/Support/Dis...fault.aspx


Please let me know if you have further questions.


Regards,


Ivan



Hi Ivan, 
  
 I used the modified code you provided. The problem still exists. If I try to click the middle of the navigation tool multiple times. the application crashes. 
  
 I am using Wpf Desktop Edition 4.5 also. 
  
 Thanks, 
 Nadia 


Hi Nadia,


Currently I can't re-produce your issue "The application crashes after clicking the middle of the navigation tool multiple times.". Maybe you could provide us a self-contained sample to track the root cause.


Besides, I attach the whole code snippet ("T9192_CodeSnippet.txt") I used for your reference.


Regards,


Ivan



P9192_CodeSnippet.txt (3.49 KB)

Hi, 
  
 I am attaching the code. If you click the middle of the navigation tool multiple times, it is crashing. 
  
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.WpfDesktopEdition;
using System.IO;

namespace ThinkGeoTest
{
/// <summary>
/// Interaction logic for ThinkGeoMap.xaml
/// </summary>
public partial class ThinkGeoMap: Window
{
public ThinkGeoMap()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(ThinkGeoMap_Loaded);
}

void ThinkGeoMap_Loaded(object sender, RoutedEventArgs e)
{
           


            wpfMap.MapUnit = GeographyUnit.DecimalDegree;
            wpfMap.Background = new SolidColorBrush(Colors.Gray);
            wpfMap.MapTools.Logo.IsEnabled = false;
            LayerOverlay rootOverlay = new LayerOverlay();
            RectangleShape rect = new RectangleShape(-122, 74, 106, -62);

            GdiPlusRasterLayer rootImageLayer = new GdiPlusRasterLayer(@"Images\Milpitas.jpg", rect);

            ((GdiPlusRasterSource)rootImageLayer.ImageSource).StreamLoading += new EventHandler<StreamLoadingEventArgs>(rootImageLayer_StreamLoading);

                       
            rootImageLayer.UpperThreshold = double.MaxValue;
            rootImageLayer.LowerThreshold = 0;
            rootOverlay.TileType = TileType.MultipleTile;
          

            rootOverlay.Layers.Add("root", rootImageLayer);
            wpfMap.Overlays.Add("rootOverlay", rootOverlay);

            wpfMap.CurrentExtent = rect;
            wpfMap.MinimumScale = GetMinZoomScale(wpfMap.MaxExtent, (float)wpfMap.ActualWidth, GeographyUnit.DecimalDegree, 20);
            wpfMap.RestrictExtent = wpfMap.MaxExtent;
            RectangleShape Map1Extend = GetFitExtent(wpfMap.MaxExtent, wpfMap.ActualWidth, wpfMap.ActualHeight);
            wpfMap.MaximumScale = GetMaxZoomScale(Map1Extend, (float)wpfMap.ActualHeight, GeographyUnit.DecimalDegree);
            wpfMap.CurrentExtent = Map1Extend;

            wpfMap.Refresh();
}

        MemoryStream memoryStream = new MemoryStream();
        void rootImageLayer_StreamLoading(object sender, StreamLoadingEventArgs e)
        {
            if (e.StreamType == "Image File")
            {
                e.AlternateStream = new FileStream(@"Images\Milpitas.jpg", FileMode.Open, FileAccess.Read);
                e.AlternateStreamName = "dummy.jpg";

            }
            else if (e.StreamType.Contains("World File"))
            {
                RectangleShape rs = new RectangleShape(-131.22, 55.05, -54.03, 16.91);
                WorldFile worldFile = new WorldFile(rs, 1813, 778);
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(worldFile.HorizontalResolution.ToString());
                sb.AppendLine(worldFile.RotationRow.ToString());
                sb.AppendLine(worldFile.RotationColumn.ToString());
                sb.AppendLine(worldFile.VerticalResolution.ToString());
                sb.AppendLine(worldFile.UpperLeftX.ToString());
                sb.AppendLine(worldFile.UpperLeftY.ToString());            

                byte[] byteArray = Encoding.ASCII.GetBytes(sb.ToString());
                MemoryStream stream = new MemoryStream(byteArray);

                e.AlternateStream = stream;
                e.AlternateStreamName = "dummy.jgw";
            }
          
        }
        public static double GetMinZoomScale(RectangleShape currentExtent, float mapActualWidth, GeographyUnit mapUnit, float dpi)
        {
            try
            {
                if (mapActualWidth > 0)
                {
                    double minScale = ExtentHelper.GetScale(currentExtent, mapActualWidth, mapUnit, dpi);
                    return minScale;
                }
                else
                {
                    throw new Exception("Invalid map width");
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static double GetMaxZoomScale(RectangleShape currentExtent, float mapActualWidth, GeographyUnit mapUnit)
        {
            try
            {
                if (mapActualWidth > 0)
                {
                    double maxScale = ExtentHelper.GetScale(currentExtent, mapActualWidth, mapUnit);
                    return maxScale;
                }
                else
                {
                    throw new Exception("Invalid map width");
                }
            }
            catch (Exception)
            {
                throw;
            }
        }


        public static RectangleShape GetFitExtent(RectangleShape sourceExtent, double mapScreenWidth, double mapScreenHeight)
        {
            try
            {
                double resolution = Math.Min(sourceExtent.Width / mapScreenWidth, sourceExtent.Height / mapScreenHeight) * .5;
                PointShape center = sourceExtent.GetCenterPoint();
                double mapHalfWorldWidth = resolution * mapScreenWidth * .5;
                double mapHalfWorldHeight = resolution * mapScreenHeight * .5;
                double left = center.X - mapHalfWorldWidth;
                double right = center.X + mapHalfWorldWidth;
                double top = center.Y + mapHalfWorldHeight;
                double bottom = center.Y - mapHalfWorldHeight;

                RectangleShape currentExtend = new RectangleShape(left, top, right, bottom);

                return currentExtend;
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

}
 
 
  
  
 I am using thinkgeo 5.0. 
  
 Thanks in advance. 
  
  
 Regards, 
 Nadia 


Nadia,


Thank you for your code snippet. I have recreated your issue, the application crashed because some bugs in GdiPlusRasterSource related to Multi-Thread, we're researching how to fix it, will let you know if we have any progress. 


Besides, if you set TileType to SingleTile, this issue will not appear.


Regards,


Ivan



Hi Ivan, 
  
 I set the TileType to SingleTile  & the issue is resolved. 
  
 Let me know when you will fix this issue. 
  
 Thanks for your help. 
  
 Regards, 
 Nadia

 Thanks Nadia, I'm glad Ivan's suggestion on Single Tile got you working for now.



 Hi Ivan,


We're having a similar issue but changing the TileType did not help.  Please provide a status update on the bug.


 


Thanks,


Josh



Hello Josh, 
  
 Thank you for your post, I have tested this problem using our latest version, I can’t reproduce the problem. 
  
 Which version are you using? If it’s not the recently version, could you please try to get the latest version and have another try? 
  
 If the problem still exist, could you please provide a sample that help us to reproduce the problem? 
  
 Regards, 
  
 Gary

Hi Gary, 
  
 We’re using 5.0.93.0 developer build.  What version did you test against?  I am working on a sample application now. 
  
 Thanks, 
 Josh

 Hi Gary,


I also meant to ask if ThinkGeo provides source code for the MapSuiteCore and WpfDesktopEdition assemblies?  I see that the source is provided for the third party code that ThinkGeo uses.  Read-only source would be wonderful; I'm sure we could determine if we're using your product incorrectly or whether there's a possible bug if we had the source.


Thanks,


Josh



 Josh,


 
For source code we have the Map Suite Source Kit which contains source to many but not all of the classes for a detailed list of what it contains you can check out:  
 
gis.thinkgeo.com/Products/Ex...fault.aspx
 
Thanks!

 Hi Gary,


Thank you for the source code link; I'll check it out.  What version of the map suite were you testing against?


Josh



Hi Gary, 
  
 I’m still working on a sample app but am having trouble reproducing the issue.  We’re having trouble when the CurrentScale on a GdiPlusGeoCanvas is below 50.  I found this post: gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/13/afv/topic/aft/5874/Default.aspx that looks related.  Can you tell me if there is a lower boundary on CurrentScale?  Our production application throws an Overflow Error exception when the CurrrentScale is  about 31.  The exception bubbles up from the GdiPlusGeoCanvase DrawWorldImageWithoutScaling method.  Other observations are that the CurrentWorldExtent on the canvas  and the Height and Width properties are very small.  Also, any insight into how I can set the current scale on a GdiPlusGeoCanvas would be helpful. 
  
 Thanks, 
 Josh

Hello Josh, 
  
 Thank you for your further information, I have tested with 5.0.146.0, you can get it from helpdesk.thinkgeo.com and have a try. 
  
 About the post you mentioned, that bug is very old and we have fix it, so that wouldn’t cause the problem. 
  
 And CurrentScale means the scale you already in use, as my understand, I don’t think it has a lower boundary. 
  
 If you can provide a sample that reproduce the problem, I can debug into DrawWorldImageWithoutScaling method and find out what’s happening. 
  
 Thanks for your help. 
  
 Regards, 
  
 Gary