Problem transforming coordinates to be compatible with Google Maps when plotting animal movement data

I’m currently doing a project trying to determine the home ranges of sharks using minimum convex polygons as a measurement. So far I’ve managed to successfully make the minimum convex polygons (MCPs) which tell you how large the home range for each animal is, however I’m running into problems when trying to place them on a map, where the map is created but the MCPs are plotted in the completely incorrect area of the world due to issues with coordinate transformations.

I think I’ve narrowed down the problem to the part of my code when I convert the data from a UTM 40 zone to a WGS84 CRS (coordinate system) to make it compatible with Google Maps which uses the WGS84 CRS. The coordinates my MCPs should be in are approximately 71.96, -5.24 which are located in the Chagos Archipelago. However, these coordinates change to 52.51, -4.72e-05 when I convert the data to the new CRS for use with the Google Maps. These new coordinates are very small and not in the Chagos area at all.

The first couple lines of code are converting the MCP data (named SP_cat2 and SP_cat2MCP) into EPSG:32640 (named SF32map_cat2 / cat2MCP), which is the UTM zone 40 / Chagos. When I check the coordinates of these outputs, they are correct:

SF32map_cat2 <- st_as_sf(SP_cat2, crs = 32640) 
SF32map_cat2MCP<- st_as_sf(SP_cat2MCP, crs = 32640)

However, when I convert them to EPSG:4326 (to be used with Google Maps) and check the coordinates, they have changed to the very small coordinates. This is the code used:

SFmap_cat2 <- st_transform(SF32map_cat2, crs = 4326) 
SFmap_cat2MCP <- st_transform(SF32map_cat2MCP, crs = 4326)

I’ve also used st_as_sf() for the second lot of code, and this does successfully put the MCPs on a map, but again, with the wrong coordinates.

After converting to the new CRS, the coordinates are completely wrong and this messes up the map as it either plots the MCPs very close to the equator which isn’t where they should be at all, or plots just the Chagos Archipelago with none of my data on top. This is the mapping code in case this is problematic as well:

ggmap(chagos_map) + 
  geom_sf(data = SFmap_cat2, aes(color = as.factor(code)), size = 2, inherit.aes = FALSE) +
  geom_sf(data = SFmap_cat2MCP, fill = NA, color = "black", alpha = 0.5, inherit.aes = FALSE) +
  ggtitle("MCP Silvertip Cat 2 Chagos") +
  theme_minimal()

I’ve plotted the MCPs themselves without the map behind them and they do plot correctly, but they are located in the complete wrong coordinates very close to the equator. I’ve double checked all the classes and structures of the data and they are all correct. I can’t see where the problem is at all.

Here are the outputs of SP_cat2:

new("SpatialPointsDataFrame", data = structure(list(code =     c("12964", 
    "12964", "12964", "12964", "12964", "12964")), row.names =     c(NA, 
    6L), class = "data.frame"), coords.nrs = 2:3, coords =     structure(c(71.9684, 
    71.9684, 71.9684, 71.9684, 71.9684, 71.9698, -5.2417,     -5.2417, 
    -5.2417, -5.2417, -5.2417, -5.3302), dim = c(6L, 2L),     dimnames = list(
    NULL, c("receiver_lon", "receiver_lat"))), bbox =     structure(c(71.9684, 
    -5.3302, 71.9698, -5.2417), dim = c(2L, 2L), dimnames = list(
    c("receiver_lon", "receiver_lat"), c("min", "max"))),     proj4string = new("CRS", 
    projargs = "+proj=utm +zone=40 +datum=WGS84 +units=m         +no_defs"))

and SP32map_cat2MCP:

structure(list(code = c("12964", "12964", "12964", "12964", "12964", 
"12964"), geometry = structure(list(structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9698, -5.3302
), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = 71.9684, ymin = -5.3302, 
xmax = 71.9698, ymax = -5.2417), class = "bbox"), crs = structure(list(
    input = "+proj=utm +zone=40 +datum=WGS84 +units=m +no_defs", 
    wkt = "PROJCRS["unknown",n    BASEGEOGCRS["unknown",n        DATUM["World Geodetic System 1984",n            ELLIPSOID["WGS 84",6378137,298.257223563,n                LENGTHUNIT["metre",1]],n            ID["EPSG",6326]],n        PRIMEM["Greenwich",0,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8901]]],n    CONVERSION["UTM zone 40N",n        METHOD["Transverse Mercator",n            ID["EPSG",9807]],n        PARAMETER["Latitude of natural origin",0,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8801]],n        PARAMETER["Longitude of natural origin",57,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8802]],n        PARAMETER["Scale factor at natural origin",0.9996,n            SCALEUNIT["unity",1],n            ID["EPSG",8805]],n        PARAMETER["False easting",500000,n            LENGTHUNIT["metre",1],n            ID["EPSG",8806]],n        PARAMETER["False northing",0,n            LENGTHUNIT["metre",1],n            ID["EPSG",8807]],n        ID["EPSG",16040]],n    CS[Cartesian,2],n        AXIS["(E)",east,n            ORDER[1],n            LENGTHUNIT["metre",1,n                ID["EPSG",9001]]],n        AXIS["(N)",north,n            ORDER[2],n            LENGTHUNIT["metre",1,n                ID["EPSG",9001]]]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(code = NA_integer_), levels = c("constant", 
"aggregate", "identity"), class = "factor"), row.names = c(NA, 
6L), class = c("sf", "data.frame"))

4

One issue you have is that the CRS for Google Maps data is WGS84 Pseudo-Mercator/EPSG:3857, and you have assigned your data WGS84/EPSG:4327.

