├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── test-coverage.yaml ├── .gitignore ├── CITATION.cff ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── main.R └── package.R ├── README.Rmd ├── README.md ├── codemeta.json ├── fisheye.Rproj ├── inst └── tinytest │ └── test_fisheye.R ├── man ├── figures │ ├── README-example-1.png │ ├── README-example-2.png │ ├── README-example2-1.png │ ├── README-example2-2.png │ ├── README-unnamed-chunk-2-1.png │ ├── README-unnamed-chunk-2-2.png │ ├── fig.jpg │ └── logo.png ├── fisheye-package.Rd └── fisheye.Rd └── tests └── tinytest.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^codecov\.yml$ 4 | ^\.github$ 5 | figures 6 | ^README\.Rmd$ 7 | ^CITATION\.cff$ 8 | ^codemeta\.json$ 9 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | 7 | name: R-CMD-check 8 | 9 | jobs: 10 | R-CMD-check: 11 | runs-on: ${{ matrix.config.os }} 12 | 13 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | config: 19 | - {os: macos-latest, r: 'release'} 20 | - {os: windows-latest, r: 'release'} 21 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 22 | - {os: ubuntu-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'oldrel-1'} 24 | 25 | env: 26 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 27 | R_KEEP_PKG_SOURCE: yes 28 | 29 | steps: 30 | - uses: actions/checkout@v3 31 | 32 | - uses: r-lib/actions/setup-pandoc@v2 33 | 34 | - uses: r-lib/actions/setup-r@v2 35 | with: 36 | r-version: ${{ matrix.config.r }} 37 | http-user-agent: ${{ matrix.config.http-user-agent }} 38 | use-public-rspm: true 39 | 40 | - uses: r-lib/actions/setup-r-dependencies@v2 41 | with: 42 | extra-packages: any::rcmdcheck 43 | needs: check 44 | 45 | - uses: r-lib/actions/check-r-package@v2 46 | with: 47 | upload-snapshots: true 48 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | 8 | # User-specific files 9 | .Ruserdata 10 | 11 | # Example code in package build process 12 | *-Ex.R 13 | 14 | # Output files from R CMD build 15 | /*.tar.gz 16 | 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | 20 | # RStudio files 21 | .Rproj.user/ 22 | 23 | # produced vignettes 24 | vignettes/*.html 25 | vignettes/*.pdf 26 | 27 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 28 | .httr-oauth 29 | 30 | # knitr and R markdown default cache directories 31 | *_cache/ 32 | /cache/ 33 | 34 | # Temporary files created by R markdown 35 | *.utf8.md 36 | *.knit.md 37 | 38 | # R Environment Variables 39 | .Renviron 40 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------- 2 | # CITATION file created with {cffr} R package, v0.5.0 3 | # See also: https://docs.ropensci.org/cffr/ 4 | # ----------------------------------------------------------- 5 | 6 | cff-version: 1.2.0 7 | message: 'To cite package "fisheye" in publications use:' 8 | type: software 9 | license: GPL-3.0-only 10 | title: 'fisheye: Transform Base Maps Using Log-Azimuthal Projection' 11 | version: 0.2.0 12 | abstract: Base maps are transformed to focus on a specific location using an azimuthal 13 | logarithmic distance transformation. 14 | authors: 15 | - family-names: Giraud 16 | given-names: Timothée 17 | email: timothee.giraud@cnrs.fr 18 | orcid: https://orcid.org/0000-0002-1932-3323 19 | - family-names: Guibard 20 | given-names: Luc 21 | repository: https://CRAN.R-project.org/package=fisheye 22 | repository-code: https://github.com/riatelab/fisheye 23 | url: https://github.com/riatelab/fisheye 24 | contact: 25 | - family-names: Giraud 26 | given-names: Timothée 27 | email: timothee.giraud@cnrs.fr 28 | orcid: https://orcid.org/0000-0002-1932-3323 29 | keywords: 30 | - map 31 | - r 32 | - spatial 33 | references: 34 | - type: software 35 | title: 'R: A Language and Environment for Statistical Computing' 36 | notes: Depends 37 | url: https://www.R-project.org/ 38 | authors: 39 | - name: R Core Team 40 | location: 41 | name: Vienna, Austria 42 | year: '2023' 43 | institution: 44 | name: R Foundation for Statistical Computing 45 | version: '>= 3.5.0' 46 | - type: software 47 | title: sf 48 | abstract: 'sf: Simple Features for R' 49 | notes: Imports 50 | url: https://r-spatial.github.io/sf/ 51 | repository: https://CRAN.R-project.org/package=sf 52 | authors: 53 | - family-names: Pebesma 54 | given-names: Edzer 55 | email: edzer.pebesma@uni-muenster.de 56 | orcid: https://orcid.org/0000-0001-8049-7069 57 | year: '2023' 58 | - type: software 59 | title: covr 60 | abstract: 'covr: Test Coverage for Packages' 61 | notes: Suggests 62 | url: https://covr.r-lib.org 63 | repository: https://CRAN.R-project.org/package=covr 64 | authors: 65 | - family-names: Hester 66 | given-names: Jim 67 | email: james.f.hester@gmail.com 68 | year: '2023' 69 | - type: software 70 | title: tinytest 71 | abstract: 'tinytest: Lightweight and Feature Complete Unit Testing Framework' 72 | notes: Suggests 73 | url: https://github.com/markvanderloo/tinytest 74 | repository: https://CRAN.R-project.org/package=tinytest 75 | authors: 76 | - family-names: van der Loo 77 | given-names: Mark 78 | email: mark.vanderloo@gmail.com 79 | orcid: https://orcid.org/0000-0002-9807-4686 80 | year: '2023' 81 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: fisheye 2 | Title: Transform Base Maps Using Log-Azimuthal Projection 3 | Version: 0.3.0 4 | Authors@R: c(person("Timothée", "Giraud", 5 | email = "timothee.giraud@cnrs.fr", 6 | role = c("cre","aut"), 7 | comment = c(ORCID = "0000-0002-1932-3323")), 8 | person(given = "Luc", 9 | family = "Guibard", 10 | role = c("aut"))) 11 | Description: Base maps are transformed to focus on a specific location using an 12 | azimuthal logarithmic distance transformation. 13 | URL: https://github.com/riatelab/fisheye 14 | BugReports: https://github.com/riatelab/fisheye/issues 15 | License: GPL-3 16 | Depends: 17 | R (>= 3.5.0) 18 | Imports: 19 | sf 20 | Encoding: UTF-8 21 | RoxygenNote: 7.3.1 22 | Suggests: 23 | covr, 24 | tinytest 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(fisheye) 4 | importFrom(sf,"st_crs<-") 5 | importFrom(sf,"st_geometry<-") 6 | importFrom(sf,st_centroid) 7 | importFrom(sf,st_coordinates) 8 | importFrom(sf,st_crs) 9 | importFrom(sf,st_geometry) 10 | importFrom(sf,st_geometry_type) 11 | importFrom(sf,st_linestring) 12 | importFrom(sf,st_point) 13 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # fisheye 0.2.0 2 | 3 | - update docs and links 4 | -------------------------------------------------------------------------------- /R/main.R: -------------------------------------------------------------------------------- 1 | #' @title fisheye 2 | #' @description This function transform an sf layer with a fisheye 3 | #' transformation. Several methods are available. This is a visualisation 4 | #' method that should not be used for geospatial calculation (area, 5 | #' distances...). 6 | #' The output sf object has no CRS as it is not relevant. 7 | #' 8 | #' 9 | #' @param x an sf object (POINT, LINESTRING, MULTILINESTRING, POLYGON, 10 | #' MULTIPOLYGON) to be transformed. This object needs to be projected 11 | #' (no lon/lat). 12 | #' @param centre an sf object, the center of the transformation. This object 13 | #' must use the same projection as x. 14 | #' @param method transfomation method, either 'log' or 'sqrt'. See Details. 15 | #' @param k integer, factor to adjust the log transformation, higher values 16 | #' soften the deformation. See Details. 17 | #' 18 | #' @details 19 | #' The 'log' method transforms distances to \code{center} with: 20 | #' \eqn{{d}' = \log(1 + 10^{-k} * d)}{% 21 | #' d' = log(1 + 10^(-k) * d)} 22 | #' \cr 23 | #' The 'sqrt' method transforms distances to \code{center} with: 24 | #' \eqn{{d}' = \sqrt(d)}{% 25 | #' d' = sqrt(d)} 26 | #' 27 | #' @return A transformed sf object is returned. 28 | #' @importFrom sf st_coordinates st_centroid st_geometry st_geometry_type 29 | #' st_linestring st_point st_crs st_crs<- st_geometry<- 30 | #' @export 31 | #' 32 | #' @examples 33 | #' library(sf) 34 | #' ncraw <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE) 35 | #' nc <- st_transform(ncraw, 3857) 36 | #' ncfe <- fisheye(nc, centre = nc[100, ], method = 'log', k = 4) 37 | #' plot(st_geometry(ncfe), col = "grey70", lwd = .2) 38 | #' plot(st_geometry(ncfe[100,]), col = NA, lwd = 2, border = "red", add = TRUE) 39 | fisheye <- function(x, centre, method = "log", k = 1){ 40 | 41 | 42 | 43 | 44 | # center geometries around center 45 | centre <- st_coordinates(st_centroid(st_geometry(centre))) 46 | geom <- st_geometry(x) 47 | geom <- geom - c(centre[1], centre[2]) 48 | pts <- st_coordinates(geom) 49 | 50 | 51 | 52 | 53 | # original distance 54 | dist <- sqrt((pts[,"X"]^2) + (pts[,"Y"]^2)) 55 | # angle 56 | ta <- atan(pts[,"Y"] / pts[,"X"]) 57 | 58 | 59 | # modified distances 60 | if (method == 'sqrt'){ 61 | d <- sqrt(dist) 62 | } else if (method =="log"){ 63 | # d <- log(1 + dist + min(dist)*2) 64 | d <- log(1 + 10^(-k) * dist) 65 | 66 | } else { 67 | stop("method should be either 'log' or 'sqrt'", 68 | call. = FALSE) 69 | } 70 | 71 | # get new coordinates 72 | sx <- sign(pts[,"X"]) 73 | sx[sx==0] <- 1 74 | pts[,"X"] <- d * cos(ta) * sx 75 | pts[,"Y"] <- d * sin(ta) * sx 76 | 77 | 78 | 79 | # asigned new coordinates 80 | gtype <- st_geometry_type(x, by_geometry = FALSE) 81 | 82 | if(gtype == "MULTIPOLYGON"){ 83 | uu <- unique(pts[, c("L1", "L2", "L3")]) 84 | for (i in 1:nrow(uu)){ 85 | geom[[rev(uu[i, ])]] <- pts[pts[,"L1"]==uu[i,"L1"] & 86 | pts[,"L2"]==uu[i,"L2"] & 87 | pts[,"L3"]==uu[i,"L3"], 1:2] 88 | } 89 | } 90 | if(gtype %in% c("POLYGON", "MULTILINESTRING")){ 91 | uu <- unique(pts[, c("L1", "L2")]) 92 | for (i in 1:nrow(uu)){ 93 | geom[[rev(uu[i, ])]] <- pts[pts[,"L1"]==uu[i,"L1"] & 94 | pts[,"L2"]==uu[i,"L2"], 1:2] 95 | } 96 | } 97 | if(gtype %in% c("LINESTRING")){ 98 | uu <- unique(pts[, c("L1")]) 99 | for (i in 1:length(uu)){ 100 | geom[[uu[i]]] <- st_linestring(pts[pts[,"L1"]==uu[i], 1:2]) 101 | } 102 | } 103 | if(gtype %in% c("POINT")){ 104 | for (i in 1:nrow(x)){ 105 | geom[[i]] <- st_point(pts[i, 1:2]) 106 | } 107 | } 108 | 109 | st_geometry(x) <- geom 110 | 111 | # update bbox 112 | cc <- st_coordinates(x) 113 | xmin <- min(cc[,1]) 114 | xmax <- max(cc[,1]) 115 | ymin <- min(cc[,2]) 116 | ymax <- max(cc[,2]) 117 | new_bb <- c(xmin, ymin, xmax, ymax) 118 | attr(new_bb, "class") = "bbox" 119 | attr(st_geometry(x), "bbox") = new_bb 120 | st_crs(x) <- NA 121 | 122 | return(x) 123 | } 124 | -------------------------------------------------------------------------------- /R/package.R: -------------------------------------------------------------------------------- 1 | #' @title Package description 2 | #' @name fisheye-package 3 | #' @description 4 | #' Base maps are transformed to focus on a specific location using an 5 | #' azimuthal logarithmic distance transformation. 6 | #' @references Hägerstrand, T. (1957). Migration and Area: A Survey of a Sample 7 | #' of Swedish Migration Fields and Hypothetical Considerations of their Genesis. 8 | #' Lund Studies in Geography, Series B, Human Geography, Department of 9 | #' Geography, University of Lund, Lund. 10 | "_PACKAGE" 11 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | ```{r, include = FALSE} 6 | knitr::opts_chunk$set( 7 | collapse = TRUE, 8 | comment = "#>", 9 | fig.path = "man/figures/README-", 10 | out.width = "100%" 11 | ) 12 | ``` 13 | 14 | # fisheye 15 | 16 | 17 | ![CRAN version](https://www.r-pkg.org/badges/version-ago/fisheye) 18 | [![codecov](https://codecov.io/gh/riatelab/fisheye/branch/main/graph/badge.svg)](https://app.codecov.io/gh/riatelab/fisheye?branch=main) 19 | [![R-CMD-check](https://github.com/riatelab/fisheye/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/riatelab/fisheye/actions/workflows/R-CMD-check.yaml) 20 | 21 | 22 | The goal of fisheye is to create base maps focusing on a specific location using an azimuthal logarithmic distance transformation. 23 | 24 | 25 | 26 | 27 | John Bachmann, [New York and environs](https://digitalcollections.nypl.org/items/510d47e3-b9bd-a3d9-e040-e00a18064a99), 1859. 28 | 29 | 30 | ## Installation 31 | 32 | You can install the released version of `fisheye` from 33 | [CRAN](https://cran.r-project.org/package=fisheye) with: 34 | 35 | ``` r 36 | install.packages("fisheye") 37 | ``` 38 | 39 | Alternatively, you can install the development version of `fisheye` from 40 | GitHub with: 41 | 42 | ``` r 43 | remotes::install_github("riatelab/fisheye") 44 | ``` 45 | ## Example 46 | 47 | This is a basic example: 48 | 49 | ```{r example, fig.width=10, fig.height = 3, out.width="100%"} 50 | library(sf) 51 | library(fisheye) 52 | library(mapsf) 53 | # Import dataset 54 | ncraw <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE) 55 | nc <- st_transform(ncraw, 3857) 56 | par(mfrow = c(1,2)) 57 | mf_map(nc, col ="grey90") 58 | mf_map(nc[51, ], add = TRUE, col = "grey40") 59 | mf_title("Original Map") 60 | # transform the basemap 61 | nc_fe <- fisheye(nc, centre = nc[51, ]) 62 | mf_map(nc_fe, col ="grey90") 63 | mf_map(nc_fe[51, ], add = TRUE, col = "grey40") 64 | mf_title("Log-Azimuthal Projection") 65 | ``` 66 | 67 | ```{r example2,fig.width=10, fig.height = 3, out.width="100%", echo=FALSE } 68 | # data import 69 | par(mfrow = c(1,2)) 70 | mf_theme(mar = c(0.5,0.5,0.5,0.5)) 71 | center <- st_centroid(st_geometry(nc[51, ])) 72 | 73 | buf_size <- c( 74 | seq(100,1000, 100), 75 | seq(1000,10000,1000), 76 | seq(10000, 100000, 10000) 77 | ) 78 | lb <- vector("list", length(buf_size)) 79 | for (i in seq_along(lb)){ 80 | lb[[i]] <- st_buffer(center, buf_size[i]) 81 | } 82 | buf <- st_sf(geom = do.call(c, lb)) 83 | 84 | 85 | mf_init(nc) 86 | mf_map(nc, col ="grey90", border = "white", add = TRUE) 87 | mf_map(buf, add = TRUE, border = "red", col = NA, lwd = .4, lty = 3) 88 | mf_map(buf[c(10,20,30), ], add = TRUE, border = "red", col = NA, 89 | lwd = 1, lty = 1) 90 | mf_map(center, pch = 20, add = TRUE) 91 | for (i in c(20, 30)){ 92 | text(x = st_coordinates(center)[1,1], 93 | y = st_bbox(buf[i, ])[4], 94 | labels = paste0(round(buf_size[i]/1000, 0), "km") 95 | ) 96 | } 97 | 98 | 99 | buffe <- fisheye(buf, centre = center, method = "log", k = 1) 100 | ncfe <- fisheye(nc, centre = center, method = "log", k = 1) 101 | mf_init(buffe) 102 | mf_map(ncfe, add = TRUE) 103 | mf_map(buffe, add = TRUE, border = "red", col = NA, lwd = .4, lty = 3) 104 | mf_map(buffe[c(1,10,20,30), ], add = TRUE, border = "red", col = NA, 105 | lwd = 1, lty = 1) 106 | points(0,0,pch = 20) 107 | for (i in c(1,10,20,30)){ 108 | text(x = 0, 109 | y = st_bbox(buffe[i, ])[4], 110 | labels = paste0(signif(buf_size[i]/1000, 0), "km") 111 | ) 112 | } 113 | 114 | 115 | ``` 116 | 117 | See a more detailed example [here](https://github.com/rcarto/fisheye-example/): 118 | 119 | ![](https://raw.githubusercontent.com/rCarto/fisheye-example/main/gif/mob.gif) 120 | 121 | ## References 122 | 123 | * Hägerstrand, T. (1957). Migration and Area: A Survey of a Sample of Swedish Migration Fields and Hypothetical Considerations of their Genesis. Lund Studies in Geography, Series B, Human Geography, Department of Geography, University of Lund, Lund. 124 | 125 | * Snyder, J.P. (1987). "Magnifying-Glass" Azimuthal Map Projections. The American Cartographer, 14:1, 61-68, https://doi.org/10.1559/152304087783875318 126 | 127 | * Fairbairn, D., & Taylor, G. (1995). Developing a variable-scale map projection for urban areas. Computers & Geosciences, 21:9, 1053-1064, https://doi.org/10.1016/0098-3004(95)00041-6 128 | 129 | * Boutoura, C., Tsioukas, V., & Tsorlini, A. (2012). Experimenting “fisheye-lens functions” in studying digitally particular historic maps. e-Perimetron (ISSN 1790 - 3769). 7. 111-123. http://www.e-perimetron.org/Vol_7_3/Boutoura_et_al.pdf 130 | 131 | * Roughan, M. (2017). Log-azimuthal maps. https://roughan.info/math/log-az/ 132 | 133 | * Rivière, P. (2018). The Log-Azimuthal projection. https://observablehq.com/@fil/log-azimuthal 134 | 135 | * Jansen, T. (2018). “Magnifying-Glass” projections. https://observablehq.com/@toja/magnifying-glass-projections 136 | 137 | * Sahasrabuddhe, R., Lambiotte, R., & Alessandretti, L. (2021). From centre to centres: polycentric structures in individual mobility. https://arxiv.org/pdf/2108.08113.pdf 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # fisheye 3 | 4 | 5 | 6 | ![CRAN version](https://www.r-pkg.org/badges/version-ago/fisheye) 7 | [![codecov](https://codecov.io/gh/riatelab/fisheye/branch/main/graph/badge.svg)](https://app.codecov.io/gh/riatelab/fisheye?branch=main) 8 | [![R-CMD-check](https://github.com/riatelab/fisheye/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/riatelab/fisheye/actions/workflows/R-CMD-check.yaml) 9 | 10 | 11 | The goal of fisheye is to create base maps focusing on a specific 12 | location using an azimuthal logarithmic distance transformation. 13 | 14 | 15 | 16 | John Bachmann, [New York and 17 | environs](https://digitalcollections.nypl.org/items/510d47e3-b9bd-a3d9-e040-e00a18064a99), 18 | 1859. 19 | 20 | ## Installation 21 | 22 | You can install the released version of `fisheye` from 23 | [CRAN](https://cran.r-project.org/package=fisheye) with: 24 | 25 | ``` r 26 | install.packages("fisheye") 27 | ``` 28 | 29 | Alternatively, you can install the development version of `fisheye` from 30 | GitHub with: 31 | 32 | ``` r 33 | remotes::install_github("riatelab/fisheye") 34 | ``` 35 | 36 | ## Example 37 | 38 | This is a basic example: 39 | 40 | ``` r 41 | library(sf) 42 | #> Linking to GEOS 3.11.1, GDAL 3.6.2, PROJ 9.1.1; sf_use_s2() is TRUE 43 | library(fisheye) 44 | library(mapsf) 45 | # Import dataset 46 | ncraw <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE) 47 | nc <- st_transform(ncraw, 3857) 48 | par(mfrow = c(1,2)) 49 | mf_map(nc, col ="grey90") 50 | mf_map(nc[51, ], add = TRUE, col = "grey40") 51 | mf_title("Original Map") 52 | # transform the basemap 53 | nc_fe <- fisheye(nc, centre = nc[51, ]) 54 | mf_map(nc_fe, col ="grey90") 55 | mf_map(nc_fe[51, ], add = TRUE, col = "grey40") 56 | mf_title("Log-Azimuthal Projection") 57 | ``` 58 | 59 | 60 | 61 | 62 | 63 | See a more detailed example 64 | [here](https://github.com/rcarto/fisheye-example/): 65 | 66 | ![](https://raw.githubusercontent.com/rCarto/fisheye-example/main/gif/mob.gif) 67 | 68 | ## References 69 | 70 | - Hägerstrand, T. (1957). Migration and Area: A Survey of a Sample of 71 | Swedish Migration Fields and Hypothetical Considerations of their 72 | Genesis. Lund Studies in Geography, Series B, Human Geography, 73 | Department of Geography, University of Lund, Lund. 74 | 75 | - Snyder, J.P. (1987). “Magnifying-Glass” Azimuthal Map Projections. The 76 | American Cartographer, 14:1, 61-68, 77 | 78 | 79 | - Fairbairn, D., & Taylor, G. (1995). Developing a variable-scale map 80 | projection for urban areas. Computers & Geosciences, 21:9, 1053-1064, 81 | 82 | 83 | - Boutoura, C., Tsioukas, V., & Tsorlini, A. (2012). Experimenting 84 | “fisheye-lens functions” in studying digitally particular historic 85 | maps. e-Perimetron (ISSN 1790 - 3769). 7. 111-123. 86 | 87 | 88 | - Roughan, M. (2017). Log-azimuthal maps. 89 | 90 | 91 | - Rivière, P. (2018). The Log-Azimuthal projection. 92 | 93 | 94 | - Jansen, T. (2018). “Magnifying-Glass” projections. 95 | 96 | 97 | - Sahasrabuddhe, R., Lambiotte, R., & Alessandretti, L. (2021). From 98 | centre to centres: polycentric structures in individual mobility. 99 | 100 | -------------------------------------------------------------------------------- /codemeta.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://doi.org/10.5063/schema/codemeta-2.0", 3 | "@type": "SoftwareSourceCode", 4 | "identifier": "fisheye", 5 | "description": "Base maps are transformed to focus on a specific location using an azimuthal logarithmic distance transformation.", 6 | "name": "fisheye: Transform Base Maps Using Log-Azimuthal Projection", 7 | "codeRepository": "https://github.com/riatelab/fisheye", 8 | "issueTracker": "https://github.com/riatelab/fisheye/issues", 9 | "license": "https://spdx.org/licenses/GPL-3.0", 10 | "version": "0.2.0", 11 | "programmingLanguage": { 12 | "@type": "ComputerLanguage", 13 | "name": "R", 14 | "url": "https://r-project.org" 15 | }, 16 | "runtimePlatform": "R version 4.3.2 (2023-10-31)", 17 | "provider": { 18 | "@id": "https://cran.r-project.org", 19 | "@type": "Organization", 20 | "name": "Comprehensive R Archive Network (CRAN)", 21 | "url": "https://cran.r-project.org" 22 | }, 23 | "author": [ 24 | { 25 | "@type": "Person", 26 | "givenName": "Timothée", 27 | "familyName": "Giraud", 28 | "email": "timothee.giraud@cnrs.fr", 29 | "@id": "https://orcid.org/0000-0002-1932-3323" 30 | }, 31 | { 32 | "@type": "Person", 33 | "givenName": "Luc", 34 | "familyName": "Guibard" 35 | } 36 | ], 37 | "maintainer": [ 38 | { 39 | "@type": "Person", 40 | "givenName": "Timothée", 41 | "familyName": "Giraud", 42 | "email": "timothee.giraud@cnrs.fr", 43 | "@id": "https://orcid.org/0000-0002-1932-3323" 44 | } 45 | ], 46 | "softwareSuggestions": [ 47 | { 48 | "@type": "SoftwareApplication", 49 | "identifier": "covr", 50 | "name": "covr", 51 | "provider": { 52 | "@id": "https://cran.r-project.org", 53 | "@type": "Organization", 54 | "name": "Comprehensive R Archive Network (CRAN)", 55 | "url": "https://cran.r-project.org" 56 | }, 57 | "sameAs": "https://CRAN.R-project.org/package=covr" 58 | }, 59 | { 60 | "@type": "SoftwareApplication", 61 | "identifier": "tinytest", 62 | "name": "tinytest", 63 | "provider": { 64 | "@id": "https://cran.r-project.org", 65 | "@type": "Organization", 66 | "name": "Comprehensive R Archive Network (CRAN)", 67 | "url": "https://cran.r-project.org" 68 | }, 69 | "sameAs": "https://CRAN.R-project.org/package=tinytest" 70 | } 71 | ], 72 | "softwareRequirements": { 73 | "1": { 74 | "@type": "SoftwareApplication", 75 | "identifier": "R", 76 | "name": "R", 77 | "version": ">= 3.5.0" 78 | }, 79 | "2": { 80 | "@type": "SoftwareApplication", 81 | "identifier": "sf", 82 | "name": "sf", 83 | "provider": { 84 | "@id": "https://cran.r-project.org", 85 | "@type": "Organization", 86 | "name": "Comprehensive R Archive Network (CRAN)", 87 | "url": "https://cran.r-project.org" 88 | }, 89 | "sameAs": "https://CRAN.R-project.org/package=sf" 90 | }, 91 | "SystemRequirements": null 92 | }, 93 | "fileSize": "11.216KB" 94 | } 95 | -------------------------------------------------------------------------------- /fisheye.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 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 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageRoxygenize: rd,collate,namespace,vignette 21 | -------------------------------------------------------------------------------- /inst/tinytest/test_fisheye.R: -------------------------------------------------------------------------------- 1 | suppressPackageStartupMessages(library(sf)) 2 | nc <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE) 3 | nc <- st_transform(nc, 3857) 4 | nc1 <- nc[1,] 5 | ncmp <- st_cast(nc, "MULTIPOLYGON") 6 | suppressWarnings(ncp <- st_cast(nc, "POLYGON")) 7 | ncml <- st_cast(nc, "MULTILINESTRING") 8 | suppressWarnings(ncl <- st_cast(ncml, "LINESTRING")) 9 | suppressWarnings(ncpt <- st_cast(ncl, "POINT")) 10 | 11 | expect_silent(fisheye(ncmp, nc1, "log", 1)) 12 | expect_silent(fisheye(ncml, nc1, "log", 1)) 13 | expect_silent(fisheye(ncl, nc1, "log", 1)) 14 | expect_silent(fisheye(ncp, nc1, "log", 1)) 15 | expect_silent(fisheye(ncpt, nc1, "sqrt")) 16 | 17 | # test garbage input 18 | expect_error(fisheye(ncmp, nc1, "logs", 1)) 19 | -------------------------------------------------------------------------------- /man/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-example-1.png -------------------------------------------------------------------------------- /man/figures/README-example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-example-2.png -------------------------------------------------------------------------------- /man/figures/README-example2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-example2-1.png -------------------------------------------------------------------------------- /man/figures/README-example2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-example2-2.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/README-unnamed-chunk-2-2.png -------------------------------------------------------------------------------- /man/figures/fig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/fig.jpg -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riatelab/fisheye/9b45777cd31cb2623cf0f0ed4d8a5d8ab81e117c/man/figures/logo.png -------------------------------------------------------------------------------- /man/fisheye-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/package.R 3 | \docType{package} 4 | \name{fisheye-package} 5 | \alias{fisheye-package} 6 | \title{Package description} 7 | \description{ 8 | Base maps are transformed to focus on a specific location using an 9 | azimuthal logarithmic distance transformation. 10 | } 11 | \references{ 12 | Hägerstrand, T. (1957). Migration and Area: A Survey of a Sample 13 | of Swedish Migration Fields and Hypothetical Considerations of their Genesis. 14 | Lund Studies in Geography, Series B, Human Geography, Department of 15 | Geography, University of Lund, Lund. 16 | } 17 | \seealso{ 18 | Useful links: 19 | \itemize{ 20 | \item \url{https://github.com/riatelab/fisheye} 21 | \item Report bugs at \url{https://github.com/riatelab/fisheye/issues} 22 | } 23 | 24 | } 25 | \author{ 26 | \strong{Maintainer}: Timothée Giraud \email{timothee.giraud@cnrs.fr} (\href{https://orcid.org/0000-0002-1932-3323}{ORCID}) 27 | 28 | Authors: 29 | \itemize{ 30 | \item Luc Guibard 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /man/fisheye.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/main.R 3 | \name{fisheye} 4 | \alias{fisheye} 5 | \title{fisheye} 6 | \usage{ 7 | fisheye(x, centre, method = "log", k = 1) 8 | } 9 | \arguments{ 10 | \item{x}{an sf object (POINT, LINESTRING, MULTILINESTRING, POLYGON, 11 | MULTIPOLYGON) to be transformed. This object needs to be projected 12 | (no lon/lat).} 13 | 14 | \item{centre}{an sf object, the center of the transformation. This object 15 | must use the same projection as x.} 16 | 17 | \item{method}{transfomation method, either 'log' or 'sqrt'. See Details.} 18 | 19 | \item{k}{integer, factor to adjust the log transformation, higher values 20 | soften the deformation. See Details.} 21 | } 22 | \value{ 23 | A transformed sf object is returned. 24 | } 25 | \description{ 26 | This function transform an sf layer with a fisheye 27 | transformation. Several methods are available. This is a visualisation 28 | method that should not be used for geospatial calculation (area, 29 | distances...). 30 | The output sf object has no CRS as it is not relevant. 31 | } 32 | \details{ 33 | The 'log' method transforms distances to \code{center} with: 34 | \eqn{{d}' = \log(1 + 10^{-k} * d)}{% 35 | d' = log(1 + 10^(-k) * d)} 36 | \cr 37 | The 'sqrt' method transforms distances to \code{center} with: 38 | \eqn{{d}' = \sqrt(d)}{% 39 | d' = sqrt(d)} 40 | } 41 | \examples{ 42 | library(sf) 43 | ncraw <- st_read(system.file("shape/nc.shp", package="sf"), quiet = TRUE) 44 | nc <- st_transform(ncraw, 3857) 45 | ncfe <- fisheye(nc, centre = nc[100, ], method = 'log', k = 4) 46 | plot(st_geometry(ncfe), col = "grey70", lwd = .2) 47 | plot(st_geometry(ncfe[100,]), col = NA, lwd = 2, border = "red", add = TRUE) 48 | } 49 | -------------------------------------------------------------------------------- /tests/tinytest.R: -------------------------------------------------------------------------------- 1 | if ( requireNamespace("tinytest", quietly=TRUE) ){ 2 | tinytest::test_package("fisheye") 3 | } 4 | --------------------------------------------------------------------------------