├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── pkgdown.yaml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CRAN-RELEASE ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── ZZ_misc_unused.R ├── adjacencies.R ├── affinething.R ├── affinity-package.R └── grids.R ├── README.Rmd ├── README.md ├── affinity.Rproj ├── appveyor.yml ├── codecov.yml ├── cran-comments.md ├── data-raw └── monterey.R ├── data └── monterey.rda ├── inst ├── extdata │ ├── C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png │ ├── C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.stx │ ├── C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.vrt │ └── czcs.r └── working_example.R ├── man ├── adjacencies.Rd ├── affinething.Rd ├── affinity-package.Rd ├── assignproj.Rd ├── domath.Rd ├── extent_dim_to_gt.Rd ├── figures │ ├── README-affine-remap-1.png │ └── README-affine-thing2-1.png ├── geo_transform0.Rd ├── geo_world0.Rd ├── gt_dim_to_extent.Rd ├── monterey.Rd ├── raster_io.Rd ├── raster_to_gt.Rd ├── raster_to_rasterio.Rd ├── raster_to_world.Rd ├── rasterio_to_sfio.Rd ├── sfio_to_rasterio.Rd └── world_to_geotransform.Rd └── vignettes ├── .gitignore └── adjacencies.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CODE_OF_CONDUCT\.md$ 2 | ^README\.Rmd$ 3 | ^.*\.Rproj$ 4 | ^\.Rproj\.user$ 5 | ^examples$ 6 | ^figures$ 7 | ^\.travis\.yml$ 8 | ^appveyor\.yml$ 9 | ^codecov\.yml$ 10 | ^docs$ 11 | ^\.github$ 12 | ^data-raw$ 13 | ^cran-comments\.md$ 14 | ^CRAN-RELEASE$ 15 | ^gdalwmscache$ 16 | ^inst/extdata$ 17 | ^inst/working_example.R$ 18 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. 2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | pull_request: 9 | branches: 10 | - main 11 | - master 12 | 13 | name: R-CMD-check 14 | 15 | jobs: 16 | R-CMD-check: 17 | runs-on: ${{ matrix.config.os }} 18 | 19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | config: 25 | - {os: windows-latest, r: 'release'} 26 | - {os: macOS-latest, r: 'release'} 27 | - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} 28 | - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} 29 | 30 | env: 31 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 32 | RSPM: ${{ matrix.config.rspm }} 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | 35 | steps: 36 | - uses: actions/checkout@v2 37 | 38 | - uses: r-lib/actions/setup-r@v1 39 | with: 40 | r-version: ${{ matrix.config.r }} 41 | 42 | - uses: r-lib/actions/setup-pandoc@v1 43 | 44 | - name: Query dependencies 45 | run: | 46 | install.packages('remotes') 47 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 48 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 49 | shell: Rscript {0} 50 | 51 | - name: Restore R package cache 52 | if: runner.os != 'Windows' 53 | uses: actions/cache@v2 54 | with: 55 | path: ${{ env.R_LIBS_USER }} 56 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 57 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 58 | 59 | - name: Install system dependencies 60 | if: runner.os == 'Linux' 61 | run: | 62 | while read -r cmd 63 | do 64 | eval sudo $cmd 65 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') 66 | 67 | - name: Install dependencies 68 | run: | 69 | remotes::install_deps(dependencies = TRUE) 70 | remotes::install_cran("rcmdcheck") 71 | shell: Rscript {0} 72 | 73 | - name: Check 74 | env: 75 | _R_CHECK_CRAN_INCOMING_REMOTE_: false 76 | run: | 77 | options(crayon.enabled = TRUE) 78 | rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check") 79 | shell: Rscript {0} 80 | 81 | - name: Upload check results 82 | if: failure() 83 | uses: actions/upload-artifact@main 84 | with: 85 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results 86 | path: check 87 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | - master 6 | 7 | name: pkgdown 8 | 9 | jobs: 10 | pkgdown: 11 | runs-on: macOS-latest 12 | env: 13 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - uses: r-lib/actions/setup-r@v1 18 | 19 | - uses: r-lib/actions/setup-pandoc@v1 20 | 21 | - name: Query dependencies 22 | run: | 23 | install.packages('remotes') 24 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 25 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 26 | shell: Rscript {0} 27 | 28 | - name: Restore R package cache 29 | uses: actions/cache@v2 30 | with: 31 | path: ${{ env.R_LIBS_USER }} 32 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 33 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 34 | 35 | - name: Install dependencies 36 | run: | 37 | remotes::install_deps(dependencies = TRUE) 38 | install.packages("pkgdown", type = "binary") 39 | shell: Rscript {0} 40 | 41 | - name: Install package 42 | run: R CMD INSTALL . 43 | 44 | - name: Deploy package 45 | run: | 46 | git config --local user.email "actions@github.com" 47 | git config --local user.name "GitHub Actions" 48 | Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | examples 5 | inst/doc 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | sudo: required 5 | cache: packages 6 | 7 | 8 | addons: 9 | apt: 10 | sources: 11 | - sourceline: 'ppa:ubuntugis/ubuntugis-unstable' 12 | packages: 13 | - libproj-dev 14 | 15 | 16 | matrix: 17 | include: 18 | - os: linux 19 | r: release 20 | dist: trusty # 14.04 21 | env: 22 | - BUILD_NAME=trusty_release 23 | - DETAILS="release build" 24 | - os: osx 25 | r: release 26 | before_install: '' 27 | disable_homebrew: true 28 | env: 29 | - BUILD_NAME=osx_release 30 | - DETAILS="release build" 31 | 32 | after_success: 33 | - Rscript -e 'covr::codecov()' 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CRAN-RELEASE: -------------------------------------------------------------------------------- 1 | This package was submitted to CRAN on 2021-06-01. 2 | Once it is accepted, delete this file and tag the release (commit 558abac). 3 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: affinity 2 | Title: Raster Georeferencing, Grid Affine Transforms, Cell Abstraction 3 | Version: 0.2.5 4 | Authors@R: person("Michael D.", "Sumner", email = "mdsumner@gmail.com", role = c("aut", "cre")) 5 | Description: Tools for raster georeferencing, grid affine transforms, and general raster logic. 6 | These functions provide converters between raster specifications, world vector, geotransform, 7 | 'RasterIO' window, and 'RasterIO window' in 'sf' package list format. There are functions to offset 8 | a matrix by padding any of four corners (useful for vectorizing neighbourhood operations), and 9 | helper functions to harvesting user clicks on a graphics device to use for simple georeferencing 10 | of images. Methods used are available from and 11 | . 12 | Depends: 13 | R (>= 3.2.3) 14 | License: GPL-3 15 | LazyData: true 16 | LazyDataCompression: xz 17 | Roxygen: list(markdown = TRUE) 18 | RoxygenNote: 7.1.1 19 | URL: https://github.com/hypertidy/affinity 20 | BugReports: https://github.com/hypertidy/affinity/issues 21 | Encoding: UTF-8 22 | Imports: 23 | raster, 24 | reproj, 25 | stats 26 | Suggests: 27 | rmarkdown, 28 | covr, 29 | knitr 30 | VignetteBuilder: knitr 31 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(affinething) 4 | export(assignproj) 5 | export(bl) 6 | export(br) 7 | export(domath) 8 | export(extent_dim_to_gt) 9 | export(geo_transform0) 10 | export(geo_world0) 11 | export(geotransform_to_world) 12 | export(gt_dim_to_extent) 13 | export(image0) 14 | export(image1) 15 | export(raster_io0) 16 | export(raster_to_gt) 17 | export(raster_to_rasterio) 18 | export(raster_to_sfio) 19 | export(raster_to_world) 20 | export(rasterio_to_sfio) 21 | export(sfio_to_rasterio) 22 | export(text0) 23 | export(tl) 24 | export(tr) 25 | export(world_to_geotransform) 26 | importFrom(graphics,image) 27 | importFrom(graphics,text) 28 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # affinity 0.25 2 | 3 | * CRAN fixes. 4 | 5 | * First release. 6 | -------------------------------------------------------------------------------- /R/ZZ_misc_unused.R: -------------------------------------------------------------------------------- 1 | # regions (intended to be a lookup for known un-referenced images, i.e. from BOM) 2 | #regions <- function(name) { 3 | # switch(name, 4 | # #rawxy <- affinething(r) 5 | # #pts <- enterPoints(80, -60, 160, 0) 6 | # swellAustralia = list(proj = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0", 7 | # extent = extent(64.97631, 201.3147, -69.72891, 26.75375 )), 8 | # #rawxy <- affinething(r) 9 | # #pts <- enterPoints(-60, -20, 140, -40) 10 | # windAntarctica = list(proj = "+proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=90 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m +no_defs", 11 | # extent = extent(-8830383,12492413,-9648532,10730455)) 12 | # ) 13 | # NULL 14 | #} 15 | 16 | #gdalvrt <- function(x, a_ullr = NULL, a_srs = NULL) { 17 | # inputname <- filename(x) 18 | # outputname <- sprintf("%svrt", substr(inputname, 1L, nchar(inputname)-3)) 19 | # cal <- sprintf("gdal_translate %s %s -of VRT", inputname, outputname) 20 | # if (!is.null(a_ullr)) cal <- paste(cal, sprintf("-a_ullr %f %f %f %f", a_ullr[1], a_ullr[2], a_ullr[3], a_ullr[4])) 21 | # if (!is.null(a_srs)) cal <- paste(cal, sprintf("-a_srs %s", a_srs)) 22 | # system(cal) 23 | 24 | #} 25 | 26 | -------------------------------------------------------------------------------- /R/adjacencies.R: -------------------------------------------------------------------------------- 1 | #' Adjacency, for use in creating area based meshes 2 | #' 3 | #' Functions 'bottom left', 'top left', 'bottom right', and 'top right' named by 4 | #' their initials, provide very low level relative positional structures for use in 5 | #' raster logic. These are used to traverse the divide left by area-based rasters which are 6 | #' inherently a discrete value across a finite element. If we want that element as part of a 7 | #' continuous surface we need to find local relative values for its corners. Used in 8 | #' quadmesh and anglr packages, and useful for calculating neighbourhood values. 9 | #' 10 | #' Some tiny functions 'image0', 'image1', 'text0' exist purely to illustrate the ideas in 11 | #' a vignette. 12 | #' @export 13 | #' @name adjacencies 14 | #' @return matrix, padded by one row and one column relative to input 15 | #' @examples 16 | #' (m <- matrix(1:12, 3)) 17 | #' tl(m) 18 | #' tr(m) 19 | #' bl(m) 20 | #' br(m) 21 | #' tl(br(m)) 22 | #' image0(tl(br(m))) 23 | #' text0(tl(br(m))) 24 | bl <- function(x) { 25 | ## top left 26 | cbind(NA_integer_, rbind(NA_integer_, x)) 27 | } 28 | #' @export 29 | #' @name adjacencies 30 | tl <- function(x) { 31 | ## top right 32 | cbind(NA_integer_, rbind(x, NA_integer_)) 33 | } 34 | #' @export 35 | #' @name adjacencies 36 | br <- function(x) { 37 | ## bottom left 38 | cbind(rbind(NA_integer_, x), NA_integer_) 39 | } 40 | #' @export 41 | #' @name adjacencies 42 | tr <- function(x) { 43 | ## bottom right 44 | cbind(rbind(x, NA_integer_), NA_integer_) 45 | } 46 | 47 | #' @export 48 | #' @name adjacencies 49 | #' @param x matrix 50 | #' @param ... arguments passed to image() 51 | image0 <- function(x, ...) image(seq(0, nrow(x)), seq(0, ncol(x)), x, ...) 52 | #' @export 53 | #' @name adjacencies 54 | #' @importFrom graphics image text 55 | image1 <- function(x, ...) image(seq(1, nrow(x) + 1), seq(1, ncol(x) + 1), x, ...) 56 | #' @export 57 | #' @name adjacencies 58 | text0 <- function(x, ...) { 59 | text(expand.grid(seq(0.5, by = 1, length.out = nrow(x)), 60 | seq(0.5, by = 1, length.out = nrow(x))), lab = x, 61 | ...) 62 | } 63 | -------------------------------------------------------------------------------- /R/affinething.R: -------------------------------------------------------------------------------- 1 | 2 | drawPoints <- function(n = 2) { 3 | print("click on two known points") 4 | do.call(cbind, graphics::locator(n)) 5 | } 6 | 7 | 8 | 9 | enterPoints <- function(x1, y1, x2, y2) { 10 | rbind(c(x1, y1), c(x2, y2)) 11 | } 12 | 13 | #' Use affine logic interactively georegister a raster 14 | #' 15 | #' User clicks are collected in a controlled way for use by [domath()]. 16 | #' 17 | #' Obtain control points for the simple affine transform (offset and scale) on an ungeoreferenced image. 18 | #' @param x a raster 19 | #' @param rgb use RGB plot for a raster with 3 layers 20 | #' @return matrix of x,y coordinates in the space of the current raster extent 21 | #' @export 22 | #' @examples 23 | #' \donttest{ 24 | #' \dontrun{ 25 | #' library(raster) 26 | #' r <- raster("my_unreferenced_raster.png") 27 | #' xy <- affinething(r) ## click on two points that you know a location of 28 | #' my_x <- c(1000, 2000) 29 | #' my_y <- c(-1000, -500) 30 | #' prj <- "+proj=laea +lon=147 +lat_0=-42" ## use your own map projection, that correspond to my_x/my_y 31 | #' pt <- cbind(my_x, my_y) 32 | #' ## now convert those control points to an extent for your raster 33 | #' ex <- domath(pt, xy, r, prj) 34 | #' 35 | #' ## now we can fix up the data 36 | #' r <- raster::setExtent(r, ex) 37 | #' raster::projection(r) <- prj 38 | #' ## hooray! 39 | #' } 40 | #' } 41 | affinething <- function(x, rgb = FALSE) { 42 | if (!interactive()) stop("affinething is only for interactive use") 43 | if (rgb) { 44 | raster::plotRGB(x) 45 | } else { 46 | if (raster::nlayers(x) == 3) message("raster has 3 layers, maybe use 'rgb = TRUE'?") 47 | raster::plot(x[[1]]) 48 | } 49 | drawPoints() 50 | } 51 | 52 | 53 | #' Calculate the math of an affine transform 54 | #' 55 | #' Given relative location and absolute locations, convert to an actual real world extent 56 | #' for a matrix of data. 57 | #' 58 | #' Convert known geographic points with raw graphic control points and a reference raster 59 | #' to an extent for the raster in geography. 60 | #' 61 | #' @param pts known points of 'xy' 62 | #' @param xy 'xy' obtain from `affinething` 63 | #' @param r raster in use 64 | #' @param proj optional projection, if the pts are longlat and the raster is not 65 | #' 66 | #' @return raster extent 67 | #' @export 68 | #' @seealso [affinething()] 69 | #' @examples 70 | #' ## not a real example, but the extent we could provide volcano if the second set of points 71 | #' ## described the real world positions of the first set of points within the matrix 72 | #' domath(cbind(c(147, 148), c(-42, -43)), cbind(c(0.2, 0.3), c(0.1, 0.5)), raster::raster(volcano)) 73 | domath <- function(pts, xy, r = NULL, proj = NULL) { 74 | if (is.null(r)) stop("need r input, a raster") 75 | if (!is.null(proj)) pts <- reproj::reproj(pts, target = proj, source = 4326) 76 | cols <- raster::colFromX(r, xy[,1]) ## extent in graphics columns 77 | rows <- raster::rowFromY(r, xy[,2]) ## and graphics rows 78 | scalex <- abs(diff(pts[,1]) / diff(cols)) 79 | scaley <- abs(diff(pts[,2]) / diff(rows)) 80 | offsetx <- pts[1,1] - cols[1] * scalex 81 | offsety <- pts[1,2] - (nrow(r) - rows[1] + 1) * scaley 82 | ## this worked by accident on 0,ncol, 0,nrow rasters 83 | # scalex <- diff(pts[, 1]) / (diff(xy[, 1])/res(r)[1]) 84 | # scaley <- diff(pts[, 2]) / (diff(xy[, 2])/res(r)[2]) 85 | # offsetx <- pts[1,1] - xy[1,1] * scalex 86 | # offsety <- pts[1,2] - xy[1,2] * scaley 87 | 88 | 89 | raster::extent(offsetx, offsetx + scalex * (ncol(r) + 1), offsety, offsety + scaley * (nrow(r) + 1)) 90 | ## override raw index-transform applied to input image 91 | } 92 | 93 | 94 | #' Assign projection 95 | #' 96 | #' Set the projection of a spatial object. 97 | #' 98 | #' @param x spatial object for use with [raster::projection()] 99 | #' @param proj PROJ.4 string 100 | #' 101 | #' @return a spatial object with the projection set 102 | #' @export 103 | assignproj <- function(x, proj = "+proj=longlat +datum=WGS84") { 104 | raster::projection(x) <- proj 105 | x 106 | } 107 | 108 | 109 | -------------------------------------------------------------------------------- /R/affinity-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | # The following block is used by usethis to automatically manage 5 | # roxygen namespace tags. Modify with care! 6 | ## usethis namespace: start 7 | ## usethis namespace: end 8 | NULL 9 | 10 | 11 | #' Monterey Bay elevation 12 | #' 13 | #' Extent is in the examples, stolen from rayshader. 14 | #' 15 | #' A matrix 270x270 of topography. Used in [affinething()] examples. 16 | #' @docType data 17 | #' @examples 18 | #' ex <- c(-122.366765, -121.366765, 36.179392, 37.179392) 19 | #' raster::setExtent(raster::t(raster::raster(monterey)), ex) 20 | "monterey" 21 | -------------------------------------------------------------------------------- /R/grids.R: -------------------------------------------------------------------------------- 1 | ## DONE vapour rasterio creator 2 | ## DONE vapour rasterio to sf-rasterio 3 | ## DONE sf-rasterio to vapour rasterio 4 | ## DONE geotransform creator 5 | ## DONE world file creator 6 | ## DONE world file to geotransform 7 | ## DONE geotransform to world file 8 | ## DONE (vapour) get gdal geotransform 9 | ## DONE gen gdal geotransform 10 | ## DONE gen extent from gt+dim 11 | ## DONE gen gt from extent+dim 12 | ## raster to geotransform 13 | ## raster to world file 14 | ## raster to rasterio 15 | ## rasterio to raster 16 | ## sf-rasterio to raster 17 | ## stars converters 18 | ## devices to rasterio, etc. ... 19 | 20 | 21 | #' Geotransform from raster object 22 | #' 23 | #' Return the geotransform defining the raster's offset and resolution. 24 | #' 25 | #' The geotransform vector is six coefficients xmin, xres, yskew, ymax, xskew, yres, values 26 | #' relative to the top left corner of the top left pixel. "yres" the y-spacing is 27 | #' traditionally negative. 28 | #' 29 | #' @param x raster object (the raster package, extends BasicRaster) 30 | #' @return a geotransform vector 31 | #' @export 32 | #' @examples 33 | #' raster_to_gt(raster::raster(volcano)) 34 | raster_to_gt <- function(x) { 35 | #x <- raster::raster(volcano) 36 | extent_dim_to_gt(c(x@extent@xmin, x@extent@xmax, x@extent@ymin, x@extent@ymax), 37 | c(x@ncols, x@nrows)) 38 | } 39 | #' World vector from raster object. 40 | #' 41 | #' Return the world transform defining the raster's offset and resolution. 42 | #' 43 | #' The world vector is the values xres, yres, xmin, ymax relative to the 44 | #' centre of the top left pixel. "yres" the y-spacing is traditionally negative. 45 | #' 46 | #' @param x raster object (the raster package, extends BasicRaster) 47 | #' @return a geotransform vector 48 | #' @export 49 | #' @examples 50 | #' raster_to_world(raster::raster(volcano)) 51 | raster_to_world <- function(x) { 52 | gt <- raster_to_gt(x) 53 | geo_world0(gt[c("xres", "yres")], ul = gt[c("xmin", "ymax")]) 54 | } 55 | 56 | 57 | #' RasterIO window from raster object 58 | #' 59 | #' Return the RasterIO window vector defining the raster's offset and resolution and dimensions. 60 | #' 61 | #' The RasterIO window is a six element vector of offset (x,y), dimension of source (nx0, ny0) and 62 | #' dimension of output (nx, ny). 63 | #' 64 | #' The sf RasterIO is the RasterIO window in a list format used by the sf package, it contains the same 65 | #' information, and is created by [raster_to_sfio()]. 66 | #' 67 | #' @param x a raster object (BasicRaster, from raster package) 68 | #' 69 | #' @return RasterIO window vector 'c(x0, y0, nx0, ny0, nx, y)' see Details 70 | #' @export 71 | #' @name raster_to_rasterio 72 | #' @examples 73 | #' raster_to_rasterio(raster::raster(volcano)) 74 | raster_to_rasterio <- function(x) { 75 | raster_io0(c(0, 0), c(x@ncols, x@nrows)) 76 | } 77 | #' @export 78 | #' @name raster_to_rasterio 79 | raster_to_sfio <- function(x) { 80 | rasterio_to_sfio( raster_to_rasterio(x)) 81 | } 82 | 83 | ## creators 84 | ## raster_io0 85 | ## geo_transform0 86 | ## geo_world0 87 | 88 | ## converters 89 | ## rasterio_to_sfio 90 | ## sfio_to_rasterio TODO 91 | ## gt_dim_to_extent 92 | 93 | #' Determine extent from eotransform vector and dimension 94 | #' 95 | #' Create the extent (xlim, ylim) from the geotransform and dimensions 96 | #' of the grid. 97 | #' 98 | #' The extent is `c(xmin, xmax, ymin, ymax)`. 99 | #' 100 | #' @param x geotransform parameters, as per [geo_transform0()] 101 | #' @param dim dimensions x,y of grid (ncol,nrow) 102 | #' @return 4-element extent c(xmin,xmax,ymin,ymax) 103 | #' @export 104 | #' @examples 105 | #' gt_dim_to_extent(geo_transform0(c(1, -1), c(0, 10)), c(5, 10)) 106 | gt_dim_to_extent <- function(x, dim) { 107 | xx <- c(x[1], x[1] + dim[1] * x[2]) 108 | yy <- c(x[4] + dim[2] * x[6], x[4]) 109 | c(xx, yy) 110 | } 111 | 112 | 113 | #' Create geotransform from extent and dimension 114 | #' 115 | #' Create the geotransform (see [geo_transform0()]) from extent and dimension. 116 | #' 117 | #' The dimension is always ncol, nrow. 118 | #' @param x extent parameters, c(xmin,xmax,ymin,ymax) 119 | #' @param dim dimensions x,y of grid (ncol,nrow) 120 | #' @return 6-element [geo_transform0()] 121 | #' @export 122 | #' @examples 123 | #' extent_dim_to_gt(c(0, 5, 0, 10), c(5, 10)) 124 | extent_dim_to_gt <- function(x, dim) { 125 | px <- c(diff(x[1:2])/dim[1L], -diff(x[3:4])/dim[2L]) 126 | geo_transform0(px, c(x[1L], x[4L])) 127 | } 128 | 129 | #' GDAL RasterIO parameter creator 130 | #' 131 | #' Basic function to create the window paramers as used by GDAL RasterIO. 132 | #' 133 | #' Resampling algorithm is one of 'NearestNeighbour' (default), 'Average', 'Bilinear', 'Cubic', 'CubicSpline', 'Gauss', 'Lanczos', 'Mode', but 134 | #' more may be available given the version of GDAL in use. 135 | #' @param src_offset index offset (0-based, top left) 136 | #' @param src_dim source dimension (XY) 137 | #' @param out_dim output dimension (XY, optional src_dim will be used if not set) 138 | #' @param resample resampling algorith for GDAL see details 139 | #' @return numeric vector of values specifying offset, source dimension, output dimension 140 | #' @name raster_io 141 | #' @export 142 | #' @examples 143 | #' raster_io0(c(0L, 0L), src_dim = c(24L, 10L)) 144 | raster_io0 <- function(src_offset, src_dim, out_dim = src_dim, resample = "NearestNeighbour") { 145 | ## GDAL, and vapour names: 146 | ## 'NearestNeighbour' (default), 'Average', 'Bilinear', 'Cubic', 'CubicSpline', 'Gauss', 'Lanczos', 'Mode' 147 | out <- stats::setNames(c(src_offset, src_dim, out_dim), c("offset_x", "offset_y", 148 | "source_nx", "source_ny", 149 | "out_nx", "out_ny")) 150 | attr(out, "resample") <- resample 151 | out 152 | } 153 | 154 | #' sf package RasterIO from RasterIO window vector 155 | #' 156 | #' Basic function to create the window parameters as used by GDAL RasterIO, in 157 | #' format used by sf, in 'gdal_read(,RasterIO_parameters)'. 158 | #' 159 | #' 160 | #' @param x a RasterIO parameter list 161 | #' 162 | #' @return a sf-RasterIO parameter list 163 | #' @export 164 | #' @examples 165 | #' sfio_to_rasterio(rasterio_to_sfio(raster_io0(c(0L, 0L), src_dim = c(24L, 10L)))) 166 | sfio_to_rasterio <- function(x) { 167 | raster_io0(unlist(x[c("nXOff", "nYOff")]), 168 | unlist(x[c("nXSize", "nYSize")]), 169 | unlist(x[c("nBufXSize", "nBufYSize")]), 170 | resample = x[["resample"]]) 171 | } 172 | 173 | #' The sf/stars RasterIO list 174 | #' 175 | #' We create the list as used by the stars/sf GDAL IO function 'gdal_read(, RasterIO_parameters)'. 176 | #' 177 | #' Note that the input is a 4 or 6 element vector, with offset 0-based and 178 | #' output dimensions optional (will use the source window). The resample argument uses the syntax 179 | #' identical to that used in GDAL itself. 180 | #' 181 | #' @param x rasterio params as from [raster_io0()] 182 | #' @return list in sf RasterIO format 183 | #' @export 184 | #' @examples 185 | #' rio <- raster_io0(c(0L, 0L), src_dim = c(24L, 10L)) 186 | #' rasterio_to_sfio(rio) 187 | rasterio_to_sfio <- function(x) { 188 | resample <- attr(x, "resample") 189 | if (is.null(resample)) { 190 | resample <- "NearestNeighbour" 191 | } 192 | ## sf names: 193 | # "nearest_neighbour", "bilinear", "cubic", "cubic_spline", "lanczos", "average", "mode", "Gauss". 194 | algo <- unname(c(NearestNeighbour = "nearest_neighbour", 195 | Average = "average", 196 | Bilinear="bilinear", 197 | Cubic = "cubic", 198 | CubicSpline = "cubic_spline", 199 | Gauss = "gauss", 200 | Lanczos = "lanczos", 201 | Mode = "mode")[resample]) 202 | if (is.na(algo)) { 203 | warning(sprintf("resampling algorithm %s unrecognized, using 'NearestNeighbour'", algo)) 204 | algo <- "nearest_neighbour" 205 | } 206 | list(nXOff = x[1L] + 1L, 207 | nYOff = x[2L] + 1L, 208 | nXSize = x[3L], 209 | nYSize = x[4L], 210 | nBufXSize = x[5L], 211 | nBufYSize = x[6L], 212 | resample = algo) 213 | } 214 | #' Geo transform parameter creator 215 | #' 216 | #' Basic function to create a geotransform as used by GDAL. 217 | #' @seealso [geo_world0()] which uses the same parameters in a different order 218 | #' @param px pixel resolution (XY, Y-negative) 219 | #' @param ul grid offset, top-left corner 220 | #' @param sh affine shear (XY) 221 | #' 222 | #' @return vector of parameters xmin, xres, yskew, ymax, xskew, yres 223 | #' @export 224 | #' 225 | #' @examples 226 | #' geo_transform0(px = c(1, -1), ul = c(0, 0)) 227 | geo_transform0 <- function(px, ul, sh = c(0, 0)) { 228 | c(xmin = ul[[1L]], 229 | xres = px[[1L]], 230 | yskew = sh[[2L]], 231 | ymax = ul[[2L]], 232 | xskew = sh[[1L]], 233 | yres = px[[2L]]) 234 | } 235 | 236 | #' Create geotransform from world vector 237 | #' 238 | #' Convert world vector (centre offset) and x,y spacing to 239 | #' geotransform format. 240 | #' 241 | #' @param x worldfile parameters, as per [geo_world0()] 242 | #' @export 243 | #' @return geotransform vector, see [geo_transform0()] 244 | #' @examples 245 | #' (wf <- geo_world0(px = c(1, -1), ul = c(0, 0))) 246 | #' gt <- world_to_geotransform(wf) 247 | #' geotransform_to_world(gt) 248 | world_to_geotransform <- function(x) { 249 | x <- unname(x) 250 | px <- x[c(1L, 4L)] 251 | ul <- x[c(5L, 6L)] + c(-1, -1)* px/2 252 | sh <- x[c(2L, 3L)] 253 | geo_transform0(px, ul, sh) 254 | } 255 | 256 | #' World file parameter creator 257 | #' 258 | #' Basic function to create a ['world file'](https://en.wikipedia.org/wiki/World_file) 259 | #' as used by various non-geo image formats 260 | #' 261 | #' Note that xmin/xmax are _centre_of_cell_ (of top-left cell) unlike the geotransform which is 262 | #' top-left _corner_of_cell_. The parameters are otherwise the same, but in a different order. 263 | #' @inheritParams geo_transform0 264 | #' @export 265 | #' @seealso [geo_transform0] 266 | #' @return vector of parameters xres, yskew, xskew, yres, xmin, ymax 267 | #' @export 268 | #' @examples 269 | #' geo_world0(px = c(1, -1), ul = c(0, 0)) 270 | geo_world0 <- function(px, ul, sh = c(0, 0)) { 271 | c(xres = px[[1L]], 272 | yskew = sh[[2L]], 273 | xskew = sh[[1L]], 274 | yres = px[[2L]], 275 | xmin = ul[[1L]] + px[[1L]]/2, 276 | ymax = ul[[2L]] + px[[2L]]/2 277 | ) 278 | } 279 | #' Convert geotransform vector to world vector 280 | #' 281 | #' Reformat to world vector. 282 | #' 283 | #' @name geo_world0 284 | #' @param x geotransform parameters, as per [geo_transform0()] 285 | #' @return world vector, as per [geo_world0()] 286 | #' @export 287 | #' @examples 288 | #' (gt <- geo_transform0(px = c(1, -1), ul = c(0, 0))) 289 | #' wf <- geotransform_to_world(gt) 290 | #' world_to_geotransform(wf) 291 | geotransform_to_world <- function(x) { 292 | x <- unname(x) 293 | px <- x[c(2L, 6L)] 294 | ul <- x[c(1L, 4L)] 295 | sh <- x[c(3L, 5L)] 296 | geo_world0(px, ul, sh) 297 | } 298 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | [![Travis build status](https://travis-ci.org/hypertidy/affinity.svg?branch=master)](https://travis-ci.org/hypertidy/affinity)[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/hypertidy/affinity?branch=master&svg=true)](https://ci.appveyor.com/project/hypertidy/affinity)[![Codecov test coverage](https://codecov.io/gh/hypertidy/affinity/branch/master/graph/badge.svg)](https://codecov.io/gh/hypertidy/affinity?branch=master)[![CRAN status](https://www.r-pkg.org/badges/version/affinity)](https://CRAN.R-project.org/package=affinity) 10 | [![R-CMD-check](https://github.com/hypertidy/affinity/workflows/R-CMD-check/badge.svg)](https://github.com/hypertidy/affinity/actions) 11 | 12 | 13 | 14 | ```{r setup, include = FALSE} 15 | knitr::opts_chunk$set( 16 | collapse = TRUE, 17 | comment = "#>", 18 | fig.path = "man/figures/README-", 19 | out.width = "100%" 20 | ) 21 | ``` 22 | # affinity 23 | 24 | The goal of affinity is to provide the basic tools used for raster grid georeferencing. This includes: 25 | 26 | * the affine transform 27 | * the world file model 28 | * the GDAL RasterIO window model 29 | * basic tools for performing grid calculations 30 | * simple control point georeferencing for un-mapped rasters. 31 | 32 | The main use at the moment is the ability to get a geotransform from an extent and dimension, this makes it easy to drive GDAL functions and to compare 33 | with the RasterIO logic in the sf package raster reader. 34 | 35 | The main functions for georeferencing are `affinething()` to collect drawn points interactively from an un-mapped raster image and `domath()` to calculate the extent of the raster in geographic terms and `assignproj()` to apply a map projection inline. There are some other experimental functions to write GDAL VRT `gdalvrt()` and to store some known cases for unmapped image sources. 36 | 37 | 38 | The basic tools still rely on the raster package. 39 | 40 | ## Installation 41 | 42 | You can install the dev version of affinity from [GitHub](https://github.com/hypertidy/affinity/) with: 43 | 44 | ``` r 45 | devtools::install_github("hypertidy/affinity") 46 | ``` 47 | 48 | ## Example 49 | 50 | This examples takes an an un-mapped raster and [georefences](https://en.wikipedia.org/wiki/Georeferencing) it by defining some control points for a simple (offset and scale) [affine transformation](https://en.wikipedia.org/wiki/Affine_transformation). 51 | 52 | 53 | Generally, we want **diagonal points**, so I tend to think "southwest" and "northeast", it doesn't really matter where they are as long as there's some pixels between them in both directions. Monterey Bay is very recognizable so I read off some long-lat control points using [mapview](https://r-spatial.github.io/mapview/). 54 | 55 | ```{r example} 56 | library(affinity) 57 | #data("montereybay", package = "rayshader") 58 | data("monterey", package = "affinity") 59 | 60 | 61 | library(raster) 62 | ## we know that rayshader works transpose 63 | r <- t(raster(monterey)) 64 | 65 | prj <- "+proj=longlat +datum=WGS84" 66 | ## the north tip of Pacific Grove 67 | sw <- c(-121.93348, 36.63674) 68 | ## the inlet at Moss Landing 69 | ne <- c(-121.78825, 36.80592) 70 | #mapview::mapview(c(sw[1], ne[1]), c(sw[2], ne[2]), crs = prj) 71 | ``` 72 | 73 | 74 | We can obtain raw (graphics) coordinates of those locations from our image, by plotting it and clicking twice with `affinething()`. 75 | 76 | Note the order, the first point is "sw" and the second is "ne" - the order is not important but it must match. 77 | 78 | ```{r affine-thing, eval = FALSE} 79 | ## mask the raster so we can see easily where we need to click 80 | xy <- affinething(r > 0) 81 | 82 | ``` 83 | 84 | In this example the points are 85 | 86 | ```{r affine-thing-points} 87 | # xy <- structure(c(0.65805655219227, 0.858931100128933, 0.367586425626388, 88 | # 0.589597209007295), .Dim = c(2L, 2L), .Dimnames = list(NULL, 89 | # c("x", "y"))) 90 | xy <- structure(c(0.440321955368224, 0.580740883913579, 0.453408220576972, 91 | 0.625733980086801), .Dim = c(2L, 2L), .Dimnames = list(NULL, 92 | c("x", "y"))) 93 | ``` 94 | 95 | Please note that if the matrix changes, then the values above will have to change as well (this has happened). 96 | 97 | ```{r affine-thing2, eval = TRUE, echo = FALSE} 98 | plot(r > 0) 99 | points(xy) 100 | text(xy, lab = 1:2, pos = 4) 101 | ``` 102 | 103 | Now we have everything we need to re-map our raster! We don't need to project our points as the known locations are in the same 104 | coordinate system as the source data. (In other situations we might georeference using a graticule on a projected map.) 105 | 106 | ```{r affine-remap} 107 | mapped <- assignproj(setExtent(r, domath(rbind(sw, ne), xy, r, proj = NULL)), prj) 108 | 109 | m <- rnaturalearth::ne_countries(country = "United States of America", scale = 10) 110 | plot(mapped, col = viridis::viridis(30)) 111 | plot(m, add = TRUE) 112 | contour(mapped, levels = -100, lty = 2, add = TRUE) 113 | 114 | #mv <- mapview::mapview(mapped) 115 | 116 | ``` 117 | 118 | 119 | 120 | 121 | ```{r, eval = FALSE, include = FALSE, echo = FALSE} 122 | ## Old rough example 123 | 124 | r <- raster("dev/www.bom.gov.au/charts_data/IDY20001/current/windarrow/10m/2015-12-21/IDY20001.windarrow-10m.066.png") 125 | a <- regions("windAntarctica") 126 | projection(r) <- a$proj 127 | extent(r) <- a$extent 128 | plot(r) 129 | library(maptools) 130 | data(wrld_simpl) 131 | library(rgdal) 132 | w <- spTransform(wrld_simpl, projection(r)) 133 | plot(w, add = TRUE) 134 | 135 | 136 | ex <- domath(pts, rawxy) 137 | gdalvrt(r, a_ullr = c(xmin(ex), ymax(ex), xmax(ex), ymin(ex)), 138 | a_srs = "\"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0\"") 139 | 140 | 141 | ``` 142 | 143 | --- 144 | 145 | Please note that the 'affinity' project is released with a [Contributor Code of Conduct](https://github.com/hypertidy/affinity/blob/master/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | [![Travis build 6 | status](https://travis-ci.org/hypertidy/affinity.svg?branch=master)](https://travis-ci.org/hypertidy/affinity)[![AppVeyor 7 | build 8 | status](https://ci.appveyor.com/api/projects/status/github/hypertidy/affinity?branch=master&svg=true)](https://ci.appveyor.com/project/hypertidy/affinity)[![Codecov 9 | test 10 | coverage](https://codecov.io/gh/hypertidy/affinity/branch/master/graph/badge.svg)](https://codecov.io/gh/hypertidy/affinity?branch=master)[![CRAN 11 | status](https://www.r-pkg.org/badges/version/affinity)](https://CRAN.R-project.org/package=affinity) 12 | [![R-CMD-check](https://github.com/hypertidy/affinity/workflows/R-CMD-check/badge.svg)](https://github.com/hypertidy/affinity/actions) 13 | 14 | 15 | # affinity 16 | 17 | The goal of affinity is to provide the basic tools used for raster grid 18 | georeferencing. This includes: 19 | 20 | - the affine transform 21 | - the world file model 22 | - the GDAL RasterIO window model 23 | - basic tools for performing grid calculations 24 | - simple control point georeferencing for un-mapped rasters. 25 | 26 | The main use at the moment is the ability to get a geotransform from an 27 | extent and dimension, this makes it easy to drive GDAL functions and to 28 | compare with the RasterIO logic in the sf package raster reader. 29 | 30 | The main functions for georeferencing are `affinething()` to collect 31 | drawn points interactively from an un-mapped raster image and `domath()` 32 | to calculate the extent of the raster in geographic terms and 33 | `assignproj()` to apply a map projection inline. There are some other 34 | experimental functions to write GDAL VRT `gdalvrt()` and to store some 35 | known cases for unmapped image sources. 36 | 37 | The basic tools still rely on the raster package. 38 | 39 | ## Installation 40 | 41 | You can install the dev version of affinity from 42 | [GitHub](https://github.com/hypertidy/affinity/) with: 43 | 44 | ``` r 45 | devtools::install_github("hypertidy/affinity") 46 | ``` 47 | 48 | ## Example 49 | 50 | This examples takes an an un-mapped raster and 51 | [georefences](https://en.wikipedia.org/wiki/Georeferencing) it by 52 | defining some control points for a simple (offset and scale) [affine 53 | transformation](https://en.wikipedia.org/wiki/Affine_transformation). 54 | 55 | Generally, we want **diagonal points**, so I tend to think “southwest” 56 | and “northeast”, it doesn’t really matter where they are as long as 57 | there’s some pixels between them in both directions. Monterey Bay is 58 | very recognizable so I read off some long-lat control points using 59 | [mapview](https://r-spatial.github.io/mapview/). 60 | 61 | ``` r 62 | library(affinity) 63 | #data("montereybay", package = "rayshader") 64 | data("monterey", package = "affinity") 65 | 66 | 67 | library(raster) 68 | #> Loading required package: sp 69 | ## we know that rayshader works transpose 70 | r <- t(raster(monterey)) 71 | 72 | prj <- "+proj=longlat +datum=WGS84" 73 | ## the north tip of Pacific Grove 74 | sw <- c(-121.93348, 36.63674) 75 | ## the inlet at Moss Landing 76 | ne <- c(-121.78825, 36.80592) 77 | #mapview::mapview(c(sw[1], ne[1]), c(sw[2], ne[2]), crs = prj) 78 | ``` 79 | 80 | We can obtain raw (graphics) coordinates of those locations from our 81 | image, by plotting it and clicking twice with `affinething()`. 82 | 83 | Note the order, the first point is “sw” and the second is “ne” - the 84 | order is not important but it must match. 85 | 86 | ``` r 87 | ## mask the raster so we can see easily where we need to click 88 | xy <- affinething(r > 0) 89 | ``` 90 | 91 | In this example the points are 92 | 93 | ``` r 94 | # xy <- structure(c(0.65805655219227, 0.858931100128933, 0.367586425626388, 95 | # 0.589597209007295), .Dim = c(2L, 2L), .Dimnames = list(NULL, 96 | # c("x", "y"))) 97 | xy <- structure(c(0.440321955368224, 0.580740883913579, 0.453408220576972, 98 | 0.625733980086801), .Dim = c(2L, 2L), .Dimnames = list(NULL, 99 | c("x", "y"))) 100 | ``` 101 | 102 | Please note that if the matrix changes, then the values above will have 103 | to change as well (this has happened). 104 | 105 | 106 | 107 | Now we have everything we need to re-map our raster! We don’t need to 108 | project our points as the known locations are in the same coordinate 109 | system as the source data. (In other situations we might georeference 110 | using a graticule on a projected map.) 111 | 112 | ``` r 113 | mapped <- assignproj(setExtent(r, domath(rbind(sw, ne), xy, r, proj = NULL)), prj) 114 | 115 | m <- rnaturalearth::ne_countries(country = "United States of America", scale = 10) 116 | plot(mapped, col = viridis::viridis(30)) 117 | plot(m, add = TRUE) 118 | contour(mapped, levels = -100, lty = 2, add = TRUE) 119 | ``` 120 | 121 | 122 | 123 | ``` r 124 | #mv <- mapview::mapview(mapped) 125 | ``` 126 | 127 | ------------------------------------------------------------------------ 128 | 129 | Please note that the ‘affinity’ project is released with a [Contributor 130 | Code of 131 | Conduct](https://github.com/hypertidy/affinity/blob/master/CODE_OF_CONDUCT.md). 132 | By contributing to this project, you agree to abide by its terms. 133 | -------------------------------------------------------------------------------- /affinity.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 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,vignette 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | environment: 17 | NOT_CRAN: true 18 | # env vars that may need to be set, at least temporarily, from time to time 19 | # see https://github.com/krlmlr/r-appveyor#readme for details 20 | # USE_RTOOLS: true 21 | # R_REMOTES_STANDALONE: true 22 | 23 | # Adapt as necessary starting from here 24 | 25 | build_script: 26 | - travis-tool.sh install_deps 27 | 28 | test_script: 29 | - travis-tool.sh run_tests 30 | 31 | on_failure: 32 | - 7z a failure.zip *.Rcheck\* 33 | - appveyor PushArtifact failure.zip 34 | 35 | artifacts: 36 | - path: '*.Rcheck\**\*.log' 37 | name: Logs 38 | 39 | - path: '*.Rcheck\**\*.out' 40 | name: Logs 41 | 42 | - path: '*.Rcheck\**\*.fail' 43 | name: Logs 44 | 45 | - path: '*.Rcheck\**\*.Rout' 46 | name: Logs 47 | 48 | - path: '\*_*.tar.gz' 49 | name: Bits 50 | 51 | - path: '\*_*.zip' 52 | name: Bits 53 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## affinity 0.2.5 2 | 3 | Resubmit (was 0.2.0) 4 | 5 | * shortened Title 6 | * lengthened Description 7 | * added return value to all documentation 8 | * improved documentation 9 | * added references to web sites to Description 10 | 11 | Thank you. 12 | 13 | ## Test environments 14 | * local R installation, R 4.0.5 15 | * win-builder (devel) 16 | 17 | ## R CMD check results 18 | 19 | 0 errors | 0 warnings | 2 note 20 | 21 | * This is a new release. 22 | * Spellings georeference and affine are intended. 23 | -------------------------------------------------------------------------------- /data-raw/monterey.R: -------------------------------------------------------------------------------- 1 | data("montereybay", package = "rayshader") 2 | image(montereybay) 3 | ## why store the class Extent ... but not actually use the raster functions 4 | ex <- attr(montereybay, "extent") 5 | ex <- c(ex@xmin, ex@xmax, ex@ymin, ex@ymax) 6 | 7 | ## drop the attributes and decimate 2x 8 | monterey <- matrix(montereybay[seq(1, nrow(montereybay), by = 2), seq(1, ncol(montereybay), by = 2)], nrow(montereybay)/2) 9 | usethis::use_data(monterey, compress = "xz") 10 | -------------------------------------------------------------------------------- /data/monterey.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hypertidy/affinity/d55748a57f1abc331974e9a516de0fa8ecf8e1d4/data/monterey.rda -------------------------------------------------------------------------------- /inst/extdata/C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hypertidy/affinity/d55748a57f1abc331974e9a516de0fa8ecf8e1d4/inst/extdata/C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png -------------------------------------------------------------------------------- /inst/extdata/C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.stx: -------------------------------------------------------------------------------- 1 | 1 0 0 0 255 255 255 2 | -------------------------------------------------------------------------------- /inst/extdata/C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.vrt: -------------------------------------------------------------------------------- 1 | 2 | -180, 0.08333333, 0, 90, 0, -0.08333333 3 | +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0 4 | 5 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.1C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.2C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.3 6 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png 7 | 0 8 | 1 9 | 12960 10 | LSB 11 | -Inf 12 | 0 13 | 1 14 | 15 | 16 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.1C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.2C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.3 17 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png 18 | 4320 19 | 1 20 | 12960 21 | LSB 22 | -Inf 23 | 0 24 | 1 25 | 26 | 27 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.1C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.2C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.3 28 | C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png 29 | 8640 30 | 1 31 | 12960 32 | LSB 33 | -Inf 34 | 0 35 | 1 36 | 37 | 38 | -------------------------------------------------------------------------------- /inst/extdata/czcs.r: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | f <- "http://oceancolor.gsfc.nasa.gov/cgi/l3/C19843361984366.L3m_MO_CHL_chlor_a_9km.nc.png?sub=img" 4 | fname <- file.path("inst", "extdata", gsub("\\?sub=img", "", basename(f))) 5 | if (!file.exists(fname)) { 6 | download.file(f, fname, mode = "wb") 7 | } 8 | 9 | library(raster) 10 | r <- brick(fname) 11 | 12 | llp <- "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0" 13 | gdalvrt(r, a_ullr = c(-180, 90, 180, -90), a_srs = llp) 14 | 15 | r <- brick(rgdal::readGDAL(gsub("png$", "vrt", fname))) 16 | -------------------------------------------------------------------------------- /inst/working_example.R: -------------------------------------------------------------------------------- 1 | x <- raadtools::readice("2020-09-07") ## as at https://twitter.com/mdsumner/status/1303565190055641088 2 | 3 | par(mfrow = c(3, 3)) 4 | image(x, axes = FALSE, legend = FALSE) 5 | rio <- rasterio_to_sfio(raster_io0(c(100, 190), c(110, 120), c(620, 520))) 6 | 7 | st <- stars::read_stars(tfile, RasterIO = rio) 8 | image(st, add = T, reset = FALSE, col = cols, breaks = brks) 9 | allvals <- st[[1]] 10 | xx <- stars:::st_as_raster(st) 11 | library(raster) 12 | alg <- c(NearestNeighbour = "nearest_neighbour", 13 | Average = "average", 14 | Bilinear="bilinear", 15 | Cubic = "cubic", 16 | CubicSpline = "cubic_spline", 17 | Gauss = "Gauss", 18 | Lanczos = "lanczos", 19 | Mode = "mode") 20 | 21 | for (i in seq_along(alg)) { 22 | rio$resample <- alg[i] 23 | st <- stars::read_stars(tfile, RasterIO = rio) 24 | allvals <- c(allvals, st[[1]]) 25 | image(xx, col = "white", asp = "", axes = FALSE, main = names(alg)[i]) 26 | image(st, add = TRUE, reset = FALSE, breaks = brks, col = cols) 27 | } 28 | 29 | ## cheat, do this post-hoc and run again 30 | brks <- quantile(allvals, seq(0, 1, length.out = 11), na.rm = TRUE) 31 | cols <- grey.colors(length(brks) - 1) 32 | -------------------------------------------------------------------------------- /man/adjacencies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adjacencies.R 3 | \name{adjacencies} 4 | \alias{adjacencies} 5 | \alias{bl} 6 | \alias{tl} 7 | \alias{br} 8 | \alias{tr} 9 | \alias{image0} 10 | \alias{image1} 11 | \alias{text0} 12 | \title{Adjacency, for use in creating area based meshes} 13 | \usage{ 14 | bl(x) 15 | 16 | tl(x) 17 | 18 | br(x) 19 | 20 | tr(x) 21 | 22 | image0(x, ...) 23 | 24 | image1(x, ...) 25 | 26 | text0(x, ...) 27 | } 28 | \arguments{ 29 | \item{x}{matrix} 30 | 31 | \item{...}{arguments passed to image()} 32 | } 33 | \value{ 34 | matrix, padded by one row and one column relative to input 35 | } 36 | \description{ 37 | Functions 'bottom left', 'top left', 'bottom right', and 'top right' named by 38 | their initials, provide very low level relative positional structures for use in 39 | raster logic. These are used to traverse the divide left by area-based rasters which are 40 | inherently a discrete value across a finite element. If we want that element as part of a 41 | continuous surface we need to find local relative values for its corners. Used in 42 | quadmesh and anglr packages, and useful for calculating neighbourhood values. 43 | } 44 | \details{ 45 | Some tiny functions 'image0', 'image1', 'text0' exist purely to illustrate the ideas in 46 | a vignette. 47 | } 48 | \examples{ 49 | (m <- matrix(1:12, 3)) 50 | tl(m) 51 | tr(m) 52 | bl(m) 53 | br(m) 54 | tl(br(m)) 55 | image0(tl(br(m))) 56 | text0(tl(br(m))) 57 | } 58 | -------------------------------------------------------------------------------- /man/affinething.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/affinething.R 3 | \name{affinething} 4 | \alias{affinething} 5 | \title{Use affine logic interactively georegister a raster} 6 | \usage{ 7 | affinething(x, rgb = FALSE) 8 | } 9 | \arguments{ 10 | \item{x}{a raster} 11 | 12 | \item{rgb}{use RGB plot for a raster with 3 layers} 13 | } 14 | \value{ 15 | matrix of x,y coordinates in the space of the current raster extent 16 | } 17 | \description{ 18 | User clicks are collected in a controlled way for use by \code{\link[=domath]{domath()}}. 19 | } 20 | \details{ 21 | Obtain control points for the simple affine transform (offset and scale) on an ungeoreferenced image. 22 | } 23 | \examples{ 24 | \donttest{ 25 | \dontrun{ 26 | library(raster) 27 | r <- raster("my_unreferenced_raster.png") 28 | xy <- affinething(r) ## click on two points that you know a location of 29 | my_x <- c(1000, 2000) 30 | my_y <- c(-1000, -500) 31 | prj <- "+proj=laea +lon=147 +lat_0=-42" ## use your own map projection, that correspond to my_x/my_y 32 | pt <- cbind(my_x, my_y) 33 | ## now convert those control points to an extent for your raster 34 | ex <- domath(pt, xy, r, prj) 35 | 36 | ## now we can fix up the data 37 | r <- raster::setExtent(r, ex) 38 | raster::projection(r) <- prj 39 | ## hooray! 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /man/affinity-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/affinity-package.R 3 | \docType{package} 4 | \name{affinity-package} 5 | \alias{affinity} 6 | \alias{affinity-package} 7 | \title{affinity: Raster Georeferencing, Grid Affine Transforms, Cell Abstraction} 8 | \description{ 9 | Tools for raster georeferencing, grid affine transforms, and general raster logic. 10 | These functions provide converters between raster specifications, world vector, geotransform, 11 | 'RasterIO' window, and 'RasterIO window' in 'sf' package list format. There are functions to offset 12 | a matrix by padding any of four corners (useful for vectorizing neighbourhood operations), and 13 | helper functions to harvesting user clicks on a graphics device to use for simple georeferencing 14 | of images. Methods used are available from and 15 | . 16 | } 17 | \seealso{ 18 | Useful links: 19 | \itemize{ 20 | \item \url{https://github.com/hypertidy/affinity} 21 | \item Report bugs at \url{https://github.com/hypertidy/affinity/issues} 22 | } 23 | 24 | } 25 | \author{ 26 | \strong{Maintainer}: Michael D. Sumner \email{mdsumner@gmail.com} 27 | 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/assignproj.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/affinething.R 3 | \name{assignproj} 4 | \alias{assignproj} 5 | \title{Assign projection} 6 | \usage{ 7 | assignproj(x, proj = "+proj=longlat +datum=WGS84") 8 | } 9 | \arguments{ 10 | \item{x}{spatial object for use with \code{\link[raster:projection]{raster::projection()}}} 11 | 12 | \item{proj}{PROJ.4 string} 13 | } 14 | \value{ 15 | a spatial object with the projection set 16 | } 17 | \description{ 18 | Set the projection of a spatial object. 19 | } 20 | -------------------------------------------------------------------------------- /man/domath.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/affinething.R 3 | \name{domath} 4 | \alias{domath} 5 | \title{Calculate the math of an affine transform} 6 | \usage{ 7 | domath(pts, xy, r = NULL, proj = NULL) 8 | } 9 | \arguments{ 10 | \item{pts}{known points of 'xy'} 11 | 12 | \item{xy}{'xy' obtain from \code{affinething}} 13 | 14 | \item{r}{raster in use} 15 | 16 | \item{proj}{optional projection, if the pts are longlat and the raster is not} 17 | } 18 | \value{ 19 | raster extent 20 | } 21 | \description{ 22 | Given relative location and absolute locations, convert to an actual real world extent 23 | for a matrix of data. 24 | } 25 | \details{ 26 | Convert known geographic points with raw graphic control points and a reference raster 27 | to an extent for the raster in geography. 28 | } 29 | \examples{ 30 | ## not a real example, but the extent we could provide volcano if the second set of points 31 | ## described the real world positions of the first set of points within the matrix 32 | domath(cbind(c(147, 148), c(-42, -43)), cbind(c(0.2, 0.3), c(0.1, 0.5)), raster::raster(volcano)) 33 | } 34 | \seealso{ 35 | \code{\link[=affinething]{affinething()}} 36 | } 37 | -------------------------------------------------------------------------------- /man/extent_dim_to_gt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{extent_dim_to_gt} 4 | \alias{extent_dim_to_gt} 5 | \title{Create geotransform from extent and dimension} 6 | \usage{ 7 | extent_dim_to_gt(x, dim) 8 | } 9 | \arguments{ 10 | \item{x}{extent parameters, c(xmin,xmax,ymin,ymax)} 11 | 12 | \item{dim}{dimensions x,y of grid (ncol,nrow)} 13 | } 14 | \value{ 15 | 6-element \code{\link[=geo_transform0]{geo_transform0()}} 16 | } 17 | \description{ 18 | Create the geotransform (see \code{\link[=geo_transform0]{geo_transform0()}}) from extent and dimension. 19 | } 20 | \details{ 21 | The dimension is always ncol, nrow. 22 | } 23 | \examples{ 24 | extent_dim_to_gt(c(0, 5, 0, 10), c(5, 10)) 25 | } 26 | -------------------------------------------------------------------------------- /man/figures/README-affine-remap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hypertidy/affinity/d55748a57f1abc331974e9a516de0fa8ecf8e1d4/man/figures/README-affine-remap-1.png -------------------------------------------------------------------------------- /man/figures/README-affine-thing2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hypertidy/affinity/d55748a57f1abc331974e9a516de0fa8ecf8e1d4/man/figures/README-affine-thing2-1.png -------------------------------------------------------------------------------- /man/geo_transform0.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{geo_transform0} 4 | \alias{geo_transform0} 5 | \title{Geo transform parameter creator} 6 | \usage{ 7 | geo_transform0(px, ul, sh = c(0, 0)) 8 | } 9 | \arguments{ 10 | \item{px}{pixel resolution (XY, Y-negative)} 11 | 12 | \item{ul}{grid offset, top-left corner} 13 | 14 | \item{sh}{affine shear (XY)} 15 | } 16 | \value{ 17 | vector of parameters xmin, xres, yskew, ymax, xskew, yres 18 | } 19 | \description{ 20 | Basic function to create a geotransform as used by GDAL. 21 | } 22 | \examples{ 23 | geo_transform0(px = c(1, -1), ul = c(0, 0)) 24 | } 25 | \seealso{ 26 | \code{\link[=geo_world0]{geo_world0()}} which uses the same parameters in a different order 27 | } 28 | -------------------------------------------------------------------------------- /man/geo_world0.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{geo_world0} 4 | \alias{geo_world0} 5 | \alias{geotransform_to_world} 6 | \title{World file parameter creator} 7 | \usage{ 8 | geo_world0(px, ul, sh = c(0, 0)) 9 | 10 | geotransform_to_world(x) 11 | } 12 | \arguments{ 13 | \item{px}{pixel resolution (XY, Y-negative)} 14 | 15 | \item{ul}{grid offset, top-left corner} 16 | 17 | \item{sh}{affine shear (XY)} 18 | 19 | \item{x}{geotransform parameters, as per \code{\link[=geo_transform0]{geo_transform0()}}} 20 | } 21 | \value{ 22 | vector of parameters xres, yskew, xskew, yres, xmin, ymax 23 | 24 | world vector, as per \code{\link[=geo_world0]{geo_world0()}} 25 | } 26 | \description{ 27 | Basic function to create a \href{https://en.wikipedia.org/wiki/World_file}{'world file'} 28 | as used by various non-geo image formats 29 | 30 | Reformat to world vector. 31 | } 32 | \details{ 33 | Note that xmin/xmax are \emph{centre_of_cell} (of top-left cell) unlike the geotransform which is 34 | top-left \emph{corner_of_cell}. The parameters are otherwise the same, but in a different order. 35 | } 36 | \examples{ 37 | geo_world0(px = c(1, -1), ul = c(0, 0)) 38 | (gt <- geo_transform0(px = c(1, -1), ul = c(0, 0))) 39 | wf <- geotransform_to_world(gt) 40 | world_to_geotransform(wf) 41 | } 42 | \seealso{ 43 | \link{geo_transform0} 44 | } 45 | -------------------------------------------------------------------------------- /man/gt_dim_to_extent.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{gt_dim_to_extent} 4 | \alias{gt_dim_to_extent} 5 | \title{Determine extent from eotransform vector and dimension} 6 | \usage{ 7 | gt_dim_to_extent(x, dim) 8 | } 9 | \arguments{ 10 | \item{x}{geotransform parameters, as per \code{\link[=geo_transform0]{geo_transform0()}}} 11 | 12 | \item{dim}{dimensions x,y of grid (ncol,nrow)} 13 | } 14 | \value{ 15 | 4-element extent c(xmin,xmax,ymin,ymax) 16 | } 17 | \description{ 18 | Create the extent (xlim, ylim) from the geotransform and dimensions 19 | of the grid. 20 | } 21 | \details{ 22 | The extent is \code{c(xmin, xmax, ymin, ymax)}. 23 | } 24 | \examples{ 25 | gt_dim_to_extent(geo_transform0(c(1, -1), c(0, 10)), c(5, 10)) 26 | } 27 | -------------------------------------------------------------------------------- /man/monterey.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/affinity-package.R 3 | \docType{data} 4 | \name{monterey} 5 | \alias{monterey} 6 | \title{Monterey Bay elevation} 7 | \format{ 8 | An object of class \code{matrix} (inherits from \code{array}) with 270 rows and 270 columns. 9 | } 10 | \usage{ 11 | monterey 12 | } 13 | \description{ 14 | Extent is in the examples, stolen from rayshader. 15 | } 16 | \details{ 17 | A matrix 270x270 of topography. Used in \code{\link[=affinething]{affinething()}} examples. 18 | } 19 | \examples{ 20 | ex <- c(-122.366765, -121.366765, 36.179392, 37.179392) 21 | raster::setExtent(raster::t(raster::raster(monterey)), ex) 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/raster_io.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{raster_io} 4 | \alias{raster_io} 5 | \alias{raster_io0} 6 | \title{GDAL RasterIO parameter creator} 7 | \usage{ 8 | raster_io0( 9 | src_offset, 10 | src_dim, 11 | out_dim = src_dim, 12 | resample = "NearestNeighbour" 13 | ) 14 | } 15 | \arguments{ 16 | \item{src_offset}{index offset (0-based, top left)} 17 | 18 | \item{src_dim}{source dimension (XY)} 19 | 20 | \item{out_dim}{output dimension (XY, optional src_dim will be used if not set)} 21 | 22 | \item{resample}{resampling algorith for GDAL see details} 23 | } 24 | \value{ 25 | numeric vector of values specifying offset, source dimension, output dimension 26 | } 27 | \description{ 28 | Basic function to create the window paramers as used by GDAL RasterIO. 29 | } 30 | \details{ 31 | Resampling algorithm is one of 'NearestNeighbour' (default), 'Average', 'Bilinear', 'Cubic', 'CubicSpline', 'Gauss', 'Lanczos', 'Mode', but 32 | more may be available given the version of GDAL in use. 33 | } 34 | \examples{ 35 | raster_io0(c(0L, 0L), src_dim = c(24L, 10L)) 36 | } 37 | -------------------------------------------------------------------------------- /man/raster_to_gt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{raster_to_gt} 4 | \alias{raster_to_gt} 5 | \title{Geotransform from raster object} 6 | \usage{ 7 | raster_to_gt(x) 8 | } 9 | \arguments{ 10 | \item{x}{raster object (the raster package, extends BasicRaster)} 11 | } 12 | \value{ 13 | a geotransform vector 14 | } 15 | \description{ 16 | Return the geotransform defining the raster's offset and resolution. 17 | } 18 | \details{ 19 | The geotransform vector is six coefficients xmin, xres, yskew, ymax, xskew, yres, values 20 | relative to the top left corner of the top left pixel. "yres" the y-spacing is 21 | traditionally negative. 22 | } 23 | \examples{ 24 | raster_to_gt(raster::raster(volcano)) 25 | } 26 | -------------------------------------------------------------------------------- /man/raster_to_rasterio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{raster_to_rasterio} 4 | \alias{raster_to_rasterio} 5 | \alias{raster_to_sfio} 6 | \title{RasterIO window from raster object} 7 | \usage{ 8 | raster_to_rasterio(x) 9 | 10 | raster_to_sfio(x) 11 | } 12 | \arguments{ 13 | \item{x}{a raster object (BasicRaster, from raster package)} 14 | } 15 | \value{ 16 | RasterIO window vector 'c(x0, y0, nx0, ny0, nx, y)' see Details 17 | } 18 | \description{ 19 | Return the RasterIO window vector defining the raster's offset and resolution and dimensions. 20 | } 21 | \details{ 22 | The RasterIO window is a six element vector of offset (x,y), dimension of source (nx0, ny0) and 23 | dimension of output (nx, ny). 24 | 25 | The sf RasterIO is the RasterIO window in a list format used by the sf package, it contains the same 26 | information, and is created by \code{\link[=raster_to_sfio]{raster_to_sfio()}}. 27 | } 28 | \examples{ 29 | raster_to_rasterio(raster::raster(volcano)) 30 | } 31 | -------------------------------------------------------------------------------- /man/raster_to_world.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{raster_to_world} 4 | \alias{raster_to_world} 5 | \title{World vector from raster object.} 6 | \usage{ 7 | raster_to_world(x) 8 | } 9 | \arguments{ 10 | \item{x}{raster object (the raster package, extends BasicRaster)} 11 | } 12 | \value{ 13 | a geotransform vector 14 | } 15 | \description{ 16 | Return the world transform defining the raster's offset and resolution. 17 | } 18 | \details{ 19 | The world vector is the values xres, yres, xmin, ymax relative to the 20 | centre of the top left pixel. "yres" the y-spacing is traditionally negative. 21 | } 22 | \examples{ 23 | raster_to_world(raster::raster(volcano)) 24 | } 25 | -------------------------------------------------------------------------------- /man/rasterio_to_sfio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{rasterio_to_sfio} 4 | \alias{rasterio_to_sfio} 5 | \title{The sf/stars RasterIO list} 6 | \usage{ 7 | rasterio_to_sfio(x) 8 | } 9 | \arguments{ 10 | \item{x}{rasterio params as from \code{\link[=raster_io0]{raster_io0()}}} 11 | } 12 | \value{ 13 | list in sf RasterIO format 14 | } 15 | \description{ 16 | We create the list as used by the stars/sf GDAL IO function 'gdal_read(, RasterIO_parameters)'. 17 | } 18 | \details{ 19 | Note that the input is a 4 or 6 element vector, with offset 0-based and 20 | output dimensions optional (will use the source window). The resample argument uses the syntax 21 | identical to that used in GDAL itself. 22 | } 23 | \examples{ 24 | rio <- raster_io0(c(0L, 0L), src_dim = c(24L, 10L)) 25 | rasterio_to_sfio(rio) 26 | } 27 | -------------------------------------------------------------------------------- /man/sfio_to_rasterio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{sfio_to_rasterio} 4 | \alias{sfio_to_rasterio} 5 | \title{sf package RasterIO from RasterIO window vector} 6 | \usage{ 7 | sfio_to_rasterio(x) 8 | } 9 | \arguments{ 10 | \item{x}{a RasterIO parameter list} 11 | } 12 | \value{ 13 | a sf-RasterIO parameter list 14 | } 15 | \description{ 16 | Basic function to create the window parameters as used by GDAL RasterIO, in 17 | format used by sf, in 'gdal_read(,RasterIO_parameters)'. 18 | } 19 | \examples{ 20 | sfio_to_rasterio(rasterio_to_sfio(raster_io0(c(0L, 0L), src_dim = c(24L, 10L)))) 21 | } 22 | -------------------------------------------------------------------------------- /man/world_to_geotransform.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/grids.R 3 | \name{world_to_geotransform} 4 | \alias{world_to_geotransform} 5 | \title{Create geotransform from world vector} 6 | \usage{ 7 | world_to_geotransform(x) 8 | } 9 | \arguments{ 10 | \item{x}{worldfile parameters, as per \code{\link[=geo_world0]{geo_world0()}}} 11 | } 12 | \value{ 13 | geotransform vector, see \code{\link[=geo_transform0]{geo_transform0()}} 14 | } 15 | \description{ 16 | Convert world vector (centre offset) and x,y spacing to 17 | geotransform format. 18 | } 19 | \examples{ 20 | (wf <- geo_world0(px = c(1, -1), ul = c(0, 0))) 21 | gt <- world_to_geotransform(wf) 22 | geotransform_to_world(gt) 23 | } 24 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/adjacencies.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "adjacencies" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{adjacencies} 6 | %\VignetteEncoding{UTF-8} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | editor_options: 9 | chunk_output_type: console 10 | --- 11 | 12 | ```{r, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | ```{r setup} 20 | library(affinity) 21 | ``` 22 | 23 | ```{r adjacency} 24 | (m <- matrix(1:12, 3)) 25 | tl(m) 26 | tr(m) 27 | bl(m) 28 | br(m) 29 | tl(br(m)) 30 | image0(tl(br(m))) 31 | text0(tl(br(m))) 32 | 33 | n <- 8 34 | nbr <- 2 35 | line <- seq(-nbr, nbr) 36 | line + n 37 | 38 | ## we have values 1:12 39 | ## if we want the topleft neighbour in a *corner* orientation 40 | matrix(c(tl(m), tr(m), bl(m), br(m)), ncol = 4L) 41 | ## see that the topleft corner of 1 (find 1 in the first column, row 4) 42 | # has values 1 and 4 (there's no column to their left) 43 | 44 | ## the topleft corner of 5 has values 4, 5, 7, 8 (row 10 in the print out) 45 | 46 | ``` 47 | 48 | This is cool because we can get the row mean for each value in the original 49 | matrix and apply that to the corner. This is better than what quadmesh originally 50 | did to create corner values. 51 | 52 | Now, we want queen's case neighbours. 53 | 54 | For 5, we need 1, 4, 7, 8, 9, 6, 3, 2, and first we note that 8 4, 7 are the topleft 55 | corner (we don't want the value we are, 5 - yet), so that means the other values for 56 | this cell are the topright of 5 (8, 9, 6), the botright of 5 (6, 3, 2), and bottomleft 57 | of 5 (2, 4, 1). 58 | 59 | 5 60 | 61 | 4, 7, 8 - row 10 62 | 6, 8, 9 - row 11 63 | 2, 3, 6 - row 7 64 | 1, 2, 4 - row 6 65 | 66 | 8 67 | 68 | 7, 10, 11 - row 14 69 | 9, 11, 12 - row 15 70 | 5, 6, 9 - row 11 71 | 4, 5, 7 - row 10 72 | 73 | TBD 74 | --------------------------------------------------------------------------------