# Create a line perpendicular to an existing line in ArcGIS

For an existing set of line features, I would like to generate a perpendicular line, of say 1km, at the midpoint of each existing line feature in ArcGIS.

I imagine that The methodology would be to:

1. create a tangent line at the midpoint of each existing line feature
2. calculate the angle of the tangent line
3. based on the angle of the tangent line, calculate the location of the endpoint of the new line
4. create the new line with the calculated endpoint of the new line and the existing midpoint of the old line

Let's assume that we are in a UTM projection and can use coordinates to calculate distance and direction.

How would I do this with ArcGIS tools or with ArcPy?

• What have you got so far? What have you tried and where are you stuck? Is there any of your code that you can post to show where you're up to? The calculation of the points to form the new line are simple high school geometry calculations, do you have equations you want to implement? – Michael Stimson Jul 12 '16 at 22:04
• The perpendicular lines tool looks promising, I will test it out and get back. @Michael-Miles-Stimson, calculating a new line is relatively straighforward when you know the bearing of the tangent - where I'm stuck is how to calculate the tangent line for a point along a line in ArcMap. – Will McInnes Jul 12 '16 at 22:25
• @WillMcInnes, get the midpoint of the line and then find the previous and next vertex. You can calculate the bearing between those two vertices, +/- 90°, and then drop a point 1km away. – Paul Jul 12 '16 at 22:45
• The Lummi Create Perpendicular line tool as mentioned will create a line perpendicular to the mid point of the line. The tool will create the line left of, right of, or on both sides of the line-at the start, end, or midpoint...As mentioned, the tool is available here: lnnr.lummi-nsn.gov/GIS_Scripts/createperpendicularlines.zip klewis 22 had a time-out error but the Lummi FTP site will not time out a connection. Try downloading outside of your professional organizations firewall. – GBG Jul 13 '16 at 20:28

• Create midpoints, using one of multiple possible techniques.
• Buffer them by small number, e.g. 0.5 m
• Clip originals by buffer, output - SHAPEFILE

Use this field calculator expression on field Shape:

``````def RotateExtend(plyP,sLength):
l=plyP.length
ptX=plyP.positionAlongLine (l/2).firstPoint
ptX0=plyP.firstPoint
ptX1=plyP.lastPoint
dX=float(ptX1.X)-float(ptX0.X)
dY=float(ptX1.Y)-float(ptX0.Y)
lenV=math.sqrt(dX*dX+dY*dY)
sX=-dY*sLength/lenV;sY=dX*sLength/lenV
leftP=arcpy.Point(ptX.X+sX,ptX.Y+sY)
rightP=arcpy.Point(ptX.X-sX, ptX.Y-sY)
array = arcpy.Array([leftP,rightP])
section=arcpy.Polyline(array)
return section
``````

# -------------------------------

``````RotateExtend( !Shape!, 1000)
``````

UPDATE:

Ooops! it creates perpendicular, not tangent. Can be easily modified

• Does this need to be used by an InsertCursor? Can I manually run this to add Polylines to a feature class? – klewis Jul 12 '16 at 23:11
• Feature Vertices to Points tool with the midpoint option specified is one way to get midpoints. – Tom Dilts Jul 12 '16 at 23:15
• @klewis it modifies existing short features, thus you cannot use it to create new – FelixIP Jul 13 '16 at 0:47
• The buffer was the missing piece! I calculated the midpoint, buffered, and then created the perpendicular lines, worked great. – Will McInnes Jul 22 '16 at 17:22

Based on @Felix's answer, here's an approach that uses built-in methods on geometry objects. Supported on 10.3+.

``````from math import atan2, pi

# epsilon
e = 1e-10

def tangentLine(line, dist):
'''creates a tangent line of length dist at line midpoint
line - arcpy.Polyline() object
dist - distance in meters
'''

midpoint = line.positionAlongLine(0.5, True)

# get points immediately before and after midpoint
before = line.positionAlongLine(0.5-e, True)
after = line.positionAlongLine(0.5+e, True)

dX = after.firstPoint.X - before.firstPoint.X
dY = after.firstPoint.Y - before.firstPoint.Y

# angle of the midpoint segment
angle = atan2(dX, dY) * 180 / pi
newpoint = midpoint.pointFromAngleAndDistance(angle + 90, dist)

return arcpy.Polyline(arcpy.Array((midpoint.firstPoint, newpoint.firstPoint)))
``````

You could use cursors to read the line geometries and write them to a new feature class. Or, for a "great" 1 liner:

``````arcpy.CopyFeatures_management([tangentLine(line, 1000)
for line in arcpy.CopyFeatures_management("myFC", arcpy.Geometry())],
"in_memory/tangentLines")
``````

The `+90` will place the tangent line on the right side of the input line (based on digitized direction).

• Interesting, I knew you could use geometries as inputs for copy features, but I didn't know you could set the output to an `arcpy.Geometry()` object as well. – crmackey Jul 13 '16 at 1:25