ThinkGeo.com    |     Documentation    |     Premium Support

ZoomLevelSet

Hi,


Though the ZoomLevelSet are easy to use in some situations it makes certain tasks quite difficult.


1. Simple example how do you find out based on the ZoomLevelSet for a layer if the layer is currently visible on the screen. So would need a function that pass in the scale of the map get if ZoomLevel Is visible


probably something like Layer.ZoomLevelSet.IsLevelActive(mapScale);


2. Also what does the active ZoomLevel return.


3. It would also be nice to know for a ZoomLevel set the ZoomLevel with the highest scale and the one with the lowest scale.


4. It would also be easy of you had an enumeration over the ZoomLevelSet to access all the ZoomLevel through a for each loop.


 



Clava, 
  
 Thanks for the post! 
  
 I’m not sure on # 1 & 2 I’m going to ask someone and see if they can provide some more information. 
  
 On #3 & 4 we think these are great ideas and have added them to our list of enhancements for a future release. 
  
 Keep the suggestions coming! 
  
 Thanks 
 

Could you tell me how to check if a  ZoomLevel is going to be used based on the scale of the map?



How do you guys know when not to draw a particular zoom level cause it is not apparent at all, would it mean the a DefaultStyle is null and there are no custom styles present.


It would be easy if you had a property on the zoom level set that tells if it will draw. Also the ZoomLevel set also need a max scale and min scale property, that will tell us the mazimum and minimum scale that the layer will be shown at.


It is really nice that your api supports adjusting the style based on the zoom level the map is at.  But alot of times we just want to know if a layer is currently visible to the user with the combination of zoom levels we apply. This is not easy to do with the current api.


 


In version 2, I liked that you could have custom zoom levels on a layer, and I could just add a ZoomLevel set the upper and lower extent and i knew when my layer would be visible, now i have to be aware of the various scales in a zoom level set and your documentation does not include the scales for your preconfigured ZoomLevelSet.  Also you have a WebZoomLevel set that has a SelectZoomLevelById, this would be useful on the base ZoomLevelSet.



Clava, 
  
 Thanks for the post, we are currently working on supporting this functionallity in the next beta refresh.

I would add to this that you should be able to set the MapControl.ZoomLevelSet.ZoomLevel01.Scale to a custom scale, and when drawing layers if the scale hasn't been set in the layer then to revert to using the MapControl.ZoomLevelSet values. I have a situation where I have a shapefile for 1:100k road data, I have another shapefile for 1:2million and 1:5million.


I have three ShapeFileFeatureLayers


Roads100k

Roads2m

Roads5m


I wish to show

Roads100k from scale 0 - 500,000

Roads 2m from scale 500,001 - 1,500,000

Roads5m from scale 4,000,000 up


I cannot seem to achieve this, I tried


        Map.StaticOverlay.Layers.Add("Roads5m", Road5mLayer)
        Road5mLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        Road5mLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Black)
        Road5mLayer.ZoomLevelSet.ZoomLevel01.Scale = 4000000
        Road5mLayer.ZoomLevelSet.ZoomLevel20.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Black)
        Road5mLayer.ZoomLevelSet.ZoomLevel20.Scale = 10000000
        Map.StaticOverlay.Layers.Add("Roads1m", Road1mLayer)
        Road1mLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Orange)
        Road1mLayer.ZoomLevelSet.ZoomLevel01.Scale = 700000
        Road1mLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        Road1mLayer.ZoomLevelSet.ZoomLevel20.Scale = 4000000
        Road1mLayer.ZoomLevelSet.ZoomLevel20.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Orange)
        Map.StaticOverlay.Layers.Add("Roads250k", Road250kLayer)
        Road250kLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Red)
        Road250kLayer.ZoomLevelSet.ZoomLevel01.Scale = 1
        Road250kLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        Road250kLayer.ZoomLevelSet.ZoomLevel20.Scale = 700000
        Road250kLayer.ZoomLevelSet.ZoomLevel20.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Red)


 Any ideas?



