maps.where identifying the wrong county - r

When I run:
maps::map.where('county', y = 40.49069996, x = -94.40780005)
# prints "missouri,webster"
Even through these GPS co-ordinates are for a point in Worth County, Missouri, and not in Webster County:

I can't say precisely why, but if you subset the counties to Missouri first and add the fill and plot paramters, Worth is returned as result as it should be. I just followed last example in help for map.where in maps package
p <- map('county','Missouri',fill = TRUE, plot = FALSE)
map.where(p, -94.40780005, 40.49069996)
[1] "missouri, worth"

This is a bug in the maps package. It will be fixed in the forthcoming version 3.2. There is a quick way to avoid the bug, as mweber explains. You can even shorten it to
map.where(map("county",fill=TRUE,plot=FALSE), -94.40780005, 40.49069996)
The bug has probably been around for ages, and only shows for the "counties" database, for missouri countries that follow alphabetically after St Louis.
For the technically minded:
In fact, you can manually fix the installed package (or rather: stop the bug from affecting counties data) by editing maps/mapdata/counties.N
In that file, you will see that around lines 1545-1564, the line numbers do not correspond to the polygon numbers because someone moved a line. If you move that single line back, everything works again. The actual bug in the R code is that for map databases map.where() assumes the polygon number is equal to the line number in the .N file, which is almost always OK, but fails in this case.

Related

Unable to create a multilinestring using st_intersection that is good enough to use border_segment from the SpatialRDD package

I’ve been following the following tutorial https://axlehner.github.io/SpatialRDD/articles/spatialrdd_vignette.html#assign-treatment for SpatialRDD using my own dataset and maps. I’ve run into a problem when attempting to use border_segment. In the tutorial the author has a cut off line he uses which describes a spatial discontinuity. In my own project I am trying to create such a cut off line using historical boundaries and by taking the intersection. I’ve been using two neighboring polygons and taking the intersection of their boundaries using st_intersection to create this cut off. However, once I reach the point where I need to use border_segment it does not work as intended.
If for instance I want 2 border segments to be created using my region, points in that region, and my cut off line, it appears border_segment creates 2 segments for each line segment of my cut off line (the cut off line I created using the intersection of boundaries). Furthermore, comparing the cut off line from the tutorial (can be loaded into R using SpatialRDD::data("cut_off.sf")) to the one I create, the one in the tutorial has one big matrix describing the geometry, while the one I create is described by many 2x2 matrices. I think this is where the problem might be stemming from, but I have no idea how to fix it. I think by finding a solution it would help to understand how to create better geographical objects using just R.
I’ve created a reproducible example to illustrate the issue:
library(SpatialRDD)
library(sf)
library(tmap)
library(spData) #loading various maps
#getting worldmap
data("world")
#changing to a localised projection system
world <- st_transform(world, "EPSG:3035")
#getting just Germany
germany <- world[world$name_long == "Germany",]
#getting just Poland
poland <- world[world$name_long == "Poland",]
#taking the union of Germany and Poland to later distribute random points in them
union <- st_union(germany, poland)
#taking the intersection of their borders, which will act as a cut off line
cut_off <- st_intersection(germany, poland)
#creating random points for exercise to work (similar code to what is done in tutorial)
set.seed(1088) # set a seed
points_samp <- sf::st_sample(union, 1000)
points_samp <- sf::st_sf(points_samp) # make it an sf object
#using border_segment to sort points into 2 border regions
points_samp$segment2 <- border_segment(points_samp, cut_off, 2)
#mapping the points in their respective border segments
tm_shape(points_samp) + tm_dots("segment2", size = 0.1) + tm_shape(cut_off) + tm_lines()
As you will see when plotting the points after creating the border segments, that there will be many border segments even though I indicated for border_segment to create only two.
I’m fairly new to R and geospatial manipulation, so maybe there is a simple solution, but I’ve searched everywhere and haven’t been able to find one. This is the first time after using stack overflow for years that I’ve had to actually post. Please let me know if you need any other information or if I was not clear enough at some point!

Mapping in R with maps package

I am currently trying to generate a map in R demonstrating where my different sampling locations are along the east coast of Canada. I had my code working previously yesterday and was able to visualize the specific area I wanted to look at, and then layer my point on top.
This morning however, when I open the project back up and try to generate the map with this line of code:
map("worldHires", "Canada", xlim=c(-80,-45), ylim=c(40,60), col="gray90", fill=TRUE)
I get the output [[1]] NULL. This is not trying to plot the sampling locations yet, just generating a blank map which I will plot the points over. All the necessary packages (to my knowledge) are loaded (maps, mapdata, maptools, scales) and I don't understand why it was working fine yesterday but today I am only getting this output. I have tried with other regions as well and no matter what I put into the argument it only returns NULL.
I have also tried just entering the line:
map("world", xlim=c(-80,-45), ylim=c(40,60), interior=TRUE)
However when I do this I get this error: Error in as_mapper(.f, ...) : argument ".f" is missing, with no default (which makes sense to me given that this line of code seems to be missing the argument of where it is drawing the geographical data from)
Any tips on what to do? I don't understand why it would be returning a NULL result and I haven't been able to find much help online so far.

Extract from OSM Planet File is incomplete

