This project is read-only.

GeometryLayer Update…

Jan 10, 2009 at 8:38 AM
Edited Jan 10, 2009 at 8:41 AM
The GeometryLayer has just gotten another makeover.  A bit of cleanup and refactoring but the major change is the addition of a new mode for updating shapes.  So here are the three modes now available and a short description of each:
  • ElementUpdate
  • TransformUpdate
  • PanOnlyUpdate

ElementUpdate:  This iterates through all GeometryBase objects on the ShapeLayer Canvas and performs and explicit update of each Geographic Point to a Pixel.  Best option for lots of Points because no scaling is involved and you get updates during zooms.

PanOnlyUpdate: This option is the same logic Polygons and Linestrings have been using exclusively to this point.  It pans the Canvas as the map viewport changes and hides the shapes during zooms.  Shapes locations are only updated on the map when zoom is complete.  Since there are no updates during zoom this will be the best performing of all options. Drawback, of coarse, is that your shapes disappear during zoom.

TransformUpdate:  This option will both pan and scale the GeometryLayer Canvas in synch with the full map extent.  Therefore, performance is pretty decent even when there are lots of points on the Canvas.  It sets the items on the Canvas once and the scaling and offsetting of the Canvas do the rest.  One thing to note is that entire shape is scaling.  So even things you wouldn’t think scale do.  Consider the case of a LineString’s Path.StrokeThickness.  To keep the stroke a constant size, an adjustment needs to be made to each child to offset the scaling.  Hence a new API on all shapes is ScaleAdjustment for when this mode is used.


Jan 10, 2009 at 8:48 PM
hi there RoadWarrior (damn I should have filled in a nickname instead of my initials avdplas),

I have been studying the code of Deep Earth all day now to get some grip on its architecture (you guys have been bitten by a comment in your youth? ;-)
Well, I think I have some good knowledge now, but still one issue I have not yet come to address.
It is the fact that I still don't know whether vector based objects are automatically scaled when a zoom on the map occurs?

Im so daze right now I can't even read and think whether this post above involves updates for this issue...
Jan 10, 2009 at 9:15 PM
If you are using the mode TransformUpdate, then any child element on the Canvas is scaled.  The example in the Prototype -> SideBar-> Developer Commands -> "Add Geometry" does this and uses this mode.  Note that the Point dimesions and LineString's thickness remain constant.  This is because we apply an inverse of the scale to keep these elements from being so small you couldn't see them.

Regarding comments.  Personally, I don't comment code for the sake of commenting.  Lot's of people like to do that, but I think it is a waste of time and only creates uneccesary maintenance.  I learned a long time ago from CodeComplete, that commenting should be reserved for defining a functions intent when it isn't clear, if any assumptions are used, or you doing something overly clever.  I believe self documenting code is the best approach.  I am pretty hard core about this.  There's probably not many classes or API's in the DeepEarth Core that hasn't been renamed to be clearer or more descriptive in it's purpose.  That being said, we still have some areas for improvement even in our naming. 
Jan 12, 2009 at 12:09 PM
Edited Jan 12, 2009 at 4:13 PM
You are doing some great work here RoadWarrior, thanks!

Jan 13, 2009 at 6:40 AM
Hi, RoadWarrior, great work! I'm using a complex shape object with ellipse, arc, and line segments like this:
<Canvas>
<Path x:Name="range" Stretch="Fill" Fill="#4000FFFF" IsHitTestVisible="False"/>
        <Path x:Name="direction" Stretch="Fill" Fill="#5000FF00"/>
        <Path x:Name="adorner" Stretch="Fill" Fill="#500000FF"/>
        <Path x:Name="path"/>
        <Ellipse x:Name="currentPoint"/>
</Canvas>
I have a subclass of LineString and update the path and ellipse objects in that class. It works well with the old GeometryLayer except it disappears during zooming. Now that the GeometryLayer is refactored, I'm planning to use the latest code to make it zoom. But unfortunately, I found the path update logic was moved to GeometryLayer class. That means I cannot update my customized path (comapring to standard polyline and polygon) with correct point locations. One dirty solution is to put all of the points I use to the Points array and let GeometryLayer generate a polyline. Then I use all the updated point locations from the polyline to generate my own paths and ellipse. Finally I have to hide the polyline returned by GeometryLayer. The other solution is to add an UpdatePoint call in GeometryLayer so that a shape can query GeometryLayer for the updated position of a point. I also recommend to move the path update logic back into the shape class. For example, update path data should be in PathBase class. The only service GeometryLayer provides should be point position update.

