예제 #1
0
        public static string CreateFromMap(Map map)
        {
            if (map == null)
            {
                throw new ArgumentNullException("map");
            }

            Rectangle extents = map.Extents.Clone();

            // reproject map extents to wgs 84 for Google Earth
            if (!string.IsNullOrEmpty(map.Projection))
            {
                using (ProjFourWrapper src = new ProjFourWrapper(map.Projection))
                {
                    using (ProjFourWrapper dst = new ProjFourWrapper(ProjFourWrapper.WGS84))
                    {
                        extents = new Rectangle(src.Transform(dst, extents.Min),
                                                    src.Transform(dst, extents.Max));
                    }
                }
            }

            MemoryStream ms = new MemoryStream();
            XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);

            xtw.WriteStartDocument();
            xtw.WriteStartElement("kml", "http://www.opengis.net/kml/2.2");
            xtw.WriteStartElement("Document");

            foreach (Layer l in map.Layers)
            {
                if (l.Data ==  null) continue;

                foreach (Style s in l.Styles)
                {
                    CreateFromStyle(xtw, s, l.Data.SourceFeatureType);
                }
            }

            foreach (Layer l in map.Layers)
            {
                if (l.Data == null) continue;

                CreateFromLayer(xtw, l, extents);
            }

            xtw.WriteEndElement(); // Document
            xtw.WriteEndElement(); // kml
            xtw.WriteEndDocument();
            xtw.Flush();

            // Now read back
            ms.Seek(0, SeekOrigin.Begin);
            TextReader tr = new StreamReader(ms);
            return tr.ReadToEnd();
        }
예제 #2
0
        public void TestSimpleFeatureSourceSerialization()
        {
            Map m = new Map();
            Layer l = new Layer();

            SimpleFeatureSource sfs = new SimpleFeatureSource(FeatureType.Polygon);
            Polygon p = new Polygon();

            Ring r = new Ring();
            r.Points.Add(new Point(0,0));
            r.Points.Add(new Point(0,5));
            r.Points.Add(new Point(5,5));
            r.Points.Add(new Point(5,0));
            r.Close();
            p.Rings.Add(r);

            Ring hole = new Ring();
            hole.Points.Add(new Point(1,1));
            hole.Points.Add(new Point(2,1));
            hole.Points.Add(new Point(2,2));
            hole.Points.Add(new Point(2,1));
            hole.Close();
            p.Rings.Add(hole);

            sfs.Features.Add(p);

            l.Data = sfs;
            m.Layers.Add(l);

            MapSerializer ms = new MapSerializer();
            string s = MapSerializer.Serialize(m);

            Map m2 = ms.Deserialize(new MemoryStream(UTF8Encoding.UTF8.GetBytes((s))));

            Assert.AreEqual(1, m2.Layers.Count);
            Assert.AreEqual(1, (m2.Layers[0].Data as SimpleFeatureSource).Features.Count);
            Assert.AreEqual(2, ((m2.Layers[0].Data as SimpleFeatureSource).Features[0] as Polygon).Rings.Count);
        }
