hypertidy / toposhop

2 stars 0 forks source link

TopoJSON #5

Open mdsumner opened 7 years ago

mdsumner commented 7 years ago

We need a parser this format, so we can demonstrate the rangl-dplyr based decomposition.

What's the best way?

"{\"type\":\"Topology\",\"objects\":{\"collection\":{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Polygon\",\"properties\":{\"a\":1},\"arcs\":[[0,1],[2]]},{\"type\":\"Polygon\",\"properties\":{\"a\":2},\"arcs\":[[-1,3]]}]}},\"arcs\":[[[6503,5999],[-894,-5999]],[[5609,0],[-5609,0],[0,9999],[6097,0],[2032,-2000],[-4064,-1000],[2438,-1000]],[[1626,2000],[2439,0],[0,2000],[-1626,1999],[-813,-1999],[0,-2000]],[[6503,5999],[2439,300],[1057,-3299],[-4390,-3000]]],\"transform\":{\"scale\":[0.00012301230123012302,0.00010001000100010001],\"translate\":[0,0]},\"bbox\":[0,0,1.23,1]}"

The last array called "arcs" are paths of transformed pair-coordinates (in R should be a list of 2-column matrices).

The properties arcs are nested 0-based indexes into that list of paths. If the index is negative the arc is reverse direction.

If you parse that with jsonlite, the paths get interpreted as vectors, matrices, lists of atomic values, or data frames depending on their size and the arguments you choose, but I can't find any that make sense. It can be a fully recursive list with atomic elements. The indexes are nested in the same way that simple features are, so arc-indexes act like matrix paths within POLYGON, MULTIPOLYGON, etc.

## toposhop-topojson branch
tx <- readLines("inst/extdata/file.topojson")

## recursive all the way down?
gx <- jsonlite::fromJSON(tx, simplifyDataFrame = FALSE, simplifyMatrix = FALSE, simplifyVector = FALSE) 
## nothing like this can work, it needs to be raw
#arcindex2tibble <- function(x) tibble::tibble(arc = unlist(as.vector(unlist(lapply(x$arcs, "[")))))
#lapply(gx$objects[[1]], function(x) dplyr::bind_rows(lapply(x$geometries, arcindex2tibble), .id = "object"))

library(sf)
sfx <- sf::st_read("inst/extdata/file.geojson")

plot(st_geometry(sfx))
url <- "https://raw.githubusercontent.com/shawnbot/d3-cartogram/master/data/us-states.topojson"

library(leaflet)
leaflet() %>% addGeoJSONv2(readLines(url))
## jsonlite does a weird simplify thing where a could-be-dimensioned array
## might be [1, 5] or [5, 1, 1] but for TopoJSON we can't just treat all
## child-of-geometry arc arrays as 1D because the rules applied have different meanings
## for the arc coordinates and the arc indexes
x <- jsonlite::fromJSON(url, simplifyVector = FALSE)
names(x)
x$type
x$transform
names(x$objects)
lapply(x$objects, "[", "type")

lapply(x$objects, function(x) unique(x$geometries$type))

lapply(x$objects, function(x) length(x$geometries$arcs))

unlist(range(lapply(x$arcs, nrow)))
unique(range(lapply(x$arcs, ncol)))

str(x)
mdsumner commented 7 years ago

rjson does not present the simplify to array problems that jsonlit haa