ThinkGeo.com    |     Documentation    |     Premium Support

ScaleBarAdornmentLayer refresh performance

Hi,


I've added the ScaleBarAdornmentLayer with the following code:




ScaleBarAdornmentLayer scaleBar = new ScaleBarAdornmentLayer();
scaleBar.Location = AdornmentLocation.LowerLeft;
scaleBar.YOffsetInPixel = -20f;
scaleBar.UnitFamily = UnitSystem.Metric;
scaleBar.HasMask = true;
scaleBar.MaskBrush = new GeoSolidBrush(GeoColor.FromArgb(150, GeoColor.StandardColors.White));
scaleBar.MaskContour = new GeoPen(GeoColor.StandardColors.Transparent);
scaleBar.TextColor = GeoColor.StandardColors.White;
wpfMap1.AdornmentOverlay.Layers.Add("ScaleBarAdornmentLayer", scaleBar);
 

I've subscribed to the AdornmentOverlay.Drawn event, and I'm logging the DrawingTime.  I've noticed that with the scale bar added to my map, the refresh is 0.1 seconds for just the AdornmentOverlay during a Pan operation.  This makes the panning seem chunky.  Without the scale bar, the panning appears much more fluid to the user. 


Is there any workaround? 


Thanks,


Greg



Greg, 
  
   I think this is happening because it is drawing for every mouse move you are doing as you pan.  For geographic layers we can do a trick and pick up the image as you pan.  For screen layers it is a bit different as you may want it to change as the person is panning.   
  
   What we really need is to know if you really intend to update the image on a pan or other interactive overlay event.  If we knew that then we could use the cache of the image already drawn.  We need to consider how to do this though at it might be tricky to expose that.  You could have an adornment overlay or layer that you might want to refresh on a pan or moving a vertex in edit mode then you are willing to pay for the drawing but other times you may not. 
  
   We need to think about how this might work… 
  
 David 
  


Hi David,


For my app,  I cannot think of any use case where I would need to change the display of a scale bar during a pan.  I only think it would change during a zoom, since conceptually the appearance of the scale bar is influenced by the zoom.  


Thanks,


Greg


 



Greg, 
  
  I agree,  we just don’t know that any particular adorent layer would be a scalebar.  Let me think on this a bit to see what we might be able to do. 
  
 David

Greg, 
  
   One thing we could do is to add conditions specifically to things like AdornmentLayers and AdornmentOverlay.  We may allow you to specify if the layer or overlay refreshes on a scale change or extent change etc.  It is kind of like the IsEmpty property we have now where if you have an overlay that is empty we just skip drawing it all together. 
  
 David

That sounds good to me.


Thanks,


Greg



Greg & David, 
  
 I have a question about this, when we panning the ScaleBar(or ScaleLine) probablly need to be updated.  
  
 For example, the scale bar or scale line ratio between Equator with North pole(or south pole) should be different. So when we pan around the world, the scale bar should be updated to reflect its location. 
  
 Any more questions just feel free to let me know. 
  
 Thanks. 
  
 Yale 


Yale, 
  
 Thanks for pointing that out.  For our application, we’re in an isolated, tight, zoomed-in area, and the user will not pan outside this area.  So, we’re not too concerned with the issue you pointed out.  Mostly, we desire to optimize refresh performance for our small area. 
  
 Thanks, 
 Greg

Greg,


Thans for your inform of detail requirement.


I have created custom ScaleBarAdornmentLayer which is what you want.


    public class CustomScaleBarAdornmentLayer : ScaleBarAdornmentLayer
    {
        private Dictionary<double, GeoImage> scaledImages;

        public CustomScaleBarAdornmentLayer()
            : base()
        {
            scaledImages = new Dictionary<double, GeoImage>();
        }

        protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
        {
            if (scaledImages.ContainsKey(canvas.CurrentScale))
            {
                PointShape centerPoint = canvas.CurrentWorldExtent.GetCenterPoint();
                canvas.DrawWorldImageWithoutScaling(scaledImages[canvas.CurrentScale]
                    , centerPoint.X, centerPoint.Y, DrawingLevel.LevelOne);
            }
            else
            {
                base.DrawCore(canvas, labelsInAllLayers);
                scaledImages.Add(canvas.CurrentScale, canvas.ToGeoImage(canvas.NativeImage));
            }
        }
    }

Please let me know if you have questions


James


 



James,


This works great!


Thanks,


Greg



Greg, 
  
 You’re welcome.  
  
 Just let me know if you have more questions. 
  
 James