How to set multiple Style.Symbol(s) in one Layer

Topics: Algorithms, SharpMap v0.9 / v1.x
Sep 25, 2014 at 7:59 AM
I would like to give multiple Style.Symbol(s) into one layer.
First, I packed three coordination points into one layer.
However, I was not able to give only one Style.Symbol to the layer.


The following is the present my source code.

About bese VectorLayer(vlay) setting, I referred to the SharpMap tutorial.
http://sharpmap.codeplex.com/wikipage?title=Tutorial%20-%20Example%201%3a%20Adding%201%20layer%20to%20the%20Map&referringTitle=SharpMap%20Tutorial

In one Layer(flay), there are three points by coodination.
However, Style.Symbol(Bitmap) has only one FigureA.bmp.

For example, I want to set the FigureA.bmp to PointA, the FigureB.bmp to PointB,
and the FigureC.bmp to PointC.

Please advice me.
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 SharpMap;
using SharpMap.Layers;
using SharpMap.Data.Providers;
using System.Collections.ObjectModel;
using GeoAPI;
using NetTopologySuite;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string[,] GpsPoint = new string[3, 3];
        GeoAPI.Geometries.Coordinate[] FPoints = new GeoAPI.Geometries.Coordinate[3];
        NetTopologySuite.Geometries.Point[] fmp = new NetTopologySuite.Geometries.Point[3];

        public Form1()
        {
            InitializeComponent();

            //VectorLayer(vlay) setting
            SharpMap.Layers.VectorLayer vlay = new SharpMap.Layers.VectorLayer("States");
            vlay.DataSource = new SharpMap.Data.Providers.ShapeFile(@"..\..\path_to_data\\states_ugl.shp", true);
            mapBox1.Map.Layers.Add(vlay);
            mapBox1.Map.ZoomToExtents();
            mapBox1.Refresh();


            //VectorLayer(flay) setting
            SharpMap.Layers.VectorLayer flay = new SharpMap.Layers.VectorLayer("GpsPoint");

            List<NetTopologySuite.Geometries.Geometry> geometries = new List<NetTopologySuite.Geometries.Geometry>();

            GpsPoint[0, 0] = "48.00";   //PointA(latitude)
            GpsPoint[0, 1] = "-95.00";  //PointA(longitude)
            GpsPoint[1, 0] = "46.00";   //PointB(latitude)
            GpsPoint[1, 1] = "-90.00";  //PointB(longitude)
            GpsPoint[2, 0] = "44.00";   //PointC(latitude)
            GpsPoint[2, 1] = "-85.00";  //PointC(longitude)

            for (int n = 0; n <= 2; n++)
            {
                FPoints[n] = new GeoAPI.Geometries.Coordinate((Convert.ToDouble(GpsPoint[n, 1])), (Convert.ToDouble(GpsPoint[n, 0])));
                fmp[n] = new NetTopologySuite.Geometries.Point(FPoints[n]);
                geometries.Add(fmp[n]); //packing three coordination points into one layer.
            }

            flay.DataSource = new SharpMap.Data.Providers.GeometryProvider(geometries);

            flay.Style.Symbol = new Bitmap(@"C:\FigureA.bmp");   //In this case, flay.Style.Symbol is only one Bitmap.

            mapBox1.Map.Layers.Add(flay);
            mapBox1.Refresh();
        }
    }
}
Editor
Sep 25, 2014 at 11:09 AM
Sep 26, 2014 at 4:47 AM
Thank you for your advice.
By reference to the tutorial, I tried to add a processing statement.
//flay.Style.Symbol = new Bitmap(@"C:\FireFighterA_s.png");   //delete this line.


//Create the style for PointA
VectorStyle A_Style = new VectorStyle();
A_Style.Symbol = new Bitmap(@"C:\FigureA.bmp");

//Create the style for PointB
VectorStyle B_Style = new VectorStyle();
B_Style.Symbol = new Bitmap(@"C:\FigureB.bmp");

//Create the style for PointC
VectorStyle C_Style = new VectorStyle();
C_Style.Symbol = new Bitmap(@"C:\FigureC.bmp");

//Create the map
Dictionary<string, SharpMap.Styles.IStyle> styles = new Dictionary<string, IStyle>();

styles.Add("???", A_Style);
styles.Add("???", B_Style);
styles.Add("???", C_Style);

//Assign the theme
flay.Theme = new SharpMap.Rendering.Thematics.UniqueValuesTheme<string>("class", styles, A_Style);

mapBox1.Map.Layers.Add(flay);
However, I did not know what you may be assigned to within, "???" in the processing line of styles.Add().
Like vlay of tutorial Example 2, the parameters equivalent to "land" and "water" were unknown.
Although I have tried the following forms, nothing was no longer displayed on the map and it was useless.
styles.Add(fmp[0].ToString(), A_Style);
styles.Add(fmp[1].ToString(), B_Style);
styles.Add(fmp[2].ToString(), C_Style);

or

