I'm working on a python toolbox tool that creates offset points along a polyline via the arcpy.CreateRoutes_lr() tool and arcpy.MakeRouteEventLayer_lr(). The tool simplifies the process by constructing a GPTable for the Offset Table and allowing the user to insert their "Offset Left" and "Offset Right" values as input parameters. The table's row length is equal to the polyline length so that there is 1 row for every 1 meter of length along the polyline. The table also has the appropriate Field Name and Data Types.

If I run these steps in the python console in ArcMap everything works as expected and there is an offset point at every 1m step along the polyline.

When I run this script from my python toolbox the number of offset points is rounded down to the nearest 1000th place + the number of km. In other words: A shape length of 1458 yields 1001 points each (left and right offsets); 4777m polyline gets me 4004 offset points each.

I have no idea why this is happening.

ArcMap Version 10.3.1 Python 2.7

enter image description here

import os
import sys
import arcpy

class Toolbox(object):
def __init__(self):
    """Define the toolbox (the name of the toolbox is the name of the
    .pyt file)."""
    self.label = "Toolbox"
    self.alias = ""

    # List of tool classes associated with this toolbox
    self.tools = [CrossSection]

class CrossSection(object):
def __init__(self):
    """Define the tool (tool name is the name of the class)."""
    self.label = "2. Create Cross Sections from Routed Centerline"
    self.description = "Create cross section polylines along the routed 
    valley centerline."
    self.canRunInBackground = False

def getParameterInfo(self):
    inputFC = arcpy.Parameter(
        displayName = "Input Routed Centerline Feature Class",
        name = "RoutedCenterline",
        datatype = "DEFeatureClass",
        parameterType = "Required",
        direction = "Input")

    routeFIELD = arcpy.Parameter(
        displayName = "Select Route Field Name",
        name = "RouteField",
        datatype = "Field",
        parameterType = "Required",
        direction = "Input")
    routeFIELD.filter.list =["LONG"]
    routeFIELD.parameterDependencies = [inputFC.name]

    routeID = arcpy.Parameter(
        displayName = "Select Centerline Route ID",
        name = "RouteId",
        datatype = "GPLong",
        parameterType = "Required",
        direction = "Input")
    routeID.filter.type = "ValueList"
    routeID.filter.list = []

    offsetLEFT = arcpy.Parameter(
        displayName = "Input Offset Left Value",
        name = "OffsetLeft",
        datatype = "GPLong",
        parameterType = "Required",
        direction = "Input")

    offsetRIGHT = arcpy.Parameter(
        displayName = "Input Offset Right Value",
        name = "OffsetRight",
        datatype = "GPLong",
        parameterType = "Required",
        direction = "Input")

    drawDIRECTION= arcpy.Parameter(
        displayName = "Direction to Start Stationing From",
        name = "DrawDirection",
        datatype = "GPString",
        parameterType = "Required",
        direction = "Input")
    drawDIRECTION.filter.type = "ValueList"

    params = [inputFC, routeFIELD, routeID, offsetLEFT, offsetRIGHT, drawDIRECTION]
    return params

def isLicensed(self):
    """Set whether tool is licensed to execute."""
    return True

def updateParameters(self, parameters):
    if parameters[1].value:  
        with arcpy.da.SearchCursor(parameters[0].valueAsText, parameters[1].valueAsText) as rows:  
            parameters[2].filter.list = sorted(list(set([row[0] for row in rows])))  
        parameters[2].filter.list = []

def updateMessages(self, parameters):

def execute(self, parameters, messages):

    #Add Products to Map
    arcpy.env.addOutputsToMap = True

    input_fc = parameters[0].valueAsText
    route_field = parameters[1].valueAsText
    route_id = parameters[2].valueAsText
    off_left = parameters[3].valueAsText
    off_right = parameters[4].valueAsText
    draw_direction = parameters[5].valueAsText
    fc_routed = input_fc + "_RT"
    offset_table = "Offset_Table"
    table_rename = input_fc + offset_table
    off_left_ly = input_fc + "_Left"
    off_right_ly = input_fc + "_Right"
    offset_merged = input_fc+"_Offsets_Merged"
    fc_xsec = input_fc + "_Xsec"

    ws = arcpy.env.workspace
    sw = arcpy.env.scratchWorkspace

    arcpy.CreateRoutes_lr(input_fc, route_field, fc_routed, "LENGTH", "", "", draw_direction, "", "", "IGNORE", "NO_INDEX")

    #Create Table

    #Add Fields
    arcpy.AddField_management(offset_table, "LOCATION", "LONG")
    arcpy.AddField_management(offset_table, "OFFSET_LEFT", "LONG")
    arcpy.AddField_management(offset_table, "OFFSET_RIGHT", "LONG")
    arcpy.AddField_management(offset_table, "NAME", "LONG")

    #Extract values from Centerline Polyline and create variable with desired row length
    fields_shapelength = ['shape_length', 'shape_Length', 'shape_LENGTH', 'Shape_length', 'Shape_Length', 'Shape_LENGTH', 'SHAPE_length', 'SHAPE_Length', 'SHAPE_LENGTH',]
    cursor_shapelength = arcpy.da.SearchCursor(input_fc, fields_shapelength,).next()[0]
    length_fc = int(cursor_shapelength)

    fields_name = ['name', 'Name', 'NAME']
    cursor_name =  arcpy.da.SearchCursor(input_fc, fields_name,).next()[0]

    #Append Extracted Values to Offset_Table
    fields_table = ["LOCATION", "OFFSET_LEFT", "OFFSET_RIGHT", "NAME"]
    cursor = arcpy.da.InsertCursor(offset_table, fields_table)
    for x in xrange(1, length_fc):
        cursor.insertRow((x, off_left, off_right, route_id, ))

    arcpy.MakeRouteEventLayer_lr(fc_routed, route_field, offset_table, "NAME POINT LOCATION", off_left_ly, "OFFSET_LEFT","NO_ERROR_FIELD","NO_ANGLE_FIELD","NORMAL","ANGLE","LEFT","POINT")
    arcpy.MakeRouteEventLayer_lr(fc_routed, route_field, offset_table, "NAME POINT LOCATION", off_right_ly, "OFFSET_RIGHT","NO_ERROR_FIELD","NO_ANGLE_FIELD","NORMAL","ANGLE","LEFT","POINT")

    arcpy.Merge_management([off_left_ly,off_right_ly], offset_merged, "")

    #Convert Points to Lines
    arcpy.PointsToLine_management(offset_merged, fc_xsec, "LOCATION", "LOCATION")

1 Answer 1


Turns out that I had an open cursor. A simple del(cursor) solved the problem.

This block of code:

cursor = arcpy.da.InsertCursor(offset_table, fields_table)
for x in xrange(1, length_fc):
    cursor.insertRow((x, off_left, off_right, route_id, ))

should have been:

cursor = arcpy.da.InsertCursor(offset_table, fields_table)
for x in xrange(1, length_fc):
    cursor.insertRow((x, off_left, off_right, route_id, ))
del cursor

Your Answer

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

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