No es realmente diferente de la creación de un sistema de coordenadas Cartesiano; la única complicación consiste en representar los arcos circulares que unen cada celda.
Como en el Cartesiano caso, la entrada debe incluir un origen, un conjunto de radios a utilizar, y un conjunto de ángulos de usar. Para mayor generalidad, no tenemos que no requieren que los radios o los ángulos de ser igualmente espaciados.
He aquí un ejemplo R
que muestra una cuadrícula con diferentes radial anchos (pero no de partida en el origen!) y angular constante anchos (pero no necesariamente cubren un círculo completo). Representa las células como polígonos, porque esto es útil para las típicas aplicaciones de la red, tales como la recolección de puntos dentro de las células (un punto en el polígono de la operación).
require(shapefiles)
shape.polygon <- 5 # Use 3 for polyline
#
# Grid specification.
#
origin <- c(100,200)
r <- c(1,3,6,10) # In same units as the origin coordinates
theta <- seq(from=-80, to=150, length.out=14) * pi/180 # Must be in radians
#
# Create and write the grid.
#
g <- radial.grid(r, theta, origin, 6 * pi/180)
shapefile <- convert.to.shapefile(g$shapes, g$attrs, "Id", shape.polygon)
write.shapefile(shapefile, "f:/temp/grid", arcgis=T)
Obviamente el trabajo duro está hecho por radial.grid
. El límite de una celda es atravesada por el siguiente al de su exterior arco, salto a la final del interior del arco, después de que, en orden inverso, y luego para volver al principio del primer arco. Poligonal aproximaciones a estos arcos crear vértices aproximadamente cada e
radianes (controlado por la persona). El trabajo de la creación de estos arcos se reduce a la mitad mediante el cálculo de uno de ellos y, a continuación, reescalado y revertir el proceso para crear el otro. (El trabajo podría ser la mitad otra vez por la no posibilidad arcos compartida por las células, pero no me molesta para hacer esta optimización.)
Dentro de radial.grid
, entonces, hay dos funciones auxiliares: arc
crea una unidad-de arco de radio a partir de un ángulo a otro. (Los ángulos se miden con la matemática de la convención: en radianes en sentido antihorario desde el oriente. A medida que [aún en radianes] en sentido horario desde el norte, solo cambie sin
y cos
.) cell
utiliza arc
como se describe a crear una poligonal de la célula. La iteración a través de todas las células se realiza por lapply
para crear una lista de polígonos. El shapefiles
paquete necesidades de esta lista que se acoplan en una matriz. Finalmente, radial.grid
crea algunos atributos interesantes: un índice del sector, con una radial del índice, y un único integral identificador.
radial.grid <- function(r, theta=c(0, 2*pi), origin=c(0,0), e=(pi/180)) {
if (length(r) < 2) stop("Provide at least two radii.")
if (length(theta) < 2) stop("Provide at least two angles.")
# origin: (x,y) coordinates of center of grid
# r: vector of radii
# theta: vector of angles
# e: angular increment to approximate circular arcs
#
# Returns a list of dataframes convertible to a shapefile, named
# `shapes` and `attrs`.
#-----------------------------------------------------------------------------#
#
# Create a sequence of cartesian coordinates, as a 2 by m matrix, tracking
# in the positive direction along a circular arc from (1,theta1) to (1,theta2).
#
arc <- function(theta1, theta2) {
dtheta <- (theta2 - theta1) %% (2 * pi) # Assure a positive orientation
theta <- seq(from=theta1, to=theta1+dtheta, length.out=ceiling(dtheta/e)+1)
sapply(theta, function(a) c(cos(a), sin(a)))
}
#
# Create a polygon with identifier `id` for a radial cell bounded by angles
# `theta1` and `theta2` and radii `r1` < `r2`.
#
cell <- function(id, origin=c(0,0), r1, r2, theta1, theta2) {
a <- arc(theta1, theta2)
if (r1==0) b <- matrix(c(0,0), nrow=2)
else b <- r1 * a[, dim(a)[2]:1]
a <- r2 * a
xy <- cbind(a, b, a[,1])
rbind(rep(id, dim(xy)[2]), xy + origin)
}
#
# Preprocess the input: make sure radii and angles are sorted.
#
rho <- sort(r)
th <- sort(theta)
#
# Create the cells delimited by `rho` and `th`.
#
n.annuli <- (length(rho)-1)
n.wedges <- (length(th)-1)
ixy <- lapply(1:(n.wedges * n.annuli)-1, function(ij) {
i <- ij %% n.wedges + 1; j <- floor(ij/n.wedges)+1;
cell(ij+1, origin, rho[j], rho[j+1], th[i], th[i+1])
}) # List of identified polygons
#
# Prepare the cells for writing in shapefile format.
#
ixy <- do.call(cbind, ixy) # Flatten into a matrix
df.shapes <- data.frame(Id=ixy[1,], X=ixy[2,], Y=ixy[3,])
df.table <- expand.grid(1:n.wedges, 1:n.annuli)
colnames(df.table) <- c("Sector", "Radius")
df.table$Id <- df.table$Sector + n.wedges*(df.table$Radius-1)
list(shapes=df.shapes, attrs=df.table)
}