2

My problem:

I have a set of points inside a polygon. My goal is to figure out how long it takes (in days) for each point to move outside the polygon, based on a daily movement which affects all the points the same way. Once each point leaves the polygon, it should stop moving. Each point has a starting date. I have a table containing dates and the X and Y values by which to shift points on each day (it varies daily). I'll be using this Shift function to move the points. Looking at the table, I'd expect the points to move in one general direction for a week or so before landing outside the polygon.

My process is something like this. FYI, each point has a Start Date (which won't change) and a Current Date, which will be used to look up the appropriate X and Y shift, and will ultimately be used to determine the days it takes for the point to move outside the polygon.

  1. Select points which are inside the border polygon.
  2. Iterate over the points, shifting each according to the Current Date and then incrementing its Current Date by 1 day.
  3. Return to #1.

I have part of a Python script written (below), but I'm still kind of a beginner to Python. My current stumbling block is figuring out how to look up the appropriate shift values in my table based on the Current Date in the point layer, and pass them on to the Shift function to get the points moved each day. Also, since I want to increment the day by 1 when I do that, it seems like I should be adding that step to the Shift function.

Here's what I have so far:

import arcpy
import csv #My shift values table is a CSV, I also converted it to an FGDB table

def shift_features(in_features, x_shift=None, y_shift=None):    
    with arcpy.da.UpdateCursor(in_features, ['SHAPE@XY']) as cursor:
        for row in cursor:
            cursor.updateRow([[row[0][0] + (x_shift or 0),
                               row[0][1] + (y_shift or 0)]])

    return

#Specify input files
startPoints = r"C:\GIS\Data.gdb\Start_Points"
shiftedPoints = r"C:\GIS\Data.gdb\End_Points"
borderPolygon = r"C:\GIS\Data.gdb\BorderPolygon"
shiftValuesTable = r"C:\GIS\Data.gdb\DailyShiftValues"

#Create a copy of the source file so the output can be compared to the input
if arcpy.Exists(shiftedPoints):
    arcpy.Delete_management(shiftedPoints)
arcpy.Copy_management(startPoints,shiftedPoints)

#Import the X and Y values to use for shifting from the source CSV and add them to a dictionary
#I had tried making the CSV into a dict with the date as the key and a list of the X and Y shifts
#as the value


#Create Feature Layers from input features
arcpy.MakeFeatureLayer_management(shiftedPoints, "pointLayer")
arcpy.MakeFeatureLayer_management(borderPolygon, "polygonLayer")

#Select points in the source data which are inside the area to be shifted.
#These are points which have not yet exited the polygon.
arcpy.SelectLayerByLocation_management("pointLayer", "WITHIN", "polygonLayer")

#my current problem:
shift_features("pointLayer",X Value from Table for the date,Y Value from Table for the date)
  • I was thinking that you might want to build a dictionary of shift values based on dates, but you apparently tried that. What didn't work there? Also, why are you passing x_shift=None, y_shift=None instead of just x_shift, y_shift? – Erica Dec 4 '14 at 19:18
  • @Erica RE: the dictionary itself worked, I stored dates (the key) and their X and Y shifts (a list as the dict value), but I realized I still didn't know how to use the date in the point layer to look up the same date in the dictionary and return the shift values. I then figured that arcpy must have a better way to deal with tables than what I was doing, but maybe that isn't the case? In any event, my main problem is using the Date in the point layer to look up the Shift values in my table (or dictionary) and pass them to the Shift function. – Dan C Dec 4 '14 at 19:32
  • @Erica RE: the function parameters, the function is copied from the Arcpy Cafe and it worked fine, so I was reluctant to change anything. I'm still not sure what exactly code=Nonecode does, I mean it assigns no value to the variable but I don't know why that's necessary. – Dan C Dec 4 '14 at 19:40
  • That's a very reasonable answer... if it ain't broke, don't fix it. – Erica Dec 4 '14 at 19:50
2

This is pseudocoded at the moment, but I think the logic needs to go something like the following. You want to keep incrementing through days until all the points are moved out. (Alternatively, increment through until you run out of shift value records -- that would be a for loop instead.)

# build dictionaries of shift values
shiftX = {}
shiftY = {}
while activePoints > 0:
    # select the points that are inside the polygon boundary
    activePoints = # count the points in the selected layer, if =0 loop will end
    shift_features("pointLayer",shiftX[date],shiftY[date])
    date += 1

Also, you're right that the current date attribute should be updated while you're in the shift_features function. Presumably it would be part of the same arcpy.da.UpdateCursor iteration, although I am not entirely sure how the syntax would work in addition to what they've already constructed.

  • That helps, thanks. Making two different dictionaries for the X and Y values didn't occur to me, I was stuck on trying to bring the table in like a database table (one key, many values). – Dan C Dec 4 '14 at 19:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.