Search code examples
rgeojsonr-sftopojson

converting sf object to topojson


I am trying to create a list that is correctly formatted as topoJSON from an sf object.

What would work when reading a valid topoJSON file is:

sa <- jsonlite::read_json("https://raw.githubusercontent.com/pachadotdev/d3po/main/dev/south-america.topojson", simplifyVector = F)

What I am trying to do is:

# install_github("pachadotdev/canadamaps")
library(canadamaps)

library(sf)
library(geojsonio)

provinces <- get_provinces()
provinces <- st_as_sf(provinces)

geojson_write(provinces, file = "provinces.geojson")

provinces2 <- geojson_read("provinces.geojson")

geo2topo(provinces)

Error: no 'geo2topo' method for sftbl_dftbldata.frame

Is there any option to convert to topoJSON from R?

I tried saving as geoJSON and then re-exporting in QGIS, but it doesn't save as topoJSON.


Solution

  • geo2topo works on JSON strings, not R objects.

    Start with the geoJSON file you wrote in your example. ogrinfo tells me its geoJSON:

    $ ogrinfo provinces.geojson 
    INFO: Open of `provinces.geojson'
          using driver `GeoJSON' successful.
    1: provinces (Multi Polygon)
    

    Read it into R as text - this is the plain text geoJSON:

    > s = readLines("provinces.geojson")
    Warning message:
    In readLines("provinces.geojson") :
      incomplete final line found on 'provinces.geojson'
    > substr(s, 1, 100)
    [1] "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"pruid\":46,\"prname\":\"Manitob"
    

    Now convert to topoJSON string:

    > tj = geojsonio::geo2topo(s)
    > substr(tj, 1, 100)
    {"type":"Topology","objects":{"foo":{"type":"GeometryCollection","geometries":[{"type":"MultiPolygon 
    

    and write text to file:

    > writeLines(tj, "tj.topojson")
    > 
    

    Giving what gdal interprets as topoJSON:

    $ ogrinfo tj.topojson 
    INFO: Open of `tj.topojson'
          using driver `TopoJSON' successful.
    1: foo (Multi Polygon)
    

    I'm not sure where it gets the foo layer name from, this can probably be set to something else somewhere, unless its actually in the data...