Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upmapPolygon(coastlineWorld) has horiz. lines in some projections #388
Comments
|
Thanks for posting this. It's long been a known problem. It may have come and gone, as various schemes have been tested for fixing the bug. It needs to be an open issue. The problem arises at the "cut points" as a land mass goes off one edge of the plot and reenters the other. I've tried some solution methods based on locating line segments that are a lot longer than others, but that is silly (e.g. what if a person wants to draw a line along the equator). A better method would perhaps look for points that are (in some sense) far apart in map-projected space, but (in some sense) near to each other on the sphere. Exactly what to do with the wild points is a question. Inserting NA will keep lines from crossing the plot but it doesn't help with filled curves. For little islands, filling is not an issue but a filled continent will be a problem, and it should really be solved by adding fake points that lie along the edge of the graph. But here's the thing. For some projections (like those illustrated above) we could figure out where the edge is, but that is tricky in general. The problem exists in Test code showing library(oce)
library(mapproj)
xy <- mapproject(coastlineWorld[['longitude']], coastlineWorld[['latitude']], proj="mollweide")
plot(xy$x, xy$y, type='l', asp=1) |
|
A quick test indicates that Below is test code library(oce)
library(proj4)
library(mapproj)
data(coastlineWorld)
lon <- coastlineWorld[['longitude']]
lat <- coastlineWorld[['latitude']]
par(mfrow=c(2,1), mar=c(3, 3, 1, 1), mgp=c(2, 0.7, 0))
xy <- project(cbind(lon,lat), "+proj=moll")
plot(xy[,1], xy[,2], type='l', asp=1)
xy <- mapproject(coastlineWorld[['longitude']], coastlineWorld[['latitude']], proj="mollweide")
plot(xy$x, xy$y, type='l', asp=1) |
|
A downside to switching to |
|
Yes, the plan is for a separate branch. (Indeed, with the name you suggest). Also, my plan was to convert from mapproj syntax to proj4 syntax, because the latter is sort of weird looking. There are only a few dozen projections in consideration, so the names will be easy. It's just a matter of figuring out the "params" and "orientation" parameters. We are on the exact same wavelength, as so often happens. I may play with this on Saturday morning. |
|
I did some tests, and proj4 doesn't look any better than mapproject. This can be seen in the following sample code. However, I am not done with proj4 yet, since I like the fact that it can do inverses. So I could imagine a scheme where bad points are found (as below) and then maybe a scheme involving the inverse could be used to alter the data. (Right now, Oce just inserts NA when there are problems, which is of no help for filled land masses.) if (!interactive()) png("01.png",
width=7, height=4.5, unit="in", res=150, pointsize=8)
## Row 1: mollweide (default)
## Row 2: mollweide (shifted to dateline)
showbad <- function(x, y, col='red', pch=16)
{
span <- 0.5 * diff(range(x, na.rm=TRUE))
dx <- c(0, diff(x))
bad <- abs(dx) > span / 2
bad[is.na(bad)] <- FALSE
points(x[bad], y[bad], col=col, pch=pch)
cat("span:", span, "\n")
}
library(oce)
library(proj4)
library(mapproj)
data(coastlineWorld)
lon <- coastlineWorld[['longitude']]
lat <- coastlineWorld[['latitude']]
par(mfrow=c(2,2), mar=c(3, 3, 1, 1), mgp=c(2, 0.7, 0), cex=2/3)
xymapproj <- mapproject(lon, lat, proj="mollweide")
plot(xymapproj$x, xymapproj$y, type='l', asp=1)
showbad(xymapproj$x, xymapproj$y)
xyproj4 <- project(cbind(lon,lat), "+proj=moll")
plot(xyproj4[,1], xyproj4[,2], type='l', asp=1)
showbad(xyproj4[,1], xyproj4[,2])
## oriented with dateline at centre
xymapproj <- mapproject(lon, lat, proj="mollweide", orientation=c(90,-180,0))
plot(xymapproj$x, xymapproj$y, type='l', asp=1)
showbad(xymapproj$x, xymapproj$y)
xyproj4 <- project(cbind(lon, lat),
list(proj="moll", lon_0=-180))
plot(xyproj4[,1], xyproj4[,2], type='l', asp=1)
showbad(xyproj4[,1], xyproj4[,2])
if (!interactive()) dev.off() |
|
Well, there is one wonky line left, this time at a 45 deg angle (to NW) from a spot in Africa. But this probably just means some tweaking is required. For example, perhaps should only look for weird line segments that have one end at high abs(x) value. Naturally, there is basically nothing to be done about Antarctica. Having looked at a few datasets, I know that some odd things are generally done there. Sigh. |
|
Possibly |
|
I wrote a new function that gets fairly close to a solution. It has some "opposite-edge shadowing" (see e.g. the edges of Antarctica, which have lines going north to the northernmost point of the continent). I may do some work to remove that later, but that can be done without changing the UI. The test code only works on the branch named Notice that the new function After the code is a snap of the first page. If you build the whole PDF, you can page through and get a mini-movie of a spinning globe. library(oce)
data(coastlineWorld)
if (!interactive()) pdf("09.pdf", width=7, height=7, pointsize=8)
par(mfrow=c(2,1), mar=c(2, 2, 1, 1), mgp=c(2, 0.7, 0))
xlim <- ylim <- NULL # yields identical map scales on successive pages
for (lon_0 in seq(-180, 180, 10)) {
proj <- "robin"
mod <- coastlineCut(coastlineWorld, lon_0=lon_0)
lon <- mod[["longitude"]]
lat <- mod[["latitude"]]
plot(lon, lat, xlim=c(-180,180), ylim=c(-90,90), type='l')
lines(c(-180, 180, 180, -180, -180), c(-90, -90, 90, 90, -90), col='gray')
polygon(lon, lat, col='gray')
proj <- sprintf("+proj=%s +lon_0=%.0f", proj, lon_0)
if (is.null(xlim)) {
mapPlot(mod, fill='gray', proj=proj)
xlim <- par('usr')[1:2]
ylim <- par('usr')[3:4]
} else {
mapPlot(mod, fill='gray', proj=proj, xlim=xlim, ylim=ylim, xaxs="i", yaxs="i")
}
mtext("BUG: opposite-edge 'shadow'", line=0, col='magenta', font=2, adj=0)
mtext(proj, side=3, line=0, adj=1)
}
if (!interactive()) dev.off() |
|
Great, I'll try testing this later when I get a chance. Though, from the pick above it looks like we've replaced UHL with some UVL! Still, it's an improvement! :) |
|
Actually the UVL would go away if PS. I feel that I'll need to merge into |
|
This issue is not gone, but I have found that http://cameron.bracken.bz/finally-an-easy-way-to-fix-the-horizontal-lines-in-ggplot2-maps and thought there might be some ideas in there. In particular, it seems that they use the PBSmapping package for do the polygon clipping. |
|
Closing now, since this has been fixed for quite some time. Certainly, the initial test is fine now. It must be noted that |






Example: