ThinkGeo.com    |     Documentation    |     Premium Support

Custom Zoom Levels

Hi guys, I accidently posted this on the desktop edition forum.


My company is looking at using Map Suite as the base software for our now online GIS solutions. however one of our requirements is that we set the zoom levels visibility based on scale.


 


I see that I can create a custom zoom level, however I'm not sure how to set the styles ApplyUntilZoomLevel to another custom zoom level. In other words I don't want to use the preset zoomlevel(0-20) levels. No offense intended as I'm sure there is a reason for the predefined levels, but I'm afraid I really don't see the point in them as everything I've ever seen done is based on specific scales.


 


I was told this is a known problem in the desktop edition but Yale thought there may be better support in the WebEdition.


 


Thanks in advance.



Jeremy,



There are some different meaning between ClientZoomLevelScales (Client Zoom Levels) and ZoomLevelSet (Server Zoom Levels).



Server Zoom Levels is responsible for rendering images on the server-side while Client Zoom Levels is responsible for generating tiles under different zoom levels on the client-side.



In another word, these two level sets are separate; client zoom levels can’t affect the Server Zoom Levels.



I guess that your application has 22 levels; you want to set different styles on the last two levels. I have an idea which may helps.



Normally, users don’t set styles for every preset zoom levels. Most of the codes are using ApplyUntilZoomLevel property to set the same style for continouse levels. Please see the code below.ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(MapPath("~/SampleData/world/cntry02.shp"));
worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1;
worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
worldLayer.ZoomLevelSet.ZoomLevel06.DefaultAreaStyle = AreaStyles.Country2;
worldLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level15;
worldLayer.ZoomLevelSet.ZoomLevel16.DefaultAreaStyle = AreaStyles.Country2;
worldLayer.ZoomLevelSet.ZoomLevel16.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

Also the same effect when you use the following code:ZoomLevelSet defaultZoomLevelSet = new ZoomLevelSet();
ZoomLevelSet customZoomLevelSet = new ZoomLevelSet();
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(defaultZoomLevelSet.ZoomLevel01.Scale));
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(defaultZoomLevelSet.ZoomLevel06.Scale));
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(defaultZoomLevelSet.ZoomLevel16.Scale));

customZoomLevelSet.CustomZoomLevels[0].DefaultAreaStyle = AreaStyles.Country1;
customZoomLevelSet.CustomZoomLevels[1].DefaultAreaStyle = AreaStyles.Country2;
customZoomLevelSet.CustomZoomLevels[2].DefaultAreaStyle = AreaStyles.County1;

worldLayer.ZoomLevelSet = customZoomLevelSet;

I want to point out is that you can enlarge some of the level scales also you can shorten some of the scales. In my sample code above, you can see there are default 20 client zoom levels while only 3 server zoom levels. 



In your scenario, you can enlarge the lower level scales and shorten the higher level scales such as setting scales as the following table; then you can find ZoomLevel21 and ZoomLevel22 on the client side is actually ZoomLevel19 and ZoomLevel20 on the server side.



For example:









    
        
            
            

Client Zoom Levels


            
            
            

Zoom   Levels


            
        
        
            
            

Level01


            
            
            

Level01


            
        
        
            
            

Level02


            
        
        
            
            

Level03


            
            
            

Level02


            
        
        
            
            

Level04


            
        
        
            
            

Level05


            
            
            

Level03


            
        
        
            
            

Level06


            
            
            

Level04


            
        
        
            
            

Level07


            
            
            

Level05


            
        
        
            
            

Level08


            
            
            

Level06


            
        
        
            
            

Level09


            
            
            

Level07


            
        
        
            
            

Level10


            
            
            

Level08


            
        
        
            
            

Level11


            
            
            

Level09


            
        
        
            
            

Level12


            
            
            

Level10


            
        
        
            
            

Level13


            
            
            

Level11


            
        
        
            
            

Level14


            
            
            

Level12


            
        
        
            
            

Level15


            
            
            

Level13


            
        
        
            
            

Level16


            
            
            

Level14


            
        
        
            
            

