Select to view content in your preferred language

Create point,spatial join and populate point attributes

4651
15
Jump to solution
07-16-2015 01:12 PM
CCWeedcontrol
Frequent Contributor

I am working on a add-on button that i would like to be able to click on a parcel and create a point where i click and i need the new populate with the Parcels attributes.

I currently have two scripts that work, one creates the point and the other does spatial join and populates the selected point with the tax parcels attributes but the point has to already be there and selected. I need to be able to combine the two scripts into one. I think my biggest problem is that i don't know how to select the point once it's created to be able to spatial join and update the point with the Parcels attributes. I would gratefully appreciate any help on combining these two.

My initial try was to use the sort to get the highest AddressID which was created in the first script (CC_list.sort()) and then was going to use selecLayerByLocation to select the parcel to do the spatial join with the point but nothing is selected.

for row in sorted(arcpy.da.SearchCursor(fc, ["OBJECTID", "AddressID"]),reverse=True):
    mostRecentOID=row[0]
    mostRecentAddressID=row[1]
    break
     #Select parcel within selected Address Points
     arcpy.SelectLayerByLocation_management(polygonLayer, "INTERSECT", pointGeom)

Create point script

import arcpy
from arcpy import env
import time
import datetime

# Allow overwrite 
arcpy.env.overwriteOutput = True

arcpy.env.qualifiedFieldNames = False
arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)"

# Script user input parameters
#pointLayer = "TEST.DBO.CCAPTEST"  #pointlayer
fc = "TEST" 

# Start an edit session. Must provide the workspace.    
edit = arcpy.da.Editor(arcpy.env.workspace)    

# Edit session is started without an undo/redo stack for versioned data    
#  (for second argument, use False for unversioned data)    
edit.startEditing(True)    

# Start an edit operation    
edit.startOperation()    

        
input = arcpy.GetParameterAsText(0)

rows = arcpy.SearchCursor(input)
for row in rows:
    geom = row.Shape
    X = geom.centroid.X
    Y = geom.centroid.Y
del rows

CC_list = []
with arcpy.da.SearchCursor(fc, ["AddressID"]) as cursor:
    for row in cursor:
        try:
            if "CC" in row[0]:
                CC_list.append(int(row[0].strip("CC")))   
        except TypeError:
            pass        
del cursor

CC_list.sort()
AddressID = CC_list[-1] + 1
AddressID = 'CC' + str(AddressID)

pointGeom = arcpy.PointGeometry(arcpy.Point(X, Y))
row_values = [(X, Y, (X, Y), AddressID)]

cursor = arcpy.da.InsertCursor(fc, ["POINT_X", "POINT_Y", "SHAPE@XY", "AddressID"])
for row in row_values:
    cursor.insertRow(row)
#del cursor

# Stop the edit operation.    
edit.stopOperation()
# Stop the edit session and save the changes
edit.stopEditing(True)

arcpy.RefreshActiveView()  

Spatial join Update point attributes script.

# Import arcpy module
import arcpy

# Allow overwrite 
arcpy.env.overwriteOutput = True

# Script user input parameters
polygonLayer = "Taxparcels" 
pointLayer = "TEST" #Point Layer
arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)" 
poly = "ACCOUNT_1"
Pnt =  "Account"
sjpoints = "In_memory\sjpoints" 

parcelsCount = int(arcpy.GetCount_management(pointLayer).getOutput(0))     
    
dsc = arcpy.Describe(pointLayer) 

selection_set = dsc.FIDSet         
if len(selection_set) == 0:       
    print "There are no features selected"  
             
elif parcelsCount >= 1: 

    #Run the Spatial Join tool, using the defaults for the join operation and join type
    arcpy.SpatialJoin_analysis(pointLayer, polygonLayer, sjpoints)

    # define the field list from the spatial join
    sourceFieldsList = ["TARGET_FID", poly,"ACCOUNT_1","SiteAddres_1",'SiteNum_1', 'SiteStreet_1','SiteNumSfx_1','Predir_1','SiteStreet_1', 'StreetType_1', 'Postdir_1', 'SiteCity_1', 'SiteZIP_1', 'OwnerName_1']    

    # define the field list to the original points
    updateFieldsList = ["OID@", Pnt,"Account","SiteAddres", 'SiteNum', 'StreetName', 'SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName']
    
    # Start an edit session. Must provide the workspace.    
    edit = arcpy.da.Editor(arcpy.env.workspace)    
  
    # Edit session is started without an undo/redo stack for versioned data    
    #  (for second argument, use False for unversioned data)    
    edit.startEditing(True)    
  
    # Start an edit operation    
    edit.startOperation()    
    manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE", "ACCOUNT", 'SiteStreet']
           
    with arcpy.da.UpdateCursor(pointLayer, manualFields) as rows:       
        for row in rows:       
            row[0] = ("Single Family Home")           
            row[1] = ("Primary, Private")           
            row[2] = ("Yes, GRM, TA")           
            row[3] = ("Active")           
            row[4] = ("Residential")           
            row[5] = ("1110")       
            rows.updateRow(row)  
        del row       
        del rows 
    # populate the dictionary from the polygon
    valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sjpoints, sourceFieldsList)}    

    with arcpy.da.UpdateCursor(pointLayer, updateFieldsList) as updateRows:    
        for updateRow in updateRows:    
            keyValue = updateRow[0]
            if keyValue in valueDict:    
                for n in range (1,len(sourceFieldsList)):      
                    updateRow = valueDict[keyValue][n-1]
                updateRows.updateRow(updateRow) 
    # Stop the edit operation.    
    edit.stopOperation()
    # Stop the edit session and save the changes
    edit.stopEditing(True)

