4

I have a polygon which I know is a rectangle, although it may be at any orientation:

Example polygon

I want to shrink this polygon by a third of the width from two sides, so that I just get the strip in the middle - ending up with a result like the red area in this image:

enter image description here

I can't think how to go about doing this easily. If I try and negatively buffer the polygon then it will be shrunk on all sides. I have many tens of thousands of these polygons to do - so obviously can't do them manually.

Any ideas? I have access to ArcGIS, QGIS and am relatively experienced at Python programming - if that helps.

6
  • 4
    How do you decide which sides are the "sides" and which the "ends"? Is it always going to end up with a red section more vertical than horizontal?
    – Spacedman
    Commented Apr 1, 2014 at 12:42
  • Can you provide a sample shapefile/other file format with a few features in?
    – Spacedman
    Commented Apr 1, 2014 at 12:47
  • 1
    Good question. The red section should always be more vertical. I was wondering if there was a way round this that didn't involve iterating through all of the polygons and changing vertices manually - I can imagine that being a pain to get properly right (particularly for polygons that go across the equator/greenwich meridian).
    – robintw
    Commented Apr 1, 2014 at 12:49
  • 1
    There's another complication. Are these in lat-long? Are they "large"? Are they rectangles in lat-long, and hence not really rectangles? Hmmm
    – Spacedman
    Commented Apr 1, 2014 at 12:58
  • 2
    Quick question, how is the polygon constructed? Is it 4 vertices, one for each corner or was it constructed through a rasterization process so actually its loads of vertices but in a straight line?
    – Hornbydd
    Commented Apr 1, 2014 at 14:32

3 Answers 3

5

Here's some R code that does the job, the caveat being we are in cartesian coordinates. The input matrix coords is a 5x2 matrix of x,y columns, with the last point being coincident with the first point. This is what you get out of spatial objects in R when you read a shapefile, for example.

thinrect <- function(coords, factor=1/3){
    dx = diff(coords[,1])
    dy = diff(coords[,2])
    ## test if slope(1-2) is > slope(2-3)
    w = diff(atan2(abs(dx[1:2]), abs(dy[1:2])) %% pi) > 0
    ## if it is, then wrap it round so the first side is the steepest
    if(w){
        coords = rbind(coords[-1,], coords[1,])
        dx = c(dx[-1],dx[1])
        dy = c(dy[-1],dy[1])
    }
    ## now its just four points offset from corners 1 and 3
    dxy = c(dx[1],dy[1])
    p1 = coords[1,] + factor*dxy
    p2 = coords[1,] + (0.5+factor/2)*dxy
    p3 = coords[3,] - (factor)*dxy
    p4 = coords[3,] - (0.5+factor/2)*dxy

    rbind(p1, p2, p3, p4, p1)
}

Here's the output on a rectangle under various rotations. Note how the selected rectangle changes to stay parallel to the steepest side.

enter image description here

Simple usage, creating a 5x2 matrix of a unit square:

> coords=matrix(c(0,0,0,1,1,1,1,0,0,0),ncol=2,byrow=TRUE)
> coords
     [,1] [,2]
[1,]    0    0
[2,]    0    1
[3,]    1    1
[4,]    1    0
[5,]    0    0
> thinrect(coords)
        [,1] [,2]
p1 0.3333333    1
p2 0.6666667    1
p3 0.6666667    0
p4 0.3333333    0
p1 0.3333333    1
> plot(coords)
> polygon(thinrect(coords))

Looping this over a shapefile is pretty trivial.

The algorithm could be ported to Python pretty simply too.

2
  • I am very interested in understanding your answer. I am not a mathematician and I have never used R. What I am struggling with is your matrix input and what a 5x2 matrix actually holds. Could you update your answer to show a simple example and the sort of data it would hold?
    – Hornbydd
    Commented Apr 7, 2014 at 8:01
  • Thanks for the example, I will go away and have a good think as I can see this approach would be orders of magnitude faster than my model builder approach!
    – Hornbydd
    Commented Apr 7, 2014 at 12:05
3

This can be solved with a model but there are 4 caveats:

  • You need an Advance (ArcInfo) license
  • This model assumes your rectangle is a rectangle so the 2 vertical sides are longer
  • Your rectangle is constructed from 4 vertices only
  • If you want to automate this then all your rectangles must have the same dimensions

Model

So after running this model you you are left with the remaining centre rectangle as shown in this image:

Finished rectangle

You would need to wrap this up with an iterator and adjust the various parameters as you require.

1

I created an ArcGIS Create Custom Grid tool that could be useful for this. However, it might have trouble if any of the rectangles are oriented like a diamond shape.

You would set the vertical division to 3 and leave the horizontal to 0.

After the tool is ran you need to use the Split Polygons tool in the Advanced Editing toolbar.

If you use it, let me know if you have any problems.

You can download the toolbox at the top of the page here:

http://ianbroad.com/creating-quarter-quarter-section-grid-python/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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