【问题标题】:Efficiently split rectangle given by top left and bottom right coordinates into smaller rectangles有效地将由左上角和右下角坐标给出的矩形分割成更小的矩形
【发布时间】:2018-12-21 13:23:06
【问题描述】:

我有一个由纬度和经度给出的矩形,用于所述矩形的左上角和右下角。我想把这个矩形分成几个较小的矩形。较小的矩形也应该由左上角和右下角的坐标给出。

到目前为止,我可以通过创建占位符列表然后运行嵌套的 for 循环来创建较小的矩形。

我不认为这是一个有效的解决方案,并希望使代码更高效。

输出最好是listdata.tabledata.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
  }
}

【问题讨论】:

  • Ups,示例代码中有错字。正在修复
  • 这个例子现在应该已经修复了。
  • 所以您正试图找到每个具有latlon 组合顶点的矩形?
  • 不是每个。我只需要将大矩形分解成一些较小的、不重叠的矩形。

标签: r


【解决方案1】:

与 Halvorsen 的基本想法相同,但由于感兴趣的坐标都以可预测的方式间隔开,因此进行匹配似乎有点浪费。

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)

【讨论】:

    【解决方案2】:

    这个怎么样?将所有的索引组合起来,保留上一步和上一步的组合,然后改回坐标?

    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]
    

    【讨论】:

    • 感谢您的建议!这看起来很有希望,尽管在我看来一定是缺少一些矩形
    • 具体来说,我认为解决方案会删除应该包含的一列和一行
    • 另外,我宁愿避免这种形式的expand.grid。它创建了一个太大的对象
    • 我认为这可能可行。首先:rectangles = expand.grid(lat1 = seq_lat,lon1 = seq_lon),然后:rectangles$lat_br = lat[rectangles$lat1]rectangles$lat_tl = lat[rectangles$lat1 + 1]rectangles$lon_br = lon[rectangles$lon1 + 1]rectangles$lon_tl = lon[rectangles$lon1]
    • 是的,看起来更好。
    【解决方案3】:

    最后,我选择了以下解决问题的方法。它的灵感来自 Svenhalvorson 在使用 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]
                      )]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 2011-04-14
      相关资源
      最近更新 更多