1.在NOAA(national oceanic and atmospheric administration)官网下载迈阿密港口船舶进出数据,时间为2008/12/31 23:59:00到2009/1/4 23:59:00,时间间隔为1分钟。以下都是轨迹点数据:

2.打开属性表,最主要的字段为时间BaseDateTime,船舶号MMSI(相当于车辆的id编号)

3.根据船舶号MMSI,利用轨迹追踪工具脚本,根据时间顺序生成轨迹线数据

代码也是由NOAA提供的,船舶轨迹点数据生成轨迹线数据

"""

August 21, 2015

Marine Cadastre

www.marinecadastre.gov

NOAA Office for Coastal Management

1234 South Hobson Avenue

Charleston, SC 29405

843-740-1200

ocm.mmc@noaa.gov

Software design and development by

RPS ASA, Inc.

55 Village Square Drive

Wakefield, RI 02879

IMSG

3206 Tower Oaks Blvd

Rockville, MD 20852

"""

########################################################################################################

#########################################################################################################

#########################################################################################################

## Input Paramaters

#Path to input points (broadcast feature class)

sInputFile = r"D:\Miami.gdb\Broadcast"

#ID field name (can keep as is most likely)

sID_Field = "MMSI"

#DateTime field name (can keep as is most likely)

sDT_Field = "BaseDateTime"

#Path to output workspace (file geodatabase)

sOutWorkspace = r"D:\Miami.gdb"

#name of output trackline feature class

sOutName = "TrackLine"

#Break Track line method option (comment/uncomment the selected option)

sLineMethod = "Maximum Time and Distance"

#sLineMethod = "Time Interval"

#Maximum Time in minutes (keep as string in quotes, use 0 if using Time Interval method, default = 60)

sMaxTimeMinutes = "60"

#Maximum Distance in miles (keep as string in quotes, use 0 if using Time Interval method, default = 6)

sMaxDistMiles = "6"

#Time Interval in hours (keep as string in quotes, use 0 if using Maximum Time and Distance method, default = 24)

sIntervalHours = "0"

#Include Voyage Attributes (comment/uncomment the selected option)

#sAddVoyageData = "true"

sAddVoyageData = "false"

#Voyage Table (path to voyage table) - OPTIONAL

voyageTable = ""

#Voyage Matching Option (comment/uncomment the selected option) - OPTIONAL

#voyageMethod = "Most Frequent"

voyageMethod = "First"

#Include Vessel Attributes (comment/uncomment the selected option)

#sAddVesselData = "true"

sAddVesselData = "false"

#Vessel Table (path to vessel table) - OPTIONAL

vesselTable = ""

#########################################################################################################

#########################################################################################################

#########################################################################################################

import arcpy, os, sys, traceback, datetime, math, re

import multiprocessing

import time as t

from functools import partial

iMaxTimeMinutes = 0

iMaxDistMiles = 0

iIntervalHours = 0

spatialRef_CURSOR = None

#########################################################################################################

class Timer:

def __init__(self):

self.startTime = t.time()

def End(self):

self.endTime = t.time()

self.elapTime = self.endTime - self.startTime

return self.elapTime

class Progress:

def __init__(self, total):

self.iTotal = float(total)

self.prog = 0

sys.stdout.write('\r 0%')

def Update(self, current):

perc = round(current/self.iTotal * 100.0,0)

if perc > self.prog:

self.prog = perc

sys.stdout.write('\r '+str(perc)+"%")

sys.stdout.flush()

def CheckAISDatabase():

"""Performs a series of checks to see if the source points are a true AIS database with vessel and voyage data."""

bAISdb = True

desc = arcpy.Describe(sInputFile)

input_wkspace = desc.Path

sInName = desc.Name

if os.path.splitext(input_wkspace)[1] <> ".gdb":

bAISdb = False

else:

if sInName.find("Broadcast") < 0:

bAISdb = False

else:

sVesselName = re.sub("Broadcast", "Vessel", sInName)

sVoyageName = re.sub("Broadcast", "Voyage", sInName)

if arcpy.Exists(input_wkspace+"\\"+sVesselName) == False:

bAISdb = False

else:

if arcpy.Exists(input_wkspace+"\\"+sVoyageName) == False:

bAISdb = False

else:

if arcpy.Exists(input_wkspace+"\\BroadcastHasVessel") == False:

bAISdb = False

else:

if arcpy.Exists(input_wkspace+"\\BroadcastHasVoyage") == False:

bAISdb = False

return bAISdb

def FormatCounts(iInCount):

"""Formats various counts to strings with comma separators, for use in dialog messages."""

sOutCount = re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % iInCount)

return sOutCount

def GetVersion():

"""Gets the version of ArcGIS being used. Faster methods to read input datasets are used when 10.1 is the version in use."""

dicInstallInfo = arcpy.GetInstallInfo()

return dicInstallInfo["Version"]

def CreateDataDict_NEW():

"""Process to read through the input point feature class. Point information is stored in a Python dictionary in memory.

All point attributes and coordinates (expect date/time) are read into Numpy Array.

The date information is read using the Data Access module search cursor.

The two parts are then combined based on the OID into the Python dictionary"""

print "\n Reading input point data..."

iTotPoints = int(arcpy.GetCount_management(sInputFile).getOutput(0))

timer = Timer()

prog = Progress(iTotPoints*3) #once for array, date dict, merge

tally = 0

i=0

if bRealAISdb == True:

fields = ["SHAPE@XY",sID_Field,"VoyageID","OID@"]

fields2 = ["OID@",sDT_Field]

##FILTERING MMSI CODES THAT ARE ZERO

