Example of LabelLayer and LabelStyle in SharpMapv2

Topics: SharpMap v2.0
Jul 1, 2010 at 9:54 PM
Hi All, I am new to sharpmap and I have loaded all the layers and modified my Map. Now I am adding a label layer but I do not see anything on the map. I tried to add it in may different ways on the MapViewerForm but no success. I get an exception on "RenderTransform = value as Matrix2D;" in Renderer2D.cs of SharpMapv2. Please if someone could give me an example or how to initialize and add LabelLayer and LabelStyle to a map. I tried to find examples but all the examples and discussions contained Shaprmapv0.9 LabelLayer. Waiting for a reply. Thanks MHV
Coordinator
Jul 2, 2010 at 10:33 AM
Edited Jul 2, 2010 at 10:33 AM

Hello mhv5362,

you probably did everything right adding the LabelLayer, it is just that the coordinates for the label are not transformed to device coordinates. As a quick fix you need to change

Rectangle2D layoutRectangle = 
new Rectangle2D(label.Location, textSize);

of BasicLabelRenderer2D`1 's RenderLabel function (row 84) to

Rectangle2D layoutRectangle =
    new Rectangle2D(
            RenderTransform.TransformVector(label.Location.X, label.Location.Y),
  textSize);

You can define the datacolumn for the label like this:

 

LabelStyle ls = new LabelStyle();
ls.LabelExpression = new PropertyNameExpression(<name of the column>);

 

Hth FObemaier

Rectangle2D layoutRectangle =
new Rectangle2D(
RenderTransform.TransformVector(label.Location.X, label.Location.Y),
  textSize);
Jul 2, 2010 at 3:49 PM
Edited Jul 2, 2010 at 4:20 PM
Hey FObemaier, Thanks for the reply, but now I m getting all the road names with their points but it doesn't render anything on the screen. I have just changed the AddLayer() code and have attached it below. Do let me know if you think any changes should be made to this code. It gets all the details till the onpaint() method but nothing on the mapViewer. So do let me know as to where did I go wrong..... private void AddLayer() { using (ChooseDataSource choose = new ChooseDataSource()) { if (choose.ShowDialog() == DialogResult.OK) { IFeatureProvider prov = choose.Provider; string name = choose.ProviderName; workQueue.AddWorkItem( string.Format("Loading Datasource {0}", name), delegate { //GeometryLayer lyr = new GeometryLayer(name,prov); LabelLayer lblyr = new LabelLayer(name,prov); //lyr.Features.IsSpatiallyIndexed = false; lblyr.Features.IsSpatiallyIndexed = false; prov.Open(); InvokeIfRequired (new Action (delegate { if (Map.Layers.Count == 0) { //if (lyr.SpatialReference != null) // Map.SpatialReference = lyr.SpatialReference; if (lblyr.SpatialReference != null) Map.SpatialReference = lblyr.SpatialReference; } //Map.Layers.Insert(0, lyr); Map.Layers.Insert(0, lblyr); LabelStyle ls = new LabelStyle(); ls.LabelExpression = new PropertyNameExpression("name"); lblyr.Style = ls; //lyr.Style = RandomStyle.RandomGeometryStyle(); if (Map.Layers.Count == 1) { mapViewControl1.Map = Map; layersView1.Map = Map; MapView.ZoomToExtents(); } } ) ); }, EnableDisableCommandsRequiringLayers , delegate(Exception ex) { MessageBox.Show(string.Format("An error occured\n{0}\n{1}", ex.Message, ex.StackTrace)); }); } } } Waiting for your reply, MHV
Jul 2, 2010 at 4:01 PM
I apologize for how the reply looks... it doesn't take the format in which I replied...
Jul 2, 2010 at 4:21 PM
Edited Jul 2, 2010 at 4:22 PM
I apologize for how the reply looks... it doesn't take the format in which I replied...
Coordinator
Jul 2, 2010 at 7:28 PM

Hello mhv5362,

the LabelLayer just produces labels, no geometries. If you want to show the geometries as well, you need to add a GeometryLayer and a LabelLayer. I think each of them needs to have its own provider, but I'm not sure about that.

Hth FObermaier

Jul 2, 2010 at 7:41 PM
Edited Jul 2, 2010 at 7:45 PM
I tried adding both a labelLayer and a GeometryLayer at the same time but only the geometryLayer showed up. The labelLayer also added but nothing shows on the mapviewer. I am just trying to add names of the roads that are displayed. So my roads are displayed with the GeometryLayer but the LabelLayer which contains the names doesn't show up!! Is there any example of how to add a label layer?? MHV
Coordinator
Jul 3, 2010 at 12:41 AM
Edited Jul 3, 2010 at 12:54 AM

My AddLayer function looks like this:

 

        private void AddLayer()
        {
            using (ChooseDataSource choose = new ChooseDataSource())
            {
                if (choose.ShowDialog() == DialogResult.OK)
                {
                    IFeatureProvider prov = choose.Provider;
                    IFeatureProvider lprov = choose.Provider;
                    string name = choose.ProviderName;

                    workQueue.AddWorkItem(
                        string.Format("Loading Datasource {0}", name),
                        delegate
                            {
                                GeometryLayer lyr =
                                    new GeometryLayer(
                                        name,
                                        prov);
                                lyr.Features.IsSpatiallyIndexed = false;
                                prov.Open();

                                System.Data.DataTable dt = prov.GetSchemaTable();
                                LabelLayer llyr = new LabelLayer("Label " + name, lprov);
                                LabelStyle ls = (LabelStyle) llyr.Style;
                                ls.LabelExpression = new PropertyNameExpression(dt.Rows[0][0].ToString());
                                ls.HorizontalAlignment = HorizontalAlignment.Center;
                                ls.VerticalAlignment = VerticalAlignment.Middle;
                                lprov.Open();
                                InvokeIfRequired(new Action(delegate
                                                                {
                                                                    if (Map.Layers.Count == 0)
                                                                    {
                                                                        if (lyr.SpatialReference != null)
                                                                            Map.SpatialReference = lyr.SpatialReference;
                                                                    }

                                                                    Map.Layers.Insert(0, lyr);

                                                                    lyr.Style = RandomStyle.RandomGeometryStyle();
                                                                    //lyr.Style = setGeometryStyle(lyr);

                                                                    if (Map.Layers.Count == 1)
                                                                    {
                                                                        mapViewControl1.Map = Map;

                                                                        layersView1.Map = Map;
                                                                        MapView.ZoomToExtents();
                                                                    }
                                                                    Map.Layers.Insert(1, llyr);
                                                                }));
                            }, EnableDisableCommandsRequiringLayers
                        ,
                        delegate(Exception ex) { MessageBox.Show(string.Format("An error occured\n{0}\n{1}", ex.Message, ex.StackTrace)); });
                }
            }
        }

The main difference to your code is - I think - that the label layer has its own Provider (even though it is the same source).
The labels did not appear at once but after a Pan/Zoom operation they appeared.

Hth FObermaier

 

Coordinator
Jul 3, 2010 at 8:27 AM
Edited Jul 4, 2010 at 9:07 AM

Hi MHV, if I recall there is a bug where-by labels are scaled by the matrix used to render geometries. This probably means that your text is being scaled to the point it becomes invisible.

Try setting really huge text sizes to check.

hth jd

Jul 6, 2010 at 3:57 PM
Hey FObermaier and Johndiss, Thanks a lot for your quick replies but still as before the label layer is inserted but cannot see anything on the screen and as usual all the details are going till the onpaint method to render. There is one thing that I observed and that is the values of the bounds ro.Bounds= {X = -51356.0 Y = -8315.0 Width = 166.0 Height = 29.0} newbounds.location= {X = -51356.0 Y = -8344.0} I am not sure whether these values should be negative or positive AND IF they should be positive, how should I change it. The values of ro.Text, ro.Font, ro.Fill are proper.... FObermaier both my geometrylayer and labellayer have different providers now and john, I increased the size of the labeltext but still nothing on the screen. MHV
Jul 6, 2010 at 4:12 PM
Hey I just tried something now. I undid what FObermaier said in the first reply and changed to Rectangle2D layoutRectangle = new Rectangle2D(label.Location, textSize); in the BasicLabelRenderer2D`1.cs and got to see the labels on the screen but all the labels were on the top left corner and one upon the other. so now my question changes to how do I render the label layer properly coz if I change to Rectangle2D layoutRectangle = new Rectangle2D(RenderTransform.TransformVector(label.Location.X, label.Location.Y), textSize); my labellayer doesnt render. Waiting for your reply, MHV
Coordinator
Jul 6, 2010 at 4:42 PM

