implementing a Layer.DataProvider with MapsUi

Sep 3, 2011 at 10:30 AM

Hello,

I have a problem rendering my own DataProvider layer within MapsUi. It keeps giving me a redcross and i wanted to know what i am doing wrong in my sample code.

I am using the Mapsui.Forms.MapControl-control in my application and i use it to display my own data. To get this error i basically performed the following steps:
1 - Create the control
2 - Created a class MyProvider implementing the interface:  SharpMap.Providers.IProvider with a method:
        public IEnumerable<IFeature> GetFeaturesInView(BoundingBox box, double resolution)
3 - Created a layer of the type SharpMap.Layers.Layer
4 - Connected them to eachother: Map.Layers.Add(new SharpMap.Layers.Layer() {});
5 - When rendering the layer, i get a red cross on the screen

How can i render vectors from a DataProvider inside MapsUi?

======================== MyProvider.cs =================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpMap.Providers;
using SharpMap.Layers;

namespace TestProvider
{
    class MyProvider: IProvider
    {
        Layer _layer;
        int _offset;
        public MyProvider(Layer layer, int offset)
        {
            _layer = layer;
            _offset = offset;
        }


        #region IProvider Members

        public string ConnectionId
        {
            get { throw new NotImplementedException(); }
        }

        public bool IsOpen
        {
            get { throw new NotImplementedException(); }
        }

        public int SRID
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public IEnumerable<IFeature> GetFeaturesInView(SharpMap.Geometries.BoundingBox box, double resolution)
        {
            System.Diagnostics.Debug.WriteLine("GetFeaturesInView:" + _layer.LayerName);

            System.Collections.ObjectModel.Collection<IFeature> result = new System.Collections.ObjectModel.Collection<IFeature>();
            for (int longitude = (int)box.MinX; longitude < box.MaxX; longitude += _offset)
            {
                for (int latitude = (int)box.MinY % _offset; latitude < box.MaxY; latitude += _offset)
                {
                    SharpMap.Providers.Features fea = new Features();
                    IFeature smf = fea.New();
                    smf.Geometry = new SharpMap.Geometries.Point()
                    {
                        X = longitude,
                        Y = latitude
                    };
                    smf["longitude"] = longitude;
                    smf["latitude"] = latitude;
                    result.Add(smf);

                }
            }
            System.Diagnostics.Debug.WriteLine("GetFeaturesInView COUNT#" + result.Count);
            return result;
        }

        public SharpMap.Geometries.BoundingBox GetExtents()
        {
            throw new NotImplementedException();
        }

        public void Open()
        {
            System.Diagnostics.Debug.WriteLine("Open:" + _layer.LayerName);
        }

