Select to view content in your preferred language

Create point,spatial join and populate point attributes

4293
15
Jump to solution
07-16-2015 01:12 PM
CCWeedcontrol
Regular 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
15 Replies
WesMiller
Regular Contributor III

Man that's great you were able to get all that in If i read correctly the only thing you needed were the Point_X and Point_Y fields I added them to code below.

#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", "POINT_X", "POINT_Y"  ]    
    for fld in manualFields:    
        fldList.append(fld)    
    fixedAtts = ["ID","Single Family Home","Primary, Private","CanyonCo", "TA", "Yes, GRM, TA","Active","Residential","1110",AddressID,x,y ]   
    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
WesMiller
Regular Contributor III

I've commented the code to help you find out where you should place the pieces your wanting to add if you'll provide me with the requested information i will help you get it in the code.I’m on geonet to help others and to learn and in saying that I also feel compelled to try to teach. Because if you want to know something really well you should try to teach and in doing so you will greatly improve your own skill. If any one sees anything in my comments that are wrong or inconsistent with the use of the code or tool please do not be shy to comment. You will not hurt my feelings I am here to learn as much as I’m here to help.

commented code

########
#information you should add these pieces of information
#Script name #the name of the script
#Author #The author of the script
#Date #date of creation it's also a good idea to add a date when you modify the
#code and list as a revision with a description of what you did and why
#Pseudo code #This would be your intial workflow thoughts to help you create the
#code below*
########




#import modules
import arcpy
#########################################
#These are the parameter settings for your tool
#tool box parameters
#point = feature set #this will allow the user to give us the xy data
#targetpoint = featurelayer #this will get the target point as a feature layer or feature layer 
#parcel = featurelayer #Same as above but if we could restrict to feature layer only we
#wouldn't need to create a feature layer below
#########################################




#This website gives you a description of how to use arcpy.GetParameterAsText()
#http://resources.arcgis.com/en/help/main/10.1/index.html#//018v00000047000000
# Syntax GetParameterAsText (index)
#You always put your variables at the top I don't know why
#This is the point variable gained from the feature set the
#only thing we need from here is the xy 
point = arcpy.GetParameterAsText(0)
#The target point feature class this is where we want to get data to
#you can call these variables anything you want but is always a good
#idea to call it something that makes sense for your use
targetpoint = arcpy.GetParameterAsText(1)
#The parcel file this is where we will be getting data from
parcel = arcpy.GetParameterAsText(2)
#This variable is used with make feature layer because you can't select
#by location from a feature class it needs to be a feature layer
parcel_lyr = 'parcel_lyr'




#This website gives you a description of how to use arcpy.da.SearchCursor
#http://resources.arcgis.com/en/help/main/10.2/index.html#//018w00000011000000
#There are a couple of different search cursor with different uses I won't try to
#explain them here I think it's sufficient that you are aware of them see this note
#Note:arcpy.da.SearchCursor should not to be confused with the arcpy.SearchCursor.
# Syntax SearchCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})
for prow in arcpy.da.SearchCursor(point,'SHAPE@XY'):
    #The only thing we need is the x and y 
    x,y = prow[0]
#You should always delete the cursor
#It often drives me crazy when I forget and can't read my data
del prow


#Not sure it's neccessary to do this part or not I probably could have created this
#in the loop above something like point1 = prow[0] would most likely would have worked
#maybe someone better than could chime in
#I'm using it here so I can get the element needed for point geometry below
point1 = arcpy.Point(x, y)
#This website gives you a description of how to use arcpy.PointGeometry
#http://resources.arcgis.com/en/help/main/10.2/index.html#//018z00000039000000
#Syntax PointGeometry (inputs, {spatial_reference}, {has_z}, {has_m})
#We'll use this in the select by location query 
ptGeometry = arcpy.PointGeometry(point1)


