Struggling to write a script that will convert coordinates in a .txt file into polygons (Using Python)

02-25-2021 12:47 PM
Labels (1)
New Contributor

Hello Everyone,

I'm a student in my first year of learning Python and am 100% stuck at the moment. I by accident created a scrip that converts shapefile coordinates into a .txt file; but I need to do the opposite..

Using as a guide

I am attempting to take a .txt document (displayed below) and turn the coordinates into Polgyons. This is an assignment, and I'm currently in my first year of coding; so I'm still trying to progressively learn. This course doesn't really provide any guidance, so everything I know I've learned from Esri; I just really need general guidance, I don't want someone to just give me the answers, I really need to learn this.

My current code and thoughts on what I need to do are below (EDIT: The error I'm now receiving 

Traceback (most recent call last):
File "<string>", line 67, in <module>
NameError: name 'coords' is not defined

# Import arcpy
import arcpy

# Specify the location of the file geodatabase containing the imported table using the environment class in arcpy
from arcpy import env
arcpy.env.workspace = "C:\Users\devot\Desktop\Justin_Rains_Module_7"
outworkspace = "C:\Users\devot\Desktop\Justin_Rains_Module_7\Module 7_Justin_Rains.gdb"


# Turn on overwriting of outputs using the environment class in arcpy
arcpy.env.overwriteOutput = True

# List feature classes in the specified workspace
fclist = arcpy.ListFeatureClasses()

# Define object that extracts the spatial reference information from the shapefile provided in the Module 7 data download
dataset = "C:\Users\devot\Desktop\Justin_Rains_Module_7\Property.shp"
spatial_ref = arcpy.Describe(dataset).spatialReference
print("Obtained spatial reference.")

#Create a polygon feature class in which the property parcel polygons will be later written (e.g. properties)
arcpy.CreateFeatureclass_management(outworkspace, "Properties", "POLYGON", "", "DISABLED", "DISABLED", spatial_ref)
print("Created new feature class to store property parcel polygons.")

# Define object for newly created polygon feature class
inTable = "C:\Users\devot\Desktop\Justin_Rains_Module_7\Module 7_Justin_Rains.gdb\module7table"

# Add field to table in which the property name will be later written
fieldName = "Name"
fieldLength = 25

arcpy.AddField_management(inTable, fieldName, "TEXT", fieldLength)
print("Added Name field to Properties FC.")

# Open, as read-only, the text file called 'Property_Module_7_Modified_No_Headers.txt'
infile = open("C:\Users\devot\Desktop\Justin_Rains_Module_7\Property_Module_7_Modified_No_Header (2).txt", mode="r")

# Define object that adds coordinate data from text file into a nested list. (hint: incorporate line.split() method.
array = arcpy.Array()
point = arcpy.Point()
for line in infile:
Segment = line.split(", ")

# Define object that employs an InsertCursor from arcpy that can modify the newly created polygon feature class.
cursor = arcpy.InsertCursor(inTable, [fieldName, "SHAPE@"])
print("Insert cursor set.")

# Define object that assigns the arcpy.Array() method so that all the coordinates of each polygon have a place to be
# stored, before the polygon is created in the feature class
polygon = arcpy.Polygon(array)
print("Polygon array set.")

# Initialize a variable for keeping track of a feature's ID
coords_list = [line.split() for line in infile]

ID = -1 # Define 'ID' object equal to -1

for coords in coords_list: # FOR loop applied to coords in nested list of coordinates
if ID == -1:
ID = coords_list[0] # associate ID object to track the ID value in the nested list of coordinates
# Add the point to the feature's array of points
# If the ID has changed, create a new feature
if ID != coords[0]:
array.add(arcpy.Point(coords[2], coords[3], ID=coords[0]))
ID = coords[0]
# Add the last feature
polygon = arcpy.Polygon(array, spatial_ref)# Define object that employs an InsertCursor from arcpy that can modify the newly created polygon feature class.

cursor = arcpy.InsertCursor(inTable, [fieldName, "SHAPE@"])



print("Input file closed.")

del cursor

print("Task complete.")


My .txt document read likes this 

1 Jones_Tract 424564.6207 4396443.553
1 Jones_Tract 425988.3089 4395630.017

0 Kudos
6 Replies
MVP Frequent Contributor

I don't know why you've set that workspace path, a textfile isn't a workspace (Folder, FGDB etc.), and the path itself is funky. I find raw string formatting handy:

arcpy.env.wokspace = r'C:\MyFiles\MyFGDB.gdb'

, although I guess it is personal preference, but note why are you setting this as an arcpy.env.workspace?

The listfeatureclasses() - why? you have a textfile you want to turn into a FC don't you? 

Yes - read the textfile and turn it into an array as formatted in the link you supplied.  Be aware of polygon geometries and how inner rings etc are created, final closing coordinates which repeat the starting coordinate must also be supplied to close the ring, clockwise and anticlockwise ring notations etc..)