Level17


            
            
            

Level15


            
        
        
            
            

Level18


            
            
            

Level16


            
        
        
            
            

Level19


            
            
            

Level17


            
        
        
            
            

Level20


            
            
            

Level18


            
        
        
            
            

Level21


            
            
            

Level19


            
        
        
            
            

Level22


            
            
            

Level20


            
        
    







If you have any questions please let me know.



Thanks,

Howard



Hi howard. I think we are talking past eachother.  
  
 I’m not overly concerned about the styles specifically as the visibility of my layers. 
  
 ok so I want to set an image catalog of our orthos to only display between the scales of 1:300,000 (meters) to 1:70,000 (meters) 
 I want our image catalog of Topos to display in the scale ranges of 1:70,000 (meters) to 1:10,000 (meters) 
  
 etc etc. for different shape files.  please note that these scales are dependant on the application. but I do need to set their visibility based on scale and not some arbitary “ZoomLevel15” which doesn’t mean much to me. 
  
 I’ve been looking at the code a bit more and it looks like i can do something like: 
  
 orthosLayer.ZoomLevelSet.ZoomLevel20.Scale = 300000d;  
 orthosLayer.ZoomLevelSet.ZoomLevel01.Scale = 70000d;  
 orthosLayer.ZoomLevelSet.ZoomLevel20.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level01;  
  
 meaning that once I’ve zoomed in closer than 1:70,000 the layers visibility will set itself to false?

Jeremy,



I found the zoom level number is reversed in our system In the code you pasted which I'm not sure that it's a misspelling or intentional. Technically, if you run the pasted code, only ZoomLevel01 is visible while invisible from ZoomLevel02.



If you change the code like the following, it'll be fine.

orthosLayer.ZoomLevelSet.ZoomLevel01.Scale = 300000d;

orthosLayer.ZoomLevelSet.ZoomLevel01.Scale = 70000d;

orthosLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 



As my understanding, "ZoomLevel15" doesn't mean much to you, while scales is much more meaningful, you can use CustomZoomLevels which you can handle it easier.



Maybe I misunderstand your issue in the last reply, and if you use CustomZoomLevels, the ApplyUntilZoomLevel is set to the target zoomlevel index in the collection plus 1.



For example, the custom zoom level set has 4 levels, the first level style need to apply to the 4th level.ZoomLevelSet customZoomLevelSet = new ZoomLevelSet();
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(300000));
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(200000));
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(100000));
customZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(50000));

customZoomLevelSet.CustomZoomLevels[0].DefaultAreaStyle = AreaStyles.Country1;
customZoomLevelSet.CustomZoomLevels[0].ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level04;

Hope it helps.



Any questions please let me know.



Thanks,

Howard



Howard 
  
 Thanks for the reply. it looks like this will do exactly what I want.

Jeremy, 
  
 You are always welcome. Sorry for the misunderstanding in the first reply. 
  
 Please feel free to let me know if you have more questions. 
  
 Thanks, 
 Howard

Howard, I’m still having problems with the different zoom levels. 
  
 I have a province layer that I have created 3 zoom levels for at the scales of (1000000, 10000, 1000 ) 
 and I have a river layer that I have created 1 zoom level for at a scale (10000) 
  
 so I have gone: 
  
 ProvinceLayer.CustomZoomLevels.Add(1000000); 
 ProvinceLayer.CustomZoomLevels.Add(10000); 
 ProvinceLayer.CustomZoomLevels.Add(1000); 
 ProvinceLayer.CustomZoomLevels[0].ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level03; 
  
 RiverLayer.CustomZoomLevels.Add(10000);  
 RiverLayer.CustomZoomLevels[0].ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level02; 
  
 Map.StaticOverlays.Layers.Add(ProvinceLayer);  
 Map.StaticOverlays.Layers.Add(RiverLayer);  
  
  
 bla bla bla. 
  
 The problem I’m having now is that the river layer is always visible even though my map if zoomed far out of its specified zoomscale. I only want it to become visible once it gets to the scale of 10000. 


