Select to view content in your preferred language

Update feature geometry?

52
4
Jump to solution
yesterday
AlfredBaldenweck
MVP Frequent Contributor

I have a script that is supposed to replace the geometry of a polygon with a new polygon constructed by reading some of its fields (minX, minY, maxX, maxY).

I can do this with traditional arcpy, but I'm running into issues when trying to do it with the arcgis module.

Specifically, I either get no edits to the geometry if I include a spatial reference OR I get a "read-only" error if I include the spatial reference. 

The documentation does not have any examples of actually updating geometry the way that you can update attributes. 

Does anyone have any pointers? Thanks

# Get inspectbl as arcgis Featureset
inspectFL = arcgis.features.FeatureLayer(inspectbl,
                                         gis=portal)

inspectFS = inspectFL.query(where=where_clause)
spatref = inspectFS.spatial_reference
for insp in inspectFS:
    # Convert arcgis.feature geometry into
    # arcpy Geometry.
    lowleft = [insp.attributes["mapminx"],
                          insp.attributes["mapminy"]]
    upleft = [insp.attributes["mapminx"],
                         insp.attributes["mapmaxy"]]
    upright = [insp.attributes["mapmaxx"],
                          insp.attributes["mapmaxy"]]
    lowright =[insp.attributes["mapmaxx"], insp.attributes["mapminy"]]
    corners = [lowleft, upleft, upright, lowright]

    geo = arcgis.geometry.Polygon(corners, spatial_reference=spatref)
    geo = arcgis.geometry.Geometry({"rings":corners,
                                    "spatial_reference": {"wkid":spatref}})

    insp.set_value(field_name="shape",
                   value= geo)

    inspectFL.edit_features(updates=inspectFS,
                        use_global_ids=True)
0 Kudos
1 Solution

Accepted Solutions
AlfredBaldenweck
MVP Frequent Contributor

Ok, so as it turns out, it was not an issue of the final point, although I've added that just in case.

The actual issue was that I was not nesting the coordinates deep enough.

The "rings" needs to be a list of lists of coordinate pairs, like:

[[[x1,y1], [x2,y2]]]

I had it as 

[[x1,y1, [x2, y2]] 

Final working is

# Get inspectbl as arcgis Featureset
inspectFL = arcgis.features.FeatureLayer(inspectbl,
                                         gis=portal)
inspectFS = inspectFL.query(where=where_clause)
spatref = inspectFS.spatial_reference
for insp in inspectFS:
    # Convert arcgis.feature geometry into
    # arcgis.geometry.Geometry.
    lowleft = [insp.attributes["mapminx"],
                          insp.attributes["mapminy"]]
    upleft = [insp.attributes["mapminx"],
                         insp.attributes["mapmaxy"]]
    upright = [insp.attributes["mapmaxx"],
                          insp.attributes["mapmaxy"]]
    lowright =[insp.attributes["mapmaxx"], insp.attributes["mapminy"]]
    corners = [[lowleft, upleft, upright, lowright, lowleft]]

    geo = arcgis.geometry.Geometry({"rings":corners,
                                    "spatial_reference":
                                        {"wkid":spatref}})

    insp.set_value(field_name="shape",
                   value= geo)
x = inspectFL.edit_features(updates=inspectFS,
                            use_global_ids=True)

 

Thanks everyone 

View solution in original post

4 Replies
DavidSolari
MVP Regular Contributor

Might be worth using the as_dict instance method and from_dict class method to create a new feature with matching attributes instead of editing the original object. Heavy handed but if it works, it works!

MobiusSnake
MVP Regular Contributor

I might be mistaken about this, but I don't think your polygons are valid.  I'm pretty sure the first point needs to be repeated as the last point to close it out, like this:

corners = [lowleft, upleft, upright, lowright, lowleft]

 

AlfredBaldenweck
MVP Frequent Contributor

That's an interesting thought and I'll check it out, but it works with only four points in normal arcpy

with arcpy.da.UpdateCursor(inspectbl,
                           ['SHAPE@', "mapminx", "mapminy",
                            "mapmaxx", "mapmaxy", "OID@"],
                           where_clause= where_clause) as cursor:
    for row in cursor:
        lowleft = arcpy.Point(row[1], row[2])
        upleft = arcpy.Point(row[1], row[4])
        upright = arcpy.Point(row[3], row[4])
        lowright = arcpy.Point(row[3], row[2])
        corners = arcpy.Array([lowleft, upleft, upright, lowright])
        row[0] = arcpy.Geometry("polygon", corners)
        cursor.updateRow(row)

 so I'm not certain that's it 

0 Kudos
AlfredBaldenweck
MVP Frequent Contributor

Ok, so as it turns out, it was not an issue of the final point, although I've added that just in case.

The actual issue was that I was not nesting the coordinates deep enough.

The "rings" needs to be a list of lists of coordinate pairs, like:

[[[x1,y1], [x2,y2]]]

I had it as 

[[x1,y1, [x2, y2]] 

Final working is

# Get inspectbl as arcgis Featureset
inspectFL = arcgis.features.FeatureLayer(inspectbl,
                                         gis=portal)
inspectFS = inspectFL.query(where=where_clause)
spatref = inspectFS.spatial_reference
for insp in inspectFS:
    # Convert arcgis.feature geometry into
    # arcgis.geometry.Geometry.
    lowleft = [insp.attributes["mapminx"],
                          insp.attributes["mapminy"]]
    upleft = [insp.attributes["mapminx"],
                         insp.attributes["mapmaxy"]]
    upright = [insp.attributes["mapmaxx"],
                          insp.attributes["mapmaxy"]]
    lowright =[insp.attributes["mapmaxx"], insp.attributes["mapminy"]]
    corners = [[lowleft, upleft, upright, lowright, lowleft]]

    geo = arcgis.geometry.Geometry({"rings":corners,
                                    "spatial_reference":
                                        {"wkid":spatref}})

    insp.set_value(field_name="shape",
                   value= geo)
x = inspectFL.edit_features(updates=inspectFS,
                            use_global_ids=True)

 

Thanks everyone