# How do I create proportionate inner buffers which reduce in size based on a percentage, to a specific point

I am working in ArcGIS and I have a 75 basin polygons and a point feature (called origin point) within each polygon. (Not necessarily in the centre of the polygons). I want to create 100 polygons inside the basin polygons ranging in distance from the origin from 1%, 2% etc through to 100% of the basin polygon. So the 1% polygon would have a boundary 1% of the way from the origin point. 100% polygon would be the original basin polygon.

I feel like there should be a function for this.

Inner buffers do not work as they are based on a distance rather than a percentage and do not take into account that I would like to 'shrink' the polygons back to the origin point.

I have seen people suggest QGIS but would this work if I want the polygons to 'shrink proportionately' back to a specific point?

I have tried:

1. converting basin polygons to vertices.
2. performing a near analysis to calculate distance of vertices to origin point and adding in X/Y coordinates
3. Creating xy lines from origin to each vertice creating star like patterns.
4. I have then split the lines by 100% and was going to convert to vertices and join the vertices to create new lines.

The issue is that because the basin polygons are not regular the lines sometimes exit the polygon and reenter making this method not work.

I am hoping to do this without coding.

• Definitely worth trying to script this out. This seems like a good opportunity to dig in to ArcPy and python. – Tangnar Jul 20 '15 at 13:48
• Just to attempt to solve the problem once (ie not for every polygon but just one) I think the issue here is you don't want to buffer them, you want to scale them. So you'd create a copy and then scale it to 99% of original size using the source point as the scaling origin. There's another question around here about 'buffering exactly 1km' from an irregular shape that is similar, but I can't find it at the moment. – Chris W Jul 20 '15 at 21:25

As one can see from the picture

the task has a solution for shapes equal to their own convex hull. If it is not the case, the position of point and 'un-convexness' of polygon might create artefacts. Output can be slightly improved by using minimum spanning tree of the points, but it's cheating and too much for today.

``````import arcpy, traceback, os, sys
from arcpy import env
env.overwriteOutput = True
try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
mxd = arcpy.mapping.MapDocument("CURRENT")
layers = arcpy.mapping.ListLayers(mxd)
points, catchments="centres","subcatchments"
pointsLr = arcpy.mapping.ListLayers(mxd,points)[0]
catchmLR = arcpy.mapping.ListLayers(mxd,catchments)[0]
dDest=arcpy.Describe(pointsLr)
SR=dDest.spatialReference
g = arcpy.Geometry()
pointsList=arcpy.CopyFeatures_management(pointsLr,g)
pgonsList=arcpy.CopyFeatures_management(catchmLR,g)
percents=range(10,100,10)
gList=[]
nPoints=len(pointsList)
for i in range(nPoints):
bigList=[]
pCentre=pointsList[i].firstPoint
pGon = pgonsList[i]
outLine=pGon.boundary()
outPoints=outLine.getPart(0)
for p in outPoints:
smalList=[]
array = arcpy.Array([pCentre,p])
ray=arcpy.Polyline(array,SR)
crosses=ray.intersect(outLine,1)
lMax=ray.length
for pnt in crosses:
lCur=ray.measureOnLine(pnt)
if lCur<=lMax:
pNearest=pnt;lMax=lCur
array = arcpy.Array([pCentre,pNearest])
short=arcpy.Polyline(array)
for perc in percents:
theP=short.positionAlongLine (float(perc)/100,True)
theP=theP.firstPoint
smalList.append(theP)
bigList.append(smalList)
m=0
for perc in percents:
array = arcpy.Array()
for smalList in bigList:
p=smalList[m]
web=arcpy.Polyline(array)
gList.append(web)
m+=1

outp=r"d:\out.shp"
arcpy.CopyFeatures_management(gList,outp)

except:
message = "\n*** PYTHON ERRORS *** "; showPyMessage()
message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()
``````

I would recommend scripting this as you'll save a hell of a lot of time...but you could do this via adding fields to the attribute field and run an analysis to produce the proportional distance value from the point to the basin edge.

Are you looking to buffer distance from the point to the basin edge or from the basin edge to the point?

With this data you can then calculate the buffer distance either derived from the basin edge to the point or from the point to the basin edge.

I am assumming you have an ArcGIS Advanced Licence as you already mentioned the Near tool

Here's an example running from the point to the basin edge. Ending by clipping the buffer to the basin edge...

1. Calculate the distance per centre point to the closest basin edge using the Near tool.
2. Take the linear distance value (make sure you run the calculation with a projected CRS) add that to the attribute table of the points database.
3. Then calculate the proportion distance, using the Field Calculator, from the point to basin edge 100 times in increments of 1 per point. Each point will end up with 100 fields (i.e. for each percentage).
4. Analysis with multi-buffer ring, you'll manually add the 100 distance values into the buffer tool for each point.
5. Then clip the buffer to the basin polygon (one by one selecting the basin before clipping).

Just to summarise how coding will same you time, and your fingers on the mouse... step three alone has 100 add field operations and a further 100 operations to manually add the percentage calculation for each field.