Jeremy, 
  
 I recreated the issue you mentioned; it doesn’t work as I expected neither and I think it’s a bug. I’m so sorry for the inconvenience. We’ll let you know when we have a fix for it immediately.  
  
 Thanks for reporting, if you have more questions please let me know. 
  
 Thanks, 
 Howard

Thanks for the update Howard.

Jeremy, 
  
 You are welcome; I think it will be fixed soon. 
  
 Please let me know if you have any queries. 
  
 Thanks, 
 Howard

Any news on the progress of this?

Jeremy, 
  
 Sorry for the inconvenience. It’s still in our track system. Please give us more time and we’ll let you know when it’s fixed. 
  
 Thanks, 
 Howard

I’m just checking up on this issue. I’ve been running into quite a few problems with custom zoom levels, and I need to get a test application of our system integrating MapSuite, running by monday.  
  
 Any ETA would be much appreciated. It is just a test system, but it would be nice if we can manage multiple layers.

Jeremy, 
  
 I think you can work this issue around by adding proper ZoomLevels. To make sure it is clear, first I would like to talk about the ZoomLevelSet and ZoomLevel. 
  
 ZoomLevel accepts a scale, which is a point not a range. That is to say we CANNOT specify the renders just by one zoomlevel. ZoomLevelSet however, as it includes multi ZoomLevels, it in fact has ranges which we can set the renders within. Take your codes for example,  
   
 ProvinceLayer.CustomZoomLevels.Add(1000000);  
 ProvinceLayer.CustomZoomLevels.Add(10000);  
 ProvinceLayer.CustomZoomLevels.Add(1000); 
  
 The ProvinceLayer.CustomZoomLevels has 3 ranges, (Double.Max~505000), (505000~5500), (5500~0). 505000 comes from (1000000 + 10000) / 2 and 5500 comes from (10000+1000)/ 2.  That means if the current scale is within (Double.Max ~ 505000), it is within the first ZoomLevel; if it is within (505000~5500), it is then within the 2nd ZoomLevel. Ideally, you can use ApplyUntilZoomLevel to set the style across different ZoomLevels, but as ApplyUntilZoomLevel is an enumeration with 20 items and has some bugs when dealing with custom ZoomLevels, you might have some issues when using that. We will work on that. 
  
 So for your codes about RiverLayer,  
  
 RiverLayer.CustomZoomLevels.Add(10000);  
 RiverLayer.CustomZoomLevels[0].ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level02; 
  
 You only have one ZoomLevel in the ZoomLevelSet, that means there is only ONE range in RiverLayer.CustomZoomLevels, which is (Double.Max ~ 0). That’s why wherever you zoom in / out, the map is always with the same style, as it is always within the only ZoomLevel.  
  
 Now let’s do some changes. Let’s say we want the River Layer be visible ONLY within the scale range (8000, 12000), I then need to add 3 ZoomLevels to the ZoomLevelSet. 
  
 RiverLayer.CustomZoomLevels.Add(14000);  
 RiverLayer.CustomZoomLevels.Add(10000);  
 RiverLayer.CustomZoomLevels.Add(6000);  
  
 And only set the style for the second ZoomLevel. 
  
 Hope that makes sense. 
  
 At last talk about the ClientZoomLevelSet in Web Edition.  The zoomLevel/ZoomLevelSet above are all on server side which defines how we want to render the map, the clientZoomLevelSet though defines what zoomlevels we can zoom to on Client. Technically we can zoom to whatever scale we want, like 6000:1, 6001:1, 6002:1,…, but usually at client side, we only provide several options (20 by default) so you can only zoom to those scales. Sure it can be changed by the method Map1.SyncClientZoomLevels(). 
  
 Let us know if you have any more issues about it. 
  
 Thanks, 
  
 Ben

Ben this makes sense but still doesn't seem to work properly. 



In my configuration system when I set up a layer, I set the upper scale and lower scale as thresholds, so when I apply this configuration to mapsuite, by your logic for a layer set as  



MyConfiguredLayer.Upperscale = 1000000 

MyConfiguredLayer.Lowerscale = 1 



my configuration should be: 



