MapInfo Pro

 View Only

MapInfo Monday: Offset Labels to the left and right

  • 1.  MapInfo Monday: Offset Labels to the left and right

    Employee
    Posted yesterday

    Sometimes labels can look a bit cluttered if they are shown in the middle of the map, next to the points you are labelling.

    A better result is often achieved by moving the labels to the left or right so they don’t overlap the center of the map. Something like the map below.
    image
    Now how can you create such a map with as little manual work as possible?
    You can do this with a small SQL Select script, but you need to set the values manually.

    The Basis for the Script

    The first step is to add a few additional columns to the table you want to label: 
    • LABEL_LONG: Holds the longitude of the label position
    • LABEL_LAT: Holds the latitude of the label position
    • LABEL_POS: Holds the directions the label is moved. Here we move them East or West, but you can also move them North or South. It's used for grouping the resulting queries so that the label position can be set depending on their position.
    Below you can see the three columns added and filled with some values.
    image
    When you need to fill these columns with values, the coordinates used should be using the projection of the table. My table is Longitude/Latitude WGS84.
    When determining suitable label positions, it can be helpful to add one or two Grid Layers to the map so you can easily identify appropriate coordinates. 
    I have added two Grid Layers: One with 0.5 degrees between the lines. The thick lines. And one with just 0.1 degrees between the lines. The thin lines. Now it's easier to determine the coordinates for the label positions.
    image
    As we are moving the labels to the east and to the west, you can start to determine the longitude values for these. I recommend using a longitude value just to the left of the data points for labels placed to the west, and a longitude value just to the right of the data points for labels placed to the east.  I'll be using -2.95 and -4.10 for my data here.
    Next you need to determine which points you would like to move to the east and which points you would like to move to the west. Assign the value E and W to these values in the column LABEL_POS and the values from above in the LABEL_LONG column.
    Now you have to assign values to the LABEL_LAT column. Here you need to determine how close the labels can be placed, how many labels there are on each side, and the total span of the latitude range. This may need a bit of trial and error to get it right. I ended up with a distance of 0.05 degrees between the label points.
    This is the final values for my points. As you can see the LABEL_LONG values are identical for the same LABEL_POS. They could differ but I chose to use the same values. The values in the LABEL_LAT change by 0.05 degrees for each point.
    These values depend on the scale of you map as well as the number of points.
    image

    The Script

    The base idea of the script is to create one point table and one line table for each value in the column LABEL_POS. In my script, I'm just searching for the values E and W. The script can be extended to use other values too.
    image

    Sometimes labels can look a bit cluttered if they are shown in the middle of the map, next to the points you are labelling.

    A better result is often achieved by moving the labels to the left or right so they don’t overlap the center of the map. Something like the map below.
    image
    Now how can you create such a map with as little manual work as possible?
    You can do this with a small SQL Select script, but you need to set the values manually.

    The Basis for the Script

    The first step is to add a few additional columns to the table you want to label: 
    • LABEL_LONG: Holds the longitude of the label position
    • LABEL_LAT: Holds the latitude of the label position
    • LABEL_POS: Holds the directions the label is moved. Here we move them East or West, but you can also move them North or South. It's used for grouping the resulting queries so that the label position can be set depending on their position.
    Below you can see the three columns added and filled with some values.
    image
    When you need to fill these columns with values, the coordinates used should be using the projection of the table. My table is Longitude/Latitude WGS84.
    When determining suitable label positions, it can be helpful to add one or two Grid Layers to the map so you can easily identify appropriate coordinates. 
    I have added two Grid Layers: One with 0.5 degrees between the lines. The thick lines. And one with just 0.1 degrees between the lines. The thin lines. Now it's easier to determine the coordinates for the label positions.
    image
    As we are moving the lables to the east and to the west, you can start to determine the longitude values for these. I recommend using a longitude value just to the left of the data points for labels placed to the west, and a longitude value just to the right of the data points for labels placed to the east.  I'll be using -9.95 and -4.10 for my data here.
    Next you need to determine which points you would like to move to the east and which points you would like to move to the west. Assign the value E and W to these values in the column LABEL_POS and the values from above in the LABEL_LONG column.
    Now you have to assign values to the LABEL_LAT column. Here you need to determine how close the labels can be placed, how many labels there are on each side, and the total span of the latitude range. This may need a bit of trial and error to get it right. I ended up with a distance of 0.05 degrees between the label points.
    This is the final values for my points. As you can see the LABEL_LONG values are identical for the same LABEL_POS. They could differ but I chose to use the same values. The values in the LABEL_LAT change by 0.05 degrees for each point.
    These values depend on the scale of your map as well as the number of points.
    image

    The Script

    The base idea of the script is to create one point table and one line table for each value in the column LABEL_POS. In my script, I'm just searching for the values E and W. The script can be extended to use other values too.
    image
    Here is the script in textual form:
    Set CoordSys Table Hospitals
    Select h.TRADE_NAME, h.*
    , CreatePoint(h.LABEL_LONG, h.LABEL_LAT) object
    From Hospitals As "h"
    Into _lbl_pnts_all NoSelect
    
    Select * From _lbl_pnts_all
    Where LABEL_POS = "W"
    Into _lbl_pnts_w NoSelect
    Select * From _lbl_pnts_all
    Where LABEL_POS = "E"
    Into _lbl_pnts_e NoSelect
    
    Add Map Auto Layer _lbl_pnts_w, _lbl_pnts_e
    Set Map Layer _lbl_pnts_w Display Global 
       Global Symbol (32,16744448,12,"MapInfo Symbols",256,0)
    Set Map Layer  _lbl_pnts_e Display Global 
       Global Symbol (32,16744448,12,"MapInfo Symbols",256,0)
    
    Select h.*
    , CreateLine(CentroidX(h.obj), CentroidY(h.Obj), h.LABEL_LONG, h.LABEL_LAT) object
    From Hospitals As "h"
    Into _lbl_lns_all NoSelect
    
    Select * From _lbl_lns_all
    Where LABEL_POS = "W"
    Into _lbl_lns_w NoSelect
    
    Select * From _lbl_lns_all
    Where LABEL_POS = "E"
    Into _lbl_lns_e NoSelect
    
    Add Map Auto Layer _lbl_lns_w, _lbl_lns_e
    Set Map Layer _lbl_lns_w Display Global Global Line (1,2,16711680) 
    Set Map Layer _lbl_lns_e Display Global Global Line (1,2,16711680) 

    For each output table (points and lines), I first create one table for all label positions. After this, I query out the individual label positions. The script also adds the query tables to the map and applies a simple style override.

    Here you can see the label lines inserted into the map where you also can see the Grid Layers. The Label Point layer is also added but it is not shown.

    image
    You may have to run the script several times until the lines add up and show in the position you wanted them to without crossing each other too much.
    Now, you can turn on Auto Labels for the Label Point layers and use the Label Position to control how the labels are shown for the labels to the left and right.
    Hopefully, this gives you some inspiration for improving your labels.
    In an upcoming article, I'll investigate if the initial manual part of assigning coordinates to the two columns can be somewhat automated. Stay tuned!
    Here is the script in textual form:
    Set CoordSys Table Hospitals
    Select h.TRADE_NAME, h.*
    , CreatePoint(h.LABEL_LONG, h.LABEL_LAT) object
    From Hospitals As "h"
    Into _lbl_pnts_all NoSelect
    
    Select * From _lbl_pnts_all
    Where LABEL_POS = "W"
    Into _lbl_pnts_w NoSelect
    Select * From _lbl_pnts_all
    Where LABEL_POS = "E"
    Into _lbl_pnts_e NoSelect
    
    Add Map Auto Layer _lbl_pnts_w, _lbl_pnts_e
    Set Map Layer _lbl_pnts_w Display Global 
       Global Symbol (32,16744448,12,"MapInfo Symbols",256,0)
    Set Map Layer  _lbl_pnts_e Display Global 
       Global Symbol (32,16744448,12,"MapInfo Symbols",256,0)
    
    Select h.*
    , CreateLine(CentroidX(h.obj), CentroidY(h.Obj), h.LABEL_LONG, h.LABEL_LAT) object
    From Hospitals As "h"
    Into _lbl_lns_all NoSelect
    
    Select * From _lbl_lns_all
    Where LABEL_POS = "W"
    Into _lbl_lns_w NoSelect
    
    Select * From _lbl_lns_all
    Where LABEL_POS = "E"
    Into _lbl_lns_e NoSelect
    
    Add Map Auto Layer _lbl_lns_w, _lbl_lns_e
    Set Map Layer _lbl_lns_w Display Global Global Line (1,2,16711680) 
    Set Map Layer _lbl_lns_e Display Global Global Line (1,2,16711680) 

    For each output table (points and lines), I first create one table for all label positions. After this, I query out the individual label positions. The script also adds the query tables to the map and applies a simple style override.

    Here you can see the label lines inserted into the map where you also can see the Grid Layers. The Label Point layer is also added but it is not shown.

    image
    You may have to run the script several times until the lines add up and show in the position you wanted them to without crossing each other too much.
    Now, you can turn on Auto Labels for the Label Point layers and use the Label Position to control how the labels are shown for the labels to the left and right.
    Hopefully, this gives you some inspiration for improving your labels.
    In an upcoming article, I'll investigate if the initial manual part of assigning coordinates to the two columns can be somewhat automated. Stay tuned!


    -------------------------------------------


    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------