How to set multiple Layer.LabelStringDelegate(s) in one Layer

Topics: Algorithms, SharpMap v0.9 / v1.x
Oct 23, 2014 at 2:55 AM
Edited Oct 23, 2014 at 6:59 AM
I would like to give multiple Label.LabelStringDelegate(s) into one layer.
First, I packed three coordination points into one layer.
However, I was not able to give only one Layer.LabelStringDelegate to the layer.


The following is the present my source code.

In one Layer(flay), there are three points by coodination.
However, Layer.LabelStringDelegate has only one "text".

For example, I want to set the text "TextA" to PointA, the text "TextB" to PointB,
and the text "TextC" to PointC.

Please advice me.
//VectorLayer setting(flay)
SharpMap.Layers.LabelLayer flay = new SharpMap.Layers.LabelLayer("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)
LabelStyle A_Style = new LabelStyle();
A_Style.Font = new Font(FontFamily.GenericSerif, 10);
A_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate_A;

//Create the style for PointB(flay)
LabelStyle B_Style = new LabelStyle();
B_Style.Font = new Font(FontFamily.GenericSerif, 10);
B_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate_B;

//Create the style for PointC(flay)
LabelStyle C_Style = new LabelStyle();
C_Style.Font = new Font(FontFamily.GenericSerif, 10);
C_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate_C;

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();



private string LabelDelegate_A(SharpMap.Data.FeatureDataRow fdr)
{
    return "TextA";
}

private string LabelDelegate_B(SharpMap.Data.FeatureDataRow fdr)
{
    return "TextB";
}

private string LabelDelegate_C(SharpMap.Data.FeatureDataRow fdr)
{
    return "TextC";
}
Previously when I tried to draw Style.Symbol (each Bitmap) as below, it was successful.
//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");
Coordinator
Oct 23, 2014 at 5:52 AM
You need to use just one Label.LabelStringDelegate:
switch(row[0])
{
    case 0:
        return "TextA";
    //...
}
Oct 23, 2014 at 6:55 AM
Edited Oct 23, 2014 at 7:00 AM
Thank you for your advice.

I have changed the source code below.

But I do not understand two points.

1.
(to distinguish between (A), (B), and (C))
How to set the parameters from (A), (B), and (C),
and how to get the parameters at
private string LabelDelegate(SharpMap.Data.FeatureDataRow fdr)
{
}
2.
Where and how to define the array "row[]" ?
Should I use "fdr"?

Could you please advice me the detail?
//Create the style for PointA(flay)
LabelStyle A_Style = new LabelStyle();
A_Style.Font = new Font(FontFamily.GenericSerif, 10);
A_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate;   //(A)

//Create the style for PointB(flay)
LabelStyle B_Style = new LabelStyle();
B_Style.Font = new Font(FontFamily.GenericSerif, 10);
B_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate;   //(B)

//Create the style for PointC(flay)
LabelStyle C_Style = new LabelStyle();
C_Style.Font = new Font(FontFamily.GenericSerif, 10);
C_Style.ForeColor = Color.Black;
flay.LabelStringDelegate = LabelDelegate;   //(C)


private string LabelDelegate(SharpMap.Data.FeatureDataRow fdr)
{
    switch(row[0])  //row is not defined.
    {
        case 0:
            return "TextA";
        case 1:
            return "TextB";
        case 2:
            return "TextC";
        default:
            return "TextA";
    }
}
Coordinator
Oct 23, 2014 at 7:35 AM
Edited Oct 23, 2014 at 7:36 AM
private void CreateAndAddLabelLayer()
{
//
// CODE FROM ABOVE
//

// Label delegate for all features
flay.LabelStringDelegate = LabelDelegate; 

//Create the style for PointA(flay)
var A_Style = new LabelStyle();
A_Style.Font = new Font(FontFamily.GenericSerif, 10);
A_Style.ForeColor = Color.Black;

//Create the style for PointB(flay)
var B_Style = new LabelStyle();
B_Style.Font = new Font(FontFamily.GenericSerif, 10);
B_Style.ForeColor = Color.Black;

//Create the style for PointC(flay)
var C_Style = new LabelStyle();
C_Style.Font = new Font(FontFamily.GenericSerif, 10);
C_Style.ForeColor = Color.Black;

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);

//Create and 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();
}

private string LabelDelegate(SharpMap.Data.FeatureDataRow fdr)
{
    switch(Convert.ToUint32(fdr["oid"])
    {
        case 0:
            return "TextA";
        case 1:
            return "TextB";
        case 2:
            return "TextC";
        default:
            return "TextA";
    }
}
Oct 23, 2014 at 8:13 AM
Edited Oct 23, 2014 at 8:14 AM
Thank you so much for showing the detailed solution.
I have finally achieved my purpose.

I do not understand why not
switch (Convert.ToUInt32(fdr))
but
switch (Convert.ToUInt32(fdr["oid"]))
is right now.

I will study enough about LabelStringDelegate by DOCUMENTATION pages.

I hope your continued cooperation in the future.
Coordinator
Oct 23, 2014 at 9:40 AM
If you put the labels you want to have for you points in the datasource, you could use LabelLayer.LabelColumn instead of a delegate.
//...
fdr.ItemArray = new object[] { i, string.Format("Point {0}", i) };
// ...
// Don't assign any delegate!
vlay.LabelColumn = "label";
this will perform better. LabelStringDelegate is for cases where you'd want to combine different attribute data to a string, e.g.
private string LabelDelegate(SharpMap.Data.FeatureDataRow fdr)
{
    return string.Format("Point ID {0}, at ({1}, {2})\nLabel: '{3}'", fdr[0], fdr.Geometry.Coordinate.X, fdr.Geometry.Coordinate.Y, fdr[1]);
}
Oct 24, 2014 at 5:35 AM
Thank you for giving further detailed advice.

To put the labels, I hear from you about the advantage of two kinds of methods, respectively, and it help me learn so much.