where = sID_Field+" > 0"

else:

fields = ["SHAPE@XY",sID_Field,"OID@"]

fields2 = ["OID@",sDT_Field]

where = None

#Store all data (except date) into numpy array

ptData_Array = arcpy.da.FeatureClassToNumPyArray(sInputFile,fields,where,spatialRef_CURSOR)

tally+=iTotPoints

prog.Update(tally)

#Get date using search cursor, store in temporary dictionary

dateDict = {}

with arcpy.da.SearchCursor(sInputFile,fields2,where,spatialRef_CURSOR,False) as rows:

for row in rows:

sOID = row[0]

dDateTime = row[1]

dateDict[sOID] = dDateTime

tally+=1

prog.Update(tally)

#to account for points without MMSI

tally=iTotPoints*2

prog.Update(tally)

#combine array and date dictionary into one final dictionary

dataDict = {}

for i in xrange(0,len(ptData_Array[sID_Field])):

if bRealAISdb == True:

sID, oid, voyageID, geo = ptData_Array[sID_Field][i], ptData_Array["OID@"][i], ptData_Array["VoyageID"][i], ptData_Array["SHAPE@XY"][i]

else:

sID, oid, geo, voyageID = ptData_Array[sID_Field][i], ptData_Array["OID@"][i], ptData_Array["SHAPE@XY"][i], None

if dataDict.has_key(sID):

dataDict[sID][dateDict[oid]] = [geo[0],geo[1],voyageID]

else:

dataDict[sID] = {dateDict[oid]:[geo[0],geo[1],voyageID]}

tally+=1

prog.Update(tally)

del sID, oid, geo, voyageID

del dateDict, ptData_Array

print "\r Read "+FormatCounts(iTotPoints)+" points"

print " Read Complete:" + str(timer.End())

del timer, prog

return dataDict, iTotPoints

def SplitDataDictEqually(input_dict, parts, total_points):

"""Splits the point data dictionary into equal parts, for separate processing."""

return_list = [dict() for idx in xrange(parts)]

min_pts_per_part = math.ceil(total_points/parts)

idx = 0

pts_added = 0

for k,v in input_dict.iteritems():

if pts_added < min_pts_per_part:

return_list[idx][k] = v

pts_added+=len(v.keys())

else:

idx += 1

pts_added = 0

return_list[idx][k] = v

pts_added+=len(v.keys())

return return_list

def CreateOuputDataset(parts=0):

"""Creates an empty feature class to store the track polylines. Adds the required fields, based on the options selected by the user."""

print "\n Building output track line feature class..."

tmp = os.path.join('in_memory', 'template')

#create a feature class in memory, to use as a template for all feature classes created

arcpy.CreateFeatureclass_management('in_memory','template',"POLYLINE","","DISABLED","DISABLED",sInputFile)

arcpy.AddField_management(tmp,sID_Field,"LONG",)

arcpy.AddField_management(tmp,"TrackStartTime","DATE",)

arcpy.AddField_management(tmp,"TrackEndTime","DATE",)

if bRealAISdb == True:

if sAddVoyageData == "true":

arcpy.AddField_management(tmp,"VoyageID","LONG",)

arcpy.AddField_management(tmp,"Destination","TEXT")

arcpy.AddField_management(tmp,"Cargo","LONG",)

arcpy.AddField_management(tmp,"Draught","LONG",)

arcpy.AddField_management(tmp,"ETA","DATE",)

arcpy.AddField_management(tmp,"StartTime","DATE",)

arcpy.AddField_management(tmp,"EndTime","DATE",)

if sAddVesselData == "true":

arcpy.AddField_management(tmp,"IMO","LONG",)

arcpy.AddField_management(tmp,"CallSign","TEXT",)

arcpy.AddField_management(tmp,"Name","TEXT",)

arcpy.AddField_management(tmp,"VesselType","LONG",)

arcpy.AddField_management(tmp,"Length","LONG",)

arcpy.AddField_management(tmp,"Width","LONG",)

arcpy.AddField_management(tmp,"DimensionComponents","TEXT",)

#create a temporary FGDB and feature class for each separate process to avoid locking issues

if parts > 1:

for i in range(1,parts+1):

tmp_wkspc_path = os.path.split(sOutWorkspace)[0]

arcpy.CreateFileGDB_management(tmp_wkspc_path, "temp" + str(i) + ".gdb")

tmp_fgdb = os.path.join(tmp_wkspc_path, "temp" + str(i) + ".gdb")

arcpy.CreateFeatureclass_management(tmp_fgdb,sOutName+str(i),"POLYLINE",tmp,"DISABLED","DISABLED",sInputFile)

#create one feature class since no multiprocessing being used

else:

arcpy.CreateFeatureclass_management(sOutWorkspace,sOutName,"POLYLINE",tmp,"DISABLED","DISABLED",sInputFile)

#delete the temporary template dataset in memory

arcpy.Delete_management(tmp)

del tmp

def GetDistance(prevX,prevY,currX,currY):

"""Calculates the distance between two latitude/longitude coordinate pairs, using the Vincenty formula for ellipsoid based distances.

Returns the distance in miles."""

#Vincenty Formula

#Copyright 2002-2012 Chris Veness

#http://www.movable-type.co.uk/scripts/latlong-vincenty.html

a = 6378137

b = 6356752.314245

f = 1/298.257223563

L = math.radians(currX - prevX)

U1 = math.atan((1-f)*math.tan(math.radians(prevY)))

U2 = math.atan((1-f)*math.tan(math.radians(currY)))

sinU1 = math.sin(U1)

sinU2 = math.sin(U2)

cosU1 = math.cos(U1)

