├── .gitignore ├── R ├── sysdata.rda ├── utils-pipe.R ├── georeference.R ├── cache.R └── locale.R ├── tests ├── testthat.R └── testthat │ └── test-get.R ├── docs ├── pkgdown.yml ├── reference │ ├── figures │ │ ├── README-example-1.png │ │ ├── README-tile-plot.png │ │ ├── README-tasmania-1.png │ │ └── README-tile-add-plot.png │ ├── pipe.html │ ├── index.html │ ├── mercator_tile_extent.html │ ├── ceramic_tiles.html │ └── down_loader.html ├── link.svg ├── docsearch.js ├── pkgdown.js ├── authors.html ├── pkgdown.css ├── CODE_OF_CONDUCT.html ├── docsearch.css └── index.html ├── man ├── figures │ ├── README-example-1.png │ ├── README-tasmania-1.png │ ├── README-tile-plot.png │ └── README-tile-add-plot.png ├── pipe.Rd ├── mercator_tile_extent.Rd ├── ceramic_tiles.Rd ├── down_loader.Rd └── cc_location.Rd ├── .Rbuildignore ├── data-raw ├── merc_world.R └── static-readme-figures.R ├── ceramic.Rproj ├── NAMESPACE ├── DESCRIPTION ├── CODE_OF_CONDUCT.md ├── README.Rmd └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/R/sysdata.rda -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ceramic) 3 | 4 | test_check("ceramic") 5 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.3.1 2 | pkgdown: 1.1.0 3 | pkgdown_sha: ~ 4 | articles: [] 5 | 6 | -------------------------------------------------------------------------------- /man/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/man/figures/README-example-1.png -------------------------------------------------------------------------------- /man/figures/README-tasmania-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/man/figures/README-tasmania-1.png -------------------------------------------------------------------------------- /man/figures/README-tile-plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/man/figures/README-tile-plot.png -------------------------------------------------------------------------------- /man/figures/README-tile-add-plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/man/figures/README-tile-add-plot.png -------------------------------------------------------------------------------- /tests/testthat/test-get.R: -------------------------------------------------------------------------------- 1 | context("test-get") 2 | 3 | test_that("getting tiles works", { 4 | expect_equal(2 * 2, 4) 5 | }) 6 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^data-raw$ 2 | ^CODE_OF_CONDUCT\.md$ 3 | ^README\.Rmd$ 4 | ^ceramic\.Rproj$ 5 | ^\.Rproj\.user$ 6 | ^docs$ 7 | ^\.Rhistory$ 8 | -------------------------------------------------------------------------------- /docs/reference/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/docs/reference/figures/README-example-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-tile-plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/docs/reference/figures/README-tile-plot.png -------------------------------------------------------------------------------- /docs/reference/figures/README-tasmania-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/docs/reference/figures/README-tasmania-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-tile-add-plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MilesMcBain/ceramic/master/docs/reference/figures/README-tile-add-plot.png -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /data-raw/merc_world.R: -------------------------------------------------------------------------------- 1 | m <- rworldmap::countriesLow 2 | library(spbabel) 3 | sptable(m) <- sptable(m) %>% dplyr::filter(y_ > -88) 4 | 5 | merc_world <- sp::spTransform(m, "+proj=merc +a=6378137.0 +b=6378137.0") 6 | usethis::use_data(merc_world, internal = TRUE) 7 | 8 | -------------------------------------------------------------------------------- /data-raw/static-readme-figures.R: -------------------------------------------------------------------------------- 1 | png("man/figures/README-tile-plot.png") 2 | ceramic::plot_tiles(ceramic_tiles(zoom = c(7, 9))) 3 | dev.off() 4 | 5 | png("man/figures/README-tile-add-plot.png") 6 | plotRGB(im) 7 | ceramic::plot_tiles(ceramic_tiles(zoom = 7), add = TRUE) 8 | dev.off() 9 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /ceramic.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /man/mercator_tile_extent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/georeference.R 3 | \name{mercator_tile_extent} 4 | \alias{mercator_tile_extent} 5 | \title{Tile extent} 6 | \usage{ 7 | mercator_tile_extent(tile_x, tile_y, zoom, tile_size = 256) 8 | } 9 | \arguments{ 10 | \item{tile_x}{x coordinate of tile} 11 | 12 | \item{tile_y}{y coordinate of tile} 13 | 14 | \item{zoom}{zoo level} 15 | 16 | \item{tile_size}{tile dimensions (assumed square atm, 256*256)} 17 | } 18 | \description{ 19 | Calculate tile extent for a given x, y tile at a zoom level. 20 | } 21 | \details{ 22 | Currently only Mapbox spherical Mercator is supported. 23 | } 24 | -------------------------------------------------------------------------------- /man/ceramic_tiles.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cache.R 3 | \name{ceramic_tiles} 4 | \alias{ceramic_tiles} 5 | \title{Tile files} 6 | \usage{ 7 | ceramic_tiles(zoom = NULL, type = "mapbox.satellite", 8 | source = "api.mapbox.com", glob = "*.jpg*", regexp = NULL) 9 | } 10 | \arguments{ 11 | \item{zoom}{zoom level} 12 | 13 | \item{type}{imagery type} 14 | 15 | \item{source}{imagery source} 16 | 17 | \item{glob}{see `fs::dir_ls`} 18 | 19 | \item{regexp}{see `fs::dir_ls`} 20 | } 21 | \description{ 22 | Find existing files in the cache. Various options can be controlled, this is WIP 23 | and due to change pending generalization across providers. 24 | } 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(cc_casey) 5 | export(cc_davis) 6 | export(cc_heard) 7 | export(cc_kingston) 8 | export(cc_location) 9 | export(cc_macquarie) 10 | export(cc_mawson) 11 | export(ceramic_tiles) 12 | export(down_loader) 13 | export(mercator_tile_extent) 14 | importFrom(curl,curl_download) 15 | importFrom(dplyr,filter) 16 | importFrom(fs,dir_create) 17 | importFrom(fs,dir_exists) 18 | importFrom(glue,glue) 19 | importFrom(graphics,rect) 20 | importFrom(graphics,text) 21 | importFrom(magrittr,"%>%") 22 | importFrom(purrr,pmap) 23 | importFrom(rappdirs,user_cache_dir) 24 | importFrom(rlang,.data) 25 | importFrom(sp,plot) 26 | importFrom(stats,setNames) 27 | importFrom(tibble,tibble) 28 | -------------------------------------------------------------------------------- /man/down_loader.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cache.R 3 | \name{down_loader} 4 | \alias{down_loader} 5 | \title{Downloader for tiles} 6 | \usage{ 7 | down_loader(x, query_string, clobber = FALSE, ..., debug = FALSE) 8 | } 9 | \arguments{ 10 | \item{x}{tiles object} 11 | 12 | \item{query_string}{an api query template (see Details)} 13 | 14 | \item{clobber}{if `TRUE` re download any existing tiles} 15 | } 16 | \value{ 17 | WIP 18 | } 19 | \description{ 20 | Tiles are cached with the native name of the source. 21 | } 22 | \details{ 23 | `query_string` takes the form of a templae, see examples 24 | } 25 | \examples{ 26 | mapbox_query_string <- paste0("https://api.mapbox.com/v4/mapbox.satellite/{zoom}/{x}/{y}.jpg90", 27 | "?access_token=", 28 | Sys.getenv("MAPBOX_API_KEY")) 29 | } 30 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ceramic 2 | Title: Get imagery tiles 3 | Version: 0.0.1 4 | Authors@R: c( 5 | person("Michael", "Sumner", email = "mdsumner@gmail.com", role = c("aut", "cre"), 6 | comment = c(ORCID = "0000-0002-2471-7511")), 7 | person("Miles", "McBain", role = c("ctb"), 8 | comment = c(ORCID = "0000-0003-2865-2548")), 9 | person("Ben", "Raymond", role = c("ctb"), comment = "regex wizardry") 10 | ) 11 | Description: Download imagery tiles to a standard cache. Currently only 'Mapbox' is available. 12 | Depends: R (>= 3.5.0) 13 | License: GPL-3 14 | Encoding: UTF-8 15 | LazyData: true 16 | RoxygenNote: 6.1.0 17 | Imports: 18 | slippymath (>= 0.1.0), 19 | curl, 20 | dplyr, 21 | fs, 22 | glue, 23 | rappdirs, 24 | tibble, 25 | stats, 26 | purrr, 27 | magrittr, 28 | rlang, 29 | sp, 30 | graphics 31 | Remotes: MilesMcBain/slippymath 32 | Suggests: 33 | testthat 34 | URL: https://github.com/hypertidy/ceramic 35 | BugReports: https://github.com/hypertidy/ceramic/issues 36 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http://contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /man/cc_location.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/locale.R 3 | \name{cc_location} 4 | \alias{cc_location} 5 | \alias{cc_macquarie} 6 | \alias{cc_davis} 7 | \alias{cc_mawson} 8 | \alias{cc_casey} 9 | \alias{cc_heard} 10 | \alias{cc_kingston} 11 | \title{Miscellaneous places} 12 | \usage{ 13 | cc_location(loc = NULL, buffer = 5000, type = "mapbox.outdoors", ..., 14 | debug = FALSE) 15 | 16 | cc_macquarie(loc = c(158.93835, -54.49871), buffer = 5000, 17 | type = "mapbox.outdoors", ..., debug = FALSE) 18 | 19 | cc_davis(loc = c(77 + 58/60 + 3/3600, -(68 + 34/60 + 36/3600)), 20 | buffer = 5000, type = "mapbox.outdoors", ..., debug = FALSE) 21 | 22 | cc_mawson(loc = c(62 + 52/60 + 27/3600, -(67 + 36/60 + 12/3600)), 23 | buffer = 5000, type = "mapbox.outdoors", ..., debug = FALSE) 24 | 25 | cc_casey(loc = cbind(110 + 31/60 + 36/3600, -(66 + 16/60 + 57/3600)), 26 | buffer = 5000, type = "mapbox.outdoors", ..., debug = FALSE) 27 | 28 | cc_heard(loc = c(73 + 30/60 + 30/3600, -(53 + 0 + 0/3600)), 29 | buffer = 5000, type = "mapbox.outdoors", ..., debug = FALSE) 30 | 31 | cc_kingston(loc = c(-147.70837, -42.98682), buffer = 5000, 32 | type = "mapbox.outdoors", ..., debug = FALSE) 33 | } 34 | \arguments{ 35 | \item{buffer}{with in metres to extend around the location} 36 | 37 | \item{...}{dots, ignored currently} 38 | 39 | \item{debug}{optionally print out files that will be used} 40 | } 41 | \value{ 42 | RasterBrick, with RGB 43 | } 44 | \description{ 45 | Visit some nice locales with web tiles. 46 | } 47 | \details{ 48 | * `cc_macquarie` Macquarie Island 49 | } 50 | \examples{ 51 | im <- cc_macquarie() 52 | library(raster) 53 | plotRGB(im) 54 | } 55 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /R/georeference.R: -------------------------------------------------------------------------------- 1 | #' @importFrom tibble tibble 2 | #' @importFrom dplyr filter 3 | spherical_mercator <- function(provider) { 4 | #MAXEXTENT is the bounds between [-180, 180] and [-85.0511, 85.0511] 5 | tibble::tibble(provider = "mapbox", 6 | MAXEXTENT = 20037508.342789244, 7 | A = 6378137.0, B = 6378137.0, 8 | crs = glue::glue("+proj=merc +a={A} +b={A}")) %>% 9 | dplyr::filter(provider == provider) 10 | } 11 | #' Tile extent 12 | #' 13 | #' Calculate tile extent for a given x, y tile at a zoom level. 14 | #' 15 | #' Currently only Mapbox spherical Mercator is supported. 16 | #' 17 | #' @param tile_x x coordinate of tile 18 | #' 19 | #' @param tile_y y coordinate of tile 20 | #' @param zoom zoo level 21 | #' @param tile_size tile dimensions (assumed square atm, 256*256) 22 | #' 23 | #' @importFrom stats setNames 24 | #' @export 25 | mercator_tile_extent <- function(tile_x, tile_y, zoom, tile_size = 256) { 26 | if (any(!c(length(tile_x), length(tile_y), length(zoom), length(tile_size)) == 1)) { 27 | stop("tile_x, tile_y, zoom, tile_size must all be of length 1") 28 | } 29 | params <- spherical_mercator(provider = "mapbox") 30 | params <- params[1, ] ## FIXME: param query should provide a unique set, this is WIP 31 | #st_transform(st_as_sfc(my_bbox), glue("+proj=merc +a={A} +b={A}")) 32 | MAXEXTENT <- params$MAXEXTENT 33 | A <- params$A 34 | ## literal width/height of a square tile at zoom = 0 35 | z0_size <- (MAXEXTENT * 2) 36 | xlim <- -MAXEXTENT + (tile_x + c(0, 1)) * (z0_size/(2^zoom)) 37 | ## upside down Ms. Jane 38 | ylim <- range(MAXEXTENT - (tile_y + c(0, 1) - 0) * (z0_size/(2^zoom))) 39 | stats::setNames(c(xlim, ylim), c("xmin", "xmax", "ymin", "ymax")) 40 | } 41 | 42 | add_extent <- function(x) { 43 | ## assert tibble with tile_x, tile_y, zoom 44 | l <- purrr::map(purrr::transpose(x), ~mercator_tile_extent(.x$tile_x, .x$tile_y, .x$zoom)) 45 | x[c("xmin", "xmax", "ymin", "ymax")] <- tibble::as_tibble(do.call(rbind, l)) 46 | x 47 | } 48 | 49 | #' @importFrom sp plot 50 | #' @importFrom graphics rect text 51 | plot_tiles <- function(x, ..., add = FALSE, label = TRUE, cex = 0.6, add_coast = TRUE, include_zoom = TRUE) { 52 | if (!all(c("xmin", "xmax", "ymin", "ymax") %in% names(x))) stop("need xmin, xmax, ymin, ymax columns") 53 | if (include_zoom && !"zoom" %in% names(x) ) stop("need zoom columns for 'include_zoom = TRUE'") 54 | if (!add) plot(range(c(x$xmin, x$xmax)), range(c(x$ymin, x$ymax)), type = "n", xlab = "x", ylab = "y") 55 | graphics::rect(x$xmin, x$ymin, x$xmax, x$ymax, ...) 56 | if (label) { 57 | if (include_zoom) { 58 | tile_lab <- sprintf("%i [%i,%i]", x$zoom, x$tile_x, x$tile_y) 59 | } else { 60 | tile_lab <- sprintf("[%i,%i]", x$tile_x, x$tile_y) 61 | } 62 | graphics::text((x$xmin + x$xmax) / 2, 63 | (x$ymin + x$ymax) / 2, label = tile_lab, cex = cex) 64 | } 65 | if (add_coast) sp::plot(merc_world, border = "darkgrey", add = TRUE) 66 | } 67 | 68 | tiles_to_polygon <- function(x) { 69 | spex::polygonize(tiles_to_raster(x)) 70 | } 71 | tiles_to_raster <- function(x) { 72 | ex <- raster::extent(min(x$xmin), max(x$xmax), min(x$ymin), max(x$ymax)) 73 | pts <- x[c("tile_x", "tile_y")] %>% dplyr::transmute(x = tile_x - min(tile_x), y = max(tile_y) - tile_y) %>% dplyr::distinct() 74 | r <- raster::setExtent(raster::rasterFromXYZ(pts), ex) 75 | cells <- raster::cellFromRowCol(r, pts$y + 1, pts$x + 1) 76 | r[cells] <- cells 77 | r 78 | } 79 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $("#sidebar") 6 | .stick_in_parent({offset_top: 40}) 7 | .on('sticky_kit:bottom', function(e) { 8 | $(this).parent().css('position', 'static'); 9 | }) 10 | .on('sticky_kit:unbottom', function(e) { 11 | $(this).parent().css('position', 'relative'); 12 | }); 13 | 14 | $('body').scrollspy({ 15 | target: '#sidebar', 16 | offset: 60 17 | }); 18 | 19 | $('[data-toggle="tooltip"]').tooltip(); 20 | 21 | var cur_path = paths(location.pathname); 22 | var links = $("#navbar ul li a"); 23 | var max_length = -1; 24 | var pos = -1; 25 | for (var i = 0; i < links.length; i++) { 26 | if (links[i].getAttribute("href") === "#") 27 | continue; 28 | var path = paths(links[i].pathname); 29 | 30 | var length = prefix_length(cur_path, path); 31 | if (length > max_length) { 32 | max_length = length; 33 | pos = i; 34 | } 35 | } 36 | 37 | // Add class to parent
See magrittr::%>% for details.
lhs %>% rhs112 | 113 | 114 |
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
103 |We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
104 |Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
105 |Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
106 |Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
107 |This Code of Conduct is adapted from the Contributor Covenant (http://contributor-covenant.org), version 1.0.0, available at http://contributor-covenant.org/version/1/0/0/
108 |Calculate tile extent for a given x, y tile at a zoom level.
108 | 109 |mercator_tile_extent(tile_x, tile_y, zoom, tile_size = 256)112 | 113 |
| tile_x | 118 |x coordinate of tile |
119 |
|---|---|
| tile_y | 122 |y coordinate of tile |
123 |
| zoom | 126 |zoo level |
127 |
| tile_size | 130 |tile dimensions (assumed square atm, 256*256) |
131 |
Currently only Mapbox spherical Mercator is supported.
137 | 138 | 139 |Find existing files in the cache. Various options can be controlled, this is WIP 109 | and due to change pending generalization across providers.
110 | 111 |ceramic_tiles(zoom = NULL, type = "mapbox.satellite", 114 | source = "api.mapbox.com", glob = "*.jpg*", regexp = NULL)115 | 116 |
| zoom | 121 |zoom level |
122 |
|---|---|
| type | 125 |imagery type |
126 |
| source | 129 |imagery source |
130 |
| glob | 133 |see `fs::dir_ls` |
134 |
| regexp | 137 |see `fs::dir_ls` |
138 |
Tiles are cached with the native name of the source.
108 | 109 |down_loader(x, query_string, clobber = FALSE)112 | 113 |
| x | 118 |tiles object |
119 |
|---|---|
| query_string | 122 |an api query template (see Details) |
123 |
| clobber | 126 |if `TRUE` re download any existing tiles |
127 |
WIP
133 | 134 |`query_string` takes the form of a templae, see examples
137 | 138 | 139 |143 |mapbox_query_string <- paste0("https://api.mapbox.com/v4/mapbox.satellite/{zoom}/{x}/{y}.jpg90", 141 | "?access_token=", 142 | Sys.getenv("MAPBOX_API_KEY"))
99 |
100 | There is a helper function to find existing tiles.
101 |
102 | ``` r
103 |
104 | ceramic_tiles(zoom = 7, type = "mapbox.satellite")
105 | #> [1] 83 4
106 | #> # A tibble: 24 x 11
107 | #> tile_x tile_y zoom type version source
108 | #>
192 |
193 | An internal function sets up a plot of tiles at particular zoom levels.
194 |
195 | ``` r
196 | ceramic::plot_tiles(ceramic_tiles(zoom = c(7, 9)))
197 | ```
198 |
199 | 
200 |
201 | And we can add the tiles to an existing plot.
202 |
203 | ``` r
204 | plotRGB(im)
205 | ceramic::plot_tiles(ceramic_tiles(zoom = 7), add = TRUE)
206 | ```
207 |
208 | 
209 |
210 | Please note that the ‘ceramic’ project is released with a [Contributor
211 | Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this project,
212 | you agree to abide by its terms.
213 |
--------------------------------------------------------------------------------
/docs/docsearch.css:
--------------------------------------------------------------------------------
1 | /* Docsearch -------------------------------------------------------------- */
2 | /*
3 | Source: https://github.com/algolia/docsearch/
4 | License: MIT
5 | */
6 |
7 | .algolia-autocomplete {
8 | display: block;
9 | -webkit-box-flex: 1;
10 | -ms-flex: 1;
11 | flex: 1
12 | }
13 |
14 | .algolia-autocomplete .ds-dropdown-menu {
15 | width: 100%;
16 | min-width: none;
17 | max-width: none;
18 | padding: .75rem 0;
19 | background-color: #fff;
20 | background-clip: padding-box;
21 | border: 1px solid rgba(0, 0, 0, .1);
22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175);
23 | }
24 |
25 | @media (min-width:768px) {
26 | .algolia-autocomplete .ds-dropdown-menu {
27 | width: 175%
28 | }
29 | }
30 |
31 | .algolia-autocomplete .ds-dropdown-menu::before {
32 | display: none
33 | }
34 |
35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] {
36 | padding: 0;
37 | background-color: rgb(255,255,255);
38 | border: 0;
39 | max-height: 80vh;
40 | }
41 |
42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
43 | margin-top: 0
44 | }
45 |
46 | .algolia-autocomplete .algolia-docsearch-suggestion {
47 | padding: 0;
48 | overflow: visible
49 | }
50 |
51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header {
52 | padding: .125rem 1rem;
53 | margin-top: 0;
54 | font-size: 1.3em;
55 | font-weight: 500;
56 | color: #00008B;
57 | border-bottom: 0
58 | }
59 |
60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper {
61 | float: none;
62 | padding-top: 0
63 | }
64 |
65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column {
66 | float: none;
67 | width: auto;
68 | padding: 0;
69 | text-align: left
70 | }
71 |
72 | .algolia-autocomplete .algolia-docsearch-suggestion--content {
73 | float: none;
74 | width: auto;
75 | padding: 0
76 | }
77 |
78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before {
79 | display: none
80 | }
81 |
82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header {
83 | padding-top: .75rem;
84 | margin-top: .75rem;
85 | border-top: 1px solid rgba(0, 0, 0, .1)
86 | }
87 |
88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column {
89 | display: block;
90 | padding: .1rem 1rem;
91 | margin-bottom: 0.1;
92 | font-size: 1.0em;
93 | font-weight: 400
94 | /* display: none */
95 | }
96 |
97 | .algolia-autocomplete .algolia-docsearch-suggestion--title {
98 | display: block;
99 | padding: .25rem 1rem;
100 | margin-bottom: 0;
101 | font-size: 0.9em;
102 | font-weight: 400
103 | }
104 |
105 | .algolia-autocomplete .algolia-docsearch-suggestion--text {
106 | padding: 0 1rem .5rem;
107 | margin-top: -.25rem;
108 | font-size: 0.8em;
109 | font-weight: 400;
110 | line-height: 1.25
111 | }
112 |
113 | .algolia-autocomplete .algolia-docsearch-footer {
114 | width: 110px;
115 | height: 20px;
116 | z-index: 3;
117 | margin-top: 10.66667px;
118 | float: right;
119 | font-size: 0;
120 | line-height: 0;
121 | }
122 |
123 | .algolia-autocomplete .algolia-docsearch-footer--logo {
124 | background-image: url("data:image/svg+xml;utf8,");
125 | background-repeat: no-repeat;
126 | background-position: 50%;
127 | background-size: 100%;
128 | overflow: hidden;
129 | text-indent: -9000px;
130 | width: 100%;
131 | height: 100%;
132 | display: block;
133 | transform: translate(-8px);
134 | }
135 |
136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight {
137 | color: #FF8C00;
138 | background: rgba(232, 189, 54, 0.1)
139 | }
140 |
141 |
142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight {
143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5)
144 | }
145 |
146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content {
147 | background-color: rgba(192, 192, 192, .15)
148 | }
149 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | The goal of ceramic is to obtain web map tiles for later re-use. Many tools for imagery services treat the imagery as transient, but here we take control over the raw data itself.
75 |Very much WIP.
80 |This complete example gets tiled imagery that we can use as real data.
96 |The code here
97 |library(sf) ## st_bbox, st_crs
104 | #> Linking to GEOS 3.6.2, GDAL 2.3.2, PROJ 4.9.3
105 | #> Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
106 | library(slippymath)
107 | my_bbox <-
108 | st_bbox(c(xmin = 130,
109 | xmax = 146,
110 | ymin = -36,
111 | ymax = -28),
112 | crs = st_crs("+proj=longlat +ellps=WGS84"))
113 | library(purrr) ## is_null clashes with testthat::is_null
114 | tile_grid <- slippymath:::bb_to_tg(my_bbox, max_tiles = 36)
115 | zoom <- tile_grid$zoom
116 |
117 | mapbox_query_string <-
118 | paste0("https://api.mapbox.com/v4/mapbox.satellite/{zoom}/{x}/{y}.jpg90",
119 | "?access_token=",
120 | Sys.getenv("MAPBOX_API_KEY"))
121 |
122 | library(ceramic)
123 | files <- unlist(down_loader(tile_grid, mapbox_query_string))
124 | tibble::tibble(filename = gsub(normalizePath(rappdirs::user_cache_dir(), winslash = "/"),
125 | "",
126 | normalizePath(files, winslash = "/")))
127 | #> # A tibble: 24 x 1
128 | #> filename
129 | #> <chr>
130 | #> 1 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/110/74.jpg90
131 | #> 2 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/111/74.jpg90
132 | #> 3 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/112/74.jpg90
133 | #> 4 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/113/74.jpg90
134 | #> 5 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/114/74.jpg90
135 | #> 6 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/115/74.jpg90
136 | #> 7 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/110/75.jpg90
137 | #> 8 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/111/75.jpg90
138 | #> 9 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/112/75.jpg90
139 | #> 10 /.ceramic/api.mapbox.com/v4/mapbox.satellite/7/113/75.jpg90
140 | #> # ... with 14 more rows
141 |
142 | library(raster)
143 | #> Loading required package: sp
144 | br <- lapply(files, raster::brick)
145 |
146 | for (i in seq_along(br)) {
147 | br[[i]] <- setExtent(br[[i]],
148 | mercator_tile_extent(tile_grid$tiles$x[i], tile_grid$tiles$y[i], zoom = zoom))
149 | }
150 |
151 | im <- purrr::reduce(br, raster::merge)
152 | plotRGB(im)
153 | # devtools::install_github("mdsumner/ozmaps")
154 | dat <- sf::st_transform(ozmaps::ozmap_states, "+proj=merc +a=6378137 +b=6378137")
155 | plot(dat$geometry, add = TRUE, lwd = 5, border = "dodgerblue")
There is a helper function to find existing tiles.
158 |
159 | ceramic_tiles(zoom = 7, type = "mapbox.satellite")
160 | #> [1] 83 4
161 | #> # A tibble: 24 x 11
162 | #> tile_x tile_y zoom type version source
163 | #> <int> <int> <int> <chr> <chr> <chr>
164 | #> 1 110 74 7 mapb… v4 api.m…
165 | #> 2 110 75 7 mapb… v4 api.m…
166 | #> 3 110 76 7 mapb… v4 api.m…
167 | #> 4 110 77 7 mapb… v4 api.m…
168 | #> 5 111 74 7 mapb… v4 api.m…
169 | #> 6 111 75 7 mapb… v4 api.m…
170 | #> 7 111 76 7 mapb… v4 api.m…
171 | #> 8 111 77 7 mapb… v4 api.m…
172 | #> 9 112 74 7 mapb… v4 api.m…
173 | #> 10 112 75 7 mapb… v4 api.m…
174 | #> # ... with 14 more rows, and 5 more variables: fullname <fs::path>,
175 | #> # xmin <dbl>, xmax <dbl>, ymin <dbl>, ymax <dbl>and every row has the extent values useable directly by raster:
177 |ceramic_tiles(zoom = 7, type = "mapbox.satellite") %>%
178 | dplyr::slice(1:5) %>%
179 | purrr::transpose() %>%
180 | purrr::map(~raster::extent(unlist(.x[c("xmin", "xmax", "ymin", "ymax")])))
181 | #> [1] 83 4
182 | #> [[1]]
183 | #> class : Extent
184 | #> xmin : 14401959
185 | #> xmax : 14715045
186 | #> ymin : -3443947
187 | #> ymax : -3130861
188 | #>
189 | #> [[2]]
190 | #> class : Extent
191 | #> xmin : 14401959
192 | #> xmax : 14715045
193 | #> ymin : -3757033
194 | #> ymax : -3443947
195 | #>
196 | #> [[3]]
197 | #> class : Extent
198 | #> xmin : 14401959
199 | #> xmax : 14715045
200 | #> ymin : -4070119
201 | #> ymax : -3757033
202 | #>
203 | #> [[4]]
204 | #> class : Extent
205 | #> xmin : 14401959
206 | #> xmax : 14715045
207 | #> ymin : -4383205
208 | #> ymax : -4070119
209 | #>
210 | #> [[5]]
211 | #> class : Extent
212 | #> xmin : 14715045
213 | #> xmax : 15028131
214 | #> ymin : -3443947
215 | #> ymax : -3130861Another example
217 |my_bbox <-
218 | st_bbox(c(xmin = 144,
219 | xmax = 147.99,
220 | ymin = -44.12,
221 | ymax = -40),
222 | crs = st_crs("+proj=longlat +ellps=WGS84"))
223 | tile_grid <- slippymath:::bb_to_tg(my_bbox, max_tiles = 36)
224 | files <- unlist(down_loader(tile_grid, mapbox_query_string))
225 | br <- lapply(files, raster::brick)
226 |
227 | for (i in seq_along(br)) {
228 | br[[i]] <- setExtent(br[[i]],
229 | mercator_tile_extent(tile_grid$tiles$x[i], tile_grid$tiles$y[i], zoom = tile_grid$zoom))
230 | }
231 |
232 | im <- purrr::reduce(br, raster::merge)
233 | projection(im) <- "+proj=merc +a=6378137 +b=6378137"
234 | plotRGB(im)
235 | plot(st_transform(ozmaps::abs_lga$geometry, projection(im)), add = TRUE, lwd = 2, border = "white")
An internal function sets up a plot of tiles at particular zoom levels.
238 | 239 |
tile plot
241 |And we can add the tiles to an existing plot.
243 | 245 |
tile add plot
247 |Please note that the ‘ceramic’ project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
249 |