# Creating rectangles along line using ArcGIS for Desktop?

I'm trying to create rectangles along a line and can't seem to find a solution anywhere.

I've got a curved line roughly 16km (~10miles) long that I've placed points along in 5m increments. From there I need to create a rectangular buffer around these points with dimensions of 1600 m length and 400 m width (200 m on either side of the line).

Is there a method that I could use that would allow me to create rectangular buffer around these points but have the rectangle rotate with the direction of the line?

• 10 k = 16 m ? Or other way around? Commented Mar 23, 2016 at 0:05

## 2 Answers

Here is how you can use Python to automate your task. It evaluates your line at each point location (determined by 'point_spacing'), offset by 'tolerance', then creates rectangles to fit those angles & distances.

``````line_fc = 'line' # line feature class
sr = arcpy.Describe(line_fc).spatialReference # spatial ref
point_spacing = 200 # how far apart to draw points
points = [] # points container
tolerance = 50 # how far from points to evaluate line AND place rectangle ends
width = 25 # distance perpendicular to line
buffs = [] # buffer container
with arcpy.da.SearchCursor(line_fc,'SHAPE@',spatial_reference=sr) as cursor:
for row in cursor:
for i in range(point_spacing,int(row[0].length),point_spacing): # loop through points
current_point = row[0].positionAlongLine(i) # get point position
points.append(current_point) # add to list
point_ahead = row[0].positionAlongLine(i+tolerance).centroid # evaluate ahead
point_behind = row[0].positionAlongLine(i-tolerance).centroid # evaluate behind
dx = point_ahead.X - point_behind.X # x diff
dy = point_ahead.Y - point_behind.Y # y diff
angle = math.atan2(dy,dx) # angle between
point_ahead = arcpy.Point(current_point.centroid.X+(math.cos(angle)*tolerance),current_point.centroid.Y+(math.sin(angle)*tolerance)) # find rectangle end ahead
point_behind = arcpy.Point(current_point.centroid.X-(math.cos(angle)*tolerance),current_point.centroid.Y-(math.sin(angle)*tolerance)) # find rectangle end behind
pt1 = arcpy.Point(point_ahead.X+(math.sin(angle)*width),point_ahead.Y-(math.cos(angle)*width)) # rectangle corners
pt2 = arcpy.Point(point_ahead.X-(math.sin(angle)*width),point_ahead.Y+(math.cos(angle)*width))
pt3 = arcpy.Point(point_behind.X-(math.sin(angle)*width),point_behind.Y+(math.cos(angle)*width))
pt4 = arcpy.Point(point_behind.X+(math.sin(angle)*width),point_behind.Y-(math.cos(angle)*width))
buffs.append(arcpy.Polygon(arcpy.Array([pt1,pt2,pt3,pt4]),sr)) # add buffer to list
arcpy.CopyFeatures_management(buffs,r'in_memory\buffs') # write buffers
arcpy.CopyFeatures_management(points,r'in_memory\points') # write points
``````

• Nice answer! I can see this code being useful for all sorts of things. Commented Mar 22, 2016 at 23:38
• I'd use atan2 to define angle which is much safer option Commented Mar 23, 2016 at 0:02
• Ok, edited. The result is the same. Commented Mar 23, 2016 at 16:23
• I'm trying to get this to work using 10.0 and having trouble. Throws an error using arcpy.de.SearchCursor() and I cant seem to find a workaround using just arcpy.SearchCursor() using the variables listed. Could this be modified to use with 10.0? Commented Mar 31, 2016 at 16:15
• You can read (help.arcgis.com/En/Arcgisdesktop/10.0/Help/index.html#//…) and write (help.arcgis.com/En/Arcgisdesktop/10.0/Help/index.html#/…) geometries using the old cursors, but you'll have to figure that out yourself. The 10.0 Polyline object also does not have a positionAlongLine method, so you'll have to do a lot more trigonometry and bookkeeping. Commented Mar 31, 2016 at 16:35

A possible solution is:

1. Create a field that will hold the rotation you will want to apply
2. Populate this field with the rotation values
3. Run the Table To Ellipse (Data Management) tool to create ellipses centre on each point rotated.
4. Run the Minimum Bounding Geometry (Data Management) with RECTANGLE_BY_WIDTH set.

The problem is creating those rotation values, a possible way is this:

1. Run the Split Line At Vertices (Data Management)
2. Run Add Geometry Attributes (Data Management) with LINE_BEARING
3. Run Spatial Join to pass back the bearing held in the line dataset into you point dataset.

This logic assumes you have an Advance license.

• LINE-BEARING is the bearing from start of line to end of line. This might not be desired. I propose, buffer each Point by 1 meter, clip the roads by buffers, add Bearing-line to small segements. Join back to Points. Good post. Commented Mar 22, 2016 at 22:01
• I was thinking the bearing would have been on the line segment split by the vertices, but there are issues with that, such as a dense sequence of vertices, I think you idea of buffering would be a more robust option. Commented Mar 22, 2016 at 23:41
• This method works but it seems that for any ellipse that is not on a right angle (90 or 0 degrees) I get an skewed rectangle (parallelogram). Where the line is roughly 45 degrees the Minimum Bounding Geometry tool give me a skewed rectangle with a width of ~420m instead of the desired 400m. Commented Mar 24, 2016 at 20:42