arcpy.RefreshActiveView()
#arcpy.Delete_management(sjpoints)
0 Kudos
1 Solution

Accepted Solutions
WesMiller
Deactivated User

Try something like below.

#import modules
import arcpy
"""
tool box parameters
point param = feature set
targetpoint = featurelayer
parcel = featurelayer
"""
point = arcpy.GetParameterAsText(0)
targetpoint = arcpy.GetParameterAsText(1)
parcel = arcpy.GetParameterAsText(2)
parcel_lyr = 'parcel_lyr'


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


point1 = arcpy.Point(x, y)
ptGeometry = arcpy.PointGeometry(point1)


arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)


fldList = ['TMS','OWNERNAME']
fldDict ={}


if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):
        for x in range(len(fldList)):
            fldDict[fldList]=parrow
    del parrow
    fldAttList = []
    for x in range(len(fldList)):
        fldAttList.append(fldDict[fldList])
    manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat"]
    for fld in manualFields:
        fldList.append(fld)
    fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"]
    for att in fixedAtts:
        fldAttList.append(att)
    fldAttList.append(point1)
    fldtuple = (fldAttList)
    fldList.append( 'SHAPE@XY')
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)
    tprow.insertRow(fldtuple)
        
del tprow

View solution in original post

15 Replies
WesMiller
Deactivated User

I think my workflow would be:

Get XY from user (for model builder: a feature set, from an addin get the mousedown XY)

Then use the XY to select by location the parcel

Make feature layer from selected

Use a search cursor to read the needed fields into a dictionary

Then use an insertcursor on the point file to insert the row with the data from dictionary

0 Kudos
CCWeedcontrol
Frequent Contributor

Thank you for the reply. I am trying to implement your suggestions but i come up with a fail.

current code.

import arcpy
from arcpy import env

# Allow overwrite
arcpy.env.overwriteOutput = True

arcpy.env.qualifiedFieldNames = False
arcpy.env.workspace = r"Database Servers\DSD15_SQLEXPRESS.gds\TwoWay (VERSION:dbo.DEFAULT)"

# Script user input parameters
fc = "TEST"
polygonLayer = "parcels"
poly = "ACCOUNT"#
Pnt =  "Account"#

       
input = arcpy.GetParameterAsText(0)

rows = arcpy.SearchCursor(input)
for row in rows:
    geom = row.Shape
    X = geom.centroid.X
    Y = geom.centroid.Y
del rows


# Create point
inPoint = arcpy.PointGeometry(arcpy.Point(X,Y))

#Select parcel within selected Address Points 
arcpy.SelectLayerByLocation_management(polygonLayer, "INTERSECT", inPoint)
   
# Make a layer from the feature class
arcpy.MakeFeatureLayer_management(fc, "Par")

# define the field list from the parcels   
sourceFieldsList = ["ACCOUNT", poly,"SiteAddres",'SiteNum', 'SiteStreet','SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZIP', 'OwnerName']     

# populate the dictionary will all selected polygons 
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor("Par", sourceFieldsList)}     

# define the field list to the points 
updateFieldsList = ["Account", Pnt,"SiteAddres", 'SiteNum', 'SiteStreet', 'SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName'] 


arcpy.da.UpdateCursor(inPoint, updateFieldsList)     
for updateRow in updateRows:     
    keyValue = updateRow[0] 
    if keyValue in valueDict: 
        for n in range (1,len(sourceFieldsList)):       
            updateRow = valueDict[keyValue][n-1] 
        updateRows.updateRow(updateRow)
               
rowInserter = arcpy.da.InsertCursor(fc, updateFieldsList)
arcpy.da.UpdateCursor(fc, updateFieldsList)     
for row in rows:     
    row[0] = ("Single Family Home")         
    row[1] = ("Primary, Private")         
    row[2] = ("Yes, GRM, TA")         
    row[3] = ("Active")         
    row[4] = ("Residential")         
    row[5] = ("1110")     
    rows.updateRow(row)     
       
    rowInserter.insertRow(row)