cosU2 = math.cos(U2)

lam = L

lamP = 9999999999

iter_count = 0

while abs(lam-lamP) > 1e-12 and iter_count <= 100:

sinLam = math.sin(lam)

cosLam = math.cos(lam)

sinSigma = math.sqrt((cosU2*sinLam)*(cosU2*sinLam) + (cosU1*sinU2-sinU1*cosU2*cosLam)*(cosU1*sinU2-sinU1*cosU2*cosLam))

if sinSigma == 0:

return 0

cosSigma = sinU1*sinU2+cosU1*cosU2*cosLam

sigma = math.atan2(sinSigma,cosSigma)

sinAlpha = cosU1*cosU2*sinLam/sinSigma

cosSqAlpha = 1 - sinAlpha*sinAlpha

if cosSqAlpha == 0: #catches zero division error if points on equator

cos2SigmaM = 0

else:

cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha

if cos2SigmaM == None:

cos2SigmaM = 0

C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))

lamP = lam

lam = L+(1-C)*f*sinAlpha*(sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)))

iter_count+=1

uSq = cosSqAlpha*(a*a - b*b)/(b*b)

A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))

B = uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)))

deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)))

s = b*A*(sigma-deltaSigma)

#convert s in meters to miles

s_miles = s*0.0006213712

return s_miles

def GetTimeDifference(prevDT,currDT):

"""Calculates the difference between to date and time variables. The difference is returned in minutes."""

timeDelta = currDT - prevDT

totMinutes = (timeDelta.days*1440) + (timeDelta.seconds/60)

return totMinutes

def MultiProcess_Main(dataDict, iTotPoints):

"""Main process to split the data and run seperate processes to build the track lines for each available CPU."""

print "\n Generating track lines..."

timer = Timer()

parts = multiprocessing.cpu_count() - 1

prog = Progress(1 + parts + 2) #split, each sub-process, merge, delete temp

tally = 0

tmp_wkspc_path = os.path.split(sOutWorkspace)[0]

#split the point data into separate dictionaries for each process.

split_dicts = SplitDataDictEqually(dataDict, parts, iTotPoints)

tally+=1

prog.Update(tally)

#start each separate process asynchronously, and wait for all to finish before moving on.

pool = multiprocessing.Pool(parts)

jobs = []

for i in range(1,parts+1):

tmp_fgdb = os.path.join(tmp_wkspc_path, "temp" + str(i) + ".gdb")

sTempFC = tmp_fgdb+"\\"+sOutName+str(i)

splitDict = split_dicts[i-1]

tally+=1

p_callback = partial(MultiProcess_Status,p=prog,t=tally)

if sLineMethod == "Maximum Time and Distance":

jobs.append(pool.apply_async(AddLines_Segmented, (splitDict, sTempFC,iMaxTimeMinutes,iMaxDistMiles,spatialRef_CURSOR), callback=p_callback))

elif sLineMethod == "Time Interval":

jobs.append(pool.apply_async(AddLines_Interval, (splitDict, sTempFC,iIntervalHours,spatialRef_CURSOR), callback=p_callback))

pool.close()

pool.join()

del split_dicts

#Merge the temporary output feature classes in separate FGDBs into one feature class in the selected output geodatabase

to_merge = []

for i in range(1,parts+1):

tmp_fgdb = os.path.join(tmp_wkspc_path, "temp" + str(i) + ".gdb")

to_merge.append(tmp_fgdb+"\\"+sOutName+str(i))

arcpy.Merge_management(to_merge, sOutWorkspace+"\\"+sOutName)

tally+=1

prog.Update(tally)

#Delete the temporary geodatabases

for i in range(1,parts+1):

tmp_fgdb = os.path.join(tmp_wkspc_path, "temp" + str(i) + ".gdb")

arcpy.Delete_management(tmp_fgdb)

tally+=1

prog.Update(tally)

iTotTracks = int(arcpy.GetCount_management(sOutWorkspace+"\\"+sOutName).getOutput(0))

print "\r Unique "+sID_Field+"'s= "+FormatCounts(len(dataDict))

print " Track lines created = "+FormatCounts(iTotTracks)

print " Track lines created in:" + str(timer.End())

del timer

def MultiProcess_Status(x, p, t):

"""Simple function to get the status of each separate track line building process."""

p.Update(t)

def AddLines_Segmented(dataDict,sOutputFC,iMaxTimeMinutes,iMaxDistMiles,spatialRef_CURSOR,progress=False):

"""Creates track polylines and saves them in the ouput feature class. Track lines are created using a maximum distance and

maximum time threshold between points."""

prog = None

tally = 0

if progress:

prog = Progress(len(dataDict))

cur = arcpy.da.InsertCursor(sOutputFC, ("SHAPE@",sID_Field,"TrackStartTime","TrackEndTime"))

pnt1 = arcpy.Point()

pnt2 = arcpy.Point()

lineArray = arcpy.Array()

for key in sorted(dataDict.iterkeys()):

tally+=1

iSegCount = 0

#list of date time dictionary keys

dtTimes = sorted(dataDict[key].keys())

#start and end date variables: start date set with the start of any new line. end date constantly updated with the second point

#so that whenever the line ends the last datetime will already be set.

dtSegStart = None

dtSegEnd = None

#skip MMSI if there is only one point provided

if len(dtTimes) > 1:

for i in range(0,len(dtTimes)-1):

pnt1.X = dataDict[key][dtTimes[i]][0]

pnt1.Y = dataDict[key][dtTimes[i]][1]

pnt2.X = dataDict[key][dtTimes[i+1]][0]

