[GIS] Searching for changes of 2 layers based on geometry, Arcgis for desktop (ArcEditor

arcgis-desktoparcpycomparisongeometrylayers

I´m trying to make a tool that would be able to compare 2 layers of any type (polygon, point, polyline) and find differences between them. Lets say i have a layer of roads (Polyline) from 2005 (layer X) and from 2015 (layer Y). This tool would check those layers and mark the roads missing in layer X (field Change = 1), roads missing in layer Y (field Change = -1) and the roads without change (field Change = 0). Note that matching objects between those layers by IDs might be uncorrect, I decided to make their own unique key.

So far I have a field named Geo_IDx and y (for both layers), that holds geometry token "SHAPE@JSON", created by arcpy.UpdateCursor:

    cursor2 = arcpy.da.UpdateCursor(Input2, [fieldnames2[0], "SHAPE@JSON", "Geo_IDx"])

Here comes the first issue: the string saved in "Geo_IDx" field is very long (currently set for 5000 signs, because I don't want to lose part of the geometry information).

  • Do you have any advice about how to make some better unique key for the comparison?

Another problem is that this comparison takes very long time for layers with big amount of objects stored in them.

Then I Merge the layers to have all those values in 1 layer, that holds the field "Change". After this I am comparing the "Geo_ID" fields from both layers, provided that if value from layer X matches with any value in layer Y, there was no change in that object. If the value is missing in either of those layers, something has changed, so by cursors I find in which layer the value is missing and update the Change value as mentioned above.

Following script shows the way I´m trying to update the "Change" field. geo1 and geo2 are lists of all values from Geo_IDx => geo1 and Geo_IDy => geo2.

    cursor3 = arcpy.da.UpdateCursor(Output,[f_names_merge[0], "Geo_IDx", "Geo_IDy", "Change"])
    for row in cursor3:
        if row[0]:
            if row[1] in geo2:
                row[3] = -1
            elif row[2] in geo1:
                row[3] = 1
            else:
                row[3] = 0
            cursor3.updateRow(row)

What I think the script is failing on is comparing the geometry strings, that are saved in Geo_ID fields. I dont have any idea why.

Questions:

  • Do you have any better idea of unique key for every object?
  • Is there any easier way to do this? (provided I´m using ArcEditor license).
  • Is it possible to compare the values of "SHAPE@JSON"?

I do not have access to FME.

Best Answer

If I understand your code right, you are using a JSON representation of your geometry to compare old and new geometry. If python can't match the string to your list of strings, it then adds a -1 to your change field.

I think using a json representation, or WKT or string, to compare geometry for changes might get tricky. What if the change was a reordering of the points where the start and end points flipped, but no actual change to the location of points? Probably a rare example, but this could cause problems.

Some none ArcPy (possible) solutions:

Use Topology. You have an ArcEditor license so it should be available to you. You can probably use the Must Be Covered By Feature Class Of rule to find pairs of lines that are different. http://resources.arcgis.com/en/help/main/10.2/index.html#//0017000000nn000000 http://resources.arcgis.com/en/help/main/10.2/index.html#//01mm0000000m000000

Use Select By Location, ARE_IDENTICAL_TO to detect lines that are not identical. Then populate your field for selected features. This may be a slow option, however.

http://resources.arcgis.com/en/help/main/10.2/index.html#//001700000072000000

ArcPy Solutions:

I think to really detect change you would need to get to the geometry. Once you get the geometry object you can use Equals() to compare two geometries. Use the select by location tool to limit which geometry you are going to compare (you don't want to loop through every feature to compare one road).

http://resources.arcgis.com/en/help/main/10.2/index.html#//001700000072000000

Here is the equals method: http://resources.arcgis.com/en/help/main/10.2/index.html#/Point/018z0000006t000000/

I also found some suggestions here (note the problems with version 10.0) that use the JSON representation if you prefer to use that:

How can one compare two geometries in arcpy successfully?

Related Question