arcpy.RefreshActiveView() 
0 Kudos
DanPatterson_Retired
MVP Emeritus

Lets be specific...since the code can't be tested because the data is not provided, could you at least provide the error message.  A 'fail' requires a reason and an error message should be given.  It could be as simple as a 'syntax error line xxxxx' but it is revealing.  And on that last note, a failure on a particular line sometimes mean the code failed a line or two up, so check for syntax errors or more specifically....logic errors

And on the ...logic note...

In lines 19- 23 you go to great lengths to cycle through a cursor getting X and Y coordinates, austensibly to use them in future work.  However, you do nothing with them.  In line 28 you DO create a point but it will only use the last X,Y pair that you had.  So is your intent to use the last point in the dataset? or is it to cycle through the points one at a time, and do something with them.  I will stop there until that issues is clarified.

WesMiller
Deactivated User

I set this code up to be used in a model and assumed the fields would be the same names and types it should help you get started.

#import modules
import arcpy
"""
tool box parameters
point param = feature set
targetpoint = featurelayer
parcel = featurelayer
"""
point = arcpy.GetParameterAsText(0)
targetpoint = arcpy.GetParameterAsText(1)
parcel = arcpy.GetParameterAsText(2)
parcel_lyr = 'parcel_lyr'


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


point1 = arcpy.Point(x, y)
ptGeometry = arcpy.PointGeometry(point1)


arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)


fldList = ['TMS','OWNERNAME']
fldDict ={}


if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):
        for x in range(len(fldList)):
            fldDict[fldList]=parrow
    del parrow
    fldAttList = []
    for x in range(len(fldList)):
        fldAttList.append(fldDict[fldList])
    fldAttList.append(point1)
    fldtuple = (fldAttList)
    fldList.append( 'SHAPE@XY')
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)
    tprow.insertRow(fldtuple)
        
del tprow


            








    




CCWeedcontrol
Frequent Contributor

Wes, that worked awesome for creating a point and updating the points attributes! but i am having trouble putting and uncertain on how to implementing the arcpy.da.update cursor into the point dictionary. I need to be able to add the manualFields into the point.

Thanks for you help Wes

manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE", "ACCOUNT", 'SiteStreet', 'SHAPE@X', 'SHAPE@Y']    
   
  
with arcpy.da.UpdateCursor(ptGeometry, manualFields) as rows:       
    for row in rows:       
        row[0] = ("Single Family Home")           
        row[1] = ("Primary, Private")           
        row[2] = ("Yes, GRM, TA")           
        row[3] = ("Active")           
        row[4] = ("Residential")           
        row[5] = ("1110")       
        rows.updateRow(row)  
0 Kudos
WesMiller
Deactivated User

Try something like below.

#import modules
import arcpy
"""
tool box parameters
point param = feature set
targetpoint = featurelayer
parcel = featurelayer
"""
point = arcpy.GetParameterAsText(0)
targetpoint = arcpy.GetParameterAsText(1)
parcel = arcpy.GetParameterAsText(2)
parcel_lyr = 'parcel_lyr'


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


point1 = arcpy.Point(x, y)
ptGeometry = arcpy.PointGeometry(point1)


arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)


fldList = ['TMS','OWNERNAME']
fldDict ={}


if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):
        for x in range(len(fldList)):
            fldDict[fldList]=parrow
    del parrow
    fldAttList = []
    for x in range(len(fldList)):
        fldAttList.append(fldDict[fldList])
    manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat"]
    for fld in manualFields:
        fldList.append(fld)
    fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"]
    for att in fixedAtts:
        fldAttList.append(att)
    fldAttList.append(point1)
    fldtuple = (fldAttList)
    fldList.append( 'SHAPE@XY')
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)
    tprow.insertRow(fldtuple)
        
del tprow
CCWeedcontrol
Frequent Contributor

Sorry to keep bugging but i just noticed that the code doesn't populate the AddressID, POINT_X, POINT_Y fields. I tried to include into your code but i am unable to work.

I also need to populate field "StreetName" on the point from the Parcels, but the Parcels has the two fields SiteStreet & StreetType. I need to take the two fields SiteStreet & StreetType from the parcels and insert them together into the StreetName of the point.

#import modules  
import arcpy  
""" 
tool box parameters 
point param = feature set 
targetpoint = featurelayer 
parcel = featurelayer 
"""  
point = arcpy.GetParameterAsText(0)  #point boolen
targetpoint = "Test1" #target point feature class 
parcel = "TaxParcels"  #target feature class
parcel_lyr = 'parcel_lyr'  
  
  
for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'):  
    x,y = prow[0]  
del prow  
   
point1 = arcpy.Point(x, y)  
ptGeometry = arcpy.PointGeometry(point1)  

