This project is read-only.

Dynamically add labels with different fonts

Feb 18, 2011 at 12:24 AM

Hi,

I would like my user to be able to add labels to a map wherever they want and each one of them could have a particular font.

I think the best way to do it is to actually create a PointLayer with a transparent Point Symbol and use a Datarow in the FeatureSet that contains the label.

Right now my user can click on a map, and it creates a new point on it with the label "Point # X" ( In the future I will open a FontDialog and let the user decides the label and the font )

However I don't know how to apply a particular font to each label. They all have the same.

My code so far :

void CreateLabelLayer()
        {
            PointScheme MyPointScheme = new PointScheme();
            MyPointScheme.ClearCategories();
            MyPointScheme.AppearsInLegend = false;

            FeatureSet MyFeatureSet = new FeatureSet(FeatureType.Point);
            MyFeatureSet.Projection = KnownCoordinateSystems.Geographic.World.WGS1984;
            MyFeatureSet.DataTable.Columns.Add("label", typeof(string));

            //LabelPoints contains the list of points to be used for label coordinates
            for (int i = 0; i < LabelPoints.Count; i++)
            {
                IFeature MyFeature = MyFeatureSet.AddFeature(LabelPoints.ElementAt(i));
                MyFeature.DataRow["label"] = "Point #" + i;

                PointSymbolizer MyPointSymbolizer = new PointSymbolizer(Color.Transparent, DotSpatial.Symbology.PointShape.Rectangle, 4);
                MyPointSymbolizer.Smoothing = true;
                MyPointSymbolizer.IsVisible = true;

                PointCategory MyPointCategory = new PointCategory(MyPointSymbolizer);
                MyPointCategory.LegendItemVisible = false;
                MyPointCategory.FilterExpression = "[FID]=" + i;
                MyPointScheme.AddCategory(MyPointCategory);
            }
            IMapPointLayer MyMapPointLayer = new MapPointLayer(MyFeatureSet);
            MyMapPointLayer.Symbology = MyPointScheme;
            MyMapPointLayer.LegendText = "Label";
            MyMapPointLayer.ShowLabels = true;
            MapLabelLayer MyMapLabelLayer = new MapLabelLayer(MyMapPointLayer);
            //PB : cannot specify the font for each label
            MyMapLabelLayer.Symbology.Categories[0].Expression = "[label]";
            MyMapPointLayer.LabelLayer = MyMapLabelLayer;
            map1.Layers.Add(MyMapPointLayer); 
        }

I am thinking about convert the label with its font to an image and then use it as PointSymbol. Do you think this could be the solution here ?

I tried working with a LabelScheme But I could not find a way to make it work.

Thanks for any help you could get me !

Bruno

Feb 18, 2011 at 12:55 AM

Labels are like all the other symbolizer concepts.  They are set up with a Scheme that can have many categories.  So you create a separate category for each font that you want to use, and then you should be able to use the attributes of the associated point featureset in the filter expression for each category.  If you don't mind me asking... why are you creating so many separate point categories and symbolizers?  If all you want to do is make the points transparent, like you are doing, you simply set

MyMapPointLayer.Symbolizer = new PointSymbolizer(Color.Transparent, DotSpatial.Symbology.PointShape.Rectangle, 4);

Which in the end only creates a single category, so rendering should go much faster.  But, fortunately, you have successfully crated categories with the points, so you just need to create categories on the labels instead, but you only want one for each separate font you plan to use.  There are direct methods where you can create the categories and then manually update the DrawnStates array for the layer, but most of the time there are only a handful of categories and the application scenario is frequently easier with a filter expression.

 

Ted