styles.Add(FPoints[0].ToString(), A_Style);
styles.Add(FPoints[1].ToString(), B_Style);
styles.Add(FPoints[2].ToString(), C_Style);
What kind of processing is appropriate?
Coordinator
Sep 26, 2014 at 8:50 AM
Edited Sep 26, 2014 at 8:52 AM
Using a GeometryProvider with a themed VectorLayer is bound to fail.
You need to setup a FeatureDataTable and use a GeometryFeatureProvider instead.
var fdt = new SharpMap.Data.FeatureDataTable { TableName = "GpsPoints" };
fdt.Columns.Add("oid", typof(uint));
fdt.Columns.Add("label", typof(string));
for (var i = 0u; i < 3u; i++)
{
    var fdr = (FeatureDataRow)fdt.NewRow();
    fdr.ItemData = new object[] { i, string.Format("Point {0}", i) };
    fdr.Geometry =  new NetTopologySuite.Geometries.Point(FPoints[n]);
    fdt.Rows.Add(fdr);
}

var p = new SharpMap.Data.Providers.GeometryFeatureProvider(fdt);
Now you can set you styles according to either "oid" or "label".
Sep 26, 2014 at 12:08 PM
Edited Sep 26, 2014 at 12:17 PM
Thank you for showing the detailed solution.

Although I read your proposal over repeatedly and tried many things, I did not find a concrete description method.
Could you please tell me about the unknown points?


1.
About
fdt.Columns.Add("oid", typeof(uint));
fdt.Columns.Add("label", typeof(string));
How can I set each Style.Symbol?
Bitmap(@"C:\FigureA.bmp"), Bitmap(@"C:\FigureB.bmp"), and Bitmap(@"C:\FigureC.bmp")
2.
About
var p = new SharpMap.Data.Providers.GeometryFeatureProvider(fdt);
How can I use "var p" for flay.Style?


I'm so sorry to trouble you.
Coordinator
Sep 26, 2014 at 9:52 PM
  1. The problem is that the ITheme.GetStyle(FeatureDataRow row) function needs more than just the geometry. That is why you need to set up a FeatureDataTable. Upon rendering the attribute data for each feature is evaluated and an apropriate style returned.
  2. You setup the theme like this:
var styles = new Dictionary<string, IStyle>();
styles.Add(0, A_Style);
styles.Add(1, B_Style);
styles.Add(2, C_Style);

//Create the theme
var theme = new SharpMap.Rendering.Thematics.UniqueValuesTheme<uint>("oid", styles, Default_Style);
  1. p is a provider, that you need to assign to the VectorLayer.Datasource. You need to assign the theme as well.
Sep 29, 2014 at 7:58 AM
Thank you for giving detailed advice.

I have finally achieved my purpose.

I will understand enough about how to assign the theme of layer.

The following is an extract of the source code about flay setting.
//VectorLayer setting(flay)
SharpMap.Layers.VectorLayer flay = new SharpMap.Layers.VectorLayer("GpsPoint");

GpsPoint[0, 0] = "48.00";   //PointA(latitude)
GpsPoint[0, 1] = "-95.00";  //PointA(longitude)
GpsPoint[1, 0] = "46.00";   //PointB(latitude)
GpsPoint[1, 1] = "-90.00";  //PointB(longitude)
GpsPoint[2, 0] = "44.00";   //PointC(latitude)
GpsPoint[2, 1] = "-85.00";  //PointC(longitude)

//Creat the DataSource(flay)
var fdt = new SharpMap.Data.FeatureDataTable { TableName = "GpsPoints" };
fdt.Columns.Add("oid", typeof(uint));
fdt.Columns.Add("label", typeof(string));
for (var i = 0u; i < 3u; i++)
{
    var fdr = (FeatureDataRow)fdt.NewRow();
    fdr.ItemArray = new object[] { i, string.Format("Point {0}", i) };
    FPoints[i] = new GeoAPI.Geometries.Coordinate((Convert.ToDouble(GpsPoint[i, 1])), (Convert.ToDouble(GpsPoint[i, 0])));
    fdr.Geometry =  new NetTopologySuite.Geometries.Point(FPoints[i]);
    fdt.Rows.Add(fdr);
}

//Assign the DataSource(flay)
var p = new SharpMap.Data.Providers.GeometryFeatureProvider(fdt);
flay.DataSource = p;


//Creat the theme(flay)
//Create the style for PointA(flay)
VectorStyle A_Style = new VectorStyle();
A_Style.Symbol = new Bitmap(@"C:\FigureA.bmp");

//Create the style for PointB(flay)
VectorStyle B_Style = new VectorStyle();
B_Style.Symbol = new Bitmap(@"C:\FigureB.bmp");

//Create the style for PointC(flay)
VectorStyle C_Style = new VectorStyle();
C_Style.Symbol = new Bitmap(@"C:\FigureC.bmp");

var flay_styles = new Dictionary<uint, IStyle>();

flay_styles.Add(0, A_Style);
flay_styles.Add(1, B_Style);
flay_styles.Add(2, C_Style);

//Assign the theme(flay)
var flay_theme = new SharpMap.Rendering.Thematics.UniqueValuesTheme<uint>("oid", flay_styles, A_Style);
flay.Theme = flay_theme;


mapBox1.Map.Layers.Add(flay);
mapBox1.Refresh();