Proj4js, transformations forward and back - to big inaccuracy - coordinate-systems

I use Proj4js v.2.3.3 to transform coordinates between two projections. The definitions of the projections I've found on spatialreference.org therefore I think it's ok.
If I transform point coordinates (pstart) from 1st projection to 2nd and back to 1st (pend) then pend and pstart differ too much - about 70m in one of the coordinates.
My code looks like:
var p3857 = "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs";
var p2180="+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +units=m +no_defs";
pstart=[2450639.368,6801358.149]
p=proj4(p3857,p2180,pstart);
pend=proj4(p2180,p3857,p);
pend after that equals:
[2450639.3686302807, 6801287.767802416]
Did I do something wrong?
Could somebody help me in this issue?
Thank you everybody for interest my problem

Related

Projecting Rasters, shift to the north. Can i correct it?

I would like to project one raster onto another and while doing so I think the values are changing their position "to the north".
Is this an expected behavior?
I was hoping to create a longlat raster to use it for lookups and GeoJSON generation.
Strangely (or maybe expected, I don't know) resulting GeoJSON positions are shifted (what feels like 10km) to the north.
Do I have a logical mistake somewhere?
This is an example:
x <- raster(ncol=900, nrow=900)
x_proj <- "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +a=6378137 +b=6356752.3142451802 +to_meter=1000 +no_defs "
proj <- CRS(x_proj)
extent(x) <- extent(-523.4622, 376.5378, -4658.645, -3758.645)
projection(x) <- x_proj
x[seq(450,455),seq(1,900)]<-1
new_raster<-raster(ncols=900,nrows=900)
new_raster_crs<- "+proj=longlat +datum=WGS84 +zone=34 +no_defs +ellps=WGS84"
new_raster_proj <- CRS(new_raster_crs)
extent(new_raster) <- extent(3.5889,14.6209, 47.0705, 54.7405)
projection(new_raster) <- new_raster_proj
new_raster<-projectRaster(x,new_raster,method = "bilinear")
Plot of raster x
Plot of Raster new_raster
Is there something I could to with source/dest raster to create a "true" longlat lookup / GeoJSON possibility?
Is there a mistake somewhere ?
Can i maybe change +y_0=0 value to correct this?
If thats the case how can I get the exact value of shift?
Currently I only see the change visually.
That is as expected. Map projections distort (at least one of) shape, size, distance, and direction. In this case, you observe a change in shape.
You do make a mistake here:
new_raster_crs <- "+proj=longlat +datum=WGS84 +zone=34 +no_defs +ellps=WGS84"
"zone" is only relevant for the "UTM" coordinate reference system (and perhaps others), and if you define a datum, you should not also define an ellipsoid. So it should be
new_raster_crs <- "+proj=longlat +datum=WGS84"
But it seems that the other parts you add are simply ignored.
Another mistake is that you still use raster, as it has been replaced by terra. With terra it goes like this:
library(terra)
x <- rast(ncol=900, nrow=900, ext=c(-523.4622, 376.5378, -4658.645, -3758.645),
crs="+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +a=6378137 +b=6356752.3142451802 +to_meter=1000 +no_defs")
x[seq(450,455),seq(1,900)]<-1
y <- rast(ncols=900, nrows=900, ext= c(3.5889,14.6209, 47.0705, 54.7405), crs="+proj=longlat +datum=WGS84")
z <- project(x, y)
plot(z)

Since update of sp package i get a warning by calling a sp::CRS definition

Since update of sp package i get a warning i did not get before:
1: In showSRID(uprojargs, format = "PROJ", multiline = "NO") :
Discarded ellps unknown in CRS definition: +proj=stere +lat_0=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +R=6370040 +units=km +no_defs
2: In showSRID(uprojargs, format = "PROJ", multiline = "NO") :
Discarded datum unknown in CRS definition
This is a code i use to define CRS
sp::CRS(
"+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +a=6370040 +b=6370040 +to_meter=1000 +no_defs"
)
I try to create a projection and it was working before :)
But since update i get this warning.
What am i doing wrong?
Thank you in advance,
Best regards,
Andreas
In your definition, you have parameters a and b --- these refer to the radii of the ellipsoid representation of the earth. As they are the same, you are using a sphere. The new version of the PROJ library require that, if you use the proj4 notation, you must used the WGS84 (or closely related) datum. Otherwise, you need to provide the EPSG code, or WKT notation. So something like this:
p4 <- "+proj=stere +lat_0=90 +lat_ts=90 +lon_0=10 +k=0.93301270189 +units=km +datum=WGS84"
sp::CRS(p4)
#CRS arguments:
# +proj=stere +lat_0=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +units=km +datum=WGS84 +units=m +no_defs
Since there does not seem to be a EPSG code for this CRS, you would need to provide WKT description. I found this one
wkt <- 'PROJCS["unknown",
GEOGCS["unknown",
DATUM["unknown",
SPHEROID["unknown",6370040,0]],
PRIMEM["Greenwich",0,
AUTHORITY["EPSG","8901"]],
UNIT["degree",0.0174532925199433,
AUTHORITY["EPSG","9122"]]],
PROJECTION["Polar_Stereographic"],
PARAMETER["latitude_of_origin",90],
PARAMETER["central_meridian",10],
PARAMETER["scale_factor",0.93301270189],
PARAMETER["false_easting",0],
PARAMETER["false_northing",0],
UNIT["kilometre",1000,
AUTHORITY["EPSG","9036"]],
AXIS["Easting",SOUTH],
AXIS["Northing",SOUTH]]'
But that still does not work because of the datum being unknown
CRS(SRS_string=wkt)
#CRS arguments:
# +proj=stere +lat_0=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +R=6370040 +units=km +no_defs
#Warning messages:
#1: In showSRID(SRS_string, format = "PROJ", multiline = "NO") :
# Discarded ellps unknown in CRS definition: +proj=stere +lat_0=90 +lon_0=10 +k=0.93301270189 +x_0=0 +y_0=0 +R=6370040 +units=km +no_defs
#2: In showSRID(SRS_string, format = "PROJ", multiline = "NO") :
# Discarded datum unknown in CRS definition
There were some big changes in sp and other spatial packages in the recent releases. See, for example:
https://www.r-spatial.org/r/2020/03/17/wkt.html
and
https://www.r-spatial.org/r/2020/06/17/s2.html
Relevant to your issues is there is a difference between crs and CRS. Perhaps things are getting stuck there.