I'm fairly new to the OSM world and I need to extract all water related polygons from the OSM planet file, except for ocean polygons. I know there is some product from a university in Tokyo, but it's from 2016 and I need it as up to date as possible.
I already extracted a good bit of it with the following code. However, comparing the resulting layers with the OSM basemap in QGIS I noticed that some parts are missing. Even though they have the same flags and relations like other parts that were extracted. I know that some parts of rivers are digitalized as lines and not polygons, so it's okay that those are missing. The missing parts are definitely polygons, since I could extract one of them with the same flags through the QuickOSM plug-in in QGIS. Also the OSM Basemap shows clearly that those areas must be polygons (see screenshot).
Is there a mistake in my code or did I make an mistake with the flags? My code however throws no errors and everything seems to be working except for the missing parts.
Thanks in advance!
Here is the code so far:
library(gdalUtils)
library(rgdal)
library(sf)
# extracting all layers with flag "natural = water"
path_pbf <- "path/to/planet_file.osm.pbf"
ogr2ogr(src_datasource_name = path_pbf,
"OSM_Waterbodies.gpkg",
f = "GPKG",
sql = "SELECT * FROM multipolygons WHERE natural = 'water'",
progress = T)
# extracting all layers with flag "other_tags LIKE waterway"
ogr2ogr(src_datasource_name = path_pbf,
"OSM_Waterways.gpkg",
f = "GPKG",
sql = "SELECT * FROM multipolygons WHERE other_tags LIKE '%waterway%'",
progress = T)
waterways <- st_read("OSM_Waterways.gpkg")
waterways$rm <- NA
# select only certain polygons since waterways also includes dams etc
check <- "*riverbank*|*river*|*stream*|*tidal channel*|*canal*|*drain*|*ditch*|*lake*"
# mark polygons which are not part of the desired selection with "remove" flag
for(i in 1:nrow(waterways)){
if (!grepl(check, waterways$other_tags[i])){
waterways$rm[i] <- "Remove"
}
}
# drop rows with "remove" flag
index <- which(waterways$rm == "Remove")
waterways <- waterways[-index,]
st_write(waterways, "OSM_Waterways_clean.gpkg", driver = "GPKG")
P.S.: The code is probably not the most efficient one, but it's not about efficiency, since I will probably run it once or twice.
It looks like you're only extracting multiploygons, which are used in OSM when a shape isn't a simple polygon. This means that river sections with islands in them will be extracted, but many simple river sections will not, as they are just mapped as closed ways (An example from your screenshot). I don't have the OSM Global file on hand to check, but I would imagine that it's as simple as running the ogr2ogr functions again with ways instead of multipolygons in the SQL, and then checking that the ways are closed (likely, check that the first and last nodes are identical, as a quick search suggests that ogr2ogr doesn't provide a way to check for closed ways explicitly).

Is it possible to access the glyph outline coordinates for a plotted string in R?

I am working on a personal project to develop wordcloud type graphics in R. I have some basic code working, but it is limited to detect collisions between words using the smallest rectangle that bounds each individual word.
I am wondering if it is possible to get access to the actual coordinates of the outline of the individual letters (glyphs?), so that I can pack words much closer to one another - and even do things such as plot a word inside the hole in the middle of a character 'o' for example.
All my searches have proved fruitless. This link seems relevant, but for TeX https://tex.stackexchange.com/questions/180510/how-to-get-intersection-points-of-two-glyphs
This question got very little traction, but after quite a lot of digging I managed to hack a bit of a solution together that worked for my purposes and am sharing for reference.
I wasn't able to get access to the plotted coordinates of characters, but instead I was able to make my own character glyphs, and plot them.
Seeing this answer https://stackoverflow.com/a/7745776/5825522 to an unrelated question started me on the path of using the grImport package to trace a postscript file. And I was able to hack a solution together (sample below) that eventually worked - although I can't confess to understanding the ins and outs of the postscript code and the XML parsing (as this was my first encounter with both topics!)
Note that during my research I also found this package https://github.com/yixuan/fontr which might be more useful for extracting actual plotted character coordinates, but it was beyond my ability to understand and use.
library(grImport)
library(magrittr)
library(xml2)
# Create postscript file for the letter 'S' in times new roman
cat("%!PS
/Times-Roman findfont
10 scalefont
setfont
newpath 0 0 moveto (S) show",
file="example.ps")
# Trace the postscript file to an XML file
grImport::PostScriptTrace("example.ps", "example.xml")
# Read the XML
xml <- xml2::read_xml("example.xml")
# Extract the XML node associated with the letter paths
letter_paths <- xml_find_all(xml, "text/path")
# Extract coordinates
x <- letter_paths %>% xml_find_all("move|line") %>% xml_attr("x") %>% as.numeric()
y <- letter_paths %>% xml_find_all("move|line") %>% xml_attr("y") %>% as.numeric()
# Remove last pair of coordinates as the post script tracing leaves undesired xy coordinates.
# These corrections are tricky for glyphs that have 'holes' in them like 'O' and 'B'
x <- x[-length(x)]
y <- y[-length(y)]
# plot
plot(x,y, asp=1, type="l")
points(x,y)
And after some fiddling I was able to produce a glyph set that worked for me

VPython graphs - Clearing the display so a new set of data can be shown

I have a list of data that I want to be animated on the plot, I'm currently using:
graph1=gdots(pos = pvalues) #pvalues is list of points
while t <= t_max:
rate(200)
... #pvalues is updated to new contain the new points
graph1=gdots(pos = pvalues)
What happens here is the old points remain on the plot, so lines are traced out when I want the points to just move. I've tried deleting the graph, making it invisible, but none of it works.
graph1.visible = False
del graph1
Including the above makes no noticeable difference to the display. I've searched a lot about this, but the VPython documentation seems to be annoyingly incomplete.
I realise this is a very old question, however I had the same issue with vpython 7. For me, graph1.delete() removed the associated data points from the graph, and rescaled the axes based on the remaining data (if any). I haven't yet found a way to remove the graph axes themselves (i.e. delete the figure).

Resources