point data to polyline: need to have an arrow at every node on the polyline

3447
3
10-21-2011 07:47 AM
michaelcollins1
Occasional Contributor III
I have a rather massive point data table for animal locations. I need to represent the individual animal movements as vectors, with an arrow at every node on the resultant polyline. We've created the polylines from the point data, but I'm rather stumped at to how to get a directional arrow at each node (or midpoint). Changing to a cartographic line only results in an arrowhead at the end of each polyline, and I can't figure out how to automatically divide each polyline into node-to-node segments.

Any ideas? Split Line at Vertices tool or Network Analyst aren't options.

Thanks in advance
Tags (2)
0 Kudos
3 Replies
RichardFairhurst
MVP Honored Contributor
I have a rather massive point data table for animal locations. I need to represent the individual animal movements as vectors, with an arrow at every node on the resultant polyline. We've created the polylines from the point data, but I'm rather stumped at to how to get a directional arrow at each node (or midpoint). Changing to a cartographic line only results in an arrowhead at the end of each polyline, and I can't figure out how to automatically divide each polyline into node-to-node segments.

Any ideas? Split Line at Vertices tool or Network Analyst aren't options.

Thanks in advance


Build your polylines with M values and calculate an M value at each node based on the length of the line (or just use the Lines OBJECTID or the ID from your point data that created the line as your Route Id in the Create Route tool to assign M values).  Then use Locate Features Along Route to translate your original points along the line into Linear referencing events.

You can now use the event table which will have all of your original point data attributes to create a Route Event point layer.  One of the Advanced Options for creating a Route Event layer (click the advanced button on the first dialog) is to automatically generate an angle field for the points from the tangent or normal angle of the point locataion relative to the line's geometry.  You can then export the layer to a true point feature class (so that they won't move if the route measures change) and use the auto generated LOC_ANGLE field in the advanced symbology settings as a rotation value for your point symbols to orient your arrowheads.

If the animals retraced their steps a lot this method will have issues since their could be one or more overlapping M values in your lines that could be assigned with these tools.  There is no way that I know of to get the line itself to do what you want.
0 Kudos
RichardFairhurst
MVP Honored Contributor
I was just realizing that you could convert your datetime information to elapsed minutes, hours or days and use that value as the basis of the M values of the lines you create if you calculate them relative to a fixed starting datetime.  Then you can use your original table directly as a Route Event Layer (without running the Locate Features Along Route tool) to find the position and angle of every point at the correct time index.  The Route Event Layer would be built using the common ID of all points that formed each line and this calculated elapsed time index value as the Measure value for the event.  Then you can use your point datetime values to create animations of movment along the path with correctly oriented symbols for each time index based on the angle field generated by the Route Event Layer options.  This would even allow you to interpolate animal locations along the path at dates and times you did not actually sample.  Creating an identical Route system (copy it) where the M values are recalulated based on line length would theoretically allow you to use the Transfer Route Events tool to find the corresponding distance traveled along the line at each time index.  Then you could create another copy of that and use the Make Query Table tool to crosslink the points to determine time and distance differentials and export the result to a permanent table.  From this table you could create a either a point or a line based Route Event Layer that could that show such things as subsegments of the path based on season or distance differentials or whatever else comes to mind from these correlations.
0 Kudos
DarrenWiens2
MVP Honored Contributor

I see this thread is quite old and I don't know that the da module existed at the time, but here's how you can currently tackle this problem with Python, if you're so inclined:

>>> lines = 'lines_dw'
... sr = arcpy.Describe(lines).spatialReference
... points = {}
... PID = 0
... with arcpy.da.SearchCursor(lines,'SHAPE@',spatial_reference=sr) as cursor:
...    for row in cursor:
...        for part in row[0]:
...            for i in range(len(part)):
...                if not part.equals(row[0].lastPoint):
...                    PID += 1
...                    dx = part.X - part[i+1].X
...                    dy = part.Y - part[i+1].Y
...                    if dx > 0 and dy >= 0:
...                        angle = math.fabs(math.degrees(math.atan(dx/dy))) + 180
...                    if dx <= 0 and dy > 0:
...                        angle = math.fabs(math.degrees(math.atan(dy/dx))) + 90
...                    if dx >= 0 and dy < 0:
...                        angle = math.fabs(math.degrees(math.atan(dy/dx))) + 270
...                    if dx < 0 and dy <= 0:
...                        angle = math.degrees(math.atan(dx/dy))
...                    points[PID] = [part,angle]
... points_list = [arcpy.PointGeometry(v[0]) for k,v in points.iteritems()]
... arcpy.CopyFeatures_management(points_list,r'in_memory\points')
... arcpy.AddField_management('points','ANGLE',"DOUBLE")
... with arcpy.da.UpdateCursor("points",['OID@','ANGLE']) as cursor:
...    for row in cursor:
...        row[1] = points[row[0]][1]
...        cursor.updateRow(row)

0 Kudos