Select to view content in your preferred language

How to calculate the value shown in scalebar?

1208
5
09-08-2010 05:10 AM
jonataspovoas
Regular Contributor
Hi,

I'm building a "zoomtoscale" application to silverlight, and i'm having quite some trouble.

here's a sample of my work so far:

<UserControl x:Class="ScaleZoom.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"
    xmlns:esri="http://schemas.esri.com/arcgis/client/2009" 
 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
    xmlns:userControls="clr-namespace:ESRI.ArcGIS.SilverlightMapApp"
    xmlns:actions="clr-namespace:ESRI.ArcGIS.SilverlightMapApp.Actions"
    mc:Ignorable="d" d:DesignWidth="780" d:DesignHeight="480">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="35"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="1">
            <Border Margin="0,-35,0,0" Background="Black">
                <esri:Map x:Name="mapa">
                        <esri:ArcGISTiledMapServiceLayer ID="Streets World 2D" 
          Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
                </esri:Map>
            </Border>
            <esri:ScaleBar x:Name="scala" Height="23" Width="200" Map="{Binding ElementName=mapa}" DisplayUnit="Kilometers"  Margin="10,0,0,10" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
        </Grid>
        <Grid Grid.Row="0" Background="#AAAAAAAA" Opacity="0.6">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock Text="Scale: " TextAlignment="Center" VerticalAlignment="Center" FontFamily="Buxton Sketch" FontSize="18"/>
                <TextBox x:Name="txtScale" Height="27" Width="100" VerticalAlignment="Center" Margin="5,0,5,0" Opacity="0.6"/>
                <Button x:Name="btnCalc" Content="Calc" FontFamily="Buxton Sketch" FontSize="18" Height="25"/>
                <Button x:Name="btnDo" Content="Do!" FontFamily="Buxton Sketch" FontSize="18" Height="25" Margin="5"/>
            </StackPanel>
        </Grid>
    </Grid>
</UserControl>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Markup;
using System.Windows.Shapes;
using System.ComponentModel;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Actions;
using ESRI.ArcGIS.Client.Behaviors;
using System.Windows.Controls.Primitives;

namespace ScaleZoom
{
    public partial class MainPage : UserControl
    {
        double actualScale;

        public MainPage()
        {
            InitializeComponent();
            btnCalc.Click += new RoutedEventHandler(BtnCalc_Click);
            btnDo.Click += new RoutedEventHandler(BtnDo_Click);
            txtScale.KeyDown += new KeyEventHandler(TxtScale_KeyDown);
        }

        private void BtnCalc_Click(object sender, RoutedEventArgs e)
        {
            var mapWidth = Application.Current.Host.Content.ActualWidth;
            var unitsPerPixel = this.mapa.Extent.Width / mapWidth;
            actualScale = unitsPerPixel;
        }

        private void BtnDo_Click(object sender, RoutedEventArgs e)
        {
            mapa.ZoomToResolution(escalaAtual);
        }

        private void TxtScale_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                BtnCalc_Click(sender, e);
            }
        }
    }
}


With this i can get the "units per pixel" of a resolution shown and return to it anytime i click the "Do!" button.

But what i need is the opposite, a function where the user types the desired scale and then go for it. Anyone has any idea of how to do it?

I added this to my calculation algorithm:

 private void BtnCalc_Click(object sender, RoutedEventArgs e)
        {
            var mapWidth = Application.Current.Host.Content.ActualWidth;
            //4711 is the number that the ScaleBar shows.
            var unitsPerPixel = ((double.Parse(txtScale.Text) * 359.99998) / 4711) / mapWidth;
            escalaAtual = unitsPerPixel;
        }
//4711 is the number that the ScaleBar shows.
var unitsPerPixel = ((double.Parse(txtScale.Text) * 359.99998) / 4711) / mapWidth;


Works if i keep the browser maximized and the same screen resolution, but it's obviously flawed.

Does anyone know what i'm doing wrong?
0 Kudos
5 Replies
dotMorten_esri
Esri Notable Contributor
The Map.Resolution property gives you what you are after.
0 Kudos
jonataspovoas
Regular Contributor
The Map.Resolution property gives you what you are after.


The Map.Resolution gives me the units per pixel of the map, but I also need the value shown on the ScaleBar to do the calculations.

Map.Resolution returned 0,28(lot of numbers). How do i get to the 4711 that shows on the ScaleBar? I need this to do the reverse process to the the number the user types to the resolution numbers.

I made this since my last post:

double actualScale = 4711; //<- So falta isto
double desiredResolution;
private void BtnCalc_Click(object sender, RoutedEventArgs e)
{
        var mapWidth = Application.Current.Host.Content.ActualWidth;
        var unitsPerPixel = ((double.Parse(txtScale.Text) * this.mapa.Extent.Width) / actualScale) / mapWidth;
        desiredResolution = unitsPerPixel;
}

private void BtnDo_Click(object sender, RoutedEventArgs e)
{
        mapa.ZoomToResolution(desiredResolution);
        actualScale = double.Parse(txtScale.Text);
}


This works, but the first value on the ScaleBar MUST be 4711, and the user can't change the browser size.
0 Kudos
dotMorten_esri
Esri Notable Contributor
I'm not sure what you need the size of the scalebar for.
Basically if your map resolution is 0.1, and the scalebar is 200 pixels wide, the scalebar's width represents 0.1 * 200 = 20 map units. The scalebar does a little fiddling with the numbers to try and show nice rounded values, so the width will constantly change.

Note that the number the scalebar shows is not the "scale" in the 1:xxxxx sense, but how large a distance the width of the scalebar represents.
0 Kudos
jonataspovoas
Regular Contributor
I think I'm not comunicating well, so I decided to add a picture to show my problem:

(Sorry for my handwriting...)


This screen has the particular case where my formula works. In this, i have the scaleBar showing 4711, and the textBox on the top bar. If the user types 2000 (like i said on the image), the map zooms in till the scaleBar shows 2000. But if i change the screen resolution, the window dimensions, or simply don't start with the scaleBar showing 4711, it won't work...

What I need help to is generalize the function to any case, and to do that, i need to calculate the exact number shown on the scale on runtime.
0 Kudos
dotMorten_esri
Esri Notable Contributor
The number you see down there is NOT the scale. It's showing how big a distance the scalebar box represents. There's no easy way to do what you want, but I don't think what you are trying to do is what you really want to have your user do.

Your textbox says "Scale". If the user wants to enter a scale, then have them enter a scale, and not the width of an arbitrary box (btw a box that constantly changes it size so this is not even consistent to the user).

Basically when you say "Scale", it means a distance relation between what you see on your map and the real world. For instance 1:25000 means that one inch on the map is 25000 inches in the real world (or 1 feet is 25000 feet, 1 meter is 25km and so on). Note that a scale has no unit in itself.

Bottom line: Scalebar and scale are two very different things.
0 Kudos