11

I would like to take a polygon feature class with multiple irregular polygons, and have Arc draw parallel lines inside of each polygon. Ideally, it would be nice for Arc to figure out the angle of the longest side of the polygon and draw parallel lines to that side, but to keep it simple, I think if I could just enter one angle for all the parallel lines, that would be easier.

So line angle, width between lines, min/max length, and buffer width from the sides of the polygons are what my basic criteria are.

Image attached if that helps.

enter image description here

  • Is it a requirement for the lines to end a certain distance from the polygon edge? – cndnflyr Sep 17 '14 at 17:00
  • yes, I need to have a buffer away from the the edges. If I can declare that value, that would be great. Thanks. – Tx_Dan Sep 17 '14 at 18:16
8

As @cndnflyr mentions, this can be scripted in Python.

Script Tool UI:

enter image description here

Sample Output: enter image description here

# import libraries
import arcpy

# set input/output parameters
polyFC = arcpy.GetParameterAsText(0)        # input polygons
outParallel = arcpy.GetParameterAsText(1)   # output parallel lines
lineSpacing = arcpy.GetParameterAsText(2)   # line spacing
buffDist = arcpy.GetParameterAsText(3)      # inner buffer distance

# parse numbers from parameters
lineSpaceNum = float(lineSpacing.split(' ')[0])
buffNum = float(buffDist.split(' ')[0])

# establish spatial reference
desc = arcpy.Describe(polyFC)
SR = desc.spatialReference

# set overwrite environment
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = SR

parallels = []
# loop through each input shape
for row in arcpy.da.SearchCursor(polyFC, ["SHAPE@"], spatial_reference=SR):

    # create inner buffer
    polyBuff = row[0].buffer(buffNum * -1)

    # create hull rectangle to establish a rotated area of interest
    coordSplit = row[0].hullRectangle.split(' ')

    # collect corner coordinates
    coordList = arcpy.Array([arcpy.Point(coordSplit[0],coordSplit[1]),arcpy.Point(coordSplit[2],coordSplit[3]),arcpy.Point(coordSplit[4],coordSplit[5]),arcpy.Point(coordSplit[6],coordSplit[7]),arcpy.Point(coordSplit[0],coordSplit[1])])

    # create lines from hull rectangle
    currentLines = []
    for pointNum in range(0,4):
        arcpy.Array([coordList.getObject(pointNum),coordList.getObject(pointNum+1)])
        hullRecLine = arcpy.Polyline(arcpy.Array([coordList.getObject(pointNum),coordList.getObject(pointNum+1)]))
        currentLines.append(hullRecLine)

    # compare first and second line to determine if first line is short or long
    firstLong = 0
    if currentLines[0].length > currentLines[1].length:
        firstLong = 1

    # calculate number of points needed along short axis
    numPoints = int(math.floor(currentLines[firstLong].length/lineSpaceNum))

    # create and join points to create parallel lines
    for point in range(1,numPoints+1):
        shortPoint1 = currentLines[firstLong].positionAlongLine(lineSpaceNum*point)
        shortPoint2 = currentLines[firstLong + 2].positionAlongLine(currentLines[firstLong + 2].length - (lineSpaceNum*point))
        parallel = arcpy.Polyline(arcpy.Array([shortPoint1.centroid,shortPoint2.centroid]), SR)

        # intersect parallel lines with buffer
        parallelBuff = parallel.intersect(polyBuff,2)
        parallels.append(parallelBuff)

# write geometries to disk
arcpy.CopyFeatures_management(parallels, outParallel)

# add to map
mxd = arcpy.mapping.MapDocument("CURRENT")
dataFrame = arcpy.mapping.ListDataFrames(mxd, "*")[0]
addLayer = arcpy.mapping.Layer(outParallel)
arcpy.mapping.AddLayer(dataFrame, addLayer)

del row
  • Wow this beautiful, phloem! Will take a look. Thank you so much! – Tx_Dan Sep 20 '14 at 3:04
  • This is a great use of the methods in the SHAPE object. It's elegant. The only thing it is missing is setting the angle of the lines. As is it is it will draw the lines along the longest side of the polygon. – cndnflyr Sep 29 '14 at 16:02
4

This could be done with Python, but it would take some time to write it out.

I think the quickest way to implement it without Python is to have a template SHP file of these parallel lines. Have a few if you have varying widths needed, and just use the appropriate one for that Polygon. Make the template lines cover enough area to cover the largest Polygon you'll encounter.

  1. While editing, move the lines over the polygon.
  2. Use the Rotate tool, move the anchor point to where a Parallel line and the Polygon edge match, and rotate the lines so it snaps to the Polygon edge you lined it up on.
  3. Convert the Polygon to a Polyline
  4. Buffer the Polyline whatever distance you want the Parallel lines to be from the polygon edge.
  5. Use the Erase tool to erase the Polylines that are covered by the Buffered Polygon Edge
  6. Select by location all the lines that aren't inside the polygon and delete them. Or I think the Clip tool would work too.
  7. Select by attribute all the lines that are less than a certain length (too short to keep, although you might need to add a field and calculate the geometry first), and more than a certain length (too long to keep if that's what you want), delete them.
  8. Rinse and Repeat...

Steps 3 through 7 could be Modeled, without having to write any code.

Much the same process could be used for coding the process, but instead of having template lines, you could have the code draw the lines at the right angle, distance apart, etc. I haven't done this for awhile, but I think a Python library like shapely would help. Just make sure it covers a larger area than the Polygon, and use the tools to automatically convert to polyline, buffer, erase, select the lines not inside the polygon, and delete them.

  • Thanks for the detailed answer. I will give this a try and see how it works. Thanks! – Tx_Dan Sep 18 '14 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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