[GIS] Offsetting points perpendicular to line using ArcMap

arcgis-10.1arcgis-desktoparcmapperpendicular

I'm trying to create offsetting points perpendicular from a line and have run into a roadblock in ArcMap 10.1. I have the ability to use the ET GeoWizards tool 'Points Along Polylines' but the tool only functions correctly in the ET GeoWizards window (not in toolbox, ModelBuilder or Python which is where I want to run it from). Essentially, I would like to have the same results as the ET GeoWizards tool 'Points Along Polylines'.

I had tried experimenting with creating a set buffer around my Polyline features and using the several different tools to try to snap a line to the extent of the buffer but some of my line features have drastic angles which creates a buffer overlap and doesn't produce the results I want.

The final product is within a Python script.

Best Answer

I found a way! I used a couple of different sources and manipulated the script to fit my needs (mostly from gotanuki on StackExchange). A variation of this is already on the site, but the of data that I was using is different. In case someone else runs into this issue, this is the solution I used:

# Define orientation (start, mid, end) and draw Matchlines function
# This function is defined before it is called
def orientMatchlines(feat,ix,iy):
        # If the line is horizontal or vertical, the slope and
        # negative reciprocal calculations will fail, so do this instead
        if starty==endy or startx==endx:
            if starty == endy:
                y1 = iy + matchDist
                y2 = iy - matchDist
                x1 = ix
                x2 = ix
            if startx == endx:
                y1 = iy
                y2 = iy
                x1 = ix + matchDist
                x2 = ix - matchDist
        else:
            # Get slope of line
            m = float((starty - endy)/(startx - endx))

            # Get negative reciprocal
            negativereciprocal = -1*((startx - endx)/(starty - endy))

            # For all values of slope, calculate perpendicular line
            # with length = matchDist
            if m > 0:
                if m >= 1:
                    y1 = negativereciprocal*(matchDist)+ iy
                    y2 = negativereciprocal*(-matchDist) + iy
                    x1 = ix + matchDist
                    x2 = ix - matchDist
                if m < 1:
                    y1 = iy + matchDist
                    y2 = iy - matchDist
                    x1 = (matchDist/negativereciprocal) + ix
                    x2 = (-matchDist/negativereciprocal)+ ix
            if m < 0:
                if m >= -1:
                    y1 = iy + matchDist
                    y2 = iy - matchDist
                    x1 = (matchDist/negativereciprocal) + ix
                    x2 = (-matchDist/negativereciprocal)+ ix
                if m < -1:
                    y1 = negativereciprocal*(matchDist)+ iy
                    y2 = negativereciprocal*(-matchDist) + iy
                    x1 = ix + matchDist
                    x2 = ix - matchDist
        point1.X = x1
        point1.Y = y1
        point2.X = x2
        point2.Y = y2
        lineArray.add(point1)
        lineArray.add(point2)

        del x1
        del x2
        del y1
        del y2

# Create search cursor in inLine
rows = arcpy.SearchCursor(inLine)

# Get number of records in inLine
numRecords = int(arcpy.GetCount_management(inLine).getOutput(0))

# Create new point files and array to collect values
point1 = arcpy.Point()
point2 = arcpy.Point()
lineArray = arcpy.Array()

# Define counter
counter = 0

# Loop over rows in outLine
for row in rows:
    # Create the geometry object
    feat = row.Shape

    # Get coordinate values as lists
    firstpoint = feat.firstPoint
    lastpoint = feat.lastPoint
    midpoint = feat.centroid

    # Get X and Y values for each point
    startx = firstpoint.X
    starty = firstpoint.Y
    endx = lastpoint.X
    endy = lastpoint.Y
    midx = midpoint.X
    midy = midpoint.Y

    m = ((starty - endy)/(startx - endx+.0001))

    # For all points besides the last one
    if counter < numRecords - 1:
        orientMatchlines(feat,startx,starty)
    # For the last point
    else:
        orientMatchlines(feat,endx,endy)

    #Create insert cursor
    cur = arcpy.InsertCursor(matchlines)

    #Insert new row from array
    feat = cur.newRow()
    #feat.slope = m
    feat.shape = lineArray
    cur.insertRow(feat)
    lineArray.removeAll()

    del cur

    # Increase counter by 1 and start again
    counter = counter + 1

del row
del rows