Skip to main content
1 of 5
FelixIP
  • 23.3k
  • 3
  • 31
  • 62

Input:

enter image description here

Output:

enter image description here

Algorithm:

  • Extend line on both ends by certain amount and do flat ends buffer
  • Repeat by changing extension length until precision required met

Script:

import arcpy
from arcpy import env
env.overwriteOutput = True
singleLine=r"in_memory\line"
singleBuffer=r"in_memory\pgon"

mxd = arcpy.mapping.MapDocument("CURRENT")
lines = arcpy.mapping.ListLayers(mxd,"LINES")[0]
buffers = arcpy.mapping.ListLayers(mxd,"BUFFERS")[0]
curT=arcpy.da.InsertCursor(buffers,"SHAPE@")

with arcpy.da.SearchCursor(lines,["SHAPE@","AREA_M2"]) as cursor:
    for shp,target in cursor:
        part=shp.getPart(0);origList=list(part)
##      get last vertices vector
        p1,p2=origList[-2],origList[-1]
        dX=p2.X-p1.X; dY=p2.Y-p1.Y; d1=pow(dX*dX+dY*dY,0.5)
        dXend=dX/d1;dYend=dY/d1
##      get first vertices vector
        p1,p2=origList[1],origList[0]
        dX=p2.X-p1.X; dY=p2.Y-p1.Y; d2=pow(dX*dX+dY*dY,0.5)
        dXstart=dX/d2;dYstart=dY/d2
##      define bounds
        L=target/shp.length/2
        low=L/2;high=L*2
            
        while True:
            middle=0.5*(low+high)
##      extend line        
            p1=arcpy.Point(origList[-1].X+middle*dXend,origList[-1].Y+middle*dYend)
            p2=arcpy.Point(origList[0].X+middle*dXstart,origList[0].Y+middle*dYstart)
            extList=[p2]+origList+[p1]
            extLine=arcpy.Polyline(arcpy.Array(extList))
            arcpy.CopyFeatures_management(extLine, singleLine)
##      get buffer ind repeat        
            arcpy.Buffer_analysis(singleLine, singleBuffer, middle,"FULL","FLAT","NONE","","PLANAR")            
            with arcpy.da.SearchCursor(singleBuffer,"SHAPE@") as inMem:
                for r in inMem:
                    pgon=r[0]
#       tolerance                    
            if (high-low)<0.01: break
            curArea=pgon.area
            if curArea<target:low=middle
            else:high=middle
        arcpy.AddMessage("Difference {:8.2f}%".format((curArea-target)/target*100))
        curT.insertRow((pgon,))
arcpy.Delete_management("in_memory")
        

It is good you are proficient with arcpy, you'll figure out parameters

FelixIP
  • 23.3k
  • 3
  • 31
  • 62