Multiple images on one layer - sindizzy/DSW GitHub Wiki

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](0);
        double y = fe[1](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"](_ID_) = pointID;
        currentFeature.DataRow["label"](_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](0)(0) == currentFeature.Coordinates[0](0)(0))
            {
                //Here you can set any image you like. You can set one for each individual point.
                Image img = listImg[pointID - 1](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](ID)='" + currentFeature.DataRow["ID"](_ID_).ToString() + "'"; // <-- this is extremely important. Here the point ID is set
                pc.LegendText = currentFeature.DataRow["label"](_label_).ToString();

                pointScheme.AddCategory(pc);

                ll.Symbology.Categories[0](0).Expression = "[" + fl.DataSet.DataTable.Columns[1](_-+-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; } }}

⚠️ **GitHub.com Fallback** ⚠️