However, somewhere in your workflow it appears you have assigned the wrong CRS to your sf/sp objects. In your dput() examples, the coordinate values are most likely WGS84/EPSG:4326 (decimal degrees), but their CRS are WGS84 UTM Zone 40/EPSG:32640 (metres). This can happen when data are incorrectly assumed to have a certain CRS.

The result is your decimal degree values are being interpreted literally as metres within the projected bounds of EPSG:32640:

xmin = 166021.4, ymax = 9329005, ymin = 0, xmax = 833978.6

where 0 is the equator. This is why, relative to their incorrectly assigned CRS, your coordinates end up ~5m south of the equator (which incidentally is outside the permitted boundary for EPSG:32640).

It’s not possible to say definitively where the incorrect CRS was assigned without access to your full workflow, but working from your example data, here is how to correct your sf/sp objects. I couldn’t access my Google account for some reason, so I have used a shapefile downloaded from Marine Regions as a proxy for chagos_map.

library(sf)
library(sp)
library(dplyr)
library(ggplot2)

# Your example data
SP_cat2 <- new("SpatialPointsDataFrame", data = structure(list(code =     c("12964", 
    "12964", "12964", "12964", "12964", "12964")), row.names =     c(NA, 
    6L), class = "data.frame"), coords.nrs = 2:3, coords =     structure(c(71.9684, 
    71.9684, 71.9684, 71.9684, 71.9684, 71.9698, -5.2417,     -5.2417, 
    -5.2417, -5.2417, -5.2417, -5.3302), dim = c(6L, 2L),     dimnames = list(
    NULL, c("receiver_lon", "receiver_lat"))), bbox =     structure(c(71.9684, 
    -5.3302, 71.9698, -5.2417), dim = c(2L, 2L), dimnames = list(
    c("receiver_lon", "receiver_lat"), c("min", "max"))),     proj4string = new("CRS", 
    projargs = "+proj=utm +zone=40 +datum=WGS84 +units=m         +no_defs"))

SP32map_cat2MCP <- structure(list(code = c("12964", "12964", "12964", "12964", "12964", 
"12964"), geometry = structure(list(structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9684, -5.2417
), class = c("XY", "POINT", "sfg")), structure(c(71.9698, -5.3302
), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = 71.9684, ymin = -5.3302, 
xmax = 71.9698, ymax = -5.2417), class = "bbox"), crs = structure(list(
    input = "+proj=utm +zone=40 +datum=WGS84 +units=m +no_defs", 
    wkt = "PROJCRS["unknown",n    BASEGEOGCRS["unknown",n        DATUM["World Geodetic System 1984",n            ELLIPSOID["WGS 84",6378137,298.257223563,n                LENGTHUNIT["metre",1]],n            ID["EPSG",6326]],n        PRIMEM["Greenwich",0,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8901]]],n    CONVERSION["UTM zone 40N",n        METHOD["Transverse Mercator",n            ID["EPSG",9807]],n        PARAMETER["Latitude of natural origin",0,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8801]],n        PARAMETER["Longitude of natural origin",57,n            ANGLEUNIT["degree",0.0174532925199433],n            ID["EPSG",8802]],n        PARAMETER["Scale factor at natural origin",0.9996,n            SCALEUNIT["unity",1],n            ID["EPSG",8805]],n        PARAMETER["False easting",500000,n            LENGTHUNIT["metre",1],n            ID["EPSG",8806]],n        PARAMETER["False northing",0,n            LENGTHUNIT["metre",1],n            ID["EPSG",8807]],n        ID["EPSG",16040]],n    CS[Cartesian,2],n        AXIS["(E)",east,n            ORDER[1],n            LENGTHUNIT["metre",1,n                ID["EPSG",9001]]],n        AXIS["(N)",north,n            ORDER[2],n            LENGTHUNIT["metre",1,n                ID["EPSG",9001]]]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(code = NA_integer_), levels = c("constant", 
"aggregate", "identity"), class = "factor"), row.names = c(NA, 
6L), class = c("sf", "data.frame"))

# Correct current CRS and project to correct Google Maps CRS (you can safely ignore warning)
SFmap_cat2 <- st_as_sf(SP_cat2) %>%
  st_set_crs(4326) %>%
  st_transform(3857)

SFmap_cat2MCP <- st_set_crs(SP32map_cat2MCP, 4326) %>%
  st_transform(3857)

# Creat proxy for your chagos_map object. Shapefile option downloaded from
# https://www.marineregions.org/gazetteer.php?p=details&id=62604&from=rss
# and unzipped in working directory
chagos_map <- st_read("eez_iho.shp")
chagos_map <- data.frame(st_coordinates(chagos_map)) %>%
  st_as_sf(coords = c("X", "Y"), crs = 4326) %>%
  summarise(geometry = st_combine(geometry), .by = L1) %>%
  st_cast("POLYGON") %>%
  filter(L1 != 1) %>%
  st_transform(3857)

ggplot() + 
  geom_sf(data = chagos_map) +
  geom_sf(data = SFmap_cat2,
          aes(colour = as.factor(code)),
          size = 2,
          inherit.aes = FALSE) +
  geom_sf(data = SFmap_cat2MCP,
          fill = NA,
          colour = "black",
          alpha = 0.5,
          inherit.aes = FALSE) +
  scale_x_continuous(breaks = seq(7930000, 8071000, length.out = 3)) +
  coord_sf(datum = 3857) +
  labs(title = "MCP Silvertip Cat 2 Chagos",
       colour = "Code") +
  theme_minimal()

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật