Select to view content in your preferred language

Dissolve with arcpy.da.UpdateCursor

6478
19
Jump to solution
09-13-2015 03:50 PM
PeterShoemark
New Contributor II

Hi, can anyone give me some guidance as to how (or if it is possible) to use arcpy.da.updatecursor to loop through multiple polylines and dissolve them one by one ? (Im on Win7, arcgis 10.2.1, Python 2.7 and the data is in an Oracle 11g sde db)

The problem I have is numerous layers that I am trying to automate removal of self overlaps but that needs to occur by objectid not by layer and I also dont want to create another dataset from the one being updated so maybe need to start an edit session first??.

While Im not a wizard at this (or I may have been able to resolve it by now), I do understand enough to be able to adjust the code below to do some other maintenance functions.

        # The "if (row[1] or 0) == 0: " code: "row[1] or 0" will return either the

        # value of the outputField, or if that value is None (null), then it will return 0...

        inputField = "SEVENTH_ID"

        outputField = "ELEVENTH_ID"

        fc = "REGION_46"

        fields = [inputField, outputField]

        with arcpy.da.UpdateCursor(fc, fields) as cursor:

            for row in cursor:

                if (row[1] or 0) == 0:

                    row[1] = row[0]

                    cursor.updateRow(row)

        del cursor, row    

I think what I am trying to do would look something like;

        # Dissolve the self overlaps by row for REGION_46

        # If the current row has no self overlaps, move onto the next row

        inputField = "OBJECTID"

        fc = "REGION_46"

        fields = [inputField]

        with arcpy.da.UpdateCursor(fc, fields) as cursor:

            for row in cursor:

                if (row[0] has self overlaps, use "DISSOLVE" to eliminate them

                    cursor.updateRow(row) then move onto the next row

        del cursor, row    

Anyone successfully acjieved this previously or can give me some useful guidance?

(Noting I have read the help menu and other resources numerous times and not been successful)

Cheers, Peter

0 Kudos
19 Replies
NeilAyres
MVP Alum

Well Joshua has effectively given you the answer.

Why not implement something like this :

with arcpy.da.UpdateCursor(fc, ["SHAPE@"]) as Cur:
    for row in Cur:
        origGeom = row[0]
        row[0] = origGeom.union(origGeom)
        Cur.updateRow(row)
PeterShoemark
New Contributor II

Thanks for the response Neil. Unfortunately I still dont have a clear handle on the process.

My code has fc set and returns the fc value to the screen with 'print'.

My fc has values in it including polylines whihc self overlap by way of returning back on themselves.

If I add the code above I get an error mesaage in my log which says;

'NoneType' object has no attribute 'union'

In my limited experience I have received that message in other situations but due to there being no value. Have I misinterperated this? Cheers, Peter

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Your error message indicates that the cursor is returning a None object for a shape, which happens when there is a NULL record or empty geometry in the feature class.  To avoid the error, just check a geometry object exists before trying to union it.

with arcpy.da.UpdateCursor(fc, ["SHAPE@"]) as cur: 
    for shape, in cur:
        if shape:
            shape = shape.union(shape)
            cur.updateRow(shape)
0 Kudos
PeterShoemark
New Contributor II

Joshua Bixby​ Thanks again Joshua. I tried the code above but received an error message " 'list' object has no attribute 'union' ". (There is also a small typo (a comma) but I saw that and removed it)

I took your comments on board and re-ran your code from the day before after manually removing the NULLs from my fc and that code then ran successfully and resolved the overlaps very nicely.

However, while I do have code that would loop through the fc and remove NULLs, there is other data in fileds that I need to keep and above all else i am trying not to create new data sets for a bunch of business reasons.

Apologies in advance for what may then be a beginners question, but should I be concatenating the 2 lots of code together or is one intended to replace the other?

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

The "extra" comma in my code wasn't extra, it was purposeful to allow for list/sequence unpacking.  Removing the comma changed the shape variable from a geometry object to a list, hence the error message.  Try re-running the code as is and see if it works for you.

0 Kudos
BruceHarold
Esri Regular Contributor

Does the Repair Geometry geoprocessing tool not do the job for you?

The Data Interoperability extension can also repair geometries in place and has fine grained control over handling various issues.

Regards

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Check/Repair Geometry won't do anything for most of these cases, at least the examples provided, since they are valid geometries.  A line that folds back onto itself isn't simple but it is valid, unless you are using SQL Server where Microsoft is the oddball with how they deal with these types of cases.

A quick example using the Check Geometry tool:

>>> SR = arcpy.SpatialReference(26915)
>>> ln = arcpy.FromWKT('LINESTRING(575000 5250000, 576000 5250000, 575500 5250000)')
>>> arcpy.CheckGeometry_management(ln, 'in_memory/ln_chk')
<Result 'in_memory\\ln_chk'>
>>> arcpy.GetCount_management("ln_chk")
<Result '0'>

0 Kudos
PeterShoemark
New Contributor II

If I leave the comma in, I  get this error message; "argument must be sequence of values"

If I leave it out I get this error message; "'list' object has no attribute 'union'"

If I remove the nulls with a sledge hammer appraoch (my effort below), your previous code (row[0] = origGeom.union(origGeom) ) works successfully.

My effort works on calculating shape.len into a new field and running a delete where len < 1 (in reality 20 is generally my shortist length)

        rows = arcpy.UpdateCursor(fc1)

        for row in rows:

            if row.LINE_LENGTH < 5:

                rows.deleteRow(row)

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Try this:

with arcpy.da.UpdateCursor(fc, ["SHAPE@"]) as cur: 
    for shape, in cur: 
        if shape: 
            shape = shape.union(shape) 
            cur.updateRow([shape])

The error you get is likely from Line #5 or my earlier code.  What is odd is that my earlier code worked when I tested on a feature class earlier today, but it generated the same error when I tried it tonight.  I must have tinkered enough to change something.  The code above here should work and not require removing NULLs or empty geometries.

PeterShoemark
New Contributor II

Exactly what I needed Joshua Bixby​. Thanks for your assistance. That code with some automated topology code I have written let me cycle through 20,000 records and validate them in very quick fashion. It was a winner.

0 Kudos