예제 #3
0
        public void SetUp()
        {
            MapSerializer ms = new MapSerializer();
            ms.AddDatabaseFeatureSourceType<DummyDBProvider>();
            ms.AddFileFeatureSourceType<DummyFileProvider>();

            m1 = new Map();
            m1.Extents = new Rectangle(0,0,10,10);
            m1.Height = 123;
            m1.Width = 321;
            m1.Projection = "+init=epsg:4326";
            m1.BackgroundColor = Color.FromArgb(4,3,2,1);

            Layer l1 = new Layer();
            l1.Id = "l1";
            DummyDBProvider db = new DummyDBProvider();
            l1.Data = db;
            l1.Projection = "+init=epsg:2236";
            l1.Theme = ThemeType.NumericRange;
            l1.ThemeField = "MyField";
            l1.LabelField = "MyLabelField";
            l1.Visible = false;
            l1.MinScale = 99;
            l1.MaxScale = 88;
            l1.AllowDuplicateLabels = false;

            db.ConnectionString = "MyConnString";
            db.ForcedFeatureType = FeatureType.Polyline;
            db.ForcedSpatialType = SpatialType.Geographic;
            db.ForcedSrid = 1234;
            db.TableName = "MyTable";
            db.ForcedGeometryColumn = "MyGeoColumn";

            Style s1 = new Style();
            s1.Id = "MyStyle";
            s1.LineColor = Color.FromArgb(255, 180, 34, 34);
            s1.LineStyle = LineStyle.Dashed;
            s1.LineWidth = 23;
            s1.PointSize = 4;
            s1.PointSymbol = PointSymbolType.Image;
            s1.PointSymbolShape = PointSymbolShapeType.Square;
            s1.UniqueThemeValue = "MyValue";
            s1.MaxRangeThemeValue = 30000;
            s1.MinRangeThemeValue = 4;
            s1.FillStyle = FillStyle.None;
            s1.ShowLabels = true;
            s1.LabelColor = Color.FromArgb(0,1,2,3);
            s1.LabelFont = LabelFont.SansSerif;
            s1.LabelFontEmSize = 1234;
            s1.LabelPosition = LabelPosition.BottomLeft;
            s1.LabelPixelOffset = 42;
            s1.LabelDecoration = LabelDecoration.Outline;
            s1.LabelOutlineColor = Color.FromArgb(9,9,9,9);
            s1.LabelOutlineWidth = 99f;
            s1.LabelAngle = 45f;
            s1.LabelCustomFont = "font";

            s1.MinScale = 0;
            s1.MaxScale = 1;
            s1.LabelMinScale = 10;
            s1.LabelMaxScale = 100;
            s1.DrawPointSymbolOnPolyLine = true;
            s1.CalculateLabelAngleForPolyLine = false;
            s1.FillTexturePath = "../../../Cumberland.Tests/maps/images/swamps.png";

            s1.Simplify = true;
            s1.SimplifyTolerance = 99;

            s1.UniqueElseFlag = true;

            l1.Styles.Add(s1);

            m1.Layers.Add(l1);

            Layer l2 = new Layer();
            l2.Id = "l2";
            l2.Data = new DummyFileProvider();
            m1.Layers.Add(l2);

            string s = MapSerializer.Serialize(m1);

            m2 = ms.Deserialize(new MemoryStream(UTF8Encoding.UTF8.GetBytes((s))));
        }
예제 #4
0
        public void TestAddUnsupportedFileFeatureSource()
        {
            Map m = new Map();
            Layer l = new Layer();
            l.Id = "l";
            l.Data = new DummyFileProvider();
            m.Layers.Add(l);

            string x = MapSerializer.Serialize(m);

            MapSerializer ms = new MapSerializer();

            // should fail as this not a supported provider
            m2 = ms.Deserialize(new MemoryStream(UTF8Encoding.UTF8.GetBytes((x))));
        }