pnt2.Y = dataDict[key][dtTimes[i+1]][1]

distance = GetDistance(pnt1.X,pnt1.Y,pnt2.X,pnt2.Y)

timeDiff = GetTimeDifference(dtTimes[i],dtTimes[i+1])

if distance < iMaxDistMiles and timeDiff < iMaxTimeMinutes:

if iSegCount == 0:

dtSegStart = dtTimes[i]

lineArray.add(pnt1)

lineArray.add(pnt2)

else:

lineArray.add(pnt2)

dtSegEnd = dtTimes[i+1]

iSegCount+=1

#Break the line as the gap exceeds the thresholds

else:

if lineArray.count > 1:

polyline = arcpy.Polyline(lineArray,spatialRef_CURSOR)

cur.insertRow((polyline,key,dtSegStart,dtSegEnd))

del polyline

lineArray.removeAll()

dtSegStart = None

dtSegEnd = None

##reset seg count,since line ended early due to thresholds

iSegCount = 0

#end line since end of this MMSI set

if lineArray.count > 1:

polyline = arcpy.Polyline(lineArray,spatialRef_CURSOR)

cur.insertRow((polyline,key,dtSegStart,dtSegEnd))

del polyline

lineArray.removeAll()

dtSegStart = None

dtSegEnd = None

if progress:

prog.Update(tally)

del prog

del cur

def AddLines_Interval(dataDict,sOutputFC,iIntervalHours,spatialRef_CURSOR,progress=False):

"""Creates track polylines and saves them in the ouput feature class. Track lines are created based on the specified time interval."""

prog = None

tally = 0

if progress:

prog = Progress(len(dataDict))

cur = arcpy.da.InsertCursor(sOutputFC, ("SHAPE@",sID_Field,"TrackStartTime","TrackEndTime"))

pnt1 = arcpy.Point()

pnt2 = arcpy.Point()

lineArray = arcpy.Array()

#create time interval from input parameter hours

tdInterval = datetime.timedelta(hours=iIntervalHours)

for key in sorted(dataDict.iterkeys()):

tally+=1

iSegCount = 0

#list of date time dictionary keys

dtTimes = sorted(dataDict[key].keys())

#start and end date variables: start date set with the start of any new line. end date constatnly updated with the second point

#so that whenever the line ends the last datetime will already be set.

dtSegStart = None

dtSegEnd = None

#initialize time interval using the first point as the start, and the end based on the selected interval

#updated as the interval threshold is reached.

dtIntervalBegin = dtTimes[0]

dtIntervalEnd = dtIntervalBegin + tdInterval

#skip MMSI if there is only one point provided

if len(dtTimes) > 1:

for i in range(0,len(dtTimes)-1):

pnt1.X = dataDict[key][dtTimes[i]][0]

pnt1.Y = dataDict[key][dtTimes[i]][1]

pnt2.X = dataDict[key][dtTimes[i+1]][0]

pnt2.Y = dataDict[key][dtTimes[i+1]][1]

if dtTimes[i] >= dtIntervalBegin and dtTimes[i+1] <= dtIntervalEnd:

if iSegCount == 0:

dtSegStart = dtTimes[i]

lineArray.add(pnt1)

lineArray.add(pnt2)

else:

lineArray.add(pnt2)

dtSegEnd = dtTimes[i+1]

iSegCount+=1

#Break the line as the next point is outside the defined interval

else:

if lineArray.count > 1:

polyline = arcpy.Polyline(lineArray,spatialRef_CURSOR)

cur.insertRow((polyline,key,dtSegStart,dtSegEnd))

del polyline

lineArray.removeAll()

dtSegStart = None

dtSegEnd = None

#update for next time interval

dtIntervalBegin = dtIntervalEnd

dtIntervalEnd = dtIntervalBegin + tdInterval

##reset seg count,since line ended early due to thresholds

iSegCount = 0

#end line since end of this MMSI set

if lineArray.count > 1:

polyline = arcpy.Polyline(lineArray,spatialRef_CURSOR)

cur.insertRow((polyline,key,dtSegStart,dtSegEnd))

del polyline

lineArray.removeAll()

dtSegStart = None

dtSegEnd = None

dtIntervalBegin = None

dtIntervalEnd = None

if progress:

prog.Update(tally)

del prog

del cur

def AddVoyageData_NEW(dataDict,sOutputFC):

"""Adds voyage attribution from Voyage table to the assocatiated track lines. Voyage data is associated with the track lines based on the VoyageID.

Since one MMSI may have multiple VoyageIDs, the matching VoyageIDs can be selected by using the most frequent or the first."""

print "\n Adding Voyage data to output..."

timer = Timer()

prog = Progress(int(arcpy.GetCount_management(sOutputFC).getOutput(0)) + int(arcpy.GetCount_management(voyageTable).getOutput(0)))

tally = 0

iTotTracks = 0

iVoyageDataAdded = 0

#read ALL the voyage data into a python dictionary

dicVoyageAttrs = {}

with arcpy.da.SearchCursor(voyageTable,("VoyageID","Destination","Cargo","Draught","ETA","StartTime","EndTime")) as vRows:

for vRow in vRows:

tally+=1

dicVoyageAttrs[vRow[0]] = [vRow[1],vRow[2],vRow[3],vRow[4],vRow[5],vRow[6]]

prog.Update(tally)

#update the tracklines based on voyage data

with arcpy.da.UpdateCursor(sOutputFC, ("MMSI","TrackStartTime","TrackEndTime","VoyageID","Destination","Cargo","Draught","ETA","StartTime","EndTime")) as rows:

for row in rows:

tally+=1

iTotTracks+=1

lMMSI = row[0]

