ThinkGeo.com    |     Documentation    |     Premium Support

Efficieny of viStyle

MapSuite Team,



In your documentation it is stated that the use of Value Style can be somewhat slow.  When I first developed my application I felt the use of Value Style was great and have made extensive use of them.  Now I strongly suspect that this is one of the reasons why my application is slow in taking roughly 4-5 seconds and longer to zoom in/out or to change extent and perform a zoom out.  And my shape file sizes are by no means massive.



A few weeks ago your group gave me some sample code to display directional arrows for one-way streets.  After reviewing the design of this code I discovered that it actually would read each record in the extent once for each of N/S/E/W directional.  So instead of reading each of the records in the extent to be displayed just once and checking the value for one of N/S/E/W and formatting the proper directional it would read each of the records in the extent to be displayed four times, once for each directional.  I have since changed the design of this code so that each record is read only once.  (In fact the original code may have been reading each record in the extent not just 4 times but 4 x 4 = 16 times.)



It dawned on me that maybe the design of this directional code is how Value Style is designed which may account for why my application is slow.



My street network SQLite Feature Layer has 12 Value Styles for just one ZoomLevel.  In one of my InMemoryFeatureLayer there are 18 Value Styles for one ZoomLevel.



I would think that the underlying MapSuite drawing methods would loop through all the records, per shape file, for any given extent to draw just once and apply the proper style.  But I have a feeling that is not what is happening.  Would you confirm for me whether each record is read once and style applied or is each record being read once per Value Style.  So if an extent contains 900 street segments is MapSuite reading 900 x 1 = 900 records or is MapSuite reading 900 x 12 = 10,800 records?



If the latter is true can you offer any suggestions as to how to create just one Custom Style for a ZoomLevel which would inherit the MapSuite Drawing methods so that I can control how many records are read and make use of the Value and Text Styles myself?  An example PointStyle layer with labels should be enough to get me started.



I really suspect this is the cause of my slowness because it’s not like there is a lot of disk activity, and sometimes there is none because Windows has cached the data, but still the map is slow to respond.



Your assistance greatly appreciated.



Dennis



 

Hi Dennis, 
  
 Thanks for your information, I need some time to look into this problem, and I think maybe I can find a way to print out how many times the style is called. 
  
 Any update I will let you know. 
  
 Regards, 
  
 Don

Hi Dennis, 
  
 Thanks very much for you waiting. 
  
 For ValueStyle drawing times.  
 I guess you didn’t set 12 value styles for your layer, you may be add 12 value item to one value style, and then set this value style to layer. In this case, we only read feature records in you layer. With you description, it only reads 900 x 1 = 900 records when drawing value styles. 
  
 Below is pseudo code for drawing value style in MapSuite: 
 foreach (var feature in features) 
 { 
 string fieldValue = feature.ColumnValues[columnName].Trim(); 
 if (ValueItems.ContainsKey(fieldValue)) 
 { 
 Feature[] tmpFeatures = new Feature[1] { feature }; 
 if (valueItem.CustomStyles.Count == 0) 
 { 
 if (valueItem.DefaultAreaStyle != null) 
 { 
 valueItem.DefaultAreaStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); 
 } 
 if (valueItem.DefaultLineStyle != null) 
 { 
 valueItem.DefaultLineStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); 
 } 
 if (valueItem.DefaultPointStyle != null) 
 { 
 valueItem.DefaultPointStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); 
 } 
 if (valueItem.DefaultTextStyle != null) 
 { 
 valueItem.DefaultTextStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); 
 } 
 } 
 } 
 } 
 foreach (var valueItem in valueItems) 
 { 
     foreach (Style style in valueItem.CustomStyles) 
     { 
         if (featuresByValue.ContainsKey(valueItem)) 
         { 
             style.Draw(featuresByValue[valueItem], canvas, labelsInThisLayer, labelsInAllLayers); 
         } 
     } 
 } 
  
 Please refer wiki.thinkgeo.com/wiki/_media/file/WpfEditionSample%20DefaultValueStyle%20CS%20110218.zip for custom value style 
 If you need any other custom style sample. Please search from wiki.thinkgeo.com/wiki/map_suite_desktop_edition_all_samples
  
 If you still fall into performance issue, please send us one sample, we can help to diagnose this issue. 
  
 Thanks,