Thanks the whole team to release a great control! 
Jan 13, 2009 at 7:13 AM
Have you tried to update your shape by calling the GeometryLayer.UpdateShape(GeometryBase shape) API. Besides that there are still a couple things we need to do to get automatic updates working better for the TransformUpdate mode.  It is not currently updating when it should.  Specifically, we can do more to automatically update the location when the Points collection is modified.  For this, we would need to make the Points list into an ObservableCollection.  Additinally, we might be able to add a DirtyFlag on the GeometryBase that could signal when any update needs to occur.

Jan 13, 2009 at 9:22 AM
Edited Jan 13, 2009 at 9:26 AM
I use Layer.UpdateChildLocation(this) to update the shape.
I added a point position query to the GeometryLayer:

        public List<Point> UpdatePosition(List<Point> points)
        {
            List<Point> updatedPoints = new List<Point>(points.Count);

            Size mapExtent = MapInstance.MapExtentPixelSize;
            double xMaxToCurrRatio = this.Width / mapExtent.Width;
            double yMaxToCurrRatio = this.Height / mapExtent.Height;

            foreach (Point pt in points)
            {
                //Add pixels relative to Layer size.
                Point pixel;
                switch (UpdateMode)
                {
                    case GeometryLayer.UpdateModes.TransformUpdate:
                        {
                            Point logicalPoint = MapInstance.CoordHelper.GeoToLogical(pt);
                            pixel = new Point(logicalPoint.X * xMaxToCurrRatio * mapExtent.Width, logicalPoint.Y * yMaxToCurrRatio * mapExtent.Height);
                            break;
                        }
                    case GeometryLayer.UpdateModes.PanOnlyUpdate:
                        {
                            Point logicalPoint = MapInstance.CoordHelper.GeoToLogical(pt);
                            pixel = new Point(logicalPoint.X * mapExtent.Width, logicalPoint.Y * mapExtent.Height);
                            break;
                        }
                    case GeometryLayer.UpdateModes.ElementUpdate:
                        {
                            pixel = MapInstance.CoordHelper.GeoToPixel(pt);
                            break;
                        }
                    default:
                        {
                            pixel = new Point();
                            break;
                        }
                }
                updatedPoints.Add(pixel);
            }
            return updatedPoints;
        }

After I modify the shape, I call this function to get the updated position for points not in the Points array. Now I can update the shape flawlessly.
Actually, what I do in this function can also be done in the shape class because everything it uses is publicly accessible. But if GeometryLayer can update all those points automatically, that'll be great!

Jan 14, 2009 at 6:40 PM
The change has been checked in that would make this more automatic.  Points is now an ObservableCollection and when the collection is modified the Shape is updated on the Canvas.  Let me know how this works for your scenario.
Jan 15, 2009 at 4:47 PM
I can agree with your general feelings on comments RoadWarrior, I don't like commenting for the sake of commenting either. However, you really should think about putting XML comments on all of the public interfaces for documentation generation and intellisense. Assume that the user is only using the compiled DLL and is easily confused by C# since they currently code in cobol.Net. (Yes, that was a joke. Yes, it really exists.)

Jan 15, 2009 at 6:57 PM
Yes, I agree with you about the usefulness of XML comments on the public interfaces.  I would be great to have some good documentation exposed for intellisense and we do plan to generate a .CHM for release 1.1. 

My statement about "not commenting for the sake of commenting" was really about setting the bar for what constitutes good documentation.  Good documentation needs to go beyond restating the obvious.  If that is all it is doing, don't bother.  We don't need useless comments cluttering up the code base.  Good documentation shouldn't be measured in volume but in how well it communicates intent, assumptions, and examples.  I think a great exercise would be for someone new to the project to go through the entire DeepEarth codebase marking everything with a ///TODO:  that was confusing or not absolutely clear.
Jan 16, 2009 at 5:44 PM
Hi, RoadWarrior: I have a tight deadline at Jan.20 so I'm not able to try out the latest code. Currently it's perfect with 17967. I'll try the new code late next week.

Feb 9, 2009 at 8:52 AM
I've incorporated DeepEarth 1.1. Everything works fine with my scenario. Thanks for the great work.