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))
  • 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 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 at 15:33
  • I gave you an answer that should do what you want – umbe1987 Jul 18 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 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 at 15:57
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])
  • 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 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 at 13:27
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))
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
  • Thanks, almost there but it would not keep the parentheses in the middle – Giacomo Jul 18 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 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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