Last active
February 15, 2016 21:25
-
-
Save andygarfield/a0700672316b37b72076 to your computer and use it in GitHub Desktop.
Create a line sequence feature class from GPS data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# CSV file must be in the format: Latitude,Longitude,datetime | |
# The third field is date time info from: datetime.datetime.utcnow() | |
# | |
from arcpy import Project_management, CreateFeatureclass_management, AddField_management, SpatialReference, da, Array,\ | |
Point, Polyline, GetParameterAsText, mapping, Describe, ListFields, MakeTableView_management, GetCount_management | |
import os | |
from datetime import datetime | |
from math import floor | |
def create_datetime(datetime_string): | |
year = int(datetime_string.split('-')[0]) | |
month = int(datetime_string.split('-')[1]) | |
day = int(datetime_string.split('-')[2].split(' ')[0]) | |
time = datetime_string.split(' ')[1] | |
hour = int(time.split(':')[0]) | |
minute = int(time.split(':')[1]) | |
second = int(floor(float(time.split(':')[2]))) | |
microsecond = int(floor((float(time.split(':')[2]) % 1) * 1000)) | |
return datetime(year, month, day, hour, minute, second, microsecond) | |
def project_better(in_dataset, out_dataset, spatial_reference): | |
# Script borrowed from http://joshwerts.com/blog/2015/09/10/arcpy-dot-project-in-memory-featureclass/ | |
# Can project a dataset and put the output in an 'in_memory' workspace | |
path, name = os.path.split(out_dataset) | |
CreateFeatureclass_management(path, name, Describe(in_dataset).shapeType, | |
template=in_dataset, | |
spatial_reference=spatial_reference) | |
# specify copy of all fields from source to destination | |
fields = ["Shape@"] + [f.name for f in ListFields(in_dataset) if not f.required] | |
# project source geometries on the fly while inserting to destination featureclass | |
with da.SearchCursor(in_dataset, fields, spatial_reference=spatial_reference) as source_curs, \ | |
da.InsertCursor(out_dataset, fields) as ins_curs: | |
for row in source_curs: | |
ins_curs.insertRow(row) | |
# Initial variables | |
mxd = mapping.MapDocument('CURRENT') | |
df = mxd.activeDataFrame | |
dfcs = df.spatialReference | |
CreateFeatureclass_management('in_memory', 'points', 'POINT', spatial_reference=SpatialReference(4326)) | |
AddField_management('in_memory\\points', 'datetime', 'TEXT') | |
point_cur = da.InsertCursor('in_memory\\points', ['SHAPE@XY', 'datetime']) | |
# Create point FC from CSV file | |
with open(GetParameterAsText(0)) as log: | |
for line in log: | |
lat = float(line.split(',')[0]) | |
lon = float(line.split(',')[1]) | |
timefield = line.split(',')[2] | |
point_cur.insertRow([(lon, lat), timefield]) | |
project_better('in_memory\\points', 'in_memory\\projected', dfcs) | |
# Set up line FC | |
CreateFeatureclass_management(os.path.dirname(GetParameterAsText(1)), os.path.basename(GetParameterAsText(1)), | |
'POLYLINE', None, None, None, dfcs) | |
AddField_management(GetParameterAsText(1), 'Speed', 'DOUBLE') | |
AddField_management(GetParameterAsText(1), 'Begin', 'TEXT') | |
AddField_management(GetParameterAsText(1), 'End', 'TEXT') | |
search_cur = da.SearchCursor('in_memory\\projected', ['SHAPE', 'datetime']) | |
with da.InsertCursor(GetParameterAsText(1), ['SHAPE@', 'Speed', 'Begin', 'End']) as line_cur: | |
# Variables for comparing to current data | |
prev_point = () | |
prev_datetime = 0 | |
for row in search_cur: | |
if prev_point == (): | |
# If it's the first data point, give it some values, and then loop back around | |
prev_point = (row[0][0], row[0][1]) | |
prev_datetime = create_datetime(row[1]) | |
continue | |
array = Array() | |
curr_point = (row[0][0], row[0][1]) | |
# Give the array the points to make the line with | |
array.append(Point(prev_point[0], prev_point[1])) | |
array.append(Point(curr_point[0], curr_point[1])) | |
# Make a new datetime object and calculate the difference between the old one | |
new_datetime = create_datetime(row[1]) | |
time_difference = (new_datetime - prev_datetime).total_seconds() | |
# Create the Polyline | |
new_line = Polyline(array) | |
# Calculate the speed | |
speed = ((new_line.length / time_difference) * 3600) / 5280 | |
# Finally, insert the row | |
line_cur.insertRow([new_line, speed, prev_datetime, new_datetime]) | |
# Set previous variables | |
prev_point = curr_point | |
prev_datetime = new_datetime |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment