2

I have a single file containing several hundred line segments created through connecting points collected detailing animal movement patterns. Each segment has a "seconds" field and a "uniqueID" field.

I am trying to split each line segment (uniqueID) into equally spaced points based on the seconds of time it took the segment took to complete.

For example: If it took said animal 60 seconds to go from point A to Point B, then that line segment would be converted to 60 equidistant points. Each segment would have a different number of points based on that "seconds" field.

2 Answers 2

3

This is where M coordinate values come into play. You can use the Create Route tool to convert the lines to use M coordinates based on your travel time. You already have a UniqueID field to act as your RouteID field, so you should just need to add a field to hold the From value of 0 seconds. Then use the TWO field option and use the 0 seconds as the From field and your time field to set the TO coordinate M value. Output to a file geodatabase, not a shapefile.

Next create an event table. The best way to do this in ArcGIS 10.2 is to create an excel spreadsheet with two columns named Join and Seconds. In the first column put 0 in all records, in the second put 0 and 1 in the first 2 records under the field names (or 1 and 2 if you do not want a point at the beginning of a line) and extend the consecutive number series in column 2 to a row that reaches or exceeds the largest number of seconds possible on the longest track. Use the Excel to Table tool to bring it into ArcMap as a geodatabase table in the same file geodatabase.

Join the new table to the original lines table on the From field in the lines and the Join field in the converted Excel table (both have 0 as their value for all records). Export the table view of the routes to a standalone table with the join in place. As of ArcGIS 10.1, the export output will convert the M:M relationship join to a 1:1 record set by duplicating the unique ID of the lines as many times as required to cover the rows in the joined table. Convert this new table to a point event table and include the option to show an Error field. Any event with an error field value of "NO ERROR" has that number of seconds in that line, any other error field value should mean that the measure is not on the line. Select all events with a NO ERROR value and export them from the layer in the TOC (not the table view). The exported points will be placed at the interpolated position of each second of time along the line.

You could alternatively hatch the lines based on the measures created in the first step output from the Create Routes tool without creating points to show tick marks on your line at every 1 second interval rather than actually creating points if you wished. The use of M coordinate means that you can create line segment events as well based on seconds of travel just by including a from measure and to measure in a table that links on the UniqueID. You also can automatically get the tangent or normal angle data of each point event you place on the line as an option in the Event table set up, in case the directional bearing of the line over different time intervals is important to you.

Any one who regularly uses line data for analysis should learn at least the basics of Linear Referencing to get the most information possible from their line networks.

7
  • If maximum=10 seconds, you'll get 10 event points ONLY
    – FelixIP
    Mar 18, 2015 at 19:54
  • Huh? If maximum = 10 seconds you will get the 10 event points for each of your lines if you do every step. As of ArcGIS 10.1, exporting a 1:M table join like I described creates duplicates of the 10 records for each line ID. This is a process I have done many times and it works to create thousands of events from a table with a fraction of that many entries set up in Excel. If you come up with a different result let me know and I will correct or clarify the steps if necessary, but if you actually followed the steps I outlined I do not see how you could end up with a result of just 10 events. Mar 19, 2015 at 0:03
  • I meant to say M:M table join, not 1:M table join. Mar 19, 2015 at 0:13
  • Where does it say in your answer about M:M join and how to make it? I think you should update your answer on this part and mention tools involved
    – FelixIP
    Mar 19, 2015 at 0:45
  • I withdraw my comments, sorry. It does export what expected, i.e. large table. No need to mention M:M
    – FelixIP
    Mar 19, 2015 at 1:03
1

This worked for me:

import arcpy, os, numpy
arcpy.env.overwriteOutput = True

def add_points_along_lines(feats, output, seconds_field):
    '''Splits lines by a distance or percentage

    Required:
    feats -- input features
    output -- output line feature class
    seconds_field -- field with seconds values
    '''
    def _range(stop, step):
        return [i for i in numpy.arange(0, stop+1, step)
                if i > 0 and i <= stop] 

    # create fc's
    path, name = os.path.split(output)
    sm = 'SAME_AS_TEMPLATE'
    output = arcpy.CreateFeatureclass_management(path, name, 'POINT',
                                        feats, sm, sm, feats).getOutput(0)

    # add 'PT_DIST' field
    add_fields = ['LINE_POS', 'SEG_LENGTH']
    for field in add_fields:
        arcpy.AddField_management(output, field, 'DOUBLE')

    # loop thru geom
    fields = [f.name for f in arcpy.ListFields(feats) if not f.required]
    fields.insert(0, 'SHAPE@')
    sec_id = fields.index(seconds_field)

    # Cursors
    irows = arcpy.da.InsertCursor(output, fields + add_fields)
    with arcpy.da.SearchCursor(feats, fields) as rows:
        for row in rows:
            length = row[0].length
            seg_leng = length / row[sec_id]
            irows.insertRow((row[0].firstPoint,) + row[1:] + (0,0))

            # step through each distance
            for i in _range(length, seg_leng):
                pt = row[0].positionAlongLine(i)
                irows.insertRow((pt,) + row[1:] + (i, seg_leng))
    del irows
    return output

if __name__ == '__main__':

    lines = r'C:\TEMP\lineCopy.shp'
    pts = r'C:\TEMP\line_pts2.shp'
    add_points_along_lines(lines, pts, 'Time_sec')
    print 'done'

The fields that are added at the end are "LINE_POS", which refers to the distance value along the line and the other is the "SEG_LENGTH", which denotes the segment length between each point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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