Select to view content in your preferred language

Map.ZoomToResolution fails to change map

2277
10
10-22-2010 01:36 PM
BryanBaker
Regular Contributor
Map.ZoomToResolution is working the first time I call it, but on subsequent calls, the map does not change its extent at all. I suspect this has something to do with the fact that my map service's spatial reference uses WKT (well-known text) rather than a WKID. I have worked around this by creating my own method, where I calculate the zoom envelope manually based on the map size and desired resolution. Using that method works consistently.
0 Kudos
10 Replies
dotMorten_esri
Esri Notable Contributor
WKT and WKID should not affect this part of the map at all (it's really only the layers that are affected by this).
Could you share some code? There could be several reason why nothing happens (ie parsing in the same resolution as the current map resolution, hitting the limit of the min/max map resolution etc).
0 Kudos
BryanBaker
Regular Contributor
I created a simple Silverlight page that replicated the issue for me. The service where I'm hitting the issue is not available online, but I've used one here that is and that uses WKT. The page has a map, two buttons and a checkbox. Each button zooms the map to a point/resolution. If the checkbox is off, it'll use the native ZoomToResolution; if on, it'll use the workaround method. This example didn't behave exactly as in my full application, in that Map.ZoomToResolution does change the extent, but it zooms to the wrong extent. If I successively click the two buttons, it'll progressively move the map to the northwest (vs. consistent zoom to the same location with the workaround).

XAML:
[HTML]<UserControl xmlns:esri="http://schemas.esri.com/arcgis/client/2009"  x:Class="ZoomToResolutionTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <esri:Map x:Name="Map1" ExtentChanged="Map1_ExtentChanged">
            <esri:ArcGISDynamicMapServiceLayer ID="base"
                Url="http://maps.cityofnovi.org/ArcGIS/rest/services/Publish/QuickSearchLayers/MapServer" />
        </esri:Map>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0" Background="WhiteSmoke">
            <TextBlock Text="Map resolution: "/>
            <TextBlock x:Name="MapResText" />
            <TextBlock x:Name="MapLocText" Margin="8,0,0,0" />
            <Button x:Name="Zoom1" Content="Zoom (13350000, 360000)" Click="Zoom1_Click" Margin="10,0,0,0"/>
            <Button x:Name="Zoom2" Content="Zoom (13370000, 350000)" Click="Zoom2_Click" Margin="5,0,0,0"/>
            <CheckBox x:Name="UseAltCkBox" Content="Use workaround" Margin="5,0,0,0" />
        </StackPanel>
    </Grid>
</UserControl>[/HTML]

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client;

namespace ZoomToResolutionTest
{
    public partial class MainPage : UserControl
    {
        double _startupRes;

        public MainPage()
        {
            InitializeComponent();
            Map1.Layers.LayersInitialized += new ESRI.ArcGIS.Client.LayerCollection.LayersInitializedHandler(Layers_LayersInitialized);
        }

        void Layers_LayersInitialized(object sender, EventArgs args)
        {
            _startupRes = Map1.Resolution;
        }

        private void Zoom1_Click(object sender, RoutedEventArgs e)
        {
            ZoomMap(13350000, 360000, _startupRes / 8);
        }

        private void Zoom2_Click(object sender, RoutedEventArgs e)
        {
            ZoomMap(13370000, 350000, _startupRes / 4);
        }

        private void ZoomMap(double x, double y, double resolution)
        {
            MapPoint pt = new MapPoint(x, y);

            if (UseAltCkBox.IsChecked == true)
                ZoomToResolution(Map1, resolution, pt);    
            else            
                Map1.ZoomToResolution(resolution, pt);
        }

        private void ZoomToResolution(Map map, double resolution, MapPoint center)
        {
            // Workaround for Map.ZoomToResolution
            double halfWidth = resolution * map.ActualWidth / 2;
            double halfHeight = resolution * map.ActualHeight / 2;
            Envelope newExtent = new Envelope(center.X - halfWidth, center.Y - halfHeight,
                center.X + halfWidth, center.Y + halfHeight);
            map.ZoomTo(newExtent);
        }

        private void Map1_ExtentChanged(object sender, ExtentEventArgs e)
        {
            MapResText.Text = String.Format("{0:N0}", Map1.Resolution);
            MapPoint centerPt = Map1.Extent.GetCenter();
            MapLocText.Text = String.Format("Center X:{0:N0}, Y:{1:N0}", centerPt.X, centerPt.Y);
        }
    }
}
0 Kudos
JenniferNery
Esri Regular Contributor
I tried to replicate this but in my sample, I zoom in and out of a fixed point for simplicity.  I used the map service you provided and also tried with another service that uses WKID. The code that were commented out are for the service with WKID spatial reference - this zooms to Hawaii. The current code uses your service with WKT spatial reference - this zooms to Providence Hospital.

XAML
<Grid x:Name="LayoutRoot" Background="White">
        <Grid.Resources>
            <!--<esri:MapPoint x:Key="ZoomTarget" X="-156.57540169918" Y="20.7720205689867"/>-->
            <esri:MapPoint x:Key="ZoomTarget" X="13351704.337736" Y="361346.969451659" />
        </Grid.Resources>
        <esri:Map x:Name="MyMap" ExtentChanged="MyMap_ExtentChanged">
            <!--<esri:ArcGISDynamicMapServiceLayer Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer"/>-->
            <esri:ArcGISDynamicMapServiceLayer Url="http://maps.cityofnovi.org/ArcGIS/rest/services/Publish/QuickSearchLayers/MapServer" />
        </esri:Map>
        <StackPanel  HorizontalAlignment="Left" VerticalAlignment="Top" >
               <TextBlock x:Name="MapResolution"/>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Zoom Target: "/>
                <TextBlock Text="{Binding Source={StaticResource ZoomTarget}}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="ZoomIn" Click="ZoomIn_Click"  Content="Zoom In"/>
                <Button x:Name="ZoomOut" Click="ZoomOut_Click"  Content="Zoom Out"/>
            </StackPanel>
        </StackPanel>
    </Grid>


Code-behind:
 public MainPage()
        {
            InitializeComponent();
            zoomTarget = this.LayoutRoot.Resources["ZoomTarget"] as MapPoint;
        }

        MapPoint zoomTarget;

        private void ZoomIn_Click(object sender, RoutedEventArgs e)
        {
            MyMap.ZoomToResolution(MyMap.Resolution / 4, zoomTarget);
        }

        private void ZoomOut_Click(object sender, RoutedEventArgs e)
        {
            MyMap.ZoomToResolution(MyMap.Resolution * 4, zoomTarget);
        }

        private void MyMap_ExtentChanged(object sender, ExtentEventArgs e)
        {
            MapResolution.Text = string.Format("Map Resolution: {0}", MyMap.Resolution);
        }
0 Kudos
BryanBaker
Regular Contributor
Jennifer - ZoomToResolution also works OK for me if I zoom in/out on the same point for both buttons. When I use different points it doesn't zoom correctly to points after the first zoom. Can you try using two different points?
0 Kudos
dotMorten_esri
Esri Notable Contributor
I think the problem comes from the confusion that ZoomToResolution doesn't center on the point you specify. It only zooms "around" that point. It's for instance the method that is used when you dblclick or mousewheel zoom. Try to do that up in the corner of the map, and you will notice that the map doesn't center on the point you dblclick, however the point instead stays under your mouse cursor.

If you need to zoom and center on a point, create an envelope around the point (the envelope must have a width or height>0) and zoom to that using the "ZoomTo" method.
0 Kudos
BryanBaker
Regular Contributor
Thanks for the reply. Two things to consider:

(1) In my sample above, using two different points, the map does not zoom anywhere near the input point. If you try it and click back and forth on the two buttons, you'll see that it progressively zooms the map further and further northwest. The "center" point input to the ZoomToResolution(resolution, center) method is not within the zoomed extent at all. To pass the method a "center" point and not even have that point within the new extent seems bizarre indeed.

(2) If the method should not necessarily zoom to make the input point in the center of the map, why does the method overload exist at all? Its effect in this case is pretty much the same as the overload ZoomToResolution(resolution). In any case, the documentation/signature should be changed to indicate that the method does not actually center on the input point. The signature names the point parameter "center" and defines it as "The center to zoom around." If you ask the average person I think they'd interpret "The center to zoom around" as meaning that the map would be centered at the "center" point.
0 Kudos
JenniferNery
Esri Regular Contributor
I think what you need to do is to create an envelope around the MapPoint of your interest and call ZoomTo(). This seems like the more appropriate method for your intention.

I had zoomTarget pointing to Providence Hospital and zoomTarget2 pointing to Walsh College.

  <esri:MapPoint x:Key="ZoomTarget" X="13351704.337736" Y="361346.969451659" />
  <esri:MapPoint x:Key="ZoomTarget2" X="13368513.3490549" Y="359874.084252657" />

         private void ZoomIn_Click(object sender, RoutedEventArgs e)
          { 
   MyMap.ZoomTo(ZoomToPoint(zoomTarget));
          }

  private void ZoomOut_Click(object sender, RoutedEventArgs e)
  {
   MyMap.ZoomTo(ZoomToPoint(zoomTarget2));

  }

  private Envelope ZoomToPoint(MapPoint p)
  {
   return new Envelope(p.X - 500, p.Y - 500, p.X + 500, p.Y + 500);   
  }
0 Kudos
dotMorten_esri
Esri Notable Contributor
Bryan you raise a good point. We'll try and make the documentation more clear. If you don't specify a center, the zoom simply happens around the center of the screen. "Center" is the point that everything scales around, ie the center of scaling, where everything expands or contracts around. So in this sense it is a "center". It's just not the center of the map.
0 Kudos
BryanBaker
Regular Contributor
I think what you need to do is to create an envelope around the MapPoint of your interest and call ZoomTo(). This seems like the more appropriate method for your intention...


Right, thanks Jennifer, I'm currently using a custom method to do the zoom. This does what I originally expected the Map.ZoomToResolution to do. Here's the method (as from my test page above):

private void ZoomToResolution(Map map, double resolution, MapPoint center)
        {
            // Workaround for Map.ZoomToResolution
            double halfWidth = resolution * map.ActualWidth / 2;
            double halfHeight = resolution * map.ActualHeight / 2;
            Envelope newExtent = new Envelope(center.X - halfWidth, center.Y - halfHeight,
                center.X + halfWidth, center.Y + halfHeight);
            map.ZoomTo(newExtent);
        }
0 Kudos