예제 #5
0
        public Bitmap Draw(Map map, Cumberland.Rectangle extents, string projection, int width, int height)
        {
            ProjFourWrapper dst = null;
            Graphics g = null;
            List<string> label_names = new List<string>();
            List<LabelRequest> labels = new List<LabelRequest>();

            try
            {
                #region setup drawing

                Bitmap b = new Bitmap(width, height);
                g = Graphics.FromImage(b);

                if (map.BackgroundColor.A > 0)
                {
                    g.Clear(map.BackgroundColor);
                }

                // set antialiasing mode
                g.SmoothingMode = Smoothing;
                g.TextRenderingHint = textRenderingHint;

                // we need to convert map points to pixel points
                // so let's do as much of this at once:
                // calculate map rectangle based on image width/height
                Rectangle envelope = extents.Clone();

                // set aspect ratio to image
                envelope.AspectRatioOfWidth = Convert.ToDouble(width) /
                    Convert.ToDouble(height);

                // get the scale
                double scale = Convert.ToDouble(envelope.Width) /
                                         Convert.ToDouble(width);
                double displayScale = scale;

                // instantiate output projection
                if (!string.IsNullOrEmpty(projection))
                {
                    dst = new ProjFourWrapper(projection);

                    if (!string.IsNullOrEmpty(map.Projection) &&
                        projection != map.Projection)
                    {
                        // we want to use the map projection for min/max scale on layers/styles/etc.
                        using (ProjFourWrapper orig = new ProjFourWrapper(map.Projection))
                        {
                            Point p1 = dst.Transform(orig, extents.Min);
                            Point p2 = dst.Transform(orig, extents.Max);

                            displayScale = Math.Abs(p1.X-p2.X) / width;
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(map.Projection))
                {
                    dst = new ProjFourWrapper(map.Projection);
                }

                #endregion

                foreach (Layer layer in map.Layers)
                {
                    if (!layer.Visible ||
                        layer.Data == null ||
                        displayScale > layer.MaxScale ||
                        displayScale < layer.MinScale)
                    {
                        continue;
                    }

                    ProjFourWrapper src = null;

                    try
                    {
                        #region set up layer drawing

                        Rectangle layerEnvelope = envelope.Clone();

                        // instantiate layer projection
                        bool reproject = false;
                        if (dst != null && !string.IsNullOrEmpty(layer.Projection))
                        {
                            src = new ProjFourWrapper(layer.Projection);
                            reproject = true;

                            // reproject extents to our source for querying
                            layerEnvelope = new Rectangle(dst.Transform(src, layerEnvelope.Min),
                                                    dst.Transform(src, layerEnvelope.Max));
                        }

                        string themeField = null;

                        // query our data
                        List<Feature> features = null;
                        if (layer.Theme == ThemeType.None)
                        {
                            features = layer.Data.GetFeatures(layerEnvelope, null, layer.LabelField);
                        }
                        else
                        {
                            // check for valid field
                            themeField = layer.ThemeField;
                            if (string.IsNullOrEmpty(themeField))
                            {
                                throw new MapConfigurationException("Layer has been set for theming, but no ThemeField was provided");
                            }

                            features = layer.Data.GetFeatures(layerEnvelope, themeField, layer.LabelField);
                        }

                        if (features.Count == 0)
                        {
                            continue;
                        }

                        if (layer.Styles.Count == 0)
                        {
                            throw new MapConfigurationException("Layer lacks a Style");
                        }

                        List<string> names = new List<string>();

                        // set up a delegate for getting style based on theme type
                        StyleForFeatureFinder getStyle = GetBasicStyleForFeature;

                        if (layer.Theme == ThemeType.Unique)
                        {
                            getStyle = GetUniqueStyleForFeature;
                        }
                        else if (layer.Theme == ThemeType.NumericRange)
                        {
                            getStyle = GetRangeStyleForFeature;
                        }

                        #endregion

                        if (layer.Data.SourceFeatureType == FeatureType.Point)
                        {
                            #region handle point rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                Point p = features[ii] as Point;

                                Style style = getStyle(layer, p.ThemeFieldValue, displayScale);

                                if (style == null)
                                {
                                    continue;
                                }

                                PointDrawer drawPoint = GetPointDrawer(style);

                                if (reproject)
                                {
                                    // convert our data point to the map projection
                                    p = src.Transform(dst, p);
                                }

                                // convert our map projected point to a pixel point
                                System.Drawing.Point pp = ConvertMapToPixel(envelope, scale, p);

                                drawPoint(style, g, pp);

                                if (style.ShowLabels &&
                                    displayScale <= style.LabelMaxScale &&
                                    displayScale >= style.LabelMinScale)
                                {
                                    labels.Add(new LabelRequest(style,
                                        p.LabelFieldValue,
                                        pp,
                                        layer.AllowDuplicateLabels,
                                        names));
                                }
                            }

                            #endregion
                        }
                        else if (layer.Data.SourceFeatureType == FeatureType.Polyline)
                        {
                            #region Handle line rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                PolyLine pol = (PolyLine) features[ii];

                                Style style = getStyle(layer, pol.ThemeFieldValue, displayScale);

                                if (style == null ||
                                    style.LineStyle == LineStyle.None)
                                {
                                    continue;
                                }

                                for (int jj=0; jj < pol.Lines.Count; jj++)
                                {
                                    Line r = pol.Lines[jj];

                                    if (style.Simplify)
                                    {
                                        r = r.Simplify(style.SimplifyTolerance);
                                    }

                                    System.Drawing.Point[] ppts = new System.Drawing.Point[r.Points.Count];

                                    int segmentIdx = 1;
                                    double maxSegment = 0;

                                    for (int kk = 0; kk < r.Points.Count; kk++)
                                    {
                                        Point p = r.Points[kk];

                                        if (reproject)
                                        {
                                            p = src.Transform(dst, p);
                                        }

                                        ppts[kk] = ConvertMapToPixel(envelope, scale, p);

                                        if ((style.DrawPointSymbolOnPolyLine ||
                                            (style.ShowLabels &&
                                            scale <= style.LabelMaxScale &&
                                            scale >= style.LabelMinScale)) &&
                                            kk > 0)
                                        {
                                            // find the segment with the longest length to pin a label to

                                            double seg = r.Points[kk-1].Distance(r.Points[kk]);

                                            if (seg > maxSegment)
                                            {
                                                maxSegment = seg;
                                                segmentIdx = kk;
                                            }
                                        }
                                    }

                                    g.DrawLines(ConvertLayerToPen(style), ppts);

                                    if (style.DrawPointSymbolOnPolyLine ||
                                        (style.ShowLabels &&
                                        pol.LabelFieldValue != null &&
                                        displayScale <= style.LabelMaxScale &&
                                        displayScale >= style.LabelMinScale))
                                    {
                                        Point start = r.Points[segmentIdx-1];
                                        Point end = r.Points[segmentIdx];

                                        // pin our label to the center point of the line
                                        Point polyCenter = new Point((start.X+end.X)/2, (start.Y+end.Y)/2);
                                        //Point polyCenter = r.CalculateBounds().Center;

                                        // transform (if neccessary) the convert to pixel point
                                        System.Drawing.Point plpt = ConvertMapToPixel(envelope,
                                                                                      scale,
                                                                                      (reproject ? src.Transform(dst, polyCenter) : polyCenter));

                                        if (style.ShowLabels)
                                        {

                                            float angle = style.LabelAngle;

                                            if (style.CalculateLabelAngleForPolyLine)
                                            {
                                                // calculate the slope of this line and use as our label angle
                                                angle = CalculateSegmentAngle(start, end);
                                            }

                                            labels.Add(new LabelRequest(style,
                                                                        pol.LabelFieldValue,
                                                                        plpt,
                                                                        layer.AllowDuplicateLabels,
                                                                        names,
                                                                        angle));
                                        }
                                    }
                                }
                            }

                            #endregion
                        }
                        else if (layer.Data.SourceFeatureType == FeatureType.Polygon)
                        {
                            #region polygon rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                Polygon po = features[ii] as Polygon;

                                Style style = getStyle(layer, po.ThemeFieldValue, displayScale);

                                if (style == null)
                                {
                                    continue;
                                }

                                GraphicsPath gp = new GraphicsPath(FillMode.Alternate);

                                for (int jj = 0; jj < po.Rings.Count; jj++)
                                {
                                    Ring r = po.Rings[jj];

                                    if (style.Simplify)
                                    {
                                        r = r.Simplify(style.SimplifyTolerance);
                                    }

                                    System.Drawing.Point[] ppts = new System.Drawing.Point[r.Points.Count];

                                    for (int kk = 0; kk < r.Points.Count; kk++)
                                    {
                                        Point p = r.Points[kk];

                                        if (reproject)
                                        {
                                            p = src.Transform(dst, p);
                                        }

                                        ppts[kk] = ConvertMapToPixel(envelope, scale, p);

                                    }

                                    gp.AddPolygon(ppts);
                                }

                                if (style.FillStyle != FillStyle.None)
                                {
                                    Brush fillBrush;

                                    if (style.FillStyle == FillStyle.Texture)
                                    {
                                        if (string.IsNullOrEmpty(style.FillTexturePath))
                                        {
                                            throw new MapConfigurationException("A style with FillStyle.Texture must have a FillTexturePath");
                                        }

                                        fillBrush = new TextureBrush(new Bitmap(style.FillTexturePath));
                                    }
                                    else
                                    {
                                        fillBrush = new SolidBrush(style.FillColor);
                                    }

                                    g.FillPath(fillBrush, gp);
                                }

                                if (style.LineStyle != LineStyle.None)
                                {
                                    g.DrawPath(ConvertLayerToPen(style), gp);
                                }

                                if (style.ShowLabels &&
                                    po.LabelFieldValue != null &&
                                    displayScale <= style.LabelMaxScale &&
                                    displayScale >= style.LabelMinScale)
                                {
                                    Point polyCenter = po.CalculateBounds().Center;

                                    labels.Add(new LabelRequest(style,
                                                                po.LabelFieldValue,
                                                                ConvertMapToPixel(envelope,
                                                                                  scale,
                                                                                  (reproject ? src.Transform(dst, polyCenter): polyCenter)),
                                                                layer.AllowDuplicateLabels,
                                                                names));
                                }
                            }

                            #endregion
                        }
                    }
                    finally
                    {
                        // dispose of proj4
                        if (src != null)
                        {
                            src.Dispose();
                        }
                    }

                }

                foreach (LabelRequest lr in labels)
                {
                    if (!lr.AllowDuplicates)
                    {
                        if (label_names.Contains(lr.Label)) continue;

                        label_names.Add(lr.Label);
                    }

                    if (lr.Style.DrawPointSymbolOnPolyLine)
                    {
                        GetPointDrawer(lr.Style)(lr.Style, g, lr.Coord);
                    }

                    DrawLabel(g, lr.Style, lr.Coord, lr.Label, lr.ForcedLabelAngle);
                }

                return b;
            }
            finally
            {
                // dispose of proj4
                if (dst != null)
                {
                    dst.Dispose();
                }

                if (g != null)
                {
                    g.Dispose();
                }
            }
        }