dtStart = row[1]

dtEnd = row[2]

if voyageMethod == "Most Frequent":

#Go through data dict and create dict of voyage IDs

dicVoyage = {}

for dt in sorted(dataDict[lMMSI].iterkeys()):

if dt >= dtStart and dt <= dtEnd:

iVoyageID = dataDict[lMMSI][dt][2]

if iVoyageID in dicVoyage:

dicVoyage[iVoyageID]+=1

else:

dicVoyage[iVoyageID] = 1

#get most frequent Voyage of Trackline

max_count = 0

for v in dicVoyage.iterkeys():

if dicVoyage[v] > max_count:

max_count = dicVoyage[v]

iVoyageID = v

else:#voyage method = "First"

for dt in sorted(dataDict[lMMSI].iterkeys()):

if dt >= dtStart and dt <= dtEnd:

iVoyageID = dataDict[lMMSI][dt][2]

break

#update row with voyageID

row[3] = iVoyageID

if dicVoyageAttrs.has_key(iVoyageID):

row[4] = dicVoyageAttrs[iVoyageID][0]

row[5] = dicVoyageAttrs[iVoyageID][1]

row[6] = dicVoyageAttrs[iVoyageID][2]

row[7] = dicVoyageAttrs[iVoyageID][3]

row[8] = dicVoyageAttrs[iVoyageID][4]

row[9] = dicVoyageAttrs[iVoyageID][5]

iVoyageDataAdded+=1

rows.updateRow(row)

prog.Update(tally)

print "\r Added to "+FormatCounts(iVoyageDataAdded)+" of "+FormatCounts(iTotTracks)+" track lines"

print " Added Voyage Data in:" + str(timer.End())

del prog

del timer

def AddVesselData_NEW(sOutputFC):

"""Adds vessel attribution from Vessel table to the assocatiated track lines. Vessel data is associated with the track lines based on the MMSI."""

print "\n Adding Vessel data to output..."

timer = Timer()

prog = Progress(int(arcpy.GetCount_management(sOutputFC).getOutput(0)) + int(arcpy.GetCount_management(vesselTable).getOutput(0)))

tally = 0

iTotTracks = 0

iVesselDataAdded = 0

#read ALL the vessel data into a python dictionary

dictVesselData = {}

with arcpy.da.SearchCursor(vesselTable,("MMSI","IMO","CallSign","Name","VesselType","Length","Width","DimensionComponents")) as vRows:

for vRow in vRows:

tally+=1

dictVesselData[vRow[0]] = [vRow[1],vRow[2],vRow[3],vRow[4],vRow[5],vRow[6],vRow[7]]

prog.Update(tally)

#update the tracklines based on vessel data

with arcpy.da.UpdateCursor(sOutputFC, ("MMSI","IMO","CallSign","Name","VesselType","Length","Width","DimensionComponents")) as rows:

for row in rows:

tally+=1

iTotTracks+=1

lMMSI = row[0]

if dictVesselData.has_key(lMMSI):

row[1] = dictVesselData[lMMSI][0]

row[2] = dictVesselData[lMMSI][1]

row[3] = dictVesselData[lMMSI][2]

row[4] = dictVesselData[lMMSI][3]

row[5] = dictVesselData[lMMSI][4]

row[6] = dictVesselData[lMMSI][5]

row[7] = dictVesselData[lMMSI][6]

iVesselDataAdded+=1

rows.updateRow(row)

prog.Update(tally)

print "\r Added to "+FormatCounts(iVesselDataAdded)+" of "+FormatCounts(iTotTracks)+" track lines"

print " Added Vessel Data in:" + str(timer.End())

del prog

del timer

def SetupVoyageCodedDomain(sOutputFC):

"""Setup the Coded Domains for the Cargo field. Creates a temporary table of the Cargo domain from the source database,

and then imports it to the ouput track feature class."""

print "\n Assigning Cargo coded domain values..."

input_wkspace = os.path.split(sInputFile)[0]

arcpy.env.workspace = sOutWorkspace

desc = arcpy.Describe(sOutWorkspace)

domains = desc.domains

#Check if domain already exists

bCargoDomExists = False

for domain in domains:

if domain == "Cargo":

bCargoDomExists = True

if bCargoDomExists == False:

#Copy the domain from the input AIS database to the output database

arcpy.DomainToTable_management(input_wkspace,"Cargo","CargoDom","code","description")

arcpy.TableToDomain_management("CargoDom","code","description",sOutWorkspace,"Cargo")

#Delete the temporary Domain Table

arcpy.Delete_management("CargoDom")

#Assign domain to the field in the track feature class

try:

arcpy.AssignDomainToField_management(sOutName,"Cargo","Cargo")

except:

print " ERROR Assigning Domain - Workspace is read only."

print " Domain can be assigned to the 'Cargo' field manually."

print " See the 'Use Limitations' section in the help documentation for details."

def SetupVesselCodedDomain(sOutputFC):

"""Setup the Coded Domains for the Vessel Type field. Creates a temporary table of the VesselType domain from the source database,

and then imports it to the ouput track feature class."""

print "\n Assigning Vessel Type coded domain values..."

input_wkspace = os.path.split(sInputFile)[0]

arcpy.env.workspace = sOutWorkspace

desc = arcpy.Describe(sOutWorkspace)

domains = desc.domains

#Check if domain already exists

bCargoDomExists = False

for domain in domains:

if domain == "VesselType":

bCargoDomExists = True

if bCargoDomExists == False:

#Copy the domain from the input AIS database to the output database

arcpy.DomainToTable_management(input_wkspace,"VesselType","VesselTypeDom","code","description")

