{"id":13857769,"url":"https://github.com/ropensci/mapscanner","last_synced_at":"2025-10-22T05:04:04.750Z","repository":{"id":41087006,"uuid":"194095221","full_name":"ropensci/mapscanner","owner":"ropensci","description":"R package to print maps, draw on them, and scan them back in","archived":false,"fork":false,"pushed_at":"2025-02-07T10:55:16.000Z","size":8967,"stargazers_count":89,"open_issues_count":5,"forks_count":7,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-06-09T13:41:14.467Z","etag":null,"topics":["maps","r-package","scan","spatial"],"latest_commit_sha":null,"homepage":"https://docs.ropensci.org/mapscanner/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ropensci.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":"codemeta.json","zenodo":null}},"created_at":"2019-06-27T12:55:23.000Z","updated_at":"2025-03-22T08:14:12.000Z","dependencies_parsed_at":"2024-04-09T14:08:18.900Z","dependency_job_id":"fed8a8a8-797e-4367-9b16-792125434993","html_url":"https://github.com/ropensci/mapscanner","commit_stats":{"total_commits":424,"total_committers":4,"mean_commits":106.0,"dds":0.04952830188679247,"last_synced_commit":"22765a6cdcb60270de4208f56d00fdd9e33159de"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/ropensci/mapscanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fmapscanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fmapscanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fmapscanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fmapscanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ropensci","download_url":"https://codeload.github.com/ropensci/mapscanner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropensci%2Fmapscanner/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264951976,"owners_count":23687993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["maps","r-package","scan","spatial"],"created_at":"2024-08-05T03:01:46.454Z","updated_at":"2025-10-22T05:03:59.708Z","avatar_url":"https://github.com/ropensci.png","language":"R","readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set (\n    collapse = TRUE,\n    comment = \"#\u003e\",\n    out.width = \"100%\"\n)\n```\n\n# mapscanner \u003ca href='https://docs.ropensci.org/mapscanner/'\u003e\u003cimg src='man/figures/logo.png' align=\"right\" height=210 width=182/\u003e\u003c/a\u003e\n\n\u003c!-- badges: start --\u003e\n[![R build\nstatus](https://github.com/ropensci/mapscanner/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/mapscanner/actions?query=workflow%3AR-CMD-check)\n[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/mapscanner)](https://cran.r-project.org/package=mapscanner/) \n[![CRAN Downloads](https://cranlogs.r-pkg.org/badges/grand-total/mapscanner?color=orange)](https://cran.r-project.org/package=mapscanner)\n[![codecov](https://codecov.io/gh/ropensci/mapscanner/branch/main/graph/badge.svg)](https://app.codecov.io/gh/ropensci/mapscanner)\n[![Project Status: Concept](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)\n\n[![](https://badges.ropensci.org/330_status.svg)](https://github.com/ropensci/software-review/issues/330)\n\n\u003c!-- badges: end --\u003e\n\n\n## What does this package do for me?\n\n`mapscanner` is an **R** package that enables lines drawn by hand on maps to be\nconverted to spatial objects. The package has two primary functions: one for\nproducing maps, and one for rectifying hand-drawn lines to the coordinate\nsystem of the original map. The package is intended for use in social surveys\nand similar endeavours in which hand-drawn markings on maps need to be\nconverted to spatial objects. Maps can be either paper- or screen-based.\nMarkings on paper maps need to be scanned, photographed, or otherwise\ndigitised, while maps with screen-based markings need to be saved as\n`.png`-format images.\n\n## Installation\n\nThe current stable version can be installed from CRAN with:\n```{r cran-inst, eval = FALSE}\ninstall.packages (\"mapscanner\")\n```\n\nAlternatively, the development version can be installed via [rOpenSci's\nr-universe](https://ropensci.r-universe.dev/) by running the following prior to\ncalling `install.packages()`:\n```{r r-univ, eval = FALSE}\noptions (repos = c (\n    ropensci = \"https://ropensci.r-universe.dev\",\n    CRAN = \"https://cloud.r-project.org\"\n))\n```\n\nThe package can then be loaded for usage in a R session with\n```{r library}\nlibrary (mapscanner)\n```\n\n## Usage\n\nThe package is designed to enable the following workflow:\n\n1. Generate a map with the\n   [`ms_generate_map()`](https://docs.ropensci.org/mapscanner/reference/ms_generate_map.html)\n   function, which automatically produces both `.pdf` and `.png` versions;\n\n2. Either print the `.pdf` version to use as desired in any kind of survey\n   environment, or use either the `.pdf` or `.png` versions in digital form for\n   screen-based surveys.\n\n3. Draw on the map;\n\n4. For paper maps, digitise the drawn-on (from here on, \"modified\") map,\n   converting it to either `.pdf` or `.png` format; and\n\n5. Rectify the modified version against the original via the\n   [`ms_rectify_map()`](https://docs.ropensci.org/mapscanner/reference/ms_rectify_map.html)\n   function, which distinguishes individual annotations,\n   and converts each one to a spatial object able to be analysed in any desired\n   manner.\n\n### Practical tips\n\nThe `mapscanner` package is intended to aid a *practical* workflow, and so\na few practical tips may be recommended here to ensure best results:\n\n1. The original digital files generated with\n   [`ms_generate_map()`](https://docs.ropensci.org/mapscanner/reference/ms_generate_map.html)\n   are necessary to rectify subsequently drawn-on and scanned maps, and so must\n   be retained at all times.\n2. Marks drawn on maps should be *coloured* -- any black or grey markings will\n   be ignored. This has the advantage that individual annotations *not*\n   intended to be converted to spatial objects (such as unique identification\n   or participant codes) may be made on maps in black or grey.\n3. For drawings of areas, best results will be achieved through ensuring that\n   all lines form closed polygons. While the default `type = \"hulls\"` argument\n   should work even when lines are not closed, the `type = \"polygons\"` argument\n   will generally produce more accurate results, yet should only be used when\n   all lines form closed polygons (see below for details on how these two differ).\n4. Digitised versions of paper maps should contain *white* borders, so do not,\n   for example, photograph modified maps lying on dark surfaces. If maps are to\n   be photographed, then best results can be achieved by simply placing them on\n   a larger, enclosing sheet of white paper.\n\nThe following two sections describe the two primary functions of the\n`mapscanner` package, corresponding to the two primary steps of producing maps\nto be used in surveys (or other activities), and rectifying modified maps\nagainst these originals in order to extract spatial objects. The second of\nthese sections also describes the kinds of markings able to be recognised, and\nthe kinds of spatial objects to which these may be converted.\n\n\n### Mapbox API tokens\n\nMap generation with `mapscanner` requires a personal token or key from\n[`mapbox`](https://www.mapbox.com/), which can be obtained by following the\nlinks from\n[https://docs.mapbox.com/api](https://docs.mapbox.com/api/#access-tokens-and-token-scopes/).\nIf you already have a token, the easiest way to use it with `mapscanner` is to\ncreate (or edit) a file `~/.Renviron`, and insert a line,\n\n``` bash\nMAPBOX_TOKEN=\u003cmy_mapbox_token\u003e\n```\nThis will then be available every time you start R, without any need to\nexplicitly set the token each time you want to use the package. The token may\nbe given any unique name that includes \"mapbox\" (case insensitive).\nAlternatively, if you wish to keep your token truly private, and only use it\nfor your current R session, you may load `mapscanner`, and then run\n`set_mapbox_token(\u003cmy_mapbox_token\u003e)`.\n\n### Map generation\n\nHaving obtained and set a [`mapbox`](https://www.mapbox.com/) token as\ndescribed above, `mapscanner` may then be used to generate maps. The package\ncomes with a sample map of Omaha, Nebraska, USA, and one with some red lines\ndrawn on it: ![](man/figures/omaha-polygons.png)\n\nThat's just a standard `png` image with no notion of geographical coordinates.\nThe original map was generated with\n\n```{r omaha-fakey, eval = FALSE}\nbbox \u003c- rbind (\n    c (-96.12923, -96.01011),\n    c (41.26145, 41.32220)\n) # portion of omaha\nms_generate_map (bbox, max_tiles = 16L, mapname = \"omaha\")\n```\n```{r omaha, echo = FALSE}\nbbox \u003c- rbind (\n    c (-96.12923, -96.01011),\n    c (41.26145, 41.32220)\n)\nmessage (\"Successfully generated 'omaha.pdf' and 'omaha.png'\")\n```\nAs indicated, the function generates a map in both `.pdf` and `.png` formats.\nThese files must be retained as the \"master\" maps against which subsequently\nmodified -- drawn-over and scanned-in -- versions will be rectified. \n\n\n### Map rectification\n\nThe magic within the `mapscanner` package happens via the [`RNiftyReg`\npackage](https://github.com/jonclayden/RNiftyReg), itself primarily intended to\nalign brain scans and other medical images, but which is precisely the tool\nneeded here. The package comes with two sample `.png` images which can be used\nto demonstrate map rectification. In the following code, `f_modified` is the\nimage shown above, modified from the original by drawing a red line around\na particular region of Omaha.\n```{r scan_maps}\nf_orig \u003c- system.file (\"extdata\", \"omaha.png\", package = \"mapscanner\")\nf_mod \u003c- system.file (\"extdata\", \"omaha-polygons.png\", package = \"mapscanner\")\nres \u003c- ms_rectify_map (f_orig, f_mod, type = \"polygons\")\nres\n```\nThe rectification can take quite some time, during which [`RNiftyReg`\npackage](https://github.com/jonclayden/RNiftyReg) is constructing the best\ntransformation of the modified image back on to the original. The result of\n`ms_rectify_map()` is a spatial object in\n[`sf`](https://cran.r-project.org/package=sf)-format in which each drawn\ncomponent is represented as a separate polygon. Finally, we can plot the result\nas an interactive map using packages like\n[`mapview`](https://github.com/r-spatial/mapview) with the following commands:\n```{r mapview, eval = FALSE}\nlibrary (mapview)\nmapview (res)\n```\nor [`mapdeck`](https://github.com/symbolixAU/mapdeck), which similarly requires\na mapbox token:\n```{r mapdeck, eval = FALSE}\nlibrary (mapdeck)\nset_token (Sys.getenv (\"\u003cmy_mapbox_token\u003e\"))\nmapdeck () %\u003e%\n    add_polygon (res,\n        fill_colour = \"#ffff00cc\",\n        stroke_colour = \"#ff0000\", stroke_width = 20\n    )\n```\n\n\n```{r leaflet, echo = FALSE, eval = FALSE}\nlibrary (leaflet)\n\nleaflet (res) %\u003e%\n    addPolygons (\n        color = \"#FF1111\", weight = 1, opacity = 1.0,\n        fillOpacity = 0.5\n    ) %\u003e%\n    addProviderTiles (\"CartoDB.Positron\") %\u003e%\n    setView (\n        lng = mean (bbox [1, ]),\n        lat = mean (bbox [2, ]),\n        zoom = 12\n    )\n```\n\n![](man/figures/leaflet-1.png)\n\nAnd our hand-drawn lines shown above have been converted to standard spatial\nobjects able to be analysed in any desired way. See the [package\nvignette](https://docs.ropensci.org/mapscanner/articles/mapscanner.html) for\nmore detail of what the `mapscanner` package can do.\n\n\n## Code of Conduct\n\nPlease note that this package is released with a [Contributor Code of\nConduct](https://ropensci.org/code-of-conduct/). By contributing to this\nproject, you agree to abide by its terms.\n\n[![ropensci_footer](https://ropensci.org/public_images/ropensci_footer.png)](https://ropensci.org)\n\n\n## Contributors\n\n\n\n\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\nAll contributions to this project are gratefully acknowledged using the [`allcontributors` package](https://github.com/ropenscilabs/allcontributors) following the [all-contributors](https://allcontributors.org) specification. Contributions of any kind are welcome!\n\n### Code\n\n\u003ctable\u003e\n\n\u003ctr\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/mpadge\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/6697851?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/commits?author=mpadge\"\u003empadge\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/mdsumner\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/4107631?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/commits?author=mdsumner\"\u003emdsumner\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/maelle\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/8360597?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/commits?author=maelle\"\u003emaelle\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/potterzot\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/477294?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/commits?author=potterzot\"\u003epotterzot\u003c/a\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/table\u003e\n\n\n### Issue Authors\n\n\u003ctable\u003e\n\n\u003ctr\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/ThomasDier\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/42271539?u=4194553fedeadf5bf3a23efcc829dfd51615b549\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3AThomasDier\"\u003eThomasDier\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/khondula\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/6106733?u=91bac57101b4e8047b2a96b8ad67437cc32e6144\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3Akhondula\"\u003ekhondula\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/tomroh\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/6668593?u=9e585864a75453fb972c50d461f58aae35d65fac\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3Atomroh\"\u003etomroh\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/SantoshSrinivas79\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/1036163?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3ASantoshSrinivas79\"\u003eSantoshSrinivas79\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/asitemade4u\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/11460106?u=2d81ef9fbaa1ebcd7b9bcf65cd4894e85850d68e\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3Aasitemade4u\"\u003easitemade4u\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/espinielli\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/891692?v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+author%3Aespinielli\"\u003eespinielli\u003c/a\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/table\u003e\n\n\n### Issue Contributors\n\n\u003ctable\u003e\n\n\u003ctr\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/dcooley\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/8093396?u=2c8d9162f246d90d433034d212b29a19e0f245c1\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+commenter%3Adcooley\"\u003edcooley\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/sckott\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/577668?u=c54eb1ce08ff22365e094559a109a12437bdca40\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+commenter%3Asckott\"\u003esckott\u003c/a\u003e\n\u003c/td\u003e\n\u003ctd align=\"center\"\u003e\n\u003ca href=\"https://github.com/jeroen\"\u003e\n\u003cimg src=\"https://avatars.githubusercontent.com/u/216319?u=4825a007eee4f78466b5f833b9728547c74067b5\u0026v=4\" width=\"100px;\" alt=\"\"/\u003e\n\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ropensci/mapscanner/issues?q=is%3Aissue+commenter%3Ajeroen\"\u003ejeroen\u003c/a\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/table\u003e\n\n\u003c!-- markdownlint-enable --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","funding_links":[],"categories":["R"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropensci%2Fmapscanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fropensci%2Fmapscanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropensci%2Fmapscanner/lists"}