Don,



I’ve confirmed that for any given ZoomLevelnn/ApplyToZoomLevelnn combination my application has one ValueStyle with multiple ValueItem’s.  So I feel I’m setting these up properly.



I’ve been studying the sample code you referenced for DefaultValueStyles.  I’ve noticed that DrawCore is called numerous times for any given ZoomIn or ZoomOut.  For example, on one ZoomOut, DrawCore was called 16 times with a feature count that varies anywhere from 13 to 136 features.  The 16 calls to DrawCore had a total number of features to draw of 1,212.  There’s only 191 features in the Shape File, and of those 191 roughly 120-150 features were visible within the extent.   It would appear that many features are being drawn more than once.



Why are features being drawn more than once?



This is a concern for me because my application contains 80 layers and I’m looking for the most efficient drawing to minimize user response time.



Thanks,

Dennis






Don,



I implemented the code from the DefaultValueStyles application into my application for use with my InMemoryFeatureLayer that is used for tracking vehicles.



I observed the DrawCore method being invoked numerous times for each feature.  I ran a test and made all the layers InVisible except for the Tracking Layer.  I added one feature to the TrackingLayer so that it remained stationary.  For each Zoom In/Out the DrawCore method was invoked 9 times.  I also observed DrawCore being invoked 3-4 times during a horizontal pan, but never during a vertical pan.  All the while the feature was in-view within the extent.



My application handles roughly 2Million GPS messages per 24hour period so this has the potential to amount to an awful lot of invocations of DrawCore for just this one layer.  My application has four active InMemoryFeatureLayer for tracking purposes.



On a Zoom In/Out the application exhibits a stall. With DrawCore being invoked so many times with multiple InMemoryFeatureLayer and 30-40 ShapeFileFeatureLayer Visible I can begin to understand why the application appears to stall on a Zoom.  Then during a Zoom there are many GPS messages coming in updating the TrackingLayer so these combined certainly exasperate the situation.



What is the reason for invoking DrawCore multiple times per feature?  I would have thought that once would have been enough.



What are your thoughts on this?



Thanks,

Dennis


Hi Dennis, 
  
 Thanks for your further information, I think it is not a bug on “DrawCore”, there are some buffers on tile’s ege, you can set “DrawingMarginInPixel” property value to “0”, the “DrawCore” should be invoked one time as following statements: 
 worldCapitalsLayer.DrawingMarginInPixel = 0; 
  
 But I don’t think this is a proper solution on this scenario, I have a workaround idea on this issue as following steps: 
 1.       Select all features which equal specifying value from all layers. 
 2.       Add these features into a separating “InMemoryFeatureLayer”. 
 3.       Set “InMemoryFeatureLayer”’s style. 
  
 Thanks, 
  
 Casper.Lee

Casper.Lee,



Thanks for your response.



Thank you very much for mentioning the DrawingMarginInPixel Property.  I had not yet transitioned my application from DrawingMarginPercentage even though I had the compiler warnings mentioning that it was obsolete.  What I discovered is that the DrawingMarginInPixel Property defaults to a value of 256.  Since my application was not setting this value the default was 256.  With a value this high for all 70+ layers DrawCore was being invoked many more times than needed for all layers, which was the reason for this post in the first place.  I have now transitioned my application to DrawingMarginInPixel and set it to an appropriate value depending on the layer.  For example, for a Point Layer that does not use labels it is set to a value of zero, for layers where I know the labels are short I set it to a value of 25.  If I know the labels have a chance of being long, I set it to anywhere from 50-100.

Going back to the DefaultValueStyles Project I set DrawingMarginInPixel = 0 and find that the number of times DrawCore is invoked is drastically reduced.



My users have noted that the map is faster after this change.



Regards,

Dennis









Hi Dennis, 
  
 I am glad to hear DrawingMarginInPixel working for your scenario and thanks for you share, your experience is helpful for us also. 
  
 Regards, 
  
 Don