arcpy.TableToDomain_management("VesselTypeDom","code","description",sOutWorkspace,"VesselType")

#Delete the temporary Domain Table

arcpy.Delete_management("VesselTypeDom")

#Assign domain to the field in the track feature class

try:

arcpy.AssignDomainToField_management(sOutName,"VesselType","VesselType")

except:

print " ERROR Assigning Domain - Workspace is read only."

print " Domain can be assigned to the 'VesselType' field manually."

print " See the 'Use Limitations' section in the help documentation for details."

def CreateTracks():

"""Main function that calls all of the other functions. Determines which functions are run, based on the user selected parameters."""

#Create Dictionary of broadcast data Key = ID, Value = Dictionary of {DateTime:[x,y,voyageID]}

dataDict, iTotPoints = CreateDataDict_NEW()

sOutputFC = sOutWorkspace+"\\"+sOutName

#If there are more than 2 CPUs then use multiprocessing approach, otherwise only use 1

# leaving one CPU to run operating system.

if multiprocessing.cpu_count() <= 2:

#Create output feature class

CreateOuputDataset(0)

#build track lines

print "\n Generating track lines..."

if sLineMethod == "Maximum Time and Distance":

AddLines_Segmented(dataDict,sOutputFC,iMaxTimeMinutes,iMaxDistMiles,spatialRef_CURSOR,True)

elif sLineMethod == "Time Interval":

AddLines_Interval(dataDict,sOutputFC,iIntervalHours,spatialRef_CURSOR,True)

iTotTracks = int(arcpy.GetCount_management(sOutputFC).getOutput(0))

print "\r Unique "+sID_Field+"'s= "+FormatCounts(len(dataDict))

print " Track lines created = "+FormatCounts(iTotTracks)

else:

#Create multiple temproary output feature classes

CreateOuputDataset(multiprocessing.cpu_count() - 1)

#Use multiprocessing method to create track lines

MultiProcess_Main(dataDict, iTotPoints)

#Add Voyage info, if table provided:

if sAddVoyageData == "true":

AddVoyageData_NEW(dataDict,sOutputFC)

SetupVoyageCodedDomain(sOutputFC)

#Add Vessel info, if table provided:

if sAddVesselData == "true":

AddVesselData_NEW(sOutputFC)

SetupVesselCodedDomain(sOutputFC)

print "\n"

def CheckParameters():

"""This function performs the checks required to make sure all the input parameters were provided and accurate.

These are the same checks performed within the Toolbox script tool validation code."""

global sAddVoyageData, sAddVesselData, spatialRef_CURSOR

global iMaxTimeMinutes, iMaxDistMiles, iIntervalHours

print "\n Checking Input Parameters..."

bPass = True

Messages = []

bRealAISdb = False

desc = None

#input points checks

if arcpy.Exists(sInputFile) == False:

bPass = False

Messages.append("Input Points do not exist")

else:

desc = arcpy.Describe(sInputFile)

if desc.datasetType <> "FeatureClass":

bPass = False

Messages.append("Input is not a feature class")

else:

if desc.shapeType <> "Point":

bPass = False

Messages.append("Input is not a point feature class")

else:

prjFile = os.path.join(arcpy.GetInstallInfo()["InstallDir"],"Coordinate Systems/Geographic Coordinate Systems/World/WGS 1984.prj")

spatialRef_WGS84 = arcpy.SpatialReference(prjFile)

spatialRef_input = arcpy.Describe(sInputFile).spatialReference

if spatialRef_WGS84.name <> spatialRef_input.name:

spatialRef_CURSOR = spatialRef_WGS84

else:

spatialRef_CURSOR = None

fields = desc.fields

#ID Field checks

bFieldExists = False

for field in fields:

if field.name == sID_Field:

bFieldExists = True

if field.type not in ["SmallInteger","Integer"]:

bPass = False

Messages.append("Input ID field is not an integer field")

break

if bFieldExists == False:

bPass = False

Messages.append("Input ID field does not exist in input feature class")

#DateTime Field checks

bFieldExists = False

for field in fields:

if field.name == sDT_Field:

bFieldExists = True

if field.type <> "Date":

bPass = False

Messages.append("Input Date/Time field is not an date field")

break

if bFieldExists == False:

bPass = False

Messages.append("Input Date/Time field does not exist in input feature class")

#check if adding vessel/voyage data is appropriate (real AIS database)

bRealAISdb = CheckAISDatabase()

#Output Workspace checks

if arcpy.Exists(sOutWorkspace) == False:

bPass = False

Messages.append("Output workspace does not exist")

else:

desc = arcpy.Describe(sOutWorkspace)

if desc.workspaceType <> "LocalDatabase":

bPass = False

Messages.append("Output workspace is not a geodatabase")

#Check output name

if sOutName <> str(arcpy.ValidateTableName(sOutName,sOutWorkspace)):

bPass = False

Messages.append("Output trackline feature class name is invalid")

#Check Break trackline option

if sLineMethod not in ["Maximum Time and Distance","Time Interval"]:

bPass = False

Messages.append("Break trackline method parameter is not a valid option")

#Check Maximum Time in minutes

try:

if sLineMethod == "Maximum Time and Distance":

test = int(sMaxTimeMinutes)

if int(sMaxTimeMinutes) <= 0:

bPass = False

Messages.append("Maximum Time must be greater than zero when using the Maximum Time and Distance option")

else:

iMaxTimeMinutes = int(sMaxTimeMinutes)

except:

bPass = False

Messages.append("Maximum Time is not numeric")

#Check Maximum Distance

try:

if sLineMethod == "Maximum Time and Distance":