예제 #6
0
 public Bitmap Draw(Map map)
 {
     return Draw(map, map.Extents, map.Projection, map.Width, map.Height);
 }
예제 #7
0
 public TileProvider(Map map)
     : this(TileConsumer.GoogleMaps)
 {
 }
예제 #8
0
        public Bitmap DrawTile(Map map, int x, int y, int zoomLevel)
        {
            Bitmap b;
            string prj = null;

            if (consumer == TileConsumer.GoogleMaps || consumer == TileConsumer.VirtualEarth)
            {
                // reproject to spherical mercator
                prj = ProjFourWrapper.SphericalMercatorProjection;
            }

            try
            {
                CheckZoomLevel(zoomLevel);

                // calculate number of tiles across
                int numTiles = CalculateNumberOfTilesAcross(zoomLevel);

                // get map units/pixel resolution for zoomlevel
                double resolution = CalculateMapUnitsPerPixel(zoomLevel);

                // set to tile size
                int adjTileSize = tileSize + (bleedInPixels * 2);

                // google tiles origin is top left
                int tileymin, tileymax;
                if (consumer == TileConsumer.GoogleMaps || consumer == TileConsumer.VirtualEarth)
                {
                    tileymin = numTiles - y - 1;
                    tileymax = numTiles - y;
                }
                else
                {
                    tileymin = y;
                    tileymax = y + 1;
                }

                double mapUnitsOffset = bleedInPixels * resolution;

                // - convert pixels to map units
                // - translate to origin
                // - offset if we need to draw a bleed
                Rectangle extents = new Rectangle((tileSize*x) * resolution + worldExtents.Min.X - (mapUnitsOffset),
                                            (tileSize*tileymin) * resolution + worldExtents.Min.Y - (mapUnitsOffset),
                                            (tileSize*(x+1)) * resolution + worldExtents.Min.X + (mapUnitsOffset),
                                            (tileSize*tileymax) * resolution + worldExtents.Min.Y + (mapUnitsOffset));

                MapDrawer renderer = new MapDrawer();

                // draw our map
                b = renderer.Draw(map,
                                  extents,
                                  prj,
                                  adjTileSize,
                                  adjTileSize);

                if (bleedInPixels > 0)
                {
                    // crop to get our tile
                    using (Bitmap old = b)
                    {
                        b = old.Clone(new System.Drawing.Rectangle(bleedInPixels,
                                              bleedInPixels,
                                              tileSize,
                                              tileSize),
                                System.Drawing.Imaging.PixelFormat.DontCare);
                    }
                }

            }
            catch (Exception ex)
            {
                if (!DrawExceptionsOnTile) throw;

                b = new Bitmap(tileSize, tileSize);

                // draw the exception on the tile
                using (Graphics gr = Graphics.FromImage(b))
                {
                    string msg = ex.Message;
                    int numCharsPerRow = (tileSize) / 5;
                    int numLineBreaks = (int) Math.Ceiling(Convert.ToSingle(msg.Length) /
                                                           Convert.ToSingle(numCharsPerRow));

                    for (int ii=0; ii < numLineBreaks; ii++)
                    {
                        msg = msg.Insert(ii*numCharsPerRow, Environment.NewLine);
                    }

                    gr.DrawString(msg,
                                  new Font("Arial", 10, GraphicsUnit.Pixel),
                                  Brushes.Red,
                                  10,
                                  10);
                }
            }

            return b;
        }