        public void Close()
        {
            System.Diagnostics.Debug.WriteLine("Close:" + _layer.LayerName);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

======================== Form1.cs ======================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ProjNet.CoordinateSystems;
using SharpMap.Layers;
using SharpMap.Styles;

namespace TestProvider
{
    public partial class Form1 : Form
    {

        // WGS84 coordinate system (lat/lon)
        public readonly ICoordinateSystem EPSG4326;
        public readonly ICoordinateSystem EPSG900913;

        public Form1()
        {
            InitializeComponent();

            #region InitializeCoordinateSystems
            CoordinateSystemFactory csf = new CoordinateSystemFactory();

            // WGS 84
            IGeographicCoordinateSystem wgs84 = csf.CreateGeographicCoordinateSystem("WGS 84", AngularUnit.Degrees, HorizontalDatum.WGS84, PrimeMeridian.Greenwich, new AxisInfo("north", AxisOrientationEnum.North), new AxisInfo("east", AxisOrientationEnum.East));
            EPSG4326 = wgs84;

            // Google
            List<ProjectionParameter> parameters = new List<ProjectionParameter>();
            parameters.Add(new ProjectionParameter("semi_major", 6378137.0));
            parameters.Add(new ProjectionParameter("semi_minor", 6378137.0));
            parameters.Add(new ProjectionParameter("latitude_of_origin", 0.0));
            parameters.Add(new ProjectionParameter("central_meridian", 0.0));
            parameters.Add(new ProjectionParameter("scale_factor", 1.0));
            parameters.Add(new ProjectionParameter("false_easting", 0.0));
            parameters.Add(new ProjectionParameter("false_northing", 0.0));
            IProjection projection = csf.CreateProjection("Google Mercator", "mercator_1sp", parameters);
            EPSG900913 = csf.CreateProjectedCoordinateSystem("Google Mercator", wgs84, projection, LinearUnit.Metre, new AxisInfo("East", AxisOrientationEnum.East), new AxisInfo("North", AxisOrientationEnum.North));
            #endregion

            #region InitializeBaseLayer
            System.IO.DirectoryInfo cachingpath = new System.IO.DirectoryInfo(System.IO.Path.GetTempPath());
            SharpMap.Layers.TileLayer baselayer = new SharpMap.Layers.TileLayer(
                 new BruTile.TileSource(
                     new BruTile.Web.WebTileProvider(
                        new BruTile.Web.TmsRequest(new Uri("http://b.tile.openstreetmap.org"), "png"),
                        new BruTile.Cache.FileCache(cachingpath.FullName, "png")),
                        new BruTile.PreDefined.SphericalMercatorInvertedWorldSchema()));

            #endregion

            mapControl1.Map.Layers.Add(baselayer);

            this.MouseWheel += new MouseEventHandler(Form1_MouseWheel);
        }

        void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
            {
                mapControl1.ZoomIn(e.Location);
            }
            else
            {
                mapControl1.ZoomOut();
            }
        }

        private void mapControl1_MouseEnter(object sender, EventArgs e)
        {
            mapControl1.Focus();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            bool usetransformation = false;
            Layer layer = null;
            if (usetransformation)
            {
                layer = new Layer("layer:" + DateTime.Now.Ticks);
                layer.DataSource = new MyProvider(layer, 1);

                // in the layer we want to use lat/longs
                ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory ctfac = new ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory();
                layer.CoordinateTransformation = ctfac.CreateFromCoordinateSystems(EPSG4326, EPSG900913);           
            }
            else
            {
                layer = new Layer("layer:" + DateTime.Now.Ticks);
                layer.DataSource = new MyProvider(layer, 100000);
            }

            // layer style
            layer.Styles.Add(new VectorStyle());

            mapControl1.Map.Layers.Add(layer);
        }

        #region Designer
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            SharpMap.Map map2 = new SharpMap.Map();
            SharpMap.Styles.Color color2 = new SharpMap.Styles.Color();
            this.mapControl1 = new Mapsui.Forms.MapControl();
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // mapControl1
            //
            this.mapControl1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.mapControl1.Location = new System.Drawing.Point(0, 0);
            color2.A = 255;
            color2.B = 255;
            color2.G = 255;
            color2.R = 255;
            map2.BackColor = color2;
            map2.MaximumZoom = 1.7976931348623157E+308D;
            map2.MinimumZoom = 0D;
            this.mapControl1.Map = map2;
            this.mapControl1.Name = "mapControl1";
            this.mapControl1.Size = new System.Drawing.Size(284, 262);
            this.mapControl1.TabIndex = 0;
            this.mapControl1.Text = "mapControl1";
            this.mapControl1.MouseEnter += new System.EventHandler(this.mapControl1_MouseEnter);
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(12, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 1;
            this.button1.Text = "Add Layer";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.mapControl1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private Mapsui.Forms.MapControl mapControl1;
        private System.Windows.Forms.Button button1;
        #endregion

        #region Main
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        #endregion
    }
}

Sep 3, 2011 at 3:33 PM

It seems this is more of a SharpMap issue than MapsUI.

LayerProviders simply provide relevant data (features). How this data is rendered is up to Style(s). I've noticed you're using

 layer.Styles.Add(new VectorStyle());

What Style are you asigning?

So I would:

  • Check if DataProvider provides the correct data
  • Assign a known style that can render such data.

Goran

Sep 5, 2011 at 12:41 PM

The problem was caused by an

throw  new ArgumentException("No bitmap symbol set in Gdi rendering")

In the class GdiRendering.GdiGeometryRenderer ::DrawPoint(..)  around line 183

After i gave the style the following code:

 

            // layer style
            Style style = new SymbolStyle
            {
                Symbol = new SharpMap.Styles.Bitmap
                {
                    data = GetImageStreamFromResource("TestProvider.icon.png")
                }
            };

 

with:

        private static Stream GetImageStreamFromResource(string resourceString)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            string icon = resourceString;
            Stream imageStream = assembly.GetManifestResourceStream(icon);
            return imageStream;
        }

everything worked fine!