Code does these things :
  • Add multiple point under one layer.
  • Each point has a different Image
  • Each point has a unique label which can be configured

public void LoadMarkers()
{
    try
    {
        //uxMap represents the DotSpatial.Control.Map instance

        double[] dd1 = new double[] { 4.99, 52.673321 };
        double[] dd2 = new double[] { 5.21, 52.912433 };
        double[] dd3 = new double[] { 5.82, 53.581653 };

        List<double[]> list = new List<double[]>();
        list.Add(dd1);
        list.Add(dd2);
        list.Add(dd3);

        //Do something similar with images
        Image img1 = Image.FromFile(@"C:\file1.png");
        Image img2 = Image.FromFile(@"C:\file2.png");
        Image img3 = Image.FromFile(@"C:\file3.png");

        List<Image> listImg = new List<Image>();
        listImg.Add(img1);
        listImg.Add(img2);
        listImg.Add(img3);

        FeatureSet pointCoords = new FeatureSet(DotSpatial.Topology.FeatureType.Point);
        pointCoords.Projection = uxMap.Projection;

        DataColumn column1 = new DataColumn("ID");
        DataColumn column2 = new DataColumn("label");

        pointCoords.DataTable.Columns.Add(column1);
        pointCoords.DataTable.Columns.Add(column2);

        pointCoords.Projection = uxMap.Projection;

        DotSpatial.Symbology.IFeatureLayer fl = uxMap.Layers.Add(pointCoords);
        MapLabelLayer ll = new MapLabelLayer();

        fl.LegendText = "<My Layer Name>";
        fl.LabelLayer = ll;

        ll.Symbolizer = new DotSpatial.Symbology.LabelSymbolizer
        {
            FontFamily = "Tahoma",
            FontColor = Color.Black,
            FontSize = 8,
            BackColor = Color.White,
            BackColorEnabled = true,
            BackColorOpacity = 0.5f
        };

        int pointID = 1;

        DotSpatial.Symbology.PointScheme pointScheme = new DotSpatial.Symbology.PointScheme();
        pointScheme.ClearCategories();

        foreach (var fe in list)
        {
            double x = fe[0];
            double y = fe[1];

            // I use a custom class to set the coordinates of the points. 
            // You may have to use your own depending on your projection.
            System.Windows.Point pLo = LatLonToMeters(y, x);

            DotSpatial.Topology.Coordinate c = new DotSpatial.Topology.Coordinate(pLo.X, pLo.Y);
            DotSpatial.Topology.Point point = new DotSpatial.Topology.Point(c);

            IFeature currentFeature = pointCoords.AddFeature(point);

            currentFeature.DataRow["ID"] = pointID;
            currentFeature.DataRow["label"] = "point #" + pointID.ToString();

            DotSpatial.Symbology.PictureSymbol pis = new DotSpatial.Symbology.PictureSymbol();
            DotSpatial.Symbology.PointCategory pc = new DotSpatial.Symbology.PointCategory(pis);

            foreach (IFeature f in pointCoords.Features)
            {
                if (f.Coordinates[0] == currentFeature.Coordinates[0])
                {
                    //Here you can set any image you like. You can set one for each individual point.
                    Image img = listImg[pointID - 1];

                    DotSpatial.Symbology.Size2D sz = new DotSpatial.Symbology.Size2D(img.Width, img.Height);
                    pis.Image = img;
                    pis.Size = sz;

                    pc.Symbolizer.ScaleMode = DotSpatial.Symbology.ScaleMode.Simple;
                    pc.FilterExpression = "[ID]='" + currentFeature.DataRow["ID"].ToString() + "'"; // <-- this is extremely important. Here the point ID is set
                    pc.LegendText = currentFeature.DataRow["label"].ToString();

                    pointScheme.AddCategory(pc);

                    ll.Symbology.Categories[0].Expression = "[" + fl.DataSet.DataTable.Columns[1].ColumnName + "]"; // <-- again, extremely important. Here the label value is set (Set to the point ID)
                }
            }

            pointID++; // bump up the ID's with one
        }

        fl.Symbology = pointScheme;
        fl.ApplyScheme(pointScheme);
        fl.ShowLabels = true; // <-- without this set, the labels won't show

        //Some built in Invoking just in case you work from a different thread as I tend to do

        if (InvokeRequired)
        {
            Invoke(new System.Windows.Forms.MethodInvoker(delegate
            {
                uxMap.Invalidate();
                uxMap.Refresh();
            }));
        }
        else
        {
            uxMap.Invalidate();
            uxMap.Refresh();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private const int TileSize = 256;
private const int EarthRadius = 6378137;
private const double InitialResolution = 2 * Math.PI * EarthRadius / TileSize;
private const double OriginShift = 2 * Math.PI * EarthRadius / 2;

//Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913
public static  System.Drawing.Point LatLonToMeters(double lat, double lon)
{
    var p = new Point();
    p.X = Convert.ToInt32(lon * OriginShift / 180);
    p.Y = Convert.ToInt32(Math.Log(Math.Tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180));
    p.Y = Convert.ToInt32(p.Y * OriginShift / 180);
    return p;
}

Last edited May 20, 2015 at 9:18 PM by mbayles, version 4