ThinkGeo.com    |     Documentation    |     Premium Support

ExtentHelper.ZoomToScale

 Hi,


 
I've noticed a regression (or a change of behavior ?) with the function ExtentHelper.ZoomToScale.
 
I've join a sample.
In this sample, I try to show a shapefile at the zoom level 7.
 
In version 5.0.0.0, the shapefile is shown at zoom level 7.
In version 5.5.138.0, the shapefile is shown at zoom level 8.
 
Regards,
P.OM
Reportive
 
NB:
 
You can find the sample here:        dl.free.fr/ioxOew128
I cannot upload it to the forum so i use a free file sharing.
The web page is unfortunately in French.
 
To validate the download, you must enter a word.
You can find the word in the sentence:
 
Recopiez " xxx " ci-dessous:
 
xxx is the word to type in the texbox below that sentence.

And then hit the button "Valider et télécharger le fichier"
 

In 5.0.0.0, you'll have:



In 5.5.138.0, you'll have:




Puthirak,


  I could download and run your sample app without a problem. The correct behavior is from the latest build 5.5.xx. So, to set the extent of the map to the country use  the zoom level 7. You can also more simply just set the extent of the map to the the bounding box of the layer.


 



var boundingbox = layer.GetBoundingBox();

var boundingboxInLevel7 = ExtentHelper.ZoomToScale(layer.ZoomLevelSet.ZoomLevel07.Scale,
                                                boundingbox, wpfMap.MapUnit,
                                                (float)wpfMap.ActualWidth, (float)wpfMap.ActualHeight);
//Or

wpfMap.CurrentExtent = boundingbox;


 Val,


 


Thank you for your answer. I need to be able to set the extent at a specific zoom level which can be different from the one obtained by setting the bounding box :)


 


P.OM


Reportive



Puthirak,


 Ok, so I think we got that covered. Thank you for participating in the Map Suite forum.



 Hi Val,


 
I have again a problem with the ExtentHelper.ZoomToScale.
 
I use this code to jump to the zoom level 7:
 

var boundingboxInLevel7 = ExtentHelper.ZoomToScale(wpfMap.ZoomLevelSet.ZoomLevel07.Scale,
boundingbox, wpfMap.MapUnit,
(float)wpfMap.ActualWidth, (float)wpfMap.ActualHeight);
wpfMap.CurrentExtent = boundingboxInLevel7;

 

In some cases, the bounding box obtained doesn't correspond to the desired zoom level.
But if I use this code, I'm at the right zoom level:

 

wpfMap.CurrentExtent = boundingbox;
wpfMap.ZoomToScale(wpfMap.ZoomLevelSet.ZoomLevel07.Scale);

 

What's the difference between the two pieces of code?
I really need to be able to calculate a bounding box at a specific zoom level
without having to modify the map CurrentExtent.
 
In version 5.5, I had no problem.
 
Unfortunately, I haven't been able to create a sample to reproduce this problem.
 
Regards,
P.OM
Reportive

 

Hi Puthirak,  
  
 Can you provide us a sample application that can demonstrate a case where your first set of code does not return the appropriate map for the bounding box and ZoomLevelScale you provided?  
  
 You stated that there ‘some cases’ in which this occurs; can you describe those cases in more detail or better yet provide a sample that demonstrate these cases?

 Hi Ryan,


 
As stated in my previous post, I hadn't been able to create a sample to reproduce the problem.
The more I tried, the more I thought that there's something in our product's code that produce the problem.
 
But then I noticed something.
 
It appears that the value of wpfMap.ActualHeight, passed to ExtentHelper.ZoomToScale, is not an integer value but had a value like 722.2 (with decimal places).
 
When I use, Math.Floor(wpfMap.ActualHeight), I got the right zoom level.
 
I hope this can help you.
 
Regards,
P.OM
Reportive
 