CC_list = []
        with arcpy.da.SearchCursor(fc, ["AddressID"]) as cursor:
            for row in cursor:
                try:
                    if "CC" in row[0]:
                        CC_list.append(int(row[0].strip("CC")))   
                except TypeError:
                    pass        
        del cursor

        CC_list.sort()
        AddressID = CC_list[-1] + 1
        AddressID = 'CC' + str(AddressID)
   
arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)  
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)  
  
fldList = ['ACCOUNT','OWNERNAME','SiteAddres','SiteNum','SiteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip', 'OwnerName']  
fldDict ={}  
  
if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:  
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):  
        for x in range(len(fldList)):  
            fldDict[fldList]=parrow  
    del parrow  
    fldAttList = []  
    for x in range(len(fldList)):  
        fldAttList.append(fldDict[fldList])  

    manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat", "APA_CODE"]  
    for fld in manualFields:  
        fldList.append(fld)  

    fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"]  
    for att in fixedAtts:  
        fldAttList.append(att)  
    fldAttList.append(point1)

    otherFields = ["X_Coord", "Y_Coord", "SHAPE@XY", "ADDRESSID"]
    for oth in otherFields:  
    fldAttList.append(point1)
    
    fldtuple = (fldAttList)  
    fldList.append( 'SHAPE@XY')  
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)  
    tprow.insertRow(fldtuple)  
          
del tprow  
0 Kudos
WesMiller
Deactivated User

Could you lay this out a little simpler for me?

Would give me a list of fields from your parcels you want to transfer to the point feature class and give me the fields they go to in the point feature class and give me a list of the preset data and the fields they go to.

0 Kudos
CCWeedcontrol
Frequent Contributor

list of fields from parcels that i need to transfer to point feature that are the same fields as the point feature class.

ACCOUNT, SiteAddres, SiteNum, SiteNumbSfx, Predir, Predir, SiteStreet, StreetType, Postdir, SiteCity, SiteZip, OwnerName, SubName. The point feature class has a field called "StreetName" that i need populate from two fields from the parcels and they are "SiteStreet" & StreetType". I also need to populate the fields called "AddressID" (unique Identifier) I currently have this working with the code below. the only thing that i need to do is populate the fields "POINT_X" and "POINT_Y" with x,y coordinates.

Thanks for the explanation of the code i was about to ask if you can explain it. I don't quiet understand the loops and python dictiionarys, and going field list and populating the dictionary with the field name and the matching attribute. you mentioned using a else statement below so if there was more or less than 1, could you show how this works with the current code?, so i could click on multiple parcels to create new address points? this would be handy of i need to create multiple points for new subdivisions. can you also attach a copy of the model that you use for please.

#import modules  
import arcpy  
""" 
tool box parameters 
point param = feature set 
targetpoint = featurelayer 
parcel = featurelayer 
"""
arcpy.env.qualifiedFieldNames = False

point = arcpy.GetParameterAsText(0)  #point boolen
targetpoint = "CCAP1" #target point feature class 
parcel = "parcels"  #target feature class
parcel_lyr = 'parcel_lyr'  
  
  
for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'):  
    x,y = prow[0]  
del prow  
   
point1 = arcpy.Point(x, y)  
ptGeometry = arcpy.PointGeometry(point1)

CC_list = []
with arcpy.da.SearchCursor(targetpoint, ["AddressID"]) as cursor:
    for row in cursor:
        try:
            if "CC" in row[0]:
                CC_list.append(int(row[0].strip("CC")))   
        except TypeError:
            pass        
del cursor

CC_list.sort()
AddressID = CC_list[-1] + 1
AddressID = 'CC' + str(AddressID)

   
arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)  
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)  
  
fldList = ['ACCOUNT','OwnerName','SiteAddres','SiteNum','siteNumSfx','Predir','SiteStreet', 'StreetType', 'Postdir', 'SiteCity', 'SiteZip']  
fldDict ={}  
  
if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:  
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):  
        for x in range(len(fldList)):  
            fldDict[fldList]=parrow  
    del parrow  
    fldAttList = []  
    for x in range(len(fldList)):  
        fldAttList.append(fldDict[fldList])  
    manualFields =  ["SiteState","FacltyType", "StructType","GIS_STEW", "UpdateBy","Verified", "Status", "StructCat", "APA_CODE","AddressID"]  
    for fld in manualFields:  
        fldList.append(fld)  
    fixedAtts = ["ID","Single Family Home","Primary, Private","CanyonCo", "TA", "Yes, GRM, TA","Active","Residential","1110",AddressID, ] 
    for att in fixedAtts:  
        fldAttList.append(att)  
    fldAttList.append(point1)  
    fldtuple = (fldAttList)  
    fldList.append( 'SHAPE@XY')  
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)  
    tprow.insertRow(fldtuple)  

     
del tprow  
0 Kudos