test = int(sMaxDistMiles)

if int(sMaxDistMiles) <= 0:

bPass = False

Messages.append("Maximum Distance must be greater than zero when using the Maximum Time and Distance option")

else:

iMaxDistMiles = int(sMaxDistMiles)

except:

bPass = False

Messages.append("Maximum Distance is not numeric")

#Check Time Interval

try:

if sLineMethod == "Time Interval":

test = int(sIntervalHours)

if int(sIntervalHours) <= 0:

bPass = False

Messages.append("Time Interval must be greater than zero when using the Time Interval option")

else:

iIntervalHours = int(sIntervalHours)

except:

bPass = False

Messages.append("Time Interval is not numeric")

#Check Include voyage option

if sAddVoyageData not in ["true","false"]:

bPass = False

Messages.append("Option to include Voyage data must be 'true' or 'false'")

else:

if not bRealAISdb and sAddVoyageData == "true":

print " Ignoring Voyage data since input data is not part of a complete AIS database"

sAddVoyageData = "false"

elif sAddVoyageData == "true":

#check voyage table

if arcpy.Exists(voyageTable) == False:

bPass = False

Messages.append("Voyage table does not exist")

else:

desc = arcpy.Describe(voyageTable)

if desc.datasetType <> "Table":

bPass = False

Messages.append("Voyage table parameter is not a table")

#Check Voyage Matching Option

if voyageMethod not in ["Most Frequent","First"]:

bPass = False

Messages.append("Voyage Matching Option parameter is not a valid option")

#Check Include vessel data option

if sAddVesselData not in ["true","false"]:

bPass = False

Messages.append("Option to include Vessel data must be 'true' or 'false'")

else:

if not bRealAISdb and sAddVesselData == "true":

print " Ignoring Vessel data since input data is not part of a complete AIS database"

sAddVesselData = "false"

elif sAddVesselData == "true":

#check vessel table

if arcpy.Exists(vesselTable) == False:

bPass = False

Messages.append("Vessel table does not exist")

else:

desc = arcpy.Describe(vesselTable)

if desc.datasetType <> "Table":

bPass = False

Messages.append("Vessel table parameter is not a table")

return bPass,Messages, bRealAISdb

def HelpText(Messages = []):

"""Returns the command line syntax and examples of usage, when there was a mistake."""

if len(Messages) > 0:

print "\n\n"

for message in Messages:

print " ERROR: " + message

if len(sys.argv) <> 1:

print "\n\n"

print "Trackbuilder Command Line Syntax:"

print """"""

print ""

print "Examples:"

print """"C:\Python27\ArcGISx6410.3\python.exe" "C:\AIS\TrackBuilderVersion2.1_x64.py" "C:\AIS\Zone19_2011_07.gdb\Broadcast" "MMSI" "BaseDateTime" "C:\AIS\Zone19_2011_07.gdb" "TrackLine" "Maximum Time and Distance" "60" "6" "0" "true" "C:\AIS\Zone19_2011_07.gdb\Voyage" "Most Frequent" "true" "C:\AIS\Zone19_2011_07.gdb\Vessel" """

print ""

print """"C:\Python27\ArcGISx6410.3\python.exe" "C:\AIS\TrackBuilderVersion2.1_x64.py" "C:\AIS\Zone19_2011_07.gdb\Broadcast" "MMSI" "BaseDateTime" "C:\AIS\Zone19_2011_07.gdb" "TrackLine" "Time Interval" "0" "0" "24" "false" "" "" "false" "" """

##########################################

##########################################

if __name__ == '__main__':

timer = Timer()

bRun = True

Errors = []

global bRealAISdb

if len(sys.argv) == 1:

bRun, Errors, bRealAISdb = CheckParameters()

else:

#only proceed if all parameters are present

if len(sys.argv) <> 15 and len(sys.argv) <> 10: #all or without voyage/vessel options

bRun = False

else:

sInputFile = sys.argv[1]

sID_Field = sys.argv[2]

sDT_Field = sys.argv[3]

sOutWorkspace = sys.argv[4]

sOutName = sys.argv[5]

sLineMethod = sys.argv[6]

sMaxTimeMinutes = sys.argv[7]

sMaxDistMiles = sys.argv[8]

sIntervalHours = sys.argv[9]

if len(sys.argv) == 15:

sAddVoyageData = sys.argv[10]

voyageTable = sys.argv[11]

voyageMethod = sys.argv[12]

sAddVesselData = sys.argv[13]

vesselTable = sys.argv[14]

else:

sAddVoyageData = "false"

voyageTable = ""

voyageMethod = ""

sAddVesselData = "false"

vesselTable = ""

bRun, Errors, bRealAISdb = CheckParameters()

#Run the process if all parameters were validated

if bRun:

#Updated to work with ArcGIS Desktop 10.1 or later

if GetVersion() in ["10.1","10.2","10.2.1","10.2.2","10.3","10.3.1","10.4","10.4.1","10.5"]:

if sys.exec_prefix.find("x64") > 0:

try:

arcpy.env.overwriteOutput = True

CreateTracks()

print "Track Lines complete!"

print " Process complete in " + str(datetime.timedelta(seconds=timer.End()))

del timer

except arcpy.ExecuteError:

for msg in range(0, arcpy.GetMessageCount()):

if arcpy.GetSeverity(msg) == 2:

print arcpy.GetMessage(msg)

except:

tb = sys.exc_info()[2]

for i in range(0,len(traceback.format_tb(tb))):

tbinfo = traceback.format_tb(tb)[i]

msg = " ERROR: \n " + tbinfo + " Error Info:\n " + str(sys.exc_info()[1])

