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(); }
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); }
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)))); }
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)))); }
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(); } } }
public Bitmap Draw(Map map) { return Draw(map, map.Extents, map.Projection, map.Width, map.Height); }
public TileProvider(Map map) : this(TileConsumer.GoogleMaps) { }
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; }