Hi MHV afaik you shouldnt need to modify that part of the code.. I havent had a chance to check though..

cheers jd

Jul 6, 2010 at 4:47 PM
Hi John, I feel the same but now the question remains as to why do all the labels show up at the same place and one upon the other. MHV
Coordinator
Jul 6, 2010 at 8:28 PM
Edited Jul 6, 2010 at 8:31 PM
Unless I've changed every copy of my SharpMap V2 sources (in the same manner) I uphold my suggestion to change BasicLabelRenderer2d`1. If I don't do that, I have real world coordinats in the OnPaint method for Labels. MHV could you please check with -just- the BCROADS.shp sample file in the TestData folder if that works. Other questions: * What kind of data source do you use? * Does it have a different projection than other layers added previously? * could you post sample file(s) As a side note: You don't need seperate providers for LabelLayer and GeometryLayer. cheers FObermaier
Jul 7, 2010 at 4:07 PM
Hey FObermaier, u were right. The BCRoads.shp file displays properly with your code. But I don't understand as to when I use other shape files, they do not render properly. And all the labels were rendering but at a different place which could not be seen on the map. So I think the projection would be different. But how is the projection different in the same shape file. Anyways the answer to your questions. 1. I have used all kinds of data sources but since the label layer only ShapeFile or MSSQLServer2008. 2. Yah it has a different projection but I m not sure how and how do I change the projection. Also how do I convert my shapefile to have all data in one projection. 3. I have taken screenshots but how do I add them here? Also for a reference I am using cloudmade shapefiles. Thanks for your help. MHV
Coordinator
Jul 7, 2010 at 5:00 PM

