8

I am using ArcPy to export PDFs from my ArcGIS Server application. I want to move a TextElement in my layout view to the centroid of a selected feature. I can get the centroid of the feature, but that's in my projected coordinate system (PCS). I need to convert that point into inches in my layout view.

elements = arcpy.mapping.ListLayoutElements(mapDoc, "TEXT_ELEMENT")
    for elem in elements:
        if elem.name == "SiteText":
            elem.elementPositionX = center.X
            elem.elementPositionY = center.Y

center.X and center.Y are in a projected coordinate system (PCS), not inches. I know it can be done with ArcObjects, as I've done it in desktop addins using C#. I need to do it from ArcPy and I don't see how. Any ideas?

1 Answer 1

10

You can use the data frame extent to scale the projected coordinates to map coordinates. I believe this should work well for rectangular coordinate systems. The returned map coordinates can be used to update your text element positions

def proj2map(data_frame,proj_x,proj_y):
    """Convert projected coordinates to map coordinates"""
    # This code relies on the data_frame specified having
    # its anchor point at lower left

    #get the data frame dimensions in map units
    df_map_w = data_frame.elementWidth
    df_map_h = data_frame.elementHeight
    df_map_x = data_frame.elementPositionX
    df_map_y = data_frame.elementPositionY

    #get the data frame projected coordinates
    df_min_x = data_frame.extent.XMin
    df_min_y = data_frame.extent.YMin
    df_max_x = data_frame.extent.XMax
    df_max_y = data_frame.extent.YMax
    df_proj_w = data_frame.extent.width
    df_proj_h = data_frame.extent.height

    #ensure the coordinates are in the dataframe
    if proj_x < df_min_x or proj_x > df_max_x:
        raise ValueError ('X coordinate is not within the data frame: %.1f - (%.1f, %.1f)' % (proj_x,df_min_x,df_max_x))

    if proj_y < df_min_y or proj_y > df_max_y:
        raise ValueError ('Y coordinate is not within the data frame: %.1f - (%.1f, %.1f)' % (proj_y,df_min_y,df_max_y))

    #scale the projected coordinates to map units from the lower left of the data frame
    map_x = (proj_x - df_min_x) / df_proj_w * df_map_w + df_map_x
    map_y = (proj_y - df_min_y) / df_proj_h * df_map_h + df_map_y

    return map_x,map_y
6
  • How does one know which units the page is in? This seems to assume that you are using inches for map units. What if you want to use metric and the projection is in imperial? Commented Jun 18, 2018 at 17:48
  • The dataframe has a property called mapUnits
    – tharen
    Commented Jun 18, 2018 at 17:52
  • I was trying to find where you could get a property like pageUnits. The dataFrame has its dimensions in page units. I understand that you set the page units in the MXD and cannot do that programmitally. I only need a read-only access anyways. Commented Jun 18, 2018 at 17:54
  • 1
    There is also a displayUnits property. You can get units for the spatial reference of the data frame and any layers you are working with. You'll have to work out the necessary conversion logic, but all the info you need should be there.
    – tharen
    Commented Jun 18, 2018 at 18:00
  • I'm looking at displayUnits and mapUnits in a debugger and both are 'Meters'. The units are clearly in inches. It is confusing. I think displayUnits means the units shown in the arcmap whereas the mapUnits is the units of the current projection for the dataframe. Commented Jun 18, 2018 at 18:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.