Projection of bubble/circle objects in maps

I am attempting to do some basic concepts with mapping spatial data in R. I started with earthquakes to get some easy data to test with. I first downloaded an earthquake database from this link:
https://www.ngdc.noaa.gov/nndc/struts/results?type_0=Exact&query_0=$ID&t=101650&s=13&d=189&dfn=signif.txt
Then ran the following code to clean/organize this dataset:
library(dplyr)
library(tmap)
library(sf)
earthquake<-read.table("signif.txt",sep="\t",header=TRUE,fill=TRUE) %>% filter(!is.na(LATITUDE) & !is.na(LONGITUDE)) %>% st_as_sf(coords=c("LONGITUDE","LATITUDE"))
Then ran the following code to display a map of all magnitude 9 and greater earthquakes:
tmap_mode("view")
tm_shape(earthquake %>% filter(EQ_PRIMARY > 9))+tm_bubbles(size = "EQ_PRIMARY",col="red",popup.vars=c("EQ_PRIMARY"))
I get this error message since I never assigned a projection to the data: Currect projection of shape earthquake %>% filter(EQ_PRIMARY > 9) unknown. Long-lat (WGS84) is assumed. This is fine, and I get the attached picture:
The problem with this is that the magnitude of that earthquake in Alaska is actually 9.2 while the magnitude of the southern one in Chile is 9.5, yet the Alaska circle is visibly bigger! The bubble icons further from the equator are being projected and distorted under the Mercator projection.
So I try to change the projection of my data to LAEA:
st_crs(earthquake)<-"+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs "
But now when I run the same map as above, the circles are being displayed at a proper size but the basemap does not render since I guess tmap doesn't have a LAEA basemap? This is where I get lost.
As a sidenote this isn't a problem for plotting mode since I can obviously put my own layer underneath that shares the same projection and everything is dandy. My confusion comes in interacting with leaflet.
What's the solution here? I would like to use the nice Mercator map because it looks nice but I don't want things like symbols to be distorted by it. Do I need to define a new size column to counteract the Mercator distortion like earthquake %>% mutate(EQ_PRIMARY1 = EQ_PRIMARY / (abs(LATITUDE)+1)) but replaced with an actual researched function that would counteract the size effect? Is this a common issue in this area or is this something this package just doesn't do correctly?
I did find a bit of a work-around as I described by getting a scale factor for each point based on its latitude. Forgive me if this is a weird work-around but I'm a bit new to this. The basic procedure was:
Add two new geometries based on projection of the existing geometry - project one of them to EQC and one of them this same EQC projection but shifted upward 1 unit (I did this by setting false northing to 1 in the proj4). We basically want two geometries where one unit is one north of the other.
Transform these two geometries to the web mercator using st_transform.
Measure the y-distance between the resulting geometries. This is how much the Web Mercator scales 1 unit of distance at that particular latitude. It is very close to 1.000 for points close to the equator and nearly 2.5 near the poles.
Scale the size of the dots by the inverse square of the above factor.
Code looks like this:
earthquake$yeqc0<-earthquake %>% st_transform("+proj=eqc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs") %>% st_geometry()
earthquake$yeqc1<-earthquake %>% st_transform("+proj=eqc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=1 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs") %>% st_geometry()
Notice the subtle y_0=1 above.
st_crs(earthquake$yeqc1)<-st_crs(earthquake$yeqc0)
earthquake$ymerc<-st_distance(st_transform(earthquake$yeqc0,crs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs"),st_transform(earthquake$yeqc1,crs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=#null +wktext +no_defs"),by_element=TRUE)
earthquake<-earthquake %>% mutate(EQ_PRIMARY1 = EQ_PRIMARY * (1 / ymerc)^2)
tm_shape(earthquake %>% filter(EQ_PRIMARY > 9))+tm_bubbles(size = "EQ_PRIMARY1",col="red",popup.vars=c("EQ_PRIMARY","EQ_PRIMARY1"))
This produces this map which has the dots as the proper size. The code is a little clunky but it could be worse I guess. Probably something that would merit a custom function if one doesn't exist.
First, you need to set the crs to the projection it is currently in, probably WGS84. Then use st_transform to change the coordinates. Here's the code, but it seems to be showing a similar result. Perhaps a different projection would work, or try changing the projection in the tm_shape function.
library(dplyr)
library(tmap)
library(sf)
earthquake<-read.table("https://www.ngdc.noaa.gov/nndc/struts/results?type_0=Exact&query_0=$ID&t=101650&s=13&d=189&dfn=signif.txt",
sep="\t",header=TRUE,fill=TRUE) %>%
filter(!is.na(LATITUDE) & !is.na(LONGITUDE)) %>%
st_as_sf(coords=c("LONGITUDE","LATITUDE"))
st_crs(earthquake) <- 4326
earthquake <- st_transform(earthquake, "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs ")
tmap_mode("view")
tm_shape(earthquake %>% filter(EQ_PRIMARY > 9))+
tm_bubbles(size = "EQ_PRIMARY",col="red",popup.vars=c("EQ_PRIMARY"))

