Rotate polygon label in ArcGIS Online

1474
5
Jump to solution
09-25-2018 11:24 AM
by Anonymous User
Not applicable

Is there a way to rotate a label in ArcGIS  using an Arcade expression?  By default the labels are horizontal, but I'd like them to be parallel with the polygons.

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

When I use the Basic Polygon labeling in ArcGIS Pro it will rotate the label (if it doesn't fit, so not always):

However, after publishing the map as a web map, the label rotation disappears:

If you label on the "center line" you will be able to obtain rotated labels, although some funky stuff is going on:

The rotation was based on the "center line" of the polygon. This was achieved by using first:

Minimum Bounding Geometry—Help | ArcGIS Desktop  (with the RECTANGLE_BY_AREA option) and then running a snippet of code to create the lines:

def main():
    import arcpy
    import os

    fc_in = r'C:\GeoNet\ParcelsMinArea\test.gdb\Parcels_MinBoundAreaRect'
    fc_out = r'C:\GeoNet\ParcelsMinArea\test.gdb\Parcels_MinBoundAreaRect_lines2'
    fld_lbl = 'ParcelID'

    # create output fc
    sr = arcpy.Describe(fc_in).spatialReference
    ws, fc_name = os.path.split(fc_out)
    arcpy.CreateFeatureclass_management(ws, fc_name, "POLYLINE", None, None, None, sr)
    arcpy.AddField_management(fc_out, fld_lbl, "TEXT", None, None, 20)

    with arcpy.da.InsertCursor(fc_out, ('SHAPE@', fld_lbl)) as curs_out:
        with arcpy.da.SearchCursor(fc_in, ('SHAPE@', fld_lbl)) as curs:
            for row in curs:
                polygon = row[0]
                parcelID = row[1]
                polyline = GetCenterLineFromRectangle(polygon)
                curs_out.insertRow((polyline, parcelID, ))


def GetCenterLineFromRectangle(polygon):
    lst_pnts = []
    for part in polygon:
        for pnt in part:
            lst_pnts.append(pnt)

    mid_pnts = []
    for i in range(len(lst_pnts)-1):
        pnt_i = lst_pnts[i]
        pnt_n = lst_pnts[i+1]
        mid_pnt = arcpy.Point((pnt_i.X + pnt_n.X)/2.0,(pnt_i.Y + pnt_n.Y)/2.0)
        mid_pnts.append(mid_pnt)

    sr = polygon.spatialReference
    line1 = arcpy.Polyline(arcpy.Array([mid_pnts[0], mid_pnts[2]]), sr)
    line2 = arcpy.Polyline(arcpy.Array([mid_pnts[1], mid_pnts[3]]), sr)

    if line1.length > line2.length:
        return line1
    else:
        return line2


if __name__ == '__main__':
    main()

Labeling is based on the lines, and a transparent color is used for the lines (using on the line alignment).

View solution in original post

5 Replies
XanderBakker
Esri Esteemed Contributor

If you look at the when creating labels for polygons, you will notice that there is no setting for rotation. The only labels that can be rotated are for lines and they will follow the orientation of the line. 

If it is really necessary to have rotated labels in you web map, the only way to achieve that is to create lines for each polygon with the proper orientation and label the lines while using a transparent color for the lines. 

AdrianWelsh
MVP Notable Contributor

What about instead of publishing a hosted feature layer, you publish a map service and have custom labels that way (maybe with a label rotation value)? Would that retain the label rotation to be displayed in AGOL?

Tutorial: Publishing a map service—Documentation | ArcGIS Enterprise 

0 Kudos
XanderBakker
Esri Esteemed Contributor

When I use the Basic Polygon labeling in ArcGIS Pro it will rotate the label (if it doesn't fit, so not always):

However, after publishing the map as a web map, the label rotation disappears:

If you label on the "center line" you will be able to obtain rotated labels, although some funky stuff is going on:

The rotation was based on the "center line" of the polygon. This was achieved by using first:

Minimum Bounding Geometry—Help | ArcGIS Desktop  (with the RECTANGLE_BY_AREA option) and then running a snippet of code to create the lines:

def main():
    import arcpy
    import os

    fc_in = r'C:\GeoNet\ParcelsMinArea\test.gdb\Parcels_MinBoundAreaRect'
    fc_out = r'C:\GeoNet\ParcelsMinArea\test.gdb\Parcels_MinBoundAreaRect_lines2'
    fld_lbl = 'ParcelID'

    # create output fc
    sr = arcpy.Describe(fc_in).spatialReference
    ws, fc_name = os.path.split(fc_out)
    arcpy.CreateFeatureclass_management(ws, fc_name, "POLYLINE", None, None, None, sr)
    arcpy.AddField_management(fc_out, fld_lbl, "TEXT", None, None, 20)

    with arcpy.da.InsertCursor(fc_out, ('SHAPE@', fld_lbl)) as curs_out:
        with arcpy.da.SearchCursor(fc_in, ('SHAPE@', fld_lbl)) as curs:
            for row in curs:
                polygon = row[0]
                parcelID = row[1]
                polyline = GetCenterLineFromRectangle(polygon)
                curs_out.insertRow((polyline, parcelID, ))


def GetCenterLineFromRectangle(polygon):
    lst_pnts = []
    for part in polygon:
        for pnt in part:
            lst_pnts.append(pnt)

    mid_pnts = []
    for i in range(len(lst_pnts)-1):
        pnt_i = lst_pnts[i]
        pnt_n = lst_pnts[i+1]
        mid_pnt = arcpy.Point((pnt_i.X + pnt_n.X)/2.0,(pnt_i.Y + pnt_n.Y)/2.0)
        mid_pnts.append(mid_pnt)

    sr = polygon.spatialReference
    line1 = arcpy.Polyline(arcpy.Array([mid_pnts[0], mid_pnts[2]]), sr)
    line2 = arcpy.Polyline(arcpy.Array([mid_pnts[1], mid_pnts[3]]), sr)

    if line1.length > line2.length:
        return line1
    else:
        return line2


if __name__ == '__main__':
    main()

Labeling is based on the lines, and a transparent color is used for the lines (using on the line alignment).

View solution in original post

AdrianWelsh
MVP Notable Contributor

Xander,

I understand what you are saying but I am wondering if publishing a map service to a server (enterprise) would answer the problem here, as opposed to publishing straight to ArcGIS Online. I do not have a server to test with but there is enhanced functionality with ArcGIS Enterprise publishing for labels versus AGOL.

https://enterprise.arcgis.com/en/server/10.3/publish-services/linux/supported-functionality-in-map-s...

The Standard Label Engine is available, as well as annotation. The Maplex Label Engine is available but is recommended for cached maps only. VBScript-based label expressions are not supported on ArcGIS for Server (Linux). JavaScript and Python-based label expressions are supported.

With this, I presume you would likely want to use a cached map, maybe.

0 Kudos
AdrianWelsh
MVP Notable Contributor

Hmmm, I guess I was looking at a linux-based article initially. Here is the link for the windows-based, 10.6 version (which has less info):

https://enterprise.arcgis.com/en/server/latest/publish-services/windows/supported-functionality-in-m...

The Standard Label Engine is available, as well as annotation. The Maplex Label Engine is available but is recommended for cached maps only.

This article may be relevant as well in regards to labeling in a map service:

Labels in map caches—Documentation | ArcGIS Enterprise