print msg

else:

msg = " ERROR: The x64 version of the TrackBuilder can only be used with a 64bit version of Python"

print msg

else:

msg = " ERROR: TrackBuilder can only be used with ArcGIS 10.1 or later"

print msg

#show syntax and examples if parameters were missing or invalid.

else:

HelpText(Errors)

4.再利用核密度分析工具,选择合适的参数值,生成轨迹热力图

5.打开新生成的图像的属性表,打开符号系统,选择合适的色带

最终效果图如下

转载自:https://blog.csdn.net/qq_912917507/article/details/81099656

python 轨迹 车辆_ArcGIS+ArcPy制作船舶(车辆)轨迹热力图相关推荐

  1. 基于OpenCV制作道路车辆计数应用程序

    基于OpenCV制作道路车辆计数应用程序 发展前景 随着科学技术的进步和工业的发展,城市中交通量激增,原始的交通方式已不能满足要求:同时,由于工业发展为城市交通提供的各种交通工具越来越多,从而加速了城 ...

  2. 【高空无人机视角下的路口车辆与行人检测跟踪与轨迹刻画】

    [高空无人机视角下的路口车辆与行人检测跟踪与轨迹刻画] 背景需求 可参考的方法 1. opencv + python 实现目标跟踪的方法: 主要代码 ① main.py ② items.py 检测效果 ...

  3. Blender车辆绑定动画制作视频教程

    MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:72节课(22小时9m) |大小解压后:22 GB ...

  4. 使用python获取共享汽车平台Evcard 的车辆位置信息

    通过python获取共享汽车平台Evcard 的车辆位置信息* 我们直接开门见山,但是本文只是提供一个思路,具体还需要大家自行操作(由于是第一次写,有些许的紧张,如有错误的地方,望大家不吝赐教). 因 ...

  5. NGSIM数据集Python处理(车辆变道时周边车辆数据提取)

    本文通过Python代码的编写,对NGSIM数据集中车辆变道时周边车辆的加速度.速度等信息进行提取,主要介绍代码逻辑及思路. 关于NGSIM数据集不再赘述,本人上传有NGSIM各路段各车型的车辆数据以 ...

  6. HighD数据集Python处理(超车变道邻近车辆数据筛选)

    由德国亚琛工业大学汽车工程研究所发布的HighD数据集,是德国高速公路的大型自然车辆轨迹数据,搜集自德国科隆附近的六个不同地点, 位置因车道数量和速度限制而异,记录的数据中包括轿车和卡车.数据集包括来 ...

  7. 车辆监控管理系统、GPS车辆监控系统、车辆监控管理系统技术方案 ,车辆监控管理系统设计,车载监控终端TBOX,车辆监控系统终端

    车辆监控管理系统是利用全球定位技术.通过无线数据传输,并 配合计算机软件(MIS)实现对车辆的各项静态和动态信息进行管理. 车辆监控管理系统的组成:包括车载设备,监控管理中心,无线通信网络. 车载监控 ...

  8. python matpoltlib绘制动态图_使用Python、Geopandas和Matplotlib制作gif动态

    原标题:使用Python.Geopandas和Matplotlib制作gif动态 不需要Photoshop:仅使用Python和命令行制作动画图表. 作为一种编程语言,Python非常灵活.这使得有时 ...

  9. 如何根据vin码查询_vin查配置 车辆VIN码查询车辆基本配置信息 知道车辆vin码怎么查配置...

    使用车架号来查询车辆信息.可以通过车架号查询车辆的车牌号码.   提供17位VIN码(车架号)在线查询服务,可以查询汽车的厂家名称.品牌.车系.车型.车身形式.年款.排量.变速箱描述.变速器类型.发动 ...

最新文章

  1. 第一周Access课总结
  2. 包继承Maven的超级POM
  3. 隐私计算,企业数字化转型的BUFF之争
  4. 流行的9个Java框架介绍: 优点、缺点等等
  5. opencv求两张图像光流_光流(optical flow)和openCV中实现
  6. 面向在线教育业务的流媒体分发演进
  7. 数据库高级知识——索引优化分析(一)
  8. linux qtcreator输入中文,新版QT creator下解决fcitx无法输入中文问题(QTcreatorV4.1.0)...
  9. 单单表单独占一行_聊一聊 Excel 数据透视表的 4 种布局选项
  10. Fusion-IO:应用应为闪存优化
  11. atomic 原子量的使用心得
  12. do还是doing imagine加to_doing与to do的用法
  13. 记录一次Broken Pipe断链问题排查
  14. python处理doc格式文档
  15. 微信小程序页面跳转失效原因
  16. 动态代理[JDK]机制解析
  17. 图片破损打不开如何修复?一招轻松恢复损坏图片!
  18. 1062 Talent and Virtue(排序)
  19. 仿iphone输入法_如何在iPhone上的法氏温度和摄氏温度之间切换
  20. C语言编程酒店房价,C语言酒店入住管理系统课设(附源码).doc

热门文章

  1. 「干货」项目经理工作流程23步,步步惊心
  2. ubuntu下Veins安装教程
  3. 【x86架构】x86平台CPU的历史
  4. 俞敏洪:快乐是一种选择
  5. teamviewer付费版,授权轻松访问后还是每次电脑重启后还需要输入密码问题。
  6. 算法(六):图解贪婪算法
  7. 6种常见电流检测电路设计方案
  8. 前端css 清除浮动的几种方式
  9. 保护眼睛的Windows和IE、Firefox、谷歌等浏览器颜色设置
  10. The environmenthvariable 'Path' seems to ave some paths containing characters (';', '' or ';;').