Error in projecting SpatialPolygonsDataFrame from geographical coordinate to UTM

I would like to project the coordinates of the 2012 Peruvian census to work with another raster layer that has the following coordinates reference system :
"+proj=utm +zone=18 +south +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ".
The answer of the post https://gis.stackexchange.com/questions/31743/projecting-sp-objects-in-r did not work in my case.
crs(census)
CRS arguments:
+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
newCRScensus=CRS("+proj=utm +zone=18 +south +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ")
projcensus=spTransform(census,crs=newCRScensus)
Error in spTransform(census, crs = CRS("+proj=utm +zone=18 +south +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ")) :
second argument needs to be of class CRS
I don't understand the error message since the second argument is indeed of class CRS.
Any suggestions for another way of projecting the geographical coordinates is welcomed.
The second argument of spTransform is called CRSobj, not crs, so the right call should be either
projcensus=spTransform(census, newCRScensus)
or
projcensus=spTransform(census, CRSobj = newCRScensus)

Gauss-Krüger coordinates to WGS84 in R

I need to convert from Gauss-Krüger coordinates to WGS84 coordinates (system uses by Google). I am using R to do it, but I don´t find a simple example where this problem is solved.
Could you please help me?
My data for testing the conversion:
Address: Hauptstraße 62
70736 Fellbach, Germany
Input(Gauss-Krüger): 3519358.50 5411371.00
Output (WGS84): 48.839580, 9.262591
Thanks!!!
I cannot comment on this so I had to post it as an answer here. But before I get to the solution, should the output coordinates be reversed?
Solution: (adapted from here)
library(rgdal)
# Creating data
GK <- data.frame(cbind("X_GK"=3519358.50,"Y_GK"=5411371.00))
#Spatial Information, Coordinates Transform
coordinates(GK) <- c("X_GK", "Y_GK")
proj4string(GK) <- CRS("+proj=tmerc +lat_0=0 +lon_0=9 +k=1 +x_0=3500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs") # Defining Gauss Krüger
GK.WGS84 <- spTransform(GK, CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")) # tranforming to WGS84 longlat
GK.WGS84
Output:
> GK.WGS84
SpatialPoints:
X_GK Y_GK
[1,] 9.262686 48.83949
Coordinate Reference System (CRS) arguments: +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0

Resources