Michael, 
  
 Here are the default scales of our 20 ZoomLevels:  
  
 ZoomLevel01 = 590591790 
 ZoomLevel02 = 295295895 
 ZoomLevel03 = 147647947.5 
 ZoomLevel04 = 73823973.75 
 ZoomLevel05 = 36911986.875 
 ZoomLevel06 = 18455993.4375 
 ZoomLevel07 = 9227996.71875 
 ZoomLevel08 = 4613998.359375 
 ZoomLevel09 = 2306999.1796875 
 ZoomLevel10 = 1153499.58984375 
 ZoomLevel11 = 576749.794921875 
 ZoomLevel12 = 288374.8974609375 
 ZoomLevel13 = 144187.44873046875 
 ZoomLevel14 = 72093.724365234375 
 ZoomLevel15 = 36046.8621826171875 
 ZoomLevel16 = 18023.43109130859375 
 ZoomLevel17 = 9011.715545654296875 
 ZoomLevel18 = 4505.8577728271484375 
 ZoomLevel19 = 2252.92888641357421875 
 ZoomLevel20 = 1126.464443206787109375 
  
 If these scale definitions are not suitable to your scenario, you can customize the ZoomLevelSet. But you need keep the ZoomLevelSet consistency for all the layers. Here is code: 
  
 
            Map1.StaticOverlay.Layers.Add("Roads5m", Road5mLayer)
            Road5mLayer.ZoomLevelSet.ZoomLevel01.Scale = 10000000
            Road5mLayer.ZoomLevelSet.ZoomLevel02.Scale = 4000000
            Road5mLayer.ZoomLevelSet.ZoomLevel03.Scale = 700000
            Road5mLayer.ZoomLevelSet.ZoomLevel04.Scale = 1
            Road5mLayer.ZoomLevelSet.ZoomLevel05.Scale = 0
            Road5mLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Black)
            Road5mLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level02

            Map1.StaticOverlay.Layers.Add("Roads1m", Road1mLayer)
            Road1mLayer.ZoomLevelSet.ZoomLevel01.Scale = 10000000
            Road1mLayer.ZoomLevelSet.ZoomLevel02.Scale = 4000000
            Road1mLayer.ZoomLevelSet.ZoomLevel03.Scale = 700000
            Road1mLayer.ZoomLevelSet.ZoomLevel04.Scale = 1
            Road1mLayer.ZoomLevelSet.ZoomLevel05.Scale = 0
            Road1mLayer.ZoomLevelSet.ZoomLevel02.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Orange)
            Road1mLayer.ZoomLevelSet.ZoomLevel02.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level03

            Map1.StaticOverlay.Layers.Add("Roads250k", Road250kLayer)
            Road250kLayer.ZoomLevelSet.ZoomLevel01.Scale = 10000000
            Road250kLayer.ZoomLevelSet.ZoomLevel02.Scale = 4000000
            Road250kLayer.ZoomLevelSet.ZoomLevel03.Scale = 700000
            Road250kLayer.ZoomLevelSet.ZoomLevel04.Scale = 1
            Road250kLayer.ZoomLevelSet.ZoomLevel05.Scale = 0
            Road250kLayer.ZoomLevelSet.ZoomLevel03.DefaultLineStyle.CenterPen = New GeoPen(GeoColor.StandardColors.Red)
            Road250kLayer.ZoomLevelSet.ZoomLevel03.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level04

            Map1.SyncClientZoomLevels(Road5mLayer.ZoomLevelSet)
 
 If the scale of one zoomlevel is set to zero, map control will not check the rest zoomlevels. The SyncClientZoomLevels method synchronizes the ZoomLevelSet scale definitions to the client, thus the PanZoomBar have 4 zoomlevels instead of 20.  
  
 For easy understanding, here talk more about the client zoomlevels and client zoomlevels. 
  
 The client zoomlevels are the zoomlevels on the PanZoomBar. Whenever you zoom in or out, you are changing the current zoomlevel to one of the client zoomlevels. The Map.ClientZoomLevelScales collection defines the client zoomlevels which can be manually set or be automatically synchronized from a ZoomLevelSet object using SyncClientZoomLevels method. 
  
 The server zoomlevels are the zoomlevels on a ZoomLevelSet object. Whenever you zoom in or out the map, the map sends the current scale to the server and the server compares it with layer’s ZoomLevel scales to determine how to render that layer. You can see it is important to make the client and the server zoomlevels synchronized otherwise switch a zoomLevel on client will not correspondingly switch a zoomLevel on server. 
  
 Hope that helps, let me know for more queries. 
  
 Ben 


Ben, 
 According to your example above, it appears that you have to set the scale for zoomlevels on layers even when they are not rendered. For example, the scale is set on all five layers of the Road5MLayer, but that layer is only rendered from zoomlevelone to zoomleveltwo.  Can you not forego setting the scale for anything beyond those two layers?   
  
 -Dustin

I must admit the “zoomlevelsets” seem to be very convaluded. 
  
 I personally prefer the ESRI way which is a simple View Scale min and max. ie. the Road5MLayer would have a Max of “Unlimited” and Min would be 4,000,000 meaning that the maps scale MUST be at least 4,000,000 to start drawing this layer. 
  
 It would seem you wouldn’t have an occasion to have ZoomLevelSet’s set to different scales, if that is the case why is there a property on the Layer, Surely there could just be a map scoped Scale collection that applies to the layers ZoomLevelSets?