Hello mhv5362,

if you have different coordinate systems/projections in your data you can add this code

if (Map.SpatialReference != null && lyr.SpatialReference != null)
{
    if (!lyr.SpatialReference.EqualParams(Map.SpatialReference))
    {
        lyr.CoordinateTransformation = GeometryServices.CoordinateTransformationFactory.
            CreateFromCoordinateSystems(prov.SpatialReference, Map.SpatialReference);
        llyr.CoordinateTransformation = lyr.CoordinateTransformation;
    }
}

in the delegate defined in the AddLayer function. If you don't have very extraordinary coordinate systems it should work.

You could use "ogr2ogr" from the gdal/fwtools package to transform your shapefiles in the same spatial reference that your other data is in.

Hth FObermaier

Jul 7, 2010 at 6:31 PM
Hi FObermaier I added the above code as well reprojected my file but still the same problem occurs when I add the shapefile to MapViewer. There seems to be some problem with the label rendering code as to when I add the shapefile to MapWindow GIS, the output of the labels and Map is proper as expected without any changes made. I would like to show you the output of of the Rendered image but cannot add an image to the post. Anyways I got the shapefile from the following location: http://downloads.cloudmade.com/north_america/united_states/rhode_island/rhode_island.shapefiles.zip Do let me know as to how can I post the pic of my output. Thanks, MHV
Jul 7, 2010 at 8:50 PM
Hey FObermaier, I have uploaded the following two images on how the image is rendered Initial Image: http://img25.imagevenue.com/img.php?image=30478_InitialPic1_122_338lo.JPG After ZoomOut u will see a pink dot which is the GeometryLayer http://img188.imagevenue.com/img.php?image=30478_After_ZoomOutPic2_122_130lo.JPG The pics are not too clear but I m sure u wd get as to where did I go wrong..... Thanks MHV
Coordinator
Jul 7, 2010 at 11:37 PM

Hello mhv,

you were right, there was another bug in the BasicLabelRenderer2D which I just fixed. Please checkout latest source from sharpmapv2 repository.

Hth FObermaier

Jul 8, 2010 at 6:52 PM
Hey FObermaier, Thanks a lot. It is rendering fine now. MHV