Select to view content in your preferred language

Select by location based on selected features

763
2
02-28-2014 06:13 AM
TonyAlmeida
MVP Regular Contributor
I am trying to do a select by location, I am trying to do a selection by location on just the parcel that the newly create point is created on, then do a spatial join to then do a search cursor on that one parcel record to grab and populate the attributes i need.


The tool's code is suppose to create a point, populate the x,y & AddressID fields and populate the "add_fields" from the Parcels.
Here my tool's code i have, but it does nothing so i am guess my select by location is not correct. I would supper appreciate help with this code.

import arcpy
import pythonaddins
import os
import time
from arcpy import env

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self

    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

class Add_points(object):
    """Implementation for AddPoints_addin.Add_points (Tool)"""
    def __init__(self):
        self.enabled = True
        self.cursor = 3 # Can set to "Line", "Circle" or "Rectangle" for interactive shape drawing and to activate the onLine/Polygon/Circle event sinks.
    def onMouseDownMap(self, x, y, button, shift):
        ###### Creats point and populates fields x,y & AddressID
        fcTarget = "TonyTwoWay.DBO.TT"
        workspace = r"C:\Users\talmeida\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to dsd15_sqlexpress.sde"
        arcpy.env.overwriteOutput = True
        
        #arcpy.ChangeVersion_management('TonyTwoWay.DBO.TT','TRANSACTIONAL','dbo.DEFAULT', "")
        # Start an edit session. Must provide the worksapce.
        edit = arcpy.da.Editor(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()

        CC_list = []
        with arcpy.da.SearchCursor(fcTarget, ["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

        t = Timer()
        with t:
             CC_list.sort()
             AddressID = CC_list[-1] + 1
             AddressID = 'CC' + str(AddressID)

             row_values = [(x, y, (x, y), AddressID)]
             cursor = arcpy.da.InsertCursor(fcTarget, ["X_Coord", "Y_Coord", "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)
             
        timetest = "completed in %.02f secs." % (t.interval)
        print timetest
#####################################################
        Parcel = "testParcelsAdmit"       
        add_fields = ["ACCOUNT","SiteNum","OwnerName","SiteAddres","SiteNumSfx","SiteStreet","predir","StreetType","SubName"]

        Parcel_lyr = arcpy.MakeFeatureLayer_management(Parcel, "Parcel lyr")
        entries = int(arcpy.GetCount_management(fcTarget).getOutput(0))

        for i in xrange(entries):
            pt_lyr = arcpy.MakeFeatureLayer_management(fcTarget, "points_layer", "\"OBJECTID\"={}".format(str(i)))
            arcpy.SelectLayerByLocation_management(Parcel_lyr, "INTERSECT", pt_lyr, "", "NEW_SELECTION")

        # fix args
        if not isinstance(add_fields, list):
            # from script tool
            add_fields = add_fields.split(';')

        # do not need this scratch file
        fcOutput = r'in_memory\temp_join'
        arcpy.SpatialJoin_analysis(Parcel_lyr, fcTarget,fcOutput, 'JOIN_ONE_TO_MANY')


        # grab oid field from points
        oid_t = arcpy.Describe(fcTarget).OIDFieldName

        # Add JOIN_FID to first item in field list
        add_fields.insert(0, 'JOIN_FID')

        # Create dictionary
        with arcpy.da.SearchCursor(fcOutput, add_fields) as rows:
            join_dict = {r[0]:[r for i in range(1,len(add_fields))] for r in rows}

        # Now update the new target
        curW = arcpy.UpdateCursor(fcTarget)
        for row in curW:
            t_oid = row.getValue(oid_t)
            if t_oid in join_dict:
                for f in add_fields:
                    row.setValue(f, join_dict[t_oid][add_fields.index(f)])
            curW.updateRow(row)
        del row, curW
        arcpy.AddMessage('Updated all records sucussefully')
            
        pass
Tags (2)
0 Kudos
2 Replies
WilliamCraft
MVP Alum
In reviewing your code briefly, you might have the parcel and point layers in opposite places when issuing your select by location.  Here are the properties of the GP tool:

SelectLayerByLocation_management (in_layer, {overlap_type}, {select_features}, {search_distance}, {selection_type})

If you're trying to select features from the parcels, then I believe parcels should be specified for the select_features parameter.  There may be other issues, but this was my observation when looking at it quickly.
0 Kudos
TonyAlmeida
MVP Regular Contributor
Thank you for the reply, creating this tool has been a pain. I am not an expert in python so i think that's my main problem.

The "Parcel Layer" contains the features that will be evaluated against the selected features (fcTarget)
and according the tool explanation is seems like the parameters are correct.

I took a closer look at my code and noticed that some parameters were incorrect.
I corrected a portion of the code and that portion of the SelectLayerByLocation_management seems to be working now... i believe
with the following.
import arcpy
import pythonaddins
import os
import time
from arcpy import env

fcTarget = "TonyTwoWay.DBO.TT"
workspace = r"C:\Users\talmeida\AppData\Roaming\ESRI\Desktop10.1\ArcCatalog\Connection to dsd15_sqlexpress.sde"
arcpy.env.overwriteOutput = True

####Select by location on parcels with created point
Parcellyr = "testParcelsAdmit"
fcTarget = "TonyTwoWay.DBO.TT"

arcpy.MakeFeatureLayer_management(Parcellyr, "Parcel layer")
entries = int(arcpy.GetCount_management(fcTarget).getOutput(0))

for i in xrange(entries):
    arcpy.MakeFeatureLayer_management(fcTarget, "point layer", "\"OBJECTID\"={}".format(str(i)))
    arcpy.SelectLayerByLocation_management("Parcel layer", "INTERSECT", fcTarget, "", "NEW_SELECTION")
    #if arcpy.Exists(pt_lyr): arcpy.Delete_management(pt_lyr)

#### populates fields
#fcTarget = "TonyTwoWay.DBO.TT"
#fcJoin = "testParcelsAdmit"
add_fields = ["ACCOUNT","SiteNum","OwnerName","SiteAddres","SiteNumSfx","SiteStreet","predir","StreetType","SubName"]

# fix args
if not isinstance(add_fields, list):
    # from script tool
    add_fields = add_fields.split(';')

# do not need this scratch file
fcOutput = r'in_memory\temp_join'
arcpy.SpatialJoin_analysis("Parcel layer", fcTarget, fcOutput, 'JOIN_ONE_TO_MANY')


# grab oid field from points
oid_t = arcpy.Describe(fcTarget).OIDFieldName

# init rowW and rowR
curR = arcpy.SearchCursor(fcOutput)
join_dict = dict([(r.JOIN_FID,[r.getValue(f) for f in add_fields]) for r in curR])
del curR

# Now update the new target
curW = arcpy.UpdateCursor(fcTarget)
for row in curW:
    t_oid = row.getValue(oid_t)
    if t_oid in join_dict:
        for f in add_fields:
            row.setValue(f, join_dict[t_oid][add_fields.index(f)])
    curW.updateRow(row)
del row, curW
arcpy.AddMessage('Updated all records sucussefully')    


But when i add to the function that creates the point the tool runs slow, takes about 3-4 minutes to create the point, populate everything. I still believe the code might be doing a spatial join on all the parcel not just the parcel where the point is created.

I tried changing the fcOutput to r"C:\Temp\default.gdb" so i can see if the code is grabbing just the parcel that pertains to that one point or if it is grabbing all the parcels.

I changed
# do not need this scratch file
fcOutput = r'in_memory\temp_join'
arcpy.SpatialJoin_analysis("Parcel layer", fcTarget, fcOutput, 'JOIN_ONE_TO_MANY')


to this
# do not need this scratch file
fcOutput = r"C:\Temp\default.gdb"
arcpy.SpatialJoin_analysis("Parcel layer", fcTarget, fcOutput, 'JOIN_ONE_TO_MANY')


but i am getting the following error. I am assuming it is because of the GloballID field but I am not for sure.
Runtime error 
Traceback (most recent call last):
  File "<string>", line 42, in <module>
  File "C:\Program Files (x86)\ArcGIS\Desktop10.1\arcpy\arcpy\__init__.py", line 1133, in SearchCursor
    return gp.searchCursor(dataset, where_clause, spatial_reference, fields, sort_fields)
  File "C:\Program Files (x86)\ArcGIS\Desktop10.1\arcpy\arcpy\geoprocessing\_base.py", line 359, in searchCursor
    self._gp.SearchCursor(*gp_fixargs(args, True)))
RuntimeError: ERROR 999999: Error executing function.
WARNING 000592: Output format does not support BLOB, Raster, or GUID fields. Field(s) GlobalID_1 will not be converted to output.
0 Kudos