Hi Puthirak,  
  
 There is an element here that is not exposed to you in that when you apply the BoundingBox to the CurrentExtent or you use the wpfMap.ZoomToScale there is a Snapping that occurs. Map Suite only has 20 ZoomLevels in the default ZoomLevelSet so we have to snap to one of the existing ZoomLevels when we set the CurrentExtent of the Map or use a method such as wpfMap.ZoomToScale. 
  
 You have demonstrated that when you set the wpfActualHeight value to 722 that you receive an identical map with the ExtentHelper.ZoomToScale as you do with the wpfMap.ZoomToScale.  
  
 What this means is that when you pass in 722.2 the snapping sets the scale to that of ZoomLevel08 as this is ‘the closest ZoomLevel’ scale and when this is set to 722 ZoomLevel07 is the closest ZoomLevel.  I am not 100% this is expected behavior as much of the math for these two methods is the same so I am creating an Internal Ticket to investigate further.

 
  Private Function WpfMapZoomLevelSetSnappedScale(ByVal Scale As Double) As Double
    'Calculates the SnappedScale (WpfMap1.GetSnappedZoomLevelIndex returns the lower Zoom at which scale fits compleately, not the closest)
    Dim SnappedZoomLevelIndex As Integer = WpfMap1.GetSnappedZoomLevelIndex(Scale)

    'Gets the ZoomLevelSet scale where Scale fits
    Dim SnappedScale As Double = WpfMap1.ZoomLevelSet.GetZoomLevels(SnappedZoomLevelIndex).Scale

    'Check if next ZoomLevelSet Scale is closer eventhought Scale does not compleately fit in it
    If SnappedZoomLevelIndex < 19 AndAlso
      (SnappedScale - Scale) > (Scale - WpfMap1.ZoomLevelSet.GetZoomLevels(SnappedZoomLevelIndex + 1).Scale) Then
      SnappedScale = WpfMap1.ZoomLevelSet.GetZoomLevels(SnappedZoomLevelIndex + 1).Scale 'Next ZoomLevel is closer
    End If

    Return SnappedScale
  End Function
 
  
  This is the code I use…

Hi Carlos,  
  
 Thanks for providing this code!

 Hi,


 
Sorry for the late feedback. But I was in a small vacation :)
 
Thank you Carlos for the code ! :)
 
But it doesn't help my case. As you can see, I give a scale that belong to the map zoom levelset.
It's not a random scale. So the scale obtained from your code will give me the same scale.
 
Ryan, honestly, I failed to understand that there's a snapping occuring here.
I just want to calculate a bounding box at a predefined standard scale.
 
have you heard any feedback from the development team ?
 
Regards,
P.OM
Reportive
 

Hi Puthirak,  
  
 I think one element that has been lost in this discussion is exactly what your goal is?  
 You stated that: “I really need to be able to calculate a bounding box at a specific zoom level 
 without having to modify the map CurrentExtent.” 
  
 Are you going to set the Map to the extent that you calculate or do you need to use it in some other method? Why are you calculating this BoundingBox? I think with this information we might be better able to direct you. 
  
 Something to consideris that when you set the resulting RectangleShape to the CurrentExtent, Map Suite has to fit that RectangleShape to the map which means that choosing from one of the 20 ZoomLevels which you have Styles setup for. This is where the ‘Snapping’ occurs. If you have a Map Width of 722.2 then you can expect to get a Map Based on ZoomLevel08 when you pass in the following parameters:  
 ExtentHelper.ZoomToScale(wpfMap.ZoomLevelSet.ZoomLevel07.Scale, boundingbox, wpfMap.MapUnit, (float)wpfMap.ActualWidth, (float)wpfMap.ActualHeight).  
  
 If our built-in snapping is not working for you then you are welcome to create intermediate ZoomLevels or utilize Carlos’s code to help modify which ZoomLevel is used.

 Hi Ryan,


 
I want to show the content of a shapefile at a specific standard zoom level (i.e. wpfMap.ZoomLevelSet.ZoomLevelxx, not a custom zoom level).
 
Let's say, I have a shapefile with a natural bounding box that will show it at zoom level 10.
But I want to show it at zoom level 7.
This code will do what I want:
 
wpfMap.CurrentExtent = boundingbox;
wpfMap.ZoomToScale(wpfMap.ZoomLevelSet.ZoomLevel07.Scale);
 
So why don't I use this code ?
 
1) It can be visually ugly if I use different styles for each zoom level.
The user will see the shapefile at level 10 with a style and then at level 7 with another style.
 
2) It can trigger some lengthy computation from our product.
Let's say that at zoom level 10, I show some points where the data come from a cube.
So setting, wpfMap.CurrentExtent = boundingbox, will trigger an MDX request.
 
So I want to calculate a bounding box that will show the shapefile at zoom level 7 when setting
wpfMap.CurrentExtent = boundingboxAtZoomLevel7
 
I thought this code would do the trick:
 
var boundingboxAtZoomLevel7 = ExtentHelper.ZoomToScale(wpfMap.ZoomLevelSet.ZoomLevel07.Scale,
                                                boundingbox, wpfMap.MapUnit,
                                                (float)wpfMap.ActualWidth, (float)wpfMap.ActualHeight);
wpfMap.CurrentExtent = boundingboxAtZoomLevel7;
 
But it doesn't in some cases.
 
I'm open to any suggestion or we can conclude that it's not actually possible.
 
Regards,
P.OM
Reportive

Puthirak, 
  
 I take over this post and just feel free to let me know if you have any more questions. 
  
 If you want to zoom to center zoom level, I suggest you call API ExtentHelper.SnapToZoomLevel, maybe better, this method focus on zoom level, if the scale is upper or lower, it will be snapped up to center zoom level. 
  
 Thanks, 
 James