ThinkGeo.com    |     Documentation    |     Premium Support

Label Positioning











Hi Guys,


We would like to ensure that labels are not cut off at the edges of the map control; this was automatic in our previous product.  In other words we want to change the LabelPlacement to ensure the label is fully visible when the points are located towards the edges of the map control.


Does anyone have any thoughts about how to do this?


Regards


John




John,


We don’t support it in the 3.0 version for now. You can implement it yourself by overwriting the GetLabelingCandidateCore method; there you can change the label’s position yourself. Sure it’s not very easy that you need to calculate if part of the label is cut off at the edge and if yes, how to modify that label. If you are very clear about the requirements, it’s not that hard. Here is a simple demo just show you how to change the position of a label in that override method.

  public partial class LabelNiceLookingRoads : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                Map1.CurrentExtent = new RectangleShape(-97.766, 30.291, -97.755, 30.286);
                Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
                Map1.MapUnit = GeographyUnit.DecimalDegree;

                ShapeFileFeatureLayer austinStreetsShapeLayer = new ShapeFileFeatureLayer(Server.MapPath(@"~\SampleData\USA\Austin\austinstreets.shp"));
                austinStreetsShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.LocalRoad1;
                austinStreetsShapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
                austinStreetsShapeLayer.DrawingMarginPercentage = 10;

                ShapeFileFeatureLayer austinStreetsLabelLayer = new ShapeFileFeatureLayer(Server.MapPath(@"~\SampleData\USA\Austin\austinstreets.shp"));
                austinStreetsLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = new myTextStyle("FENAME", new GeoFont("Arial", 10), new GeoSolidBrush(GeoColor.StandardColors.Black));
                austinStreetsLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
                austinStreetsLabelLayer.DrawingMarginPercentage = 100;

                Map1.StaticOverlay.Layers.Add(austinStreetsShapeLayer);
                Map1.StaticOverlay.TileType = TileType.MultipleTile;
                Map1.DynamicOverlay.Layers.Add(austinStreetsLabelLayer);

            }
        }
    }

    class myTextStyle : TextStyle
    {
        public myTextStyle()
            : this("", new GeoFont(), new GeoSolidBrush())
        { }
        public myTextStyle(string textColumnName, GeoFont textFont, GeoSolidBrush textSolidBrush)
            : base(textColumnName, textFont, textSolidBrush)
        { }

        protected override Collection<LabelingCandidate> GetLabelingCandidateCore(Feature feature, GeoCanvas canvas)
        {
            Collection<LabelingCandidate>  candidates = base.GetLabelingCandidateCore(feature, canvas);
            foreach (LabelingCandidate candidate in candidates)
            {
                foreach (LabelInformation labelInformation in candidate.LabelInformation)
                {
                    labelInformation.PositionInScreenCoordinates.Y += 10;
                }
            }
            return candidates;
        }
    }


Thanks,


Ben



Hi Ben,


Spot on mate, just exactly what I was looking for, I was just looking in the wrong place!


Regards


John


 



Great it helps, let us know if you have any issues. 
  
 Ben











Hi Ben,


Back again, not quite there yet.


I'm very confused as to exactly what PositionInScreenCoordinates is and how it relates to the width and height of the winforms map control and the absolute position in pixels.  The PositionInScreenCoordinates also seems to change with the zoom factor even if the point remains in the same physical poition on the winforms control.


I have the map control on a form, its width is 668 pixels and its height is 400 pixels, one single point with a label.


If I pan the map and position the point at the extreme top left hand edge of the map control its PositionInScreenCoordinates is reported as X = 165, Y = 247, move it to the right hand top corner and we get X = 933 and Y = 165, move it to the bottom right hand corner and we get X = 933 and Y = 503.  This would seem to indicate that the width is 768 pixels and the height is 256 pixels.  I'm confused. I kind of thought that the position in screen coordinates would be for the top left hand corner X = 0 and Y = 0 and for the left hand top corner x = 668 and Y = 0 etc.


What I am trying to do is to make sure that the labels that are positioned PointPlacement.UpperRight are always visible, so if the point is located on the left hand edge of the screen and is visible the label is displayed to the right of the point and is thus always fully visible.


My logic here would be to get the length of the label as drawn in pixels subtract that from PositionInScreenCoordinates.X and if the value is negative i.e off the visible screen, move the printed position of the label by adding the label width to PositionInScreenCoordinates.X to shift the label to the right of the point.


It seems daft to have a point visible on the screen with the label positioned to the right and not or only partially visible.


Any thoughts?


John




Hi Ben,


Found the solutiuon.


John



That’s great, John.