Adding Polygons

Jul 14, 2008 at 10:04 PM
Nice work.  Playing around, what's suggestion for best way to add polygon shapes.  For example, let's say we want to add jurisdictional areas, such as counties.
Coordinator
Jul 15, 2008 at 3:23 AM
So we have a base "shape" class that you can inherit from and therefore add to a shape layer, it has to impliment some functionliaty like how to align to the map as the underlying map moves. The pin example is very simple.
If you take a look at the prototype web project it has a custom interaction behavour that adds a pin "shape" when you "Alt" click on the map, clearly you could do this on load instead. I would start by using this to add a simple set of pins to the centre of the jurisdictional areas then look at implimenting your own shape  - a polygon.

I imagined that an interesting thing to do with polygons would be to use a native path object, calulating the points from a stored set of Lat/long values based on the current map zoomlevel. I was thinking of using some clever algorithms to do proper curved lines that plot the shortest distance between the two points rather then the old misleading straight line on the mecator project. This would make it an improvement on VE in my mind but in your case may not be what you are after at all.
I believe that Darko is building some drawing tools curently but don't this stop you from having a play and letting us know how you go with it.
I'd love to see you implimentation of a polygon shape and how it works with the control. Any questions please ask, the whole point of this project is for poeple to learn and have fun.
John. 
Jul 15, 2008 at 2:55 PM
Here's a simple polygon implementation that follows the suggestion above.  It only handles simple polygons, but could probably be updated fairly easily to handle more complex shapes if needed.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DeepEarth
{
    public class Polygon : Shape
    {
        private Rect extent { get; set; }

        private Point[] _points;
        public Point[] Points
        {
            get { return _points; }
            set
            {
                _points = value;
                double minx = double.MaxValue;
                double miny = double.MaxValue;
                double maxx = double.MinValue;
                double maxy = double.MinValue;
                foreach (Point pt in _points)
                {
                    if (pt.X < minx) minx = pt.X;
                    if (pt.Y < miny) miny = pt.Y;
                    if (pt.X > maxx) maxx = pt.X;
                    if (pt.Y > maxy) maxy = pt.Y;
                }
                extent = new Rect(new Point(minx, miny), new Point(maxx, maxy));
            }
        }

        public override bool Intersects(Rect bounds)
        {
            Rect intersect = new Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height);
            intersect.Intersect(extent);
            return (intersect.Width > 0 || intersect.Height > 0);
        }

        public override UIElement CreateElement(IProjection projection)
        {
            Path path = CreatePolygon();
            return path;
        }

        private Path CreatePolygon()
        {
            Path path = new Path();
            path.Data = CreateGeometry();
            path.StrokeThickness = 1;
            path.Stroke = new SolidColorBrush(Colors.Black);
            path.Fill = new SolidColorBrush(Color.FromArgb(128, 255, 255, 255));
            return path;
        }

        private PathGeometry CreateGeometry()
        {
            PathGeometry geom = new PathGeometry();
            PathFigure pf = new PathFigure();
            int idx = 0;
            foreach (Point pt in Points)
            {
                Point pixel = Map.GetProjectionToDisplay(pt);
                if (idx == 0)
                {
                    pf.StartPoint = pixel;
                }
                else
                {
                    LineSegment ls = new LineSegment();
                    ls.Point = pixel;
                    pf.Segments.Add(ls);
                }
                idx++;
            }
            pf.IsClosed = true;
            geom.Figures.Add(pf);
            return geom;
        }

        public override void UpdateElement(UIElement element, IProjection projection)
        {
            Path path = element as Path;
            path.Data = CreateGeometry();
        }
    }
}

 

Coordinator
Jul 15, 2008 at 10:43 PM
gmschwartz, you rock!
I've added your class to the project with some very subtle changes (not using underscores for private vars, changed array to generic list, used new .net3.5 constructor things) which I'm more then happy to discuss / modify.
Thankyou very much for your contribution. If you want to join the project and help directly just send me a message.

I've added a simple "add polygon" button to the prototype example so you can see it in action.

Next steps here:

  • We should allow the line thinkness and colors to be set as properties
  • Do we need to validate at least 3 points have been supplied?
  • Should we do the VE thing of having a pin "anchor point" optionally?

This is a great example of a little thing you can do with this project that has great value to everyone else. If others want to simply contibute by posting little additions like this I'm more then happy to help integrate, if you want to do more then just message me.

thanks again!