#This website gives you a description of how to use arcpy.MakeFeatureLayer_management
#http://resources.arcgis.com/en/help/main/10.2/index.html#//00170000006p000000
# Syntax MakeFeatureLayer_management (in_features, out_layer, {where_clause}, {workspace}, {field_info})
# We need to do this in case the user selects a feature class above instead of a feature layer
arcpy.MakeFeatureLayer_management(parcel,parcel_lyr)
#This website gives you a description of how to use arcpy.SelectLayerByLocation_management
#http://resources.arcgis.com/en/help/main/10.2/index.html#//001700000072000000
# Syntax SelectLayerByLocation_management (in_layer, {overlap_type}, {select_features}, {search_distance}, {selection_type})
#Get the intesecting parcel so we can get the data
arcpy.SelectLayerByLocation_management(parcel_lyr,"INTERSECT",ptGeometry)


#We are using a field list to identify the fields we want to get from the parcel
#layer I'm also using for a few shortcuts I'll explain those when we get to them
fldList = ['TMS','OWNERNAME']
#We are creating a field dictionary here to hold the field names and the field data
#this is a shortcut so I don't have to write out every field and every row. When
#get to that part I'll give a description of how to do it the other way and with
#needing a concantination of fields in the insert cursor we may do it the other way
#so you'll be able to see it
fldDict ={}


#We are simply making sure we are only dealing with one parcel
#you could put an else statement below so if there was more or less than 1
#you could give the user a message letting them know that we got more or less
#than expected so we wont transfer any data or create a point in the targetpoint 
if int(arcpy.GetCount_management(parcel_lyr).getOutput(0))==1:
    #This is another searchcursor see above
    for parrow in arcpy.da.SearchCursor(parcel_lyr,fldList):
        #You can find explinations of for loops and python dictiionarys all over the
        #web. basically we are iterating through the field list and populating
        #the dictionary with the field name and the matching attribute
        for x in range(len(fldList)):
            fldDict[fldList]=parrow
    #again delete the cursor
    del parrow
    #we are creating a field attribute list to use below
    fldAttList = []
    #Populating the field attribute list with the attributes from the dictionary
    for x in range(len(fldList)):
        fldAttList.append(fldDict[fldList])
    #These are the manual fields we'll need to add them to the list of fields 
    manualFields =  ["FacltyType", "StructType", "Verified", "Status", "StructCat"]
    #We will probably change these out with a different set of fields for the target
    #feature class
    for fld in manualFields:
        fldList.append(fld)
    #These are the attributes for the manual fields
    fixedAtts = ["Single Family Home","Primary, Private","Yes, GRM, TA","Active","Residential","1110"]
    #Add the above attributes to the attributes list
    for att in fixedAtts:
        fldAttList.append(att)
    #add the coordinates to the list so the point can be created
    fldAttList.append(point1)
    #convert field attribute list to a tuple
    fldtuple = (fldAttList)
    #Add the xy field so the insert cursor knows where to put the coordinates
    fldList.append( 'SHAPE@XY')
    #This website gives you a description of how to use arcpy.da.InsertCursor
    #http://resources.arcgis.com/en/help/main/10.2/index.html#//018w0000000t000000
    # Syntax InsertCursor (in_table, field_names)
    #Note:arcpy.da.InsertCursor should not to be confused with arcpy.InsertCursor.
    tprow = arcpy.da.InsertCursor(targetpoint,fldList)
    tprow.insertRow(fldtuple)
    #again delete the cursor        
    del tprow


            








    




CCWeedcontrol
Regular Contributor

That is the weirdest thing. I added the "POINT_X", "POINT_Y" and x,y to the same lines as you did but i got an error but now that i copied and pasted what you have i got it to work, kind of for some weird reason i have "10" in the "POINT_x" field. I know that is not correct. also the point feature class has a field called "StreetName" that i need populate from two fields from the parcels and they are "SiteStreet" & StreetType".

as far as my other quesitons, would you like me to start a different post?

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.

0 Kudos
WesMiller
Regular Contributor III

I've attached the code with the else statement in it with a simple message returned to the user, I also included the tool used. As far as creating multiple points for doing a subdivision i think i would start a new script and get it to work and either use as stand alone tool or incorporate into this tool. I think i would more lean towards using it as a stand alone, but that's just my opinion. You may also want to look into LGIM sounds like your doing address points and there some tools that work with the LGIM that will help with creating address points, not to mention a good format for storing your data.

0 Kudos
CCWeedcontrol
Regular Contributor

Wes, thank you for all your help.

WesMiller
Regular Contributor III

You are welcome

0 Kudos