populate x,y

4839
17
Jump to solution
07-29-2015 02:30 PM
PacoAlverez
New Contributor III

I am trying to populate ever point's x,y when a point is created by a mouse click or clicking. Some times i might only create one point but sometimes i may have to create more then one. I am having trouble populating the x,y of the new created points.

this is currently what i have. I know it's wrong. i would like to see how to do this correctly.

getting error at

Traceback (most recent call last):

  File "C:\GIS\Python\AddPoint\AddPoint_4.py", line 18, in <module>

    geom = prow.SHAP

AttributeError: 'tuple' object has no attribute 'SHAPE'

Failed to execute (Script).

#import modules  
import arcpy  

arcpy.env.qualifiedFieldNames = False
pointFC = "Animal Sightings" #target point feature class Animal Sightings

mxd = arcpy.mapping.MapDocument("CURRENT")  
df = arcpy.mapping.ListDataFrames(mxd)[0]  
dfsr = df.spatialReference  
fcsr = arcpy.Describe(pointFC).spatialReference  
if dfsr.name == fcsr.name:  
    """Now do your work"""  

point = arcpy.GetParameterAsText(0)  #click

for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'):        
        x,y = prow[0]
        geom = prow.SHAPE
        prow.x = geom.X
        prow.y = geom.Y
del prow          

insCursor = arcpy.da.InsertCursor(pointFC,('POINT_X','POINT_Y','SHAPE@XY')) # create insert cursor  

with arcpy.da.SearchCursor(point,('POINT_X','POINT_Y','SHAPE@XY')) as cursor: # loop through feature set  
    for row in cursor:
        POINT_X = row[0]    
        POINT_Y = row[1]
        insCursor.insertRow(row) # insert row  

del insCursor # delete insert cursor          
0 Kudos
1 Solution

Accepted Solutions
DarrenWiens2
MVP Honored Contributor

I think you're overthinking this. The following works for me:

import arcpy

point = arcpy.GetParameterAsText(0)

pointFC = r'C:/junk/points.shp'

insCursor = arcpy.da.InsertCursor(pointFC,['POINT_X','POINT_Y','SHAPE@XY'])

with arcpy.da.SearchCursor(point,['POINT_X','POINT_Y','SHAPE@XY']) as cursor:
    for row in cursor:
        insCursor.insertRow([row[2][0],row[2][1],row[2]])

del insCursor

A happy coincidence: the units recorded in the final "POINT_X" and "POINT_Y" fields will be in the units of "pointFC", regardless of the data frame's coordinate system.

View solution in original post

17 Replies
DarrenWiens2
MVP Honored Contributor

I think you're overthinking this. The following works for me:

import arcpy

point = arcpy.GetParameterAsText(0)

pointFC = r'C:/junk/points.shp'

insCursor = arcpy.da.InsertCursor(pointFC,['POINT_X','POINT_Y','SHAPE@XY'])

with arcpy.da.SearchCursor(point,['POINT_X','POINT_Y','SHAPE@XY']) as cursor:
    for row in cursor:
        insCursor.insertRow([row[2][0],row[2][1],row[2]])

del insCursor

A happy coincidence: the units recorded in the final "POINT_X" and "POINT_Y" fields will be in the units of "pointFC", regardless of the data frame's coordinate system.

PacoAlverez
New Contributor III

Darren you were right, i see now.

0 Kudos
PacoAlverez
New Contributor III

Darren can you explain the inserRow([row[2][0],row[2][1],row[2]]).

I am trying to figure out what is going on here, [row[2][0],row[2][1],row[2]] and if you don't mind can you give an example if there were more fields please.

Thanks.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

The ArcPy Data Access Search Cursor documentation states the search cursors next() method "returns the next row as a tuple."  Furthermore, the SHAPE@XY token returns a "tuple of the feature's centroid x,y coordinates," which for a point is the point itself.  (Note, this isn't necessarily the case with a Multipoint).  When a user returns the SHAPE@XY token in a search cursor, like here, there will be a tuple within a tuple.

Tuples are a built-in Python data type and one of seven sequence types (Sequence Types — str, unicode, list, tuple, bytearray, buffer, xrange); as such, tuples support indexing, slicing, sequence packing, and more.  Darren Wiens'​ code is accessing the values in the nested or inner tuple by nesting or chaining multiple indexes.  With your code, row[2] is retrieving the third element of the tuple returned by the search cursor, which happens to be the tuple containing x,y coordinates.  row[2][0] is the first element of that SHAPE@XY tuple, the x coordinate, and row[2][1] is the second element of that tuple, the y coordinate.

Since tuples are sequences, you could also use sequence unpacking if you think it would make the code more readable.  For example, lines 09-11 could be replaced with:

with arcpy.da.SearchCursor(point,['POINT_X','POINT_Y','SHAPE@XY']) as cursor:  
   for pt_x, pt_y, xy in cursor:  
       insCursor.insertRow([xy[0], xy[1], xy]) 

Now that I write it, something seems off, but I think it may be redundant information.  That is,  'POINT_X' and 'POINT_Y' are being retrieved in the search cursor but not being used.  Anyhow, my point was to point out sequence unpacking and not what the code is doing or not doing (double pun not intended).

PacoAlverez
New Contributor III

thanks Joshua so if there were more fields then just the x,y what would be the syntax ?

([row[2][0],row[2][1],row[2]],[row[3][0],row[3]])?

0 Kudos
DarrenWiens2
MVP Honored Contributor

If you list 3 fields when you create the insert cursor, then you need to fill it with 3 appropriate things when you insert a row. If you list 100 fields when you create the insert cursor, then you need to fill it with 100 appropriate things when you insert a row.

0 Kudos
PacoAlverez
New Contributor III

so if i had two more fields would this be correct?

insCursor = arcpy.da.InsertCursor(pointFC, ['Minrights', 'FCVTotal','POINT_X','POINT_Y','SHAPE@XY']) # create insert cursor  


    with arcpy.da.SearchCursor(point,['Minrights', 'FCVTotal','POINT_X','POINT_Y','SHAPE@XY']) as cursor: # loop through feature set  
        for row in cursor:
            row.Minrights = row[0]      
            row.FCVTotal = row[1]
            row.POINT_X = row[2]
            row.POINT_Y = row[3]
            insCursor.insertRow(row) 
0 Kudos
DarrenWiens2
MVP Honored Contributor

I'm not sure exactly what you're trying to do inside the search cursor, but 'row' (from the search cursor) is already the 5-part list that will populate your insert cursor. Because you've set up the insert cursor fields and search cursor fields exactly the same, you can slide the 'row' from the search cursor right into the insert cursor.

Doesn't this work?

insCursor = arcpy.da.InsertCursor(pointFC, ['Minrights', 'FCVTotal','POINT_X','POINT_Y','SHAPE@XY']) # create insert cursor    

with arcpy.da.SearchCursor(point,['Minrights', 'FCVTotal','POINT_X','POINT_Y','SHAPE@XY']) as cursor: # loop through feature set    
    for row in cursor: 
        insCursor.insertRow(row) 
0 Kudos
PacoAlverez
New Contributor III

no it does not work, i does create a point but nothing is populated not Point_X or Point_y and i don't get an error. I had this in the beginning but it wasn't working so i thought of listing the row = [0], row = [1]under the arcpy.da.SearchCursor()

0 Kudos