//--------------------------------------------------------------------------------- 



ZoomLevel myZoomLevel01 = new ZoomLevel((double.MaxValue + 1000000) / 2);  

ZoomLevel myZoomLevel02 = new ZoomLevel((1000000 + 1) / 2);  

ZoomLevel myZoomLevel03 = new ZoomLevel((1 + 0) / 2);  



//Apply Styling to myZoomLevel02; then add the zoom levels to the layer 



MapLayer.ZoomLevelSet.CustomZoomLevels.Add(myZoomLevel01);  

MapLayer.ZoomLevelSet.CustomZoomLevels.Add(myZoomLevel02);  

MapLayer.ZoomLevelSet.CustomZoomLevels.Add(myZoomLevel03);  



//--------------------------------------------------------------------------------- 



Now I will admit that this seems to work to a degree, which I'm quite excited about, however my layer looses its styling well before the MyZoomLevel03 scale. in fact I seem to loose it at about 1:50km on the scale bar. Now I realize I shouldn't be setting a third custom zoom level 

if my lower threshold is set to 1. however because my configuration of mapsuite is automated by my own configuration system it is currently easier to do this, as most of my layers will have a minimum threshold greater than 1. 



I'll continue testing and update you if I find a problem in my code causing this, but as I even tried hard coding the scales for test purposes, I don't hold out much hope that its a problem on my side.



ok, I’ve altered my code and where the lower threshold is set to 0 I will not create a final zoomlevel with no styling. However I still think there is something strange going on here with the scale for this final zoomlevel with no styling. 
  
 for example I said above that it was begin set at a lower threshold of 1 then my styles switch of at about 1:50km.  
 well when I set it to scale of 0, then it goes off at about 1:5km.

The other problem I’ve noticed is that my first zoomlevel which should display no styles never seems to switch on. because of this all my layers appear at the upper scales. I still need to test this in the lower scales. 
  
 as per the example above I have a  
 provincial layer with the thresholds set to [upper: 10000000, lower: 0] 
 rivers layer with the thresholds set to [upper: 50000, lower: 0] 
  
 so my code is: 
 //---------------------------------------------------------------------- 
  
 MyProvinceLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel((double.MaxValue + 10000000) / 2));  
 MyProvinceLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel((10000000 + 0) / 2));  
 //Apply styles to MyProvinceLayer.ZoomLevelSet.CustomZoomLevels[1]; 
  
 MyRiversLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel((double.MaxValue + 10000000) / 2));  
 MyRiversLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel((50000 + 0) / 2));  
 //Apply Styles to MyRiversLayer.ZoomLevelSet.CustomZoomLevels[1]; 
  
 Map.DynamicOverlay.Layers.Add(MyProvinceLayer);  
 Map.DynamicOverlay.Layers.Add(MyRiversLayer);  
  
 //---------------------------------------------------------------------- 
  
 now, no matter how far out I zoom both layers are still visible. When I zoom out the rivers layer should become invisible first, then further out my provincial layer should also become invisible. 


Jeremy,


I think your logic has a small issue. For your example,
 
provincial layer with the thresholds set to [upper: 10000000, lower: 0]
rivers layer with the thresholds set to [upper: 50000, lower: 0]
 
The code should be like this
 
//---------------------------------------------------------------------- 



MyProvinceLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(10000000 * 2 – 10000000 / 2); 

MyProvinceLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(10000000 / 2)); 

//Apply styles to MyProvinceLayer.ZoomLevelSet.CustomZoomLevels[1]; 



MyRiversLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(50000 * 2 – 50000 / 2); 

MyRiversLayer.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(50000 / 2)); 

//Apply Styles to MyRiversLayer.ZoomLevelSet.CustomZoomLevels[1]; 




Map.DynamicOverlay.Layers.Add(MyProvinceLayer); 

Map.DynamicOverlay.Layers.Add(MyRiversLayer); 



//----------------------------------------------------------------------
 
So you see, if we want the ZoomLevel to be (10000000 ~ 0), the 2 zoomLevels we need is
 
