Эффективно разделить прямоугольник, заданный верхними левыми и нижними правыми координатами, на меньшие прямоугольники - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть прямоугольник, заданный широтой и долготой для верхнего левого и нижнего правого углов указанного прямоугольника.Я хотел бы разбить этот прямоугольник на несколько меньших прямоугольников.Меньшие прямоугольники также должны быть заданы координатами для верхнего левого и нижнего правого угла.

До сих пор я мог создавать меньшие прямоугольники, создав список заполнителей, а затем запустив вложенный цикл for.

Я не думаю, что это эффективное решение и хотел бы сделать код более эффективным.

Выходные данные должны быть предпочтительно list или data.table.Каждая строка data.table может иметь 4 столбца, указывающих координаты.

Мой код пока:

# the big rectangle i want to split
big_rectangle <- list(top_left = c("lat" = 50.183297, "lon" = 14.223024),
                      bottom_right = c("lat" = 49.945189, "lon" = 14.706829))

# sequence along the sides of the rectangle:
lat <- seq(from = big_rectangle[["bottom_right"]]["lat"],
           to = big_rectangle[["top_left"]]["lat"], length = 20)
lon <- seq(from = big_rectangle[["top_left"]]["lon"],
           to = big_rectangle[["bottom_right"]]["lon"], length = 20)

# create a list of small rectangles, each given by its top left and bottom right corners:
holder <- vector("list", (length(lat) - 1) * (length(lon) - 1))
iterator <- 1
for (i in 1:(length(lat) - 1))
{
  for (j in 1:(length(lon) - 1))
  {
    holder[[iterator]] <- list(top_left = c("lat" = lat[i + 1], "lon" = lon[j]), bottom_right = c("lat" = lat[i], "lon" = lon[j+1]))
    iterator = iterator + 1
  }
}

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

Та же основная идея, что и у Халворсена, но, поскольку все интересующие координаты разнесены предсказуемым образом, сопоставление показалось немного расточительным.

width <- 5
height <- 4

brm <- do.call(cbind, big_rectangle)
lat <- seq(brm[1, 1], brm[1, 2], length.out=width+1)
lon <- seq(brm[2, 1], brm[2, 2], length.out=height+1)

eg <- expand.grid(lon=lon, lat=lat)

lr <- eg[-(1:(width+1)),]
ul <- eg[1:(nrow(eg)-(width+1)),]

corners <- cbind(upper_left=ul, lower_right=lr)
corners <- corners[1:nrow(corners) %% width != 0,]
rownames(corners) <- NULL
head(corners)

#   upper_left.lon upper_left.lat lower_right.lon lower_right.lat
# 1       14.22302       50.18330        14.34398        50.13568
# 2       14.34398       50.18330        14.46493        50.13568
# 3       14.46493       50.18330        14.58588        50.13568
# 4       14.58588       50.18330        14.70683        50.13568
# 5       14.22302       50.13568        14.34398        50.08805
# 6       14.34398       50.13568        14.46493        50.08805

Чтобы расположить координаты обратно в список по мереесли бы вы их могли сделать.

corners.l <- apply(corners, 1, 
  function(x) 
    list(upper_left=c(lon=x[[1]], lat=x[[2]]), 
        lower_right=c(lon=x[[3]], lat=x[[4]])))

corners.l[1]
# [[1]]
# [[1]]$upper_left
#      lon      lat 
# 14.22302 50.18330 

# [[1]]$lower_right
#      lon      lat 
# 14.34398 50.13568 

И только потому, что

plot(eg, cex=0, axes=FALSE)
points(corners[,1:2], pch=1, cex=2)
points(corners[,3:4], pch=16)
axis(1, unique(eg[,1]), floor(unique(eg[,1])*100)/100)
axis(2, unique(eg[,2]), floor(unique(eg[,2])*100)/100)

enter image description here

0 голосов
/ 29 декабря 2018

В итоге я выбрал следующее решение проблемы.Он вдохновлен ответом Свенхальворсона об использовании функции expand.grid.Кроме того, он избегает использования ненужных комбинаций и выводит data.table:

# load data.table library
library(data.table)
# create the large bounding box
big_rectangle <- list(top_left = c("lat" = 50.183297, "lon" = 14.223024),
                      bottom_right = c("lat" = 49.945189, "lon" = 14.706829))

# split the rectangle into smaller pieces
lat <- seq(from = big_rectangle[["bottom_right"]]["lat"], to = big_rectangle[["top_left"]]["lat"], length = 20)
lon <- seq(from = big_rectangle[["top_left"]]["lon"], to = big_rectangle[["bottom_right"]]["lon"], length = 20)

# index of the lon and lat vectors
seq_lat = 1:(length(lat)-1)
seq_lon = 1:(length(lon)-1)

# create combinanations of indices and store as data.table
rectangles = data.table(expand.grid(lat1 = seq_lat,lon1 = seq_lon))

# store the coordinates of small rectangles into data.table
rectangles[, `:=`(lat_br = lat[lat1],
                  lon_tl = lon[lon1],
                  lat_tl = lat[lat1 + 1],
                  lon_br = lon[lon1 + 1]
                  )]
0 голосов
/ 21 декабря 2018

Как насчет этого?Сделайте все комбинации индексов, оставьте те, которые являются шагом вверх и шагом, затем вернитесь к координатам?

seq_lat = 1:(length(lat)-1)
seq_lon = 1:(length(lon)-1)

rectangles = expand.grid(lat1 = seq_lat, lat2 = seq_lat, lon1 = seq_lon, lon2 = seq_lon)
keeps = rectangles$lat1 + 1 == rectangles$lat2 &  rectangles$lon1 + 1 == rectangles$lon2
rectangles = rectangles[keeps,]
rectangles$lat1 = lat[rectangles$lat1]
rectangles$lat2 = lat[rectangles$lat2]
rectangles$lon1 = lon[rectangles$lon1]
rectangles$lon2 = lon[rectangles$lon2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...