0

My code from Returning strings showing all vertices from all polygons in shapefile using ArcPy? creates is the following:

import arcpy

fc=r'D:\GIS Data\TOOLS\EV calc in Python\Data.gdb\PolyWGS842'

with arcpy.da.SearchCursor(fc,['OID@','SHAPE@']) as cursor:
    for row in cursor:
        myList = []
        array1=row[1].getPart()
        for vertice in range(row[1].pointCount):
            pnt=array1.getObject(0).getObject(vertice)
            #print row[0],pnt.X,pnt.Y
            myList.append(str(pnt.X) + " " + str(pnt.Y))

        a = "((" + ", ".join(myList) + "))"
        print a

Outputs this:

((150.523124571 -32.391945847, 150.904615846 -32.362024963, 151.129022478 -32.603885445, 150.784932308 -32.843252519, 150.525617978 -32.696141505, 150.523124571 -32.391945847))
((151.168916991 -32.843252519, 151.405790658 -33.040231674, 151.308547784 -33.214770166, 151.019312569 -33.125007513, 151.168916991 -32.843252519))
((150.568005897 -33.234717422, 150.894642218 -33.090099815, 150.919576288 -33.511485602, 150.570499304 -33.501511974, 150.568005897 -33.234717422))

But I would like to concatenate the strings with a come, like this:

((150.523124571 -32.391945847, 150.904615846 -32.362024963, 151.129022478 -32.603885445, 150.784932308 -32.843252519, 150.525617978 -32.696141505, 150.523124571 -32.391945847)), ((151.168916991 -32.843252519, 151.405790658 -33.040231674, 151.308547784 -33.214770166, 151.019312569 -33.125007513, 151.168916991 -32.843252519)), ((150.568005897 -33.234717422, 150.894642218 -33.090099815, 150.919576288 -33.511485602, 150.570499304 -33.501511974, 150.568005897 -33.234717422))
7
  • 1
    Is there a reason why you need to wrap the final result within double parentesis? Also, Are you ceoncerned that you are building a string and not a tuple (is this what you want)?
    – umbe1987
    Jul 18, 2019 at 15:24
  • 1
    Yes, I am trying to build a string that I will later need to pass to a SQL statement using pymssql. the double parenthesis is needed to specify the coordinates for a multipolygon, see example link
    – Giacomo
    Jul 18, 2019 at 15:33
  • I gave you an answer that should do what you want
    – umbe1987
    Jul 18, 2019 at 15:34
  • 1
    Keep in mind that multi-part polygons also exist. WKT for MULTIPOLYGON has a triple-paren, with comma-delimited double-paren for parts, in addition to single-paren nested sub-parts (holes). This approach is HIGHLY dependent on very simple polygons. A far more reliable approach would be to use the shape@WKT source designator.
    – Vince
    Jul 18, 2019 at 15:39
  • @Vince This is interesting, but wouldn't that give me the same result? I am passing: for row in arcpy.da.SearchCursor(fc, ["SHAPE@WKT"]): print row[0] And it gives me back: MULTIPOLYGON (((150.56800589700003 -33.23471742199996, 150.57049930400001 -33.501511973999982, 150.91957628800003 -33.511485601999937, 150.89464221800006 -33.090099814999974, 150.56800589700003 -33.23471742199996)))
    – Giacomo
    Jul 18, 2019 at 15:57

3 Answers 3

3

One possibility is to create another list which then contains your individual a variables. Finally, we then concatenate those outside the loop. Hence:

outer_list = []    
with arcpy.da.SearchCursor(fc,['OID@','SHAPE@']) as cursor:
    for row in cursor:
        myList = []
        array1=row[1].getPart()
        for vertice in range(row[1].pointCount):
            pnt=array1.getObject(0).getObject(vertice)
            myList.append(str(pnt.X) + " " + str(pnt.Y))

        a = "((" + ", ".join(myList) + "))"
        outer_list.append(a)
    print(", ".join(outer_list))
0
2

The main issue here is that you're trying to reinvent the wheel. ArcGIS already has a fully functional Well-Known Text generator built into the da.SearchCursor and Geometry objects. This generator handles both polygons with sub-parts (aka holes), and multi-polygons (potentially with sub-parts), so using the shape@WKT column tag removes the need for list concatenation:

with arcpy.da.SearchCursor(fc,['OID@','SHAPE@WKT']) as cursor:
    for row in cursor:
        print(row[1])
2
  • Thank you! You are right saying using shape@WKT is more correct otherwise I won't be able to deal with sub-parts. I have changed my code to: ` with arcpy.da.SearchCursor(fc,['OID@','SHAPE@WKT']) as cursor: myList = [] for row in cursor: myList.append(row[1][14:][:-1]) a = "MULTIPOLYGON (" + ", ".join(myList) + ")" print a`
    – Giacomo
    Jul 22, 2019 at 12:59
  • No, that's not right either. There is no need to make a one-element list and use join on it. If the result could be POLYGON or MULTIPOLYGON, erasing the first 14 characters is wrong.
    – Vince
    Jul 22, 2019 at 13:27
1

Just declare your variable a outside of the main loop and de-indent the final print like so (not tested):

import arcpy

fc=r'D:\GIS Data\TOOLS\EV calc in Python\Data.gdb\PolyWGS842'

with arcpy.da.SearchCursor(fc,['OID@','SHAPE@']) as cursor:
    a = "((" # ADD THIS
    for row in cursor:
        myList = []
        array1=row[1].getPart()
        for vertice in range(row[1].pointCount):
            pnt=array1.getObject(0).getObject(vertice)
            #print row[0],pnt.X,pnt.Y
            myList.append(str(pnt.X) + " " + str(pnt.Y))

        a += ", ".join(myList) # CHANGE THIS
    a += "))"
    print a # DE-INDENT OUT OF THE MAIN LOOP
2
  • Thanks, almost there but it would not keep the parentheses in the middle
    – Giacomo
    Jul 18, 2019 at 15:46
  • no worries, although in you question your aim was to only have parenthesis at the beginning and end. Anyways, glad you found a solution. Cheers.
    – umbe1987
    Jul 18, 2019 at 16:16

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.