I have a matrix that consists of X and Y coordinates and their offsets (nXSize
, nYSize
). Based on it, I create polygons in a loop. Below code is very slow for a large number of points, can I somehow optimize it?
mat = structure(c(1, 1, 1, 1, 1, 1, 1, 65, 129, 193, 257, 321, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64), .Dim = c(6L, 4L),
.Dimnames = list(
c("1", "2", "3", "4", "5", "6"),
c("x", "y", "nXSize", "nYSize")))
lst = sf::st_sfc(sf::st_polygon())
for (i in seq_len(nrow(mat))) {
p1 = c(mat[i, 1], mat[i, 2])
p2 = c(mat[i, 1] + mat[i, 3], mat[i, 2])
p3 = c(mat[i, 1] + mat[i, 3], mat[i, 2] + mat[i, 4])
p4 = c(mat[i, 1], mat[i, 2] + mat[i, 4])
pts = matrix(c(p1, p2, p3, p4, p1), ncol = 2, byrow = TRUE)
pts = pts - 1 # align matrix to P(0, 0)
polygon = sf::st_sfc(sf::st_polygon(list(pts)))
lst = c(lst, polygon)
}
# remove empty geometry
lst = lst[-1]
This should be faster. First use vectorization to compute all of the vertices and center them:
p1 <- cbind(mat[, 1], mat[, 2]) - 1
p2 <- cbind(mat[, 1] + mat[, 3], mat[, 2]) - 1
p3 <- cbind(mat[, 1] + mat[, 3], mat[, 2] + mat[, 4]) - 1
p4 <- cbind(mat[, 1], mat[, 2] + mat[, 4]) - 1
ply <- cbind(p1, p2, p3, p4, p1)
Now ply
is a matrix with one row for each polygon. Next convert ply
into a list of matrices (plys
) and then convert the list of matrices into a list of polygons (lst
):
plys <- lapply(1:nrow(ply), function(i) matrix(ply[i, ], ncol=2, byrow=TRUE))
lst <- sapply(plys, function(x) sf::st_sfc(sf::st_polygon(list(x))))