I don't quite get the textfile format, is 1 Jones_Tract a single polygon, with each coordinate being supplied per line, if so, are they in the correct clockwise order, and/or are there any inner rings or complexity?

Does that format continue each for i.e.:

2 Jones_Tract .... X Y

2 Jones_Tract .... X Y

2 Jones_Tract .... X Y

2 Jones_Tract .... X Y

3 Jones_Tract .... X Y

3 Jones_Tract .... X Y


New Contributor

I believe I addressed some of your concerns in this updated code; my code is more or less done at this point, but I am running into this error which I for some reason can't resolve. 

0 Kudos
Esri Esteemed Contributor

Hi @JustinRains ,


Let me share some code from a couple of years ago when I created a tool to create polygons from a text file. Although the structure of the textfile I worked on is different from yours it should get you started.

# Name:
# Purpose:     covert TXT file with points to polygons
# Author:      xbakker
# Created:     10/04/2015

import arcpy
import os

def main():

    import sys
    import traceback

        arcpy.env.overwriteOutput = True

        # first parameter is txt file
        txt = arcpy.GetParameterAsText(0)

        # second parameter (provide default NAME)
        fld_name = arcpy.GetParameterAsText(1)

        # third parameter is output fc
        fc_out = arcpy.GetParameterAsText(2)

        # forth  parameter is spatial reference
        sr = arcpy.GetParameter(3)

        # create empty output fc
        ws_name, fc_name = os.path.split(fc_out)
        geomtype = "POLYGON"
        arcpy.CreateFeatureclass_management(ws_name, fc_name, geomtype, spatial_reference=sr)

        # add field
        arcpy.AddField_management(fc_out, fld_name, "TEXT", field_length=255)

        # start insert cursor
        flds = ("SHAPE@", fld_name)
        with arcpy.da.InsertCursor(fc_out, flds) as curs:

            # read input file
            cnt = 0
            name = ""
            first_point = None
            lst_pnt = []

            with open(txt, 'r') as f:
                for line in f.readlines():
                    cnt += 1
                    if cnt > 1:
                        line = line.replace('\n','')
                        lst_line = line.split('\t')
                        a = lst_line[0]
                        if a.isdigit():
                            # point
                            if bln_start:
                                first_point = GetPoint(line)
                                pnt = GetPoint(line)
                                pnt = GetPoint(line)
                            bln_start = False
                            # name or header
                            if a[:5].upper() == 'PUNTO':
                                if first_point != None:

                                if len(lst_pnt) > 2:
                                    # create previous polygon and write to fc
                                    polygon = arcpy.Polygon(arcpy.Array(lst_pnt), sr)
                                    curs.insertRow((polygon, name, ))
                                lst_pnt = []
                                name = line.strip()
                                bln_start = True
                                arcpy.AddMessage("Processing  polygon: '{0}'".format(name))

                if first_point != None:
                    polygon = arcpy.Polygon(arcpy.Array(lst_pnt), sr)
                    curs.insertRow((polygon, name, ))

        tb = sys.exc_info()[2]
        tbinfo = traceback.format_tb(tb)[0]
        pymsg = "Errores de Python:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
        msgs = "Errores de ArcPy:\n" + arcpy.GetMessages(2) + "\n"

def GetPoint(line):
    line = line.replace(',','.')
    lst_line = line.split('\t')
    x = float(lst_line[1])
    y = float(lst_line[2])
    return arcpy.Point(x, y)

if __name__ == '__main__':
New Contributor

Thanks so much for the reference. I went ahead and made some adjustments to my code and actually have it almost complete.

My final issue is that I'm running into this error based off the updated code 

Traceback (most recent call last):
File "<string>", line 67, in <module>
NameError: name 'coords' is not defined

0 Kudos
MVP Frequent Contributor

You've not formatted the code so I can't see the indentation, although I'd expect that coords is referenced outside the for loop - for coords in... :

0 Kudos
MVP Honored Contributor

Code formatting ... the Community Version - GeoNet, The Esri Community

so people can assess your indentation etc

... sort of retired...
0 Kudos