15000000 and 5000000
And the ranges for the 2 zoomLevels are (Double.Max ~ 10000000) and (1000000, 0)
 
If we want the ZoomLevel to be (50000 ~ 0), the 2 zoomLevels we need is 
75000 and 25000
And the ranges for the 2 zoomLevels are (Doulbe.Max ~ 50000) and (50000 ~ 0)
 
By the way, we cannot add anything to Double.MaxValue, it will be out of the range of a double and might have some unexpected result.
 
Further more, if what you need is the range from 1000000 to 1, here are the zoomLevels you need to add.
 
ZoomLevel[2] = (1 + 0) / 2  = 0.5
ZoomLevel[1] = 1 * 2 – ZoomLevel[2] = 1.5
ZoomLevel[0] = 1000000 * 2 –ZoomLevel[1] =  1999998.5
 
 


 
Let me know if you have any more issues.
 
Thanks,
 
Ben

 



Sorry Ben, This still doesn’t work.  I adjusted my code to work like your diagram for a layer with an upper threshold of 1,000,000 and lower threshold of 1 
  
 here is a breakdown of my code. 
  
 //The Lower clear Zoom Level 
 MyZoomLevel00 = new ZoomLevel((1 + 0) / 2); //0.5 
  
 //The actual threshold zoom levels 
 MyZoomLevel01 = new ZoomLevel((1 * 2) - MyZoomLevel00.Scale); //1.5d 
 MyZoomLevel02 = new ZoomLevel((1000000 * 2) - MyZoomLevel01.Scale); //1999998.5d 
  
 //MyZoomLevel02 – Apply Styling! 
  
 // Then I tried the upper clear zoom level.  
 //------------------------------------------------------------- 
 MyZoomLevel03 = new ZoomLevel((1000000 * 2 - 1000000 / 2);    
 //This is from your first example. however you will notice the scale here is 1500000d which doesn’t correspond with the one above. 
  
 Layer.ZoomLevelSet.CustomZoomLevels.Add(MyZoomLevel03);  
 Layer.ZoomLevelSet.CustomZoomLevels.Add(MyZoomLevel02);  
 Layer.ZoomLevelSet.CustomZoomLevels.Add(MyZoomLevel01);  
 Layer.ZoomLevelSet.CustomZoomLevels.Add(MyZoomLevel00);  
  
  
 //-------------------------------------------------------------------------------- 
 Ok, now I the I cant get my layer to disappear off the upper threshold. and the lower threshold still comes in too early. 
 if fact it switches of between 1:20km and 1:10km which on my maps currentScale measurements are between [1,153,499.59 and 576,749.79]. 
  
 I even tried adding my zoom levels to the CustomZoomLevelSet in the reverse order, just to check, but I got the same results. 
  
 Even stranger, is when I add another layer with  thresholds set at upper: 500000 and lower: 1000 and I use the exact same logic. This layers lower threshold allows me to zoom in closer than the first layer, before the lower threshold kicks in. i.e. this layer switches off between 1:10km and 1:5km. 
  
  
  
 Would it be possible for you to send me a working test solution. Specifically where I only want OuterLayer visible between 100000 and 1, and InnerLayer only visible between 50000 and 1000.

Jeremy,


Here is the sample for you. There are 2 Layers in this sample, the USStates layer and Major Cities Layer. USStates has 3 zoomLevels, (MaxScale~100000) in Red, (100000~1) in Yellow and (1~0) in Green; Cities Layer has 3 zoomLevels, (Max~50000) in Black, (50000 ~ 1000) in Green and (1000, 0) in Red. To make it clear, I created a custom client zoomLevelset,  I set the scale to 110000, 100000, 90000;  51000, 50000, 49000; 1100, 1000, 900; 1.5, 1, 0.5; so you can easily see what happened when the scale break the lines coming to a new zoomLevel.  The scale is displayed below the map so you can easily tell what the current status is. The map is displayed all the time to make it easy to find, if you only want a layer be visible within a specific zoomLevel, just avoid adding styles to the other zoomLevel will be fine.


Thanks,


Ben



1061-CustomZoomLevelSet.zip (106 KB)