Michael, 
  
   Can you tell me a bit more about this?  For example is there a collection on zoom levels?  I mean if I set one to 4,000 to unlimited then this obviously only work for one level.  Would you need to add more such as a 2,000 to 4,000 one?  This is the way we had it in previous version of Map Suite 2.x and we found that it caused allot of confusion for developers new to GIS and also caused experienced programmers hassles.  Two scenarios stick out in my mind.  The first is people having no idea about what scales are and what to set them to.  They had to do allot more trial and error, mostly error.  The second is that it was an easy way to introduce bugs like where they tweaked scales and made some overlap or they put them out of order in the collection and had a hard time debugging them. 
  
 I know from my limited experience with Map Objects that there they just let the user write code to check the scale.  It would yield code like ‘If(scale > 1000 && scale < 2000) then’  and you would take care of the rest.  The issues with this way is that there is nothing to reference for things like a scale bar etc. 
  
  Next enter in Google Maps, Virtual Earth and Yahoo Maps.  These companies set some standards around zoom levels and we followed mostly with them.  Before them zooming to any scale was fashionable.  After that our feedback from customers was that they didn’t want that and they wanted scales to match up with these tools.  Also they didn’t want granular zooming, they wanted snapping to zoom levels like Google.  The track zoom was too complicated we heard.  Of course we had to still support these things so we create the zoom levels which are a mix of the ideas.  Google Maps did the snapping because their entire dataset was cached and they had no choice.  In my mind this was a big limitation and I didn’t think people would stand for it.  I got the opposite feedback that they don’t want to zoom in half way between two zoom levels.  It was a moment I was a little disappointed in the user community.  It did work out well as it allowed us to do more caching if people used the snap to zoom level. 
  
   The other reason we went with the zoom level objects as pre-defined, though changeable, objects was that it made the code very easy to read, and update for in experienced users.  For example in an API where you have a collection of zoom levels you would need to write code like this. 
  
 // To create your zoom level. 
 // This is prone to error if you set the zoom levels incorrectly 
 ZoomLevel zoomlevel1 = new ZoomLevel(); 
 zoomLevel.MinScale = 5000; 
 zoomLevel.MaxScale = 10000; 
 zoomLevel1.DefaultAreaStyle.Color = Geocolors.StandardColors.Red; 
 Layer.ZoomLevels.Add(“zoomLevel1”,zoomLevel); 
  
 //To change something later once you created it. 
 ZoomLevel zoomlevel = (ZoomLevel) Map1.ZoomLevels(“zoomLevel1”); 
 zoomLevel.DefaultAreaStyle.Color = Geocolors.StandardColors.Blue; 
  
 //Now the system where they are predefined… 
 Layer.ZoomLevels.ZoomLevel1.DefaultAreaStyle.Color = Geocolors.StandardColors.Red; 
  
 // And if you want to change it later 
 Layer.ZoomLevels.ZoomLevel1.DefaultAreaStyle.Color = Geocolors.StandardColors.Blue; 
  
 You can see it is much cleaner to have the objects pre-lit.  Now it is true that if you need some custom zoom levels than the second case becomes as many lines of code as the first case.  This was a trade off.  We wanted to make the most common scenarios easy and then if you wanted something more complex and custom then it got harder.  We avoided the pure but more complex case 1 as it makes it harder for everyone. 
  
 To answer one of the questions on there.  Each ZoomLevel has an Active property.  You can set that to false and it disables the scale.  I think we may have a bug around this that I am looking into but thats the theory anyway.  Don’t forget about the CustomZoomLevels collection! 
  
 If you really like the way you are used to we can accommodate that as well.  We have a CustomZoomLevels collection where you can add zoom levels there and we ignore the default ones.  You can also set the scale property on the scales themselves like.  ZoomLevelSet.ZoomLevel01.Scale = 5000;  I am not sure what you mean by your last statement about the layer. 
  
   Another option would be that we can expose a few methods as virtual on the zoom level set and you can add to the zoom levels a Min & Max scale.  Override the virtual methods and determine scale however you want.  I would be willing to help you with this and we could work through it.  We didn’t expose them as virtual for now as we did not have a scenario that warranted it but if you want to we can try  this. 
  
 Ok, this was allot long than it needed to be but I wanted to give you a brain dump of sorts on why we went with what we did.  We tried many thing in the past and they all have their weaknesses with different user groups of different levels.  We went with the one that made the best looking code and was the easiest to understand to the most users we knew about. 
  
 David