2

Say I have a spatialLines(DataFrame) object in R with a high level of geographic detail. I want to simplify this object (reduce the number of coordinate points needed to create the object, some loss of detail is ok) and then convert it into an igraph object.

Each coordinate point should be a node in the graph. The graph node attributes should contain the geographic coordinates and the edge attributes should contain the geographic distance between the nodes. The edges should also inherit the attributes stored in the DataFrame portion of the SpatialLines object.

Here is what I've done so far:

readShapeFile <- function(path, filename, crs){
    shapefile <- readOGR(path.expand(path), filename)
    if(is.na(is.projected(shapefile))){
        projection(shapefile) <- CRS(crs)
    } else{
        shapefile <- spTransform(shapefile, CRS(crs))
    }
    return(shapefile)
}

canal_shapefile <- readShapeFile(PATH, FILENAME, "+init=epsg:4326")

lines <- canal_shapefile
length(coordinates(lines)[[1]][[1]][, 1]) ### To indicate how 'complex' the object is.
lines <- gSimplify(lines, tol = .001)
length(coordinates(lines)[[1]][[1]][, 1])

nodes <- NULL
edges <- NULL
for(i in 1:length(coordinates(lines))){
  nodes <- rbind(nodes, coordinates(lines)[[i]][[1]])
  for (j in 2:length(coordinates(lines)[[i]][[1]][, 1])){
    node1 <- coordinates(lines)[[i]][[1]][j - 1, ]
    node2 <- coordinates(lines)[[i]][[1]][j, ]
    dist  <- distance(node1[2], node1[1], node2[2], node2[1])$distance
    edges <- rbind(edges, c(node1, node2, dist))
  }
}
colnames(edges) <- c("node1_long", "node1_lat", "node2_long", "node2_lat", "dist")

NODE1 <- match(sprintf("%s:%s", edges[, "node1_long"], edges[, "node1_lat"]),
           sprintf("%s:%s", nodes[, 1], nodes[, 2]))
NODE2 <- match(sprintf("%s:%s", edges[, "node2_long"], edges[, "node2_lat"]),
           sprintf("%s:%s", nodes[, 1], nodes[, 2]))
EDGES <- cbind(NODE1, NODE2, edges[, "dist"])
NODES <- cbind(1:length(nodes[, 1]), nodes)

g <- graph.data.frame(EDGES, FALSE, NODES)

However, the gSimplify command removes the DataFrame. I still need to double check this is right.

Data is the canals shapefile loaded as a SpatialLinesDataFrame from https://my.vanderbilt.edu/jeremyatack/data-downloads/.

LJB
  • 353
  • 4
  • 10
  • 2
    Please provide the reproducible code and data for what you've tried thus far. http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Hack-R Jun 02 '16 at 05:14
  • @Hack-R, I added the data source and partial solution. Thanks. – LJB Jun 04 '16 at 05:04

1 Answers1

0

Without getting into details of your spatialLines object your most likely approach is using graph.data.frame with argument vertices not NULL.

Based on your scarce description it could be like this:

g = graph.data.frame(edge_list_with_distances, FALSE, points_with_coordinates) 

where:

points_with_coordinates is a data frame containing all the points with their attributes (first column is a point name or unique id, which become symbolic vertex names in the resulting graph)

edge_list_with_distances is a data frame with the distances between those points: the first two columns must correspond to vertex symbolic names from points_with_distances).

topchef
  • 19,091
  • 9
  • 63
  • 102