Wikipedia: a polygon is a plane figure that is bounded by a finite chain of straight line segments closing in a loop to form a closed chain or circuit

- Straight line segments?

OR

- Coordinates connected by a boundary “line”?

Does it matter?

Aren’t these all the same thing?

```
p <- cbind(x = c(0, 0, 0.75, 1, 0.5, 0.8, 0.69, 0),
y = c(0, 1, 1, 0.8, 0.7, 0.6, 0, 0))
plot(p, xlim = xl, ylim = yl)
lines(p)
```

```
## x y
## pt1 0.00 0.0
## pt2 0.00 1.0
## pt3 0.75 1.0
## pt4 1.00 0.8
## pt5 0.50 0.7
## pt6 0.80 0.6
## pt7 0.69 0.0
## pt8 0.00 0.0
```

Note that we visited 0,0 twice, when we first started as “pt1” and at the final destination as “pt8”. What if we left out the last 0,0?

```
npoints <- nrow(p)
plot(p, xlim = xl, ylim = yl, main = "no final link")
lines(p[seq(npoints - 1), ])
```

Well it’s obvious, we don’t have a polygon so we just end up with a line.

What if we use `polygon()`

rather than `lines()`

?

```
plot(p, xlim = xl, ylim = yl, main = "default polygon()")
polygon(p)
```

What happened? We have a closed loop of line segments.

We are seeing right through this polygon. We have to tell `polygon()`

to fill the space it contains with a colour (which might be white).

```
plot(p, xlim = xl, ylim = yl, main = "grey-fill")
polygon(p, col = "grey")
```

What if we have two of these kinds of objects? What goes wrong here?

```
p1 <- cbind(x = c(0, 0, 0.75, 1, 0.5, 0.8, 0.69, 0),
y = c(0, 1, 1, 0.8, 0.7, 0.6, 0, 0))
p2 <- cbind(x = c(0.2, 0.2, 0.3, 0.5, 0.5, 0.2),
y = c(0.2, 0.4, 0.6, 0.4, 0.2, 0.2))
pp <- rbind(p1, p2)
plot(pp, xlim = xl, ylim = yl, main = "yikes!")
polygon(rbind(p1, p2), col = "grey")
```

We have defined a *path* and we’ve told the polygon-drawing-tool to follow that path and fill space with a particular rule. (What?).

One way to fix this is to plot the two parts separately, but we have to cheat since the white “hole” is not a hole - we can no longer see the points on the inner ring.

```
plot(pp, xlim = xl, ylim = yl, main = "cheat's hole")
polygon(p1, col = "grey")
polygon(p2, col = "white")
```

The proper way to do this is to separate the parts of the path with the missing “NA” where we don’t want the path to stay connected. But, here `polygon`

doesn’t understand that it was meant to draw it as a hole.

```
pph <- rbind(p1, NA, p2)
plot(pph, xlim = xl, ylim = yl, main = "polygon with hole, or overlapping polygons?")
polygon(pph, col = "grey")
```

To really get a hole, we need to use `polypath`

, with the right rule.

```
pph <- rbind(p1, NA, p2)
plot(pph, xlim = xl, ylim = yl, main = "evenodd - clockwise/clockwise")
polypath(pph, col = "grey", rule = "evenodd")
```

```
pph <- rbind(p1, NA, p2[nrow(p2):1, ])
plot(pph, xlim = xl, ylim = yl, main = "winding - clockwise/anti-clockwise")
polypath(pph, col = "grey", rule = "winding")
```

- polygon() and polypath() are the same, until we need holes
- the “evenodd” rule counts how many boundaries are crossed from the inside-out
- the “winding” rule counts clock-wise and many anti-clock-wise turns (or vice versa)

Yes it’s more complicated - not just holes, but generally “self-intersecting” polygon paths.

This time the second polygon is an “island”.

```
p1 <- cbind(x = c(0, 0, 0.75, 1, 0.5, 0.8, 0.69, 0),
y = c(0, 1, 1, 0.8, 0.7, 0.6, 0, 0))
p3 <- cbind(x = c(0.2, 0.2, 0.3, 0.5, 0.5, 0.2) + 0.8,
y = c(0.2, 0.4, 0.6, 0.4, 0.2, 0.2))
pp <- rbind(p1, NA, p3)
plot(pp, main = "two polygons")
polypath(pp, col = "grey")
```

What if the smaller poly should be another colour?

```
plot(pp, main = "two polygons, or one multi-polygon?")
polypath(pp, col = c("grey", "firebrick"))
```

What if we had holes and islands, how does the function apply two different colours? (It can’t).

To get different colours we have to call polypath separately.

```
plot(pp, main = "polypath() multiple")
polypath(p1, col = "grey")
polypath(p3, col = "firebrick")
```

The `sp`

package makes this easy, right?

```
library(sp)
## no, this really is not easy
spoly <- SpatialPolygons(list(Polygons(list(Polygon(p1)), "p1"), Polygons( list(Polygon(p3)), "p3")))
plot(spoly, col = c("grey", "firebrick"), main = "sp SpatialPolygons")
```

(It’s another level of detail if we want attributes on each object.)

`Raster`

to the rescue, at least a little.

```
library(raster)
rpoly <- spPolygons(p1, p3)
plot(rpoly, col = c("grey", "firebrick"), main = "raster::spPolygons")
```