rspatialgdalshapefilergdal

Coordinates of dataframe in a clockwise direction


I'd like to join the list of polygons in a data frame, but it is important to sort a set of coordinates in a clockwise direction. In my example:

library(dplyr)
library(sf)

test.all <- list(structure(list(year = "2010", locality_id = "L2228604", 
    observation_count = 0, geometry = structure(list(structure(list(
        structure(c(-8773389.28986396, -8773390.87960364, -8773395.64446533, 
        -8773403.57138886, -8773414.6386471, -8773428.81590546, 
        -8773446.06430505, -8773466.33656922, -8773489.57713309, 
        -8773515.7222959, -8773544.70039557, -8773576.43200514, 
        -8773610.83015048, -8773647.80054867, -8773687.2418664, 
        -8773729.04599778, -8773773.09836058, -8773819.27821034, 
        -8773867.4589713, -8773917.50858334, -8773969.28986396, 
        -8774022.66088426, -8774077.47535799, -8774133.58304248, 
        -8774190.83015048, -8774249.05977164, -8774308.11230261, 
        -8774367.82588451, -8774428.03684657, -8774488.58015471, 
        -8774549.28986396, -8774609.9995732, -8774670.54288135, 
        -8774730.7538434, -8774790.4674253, -8774849.51995627, 
        -8774907.74957743, -8774964.99668543, -8775021.10436992, 
        -8775075.91884365, -8775129.28986396, -8775181.07114457, 
        -8775231.12075661, -8775279.30151757, -8775325.48136733, 
        -8775369.53373013, -8775411.33786151, -8775450.77917925, 
        -8775487.74957743, -8775522.14772277, -8775553.87933234, 
        -8775582.85743201, -8775609.00259482, -8775632.24315869, 
        -8775652.51542286, -8775669.76382245, -8775683.94108081, 
        -8775695.00833905, -8775702.93526258, -8775707.70012427, 
        -8775709.28986396, -8775707.70012427, -8775702.93526258, 
        -8775695.00833905, -8775683.94108081, -8775669.76382245, 
        -8775652.51542286, -8775632.24315869, -8775609.00259482, 
        -8775582.85743201, -8775553.87933234, -8775522.14772277, 
        -8775487.74957743, -8775450.77917925, -8775411.33786151, 
        -8775369.53373013, -8775325.48136733, -8775279.30151757, 
        -8775231.12075661, -8775181.07114457, -8775129.28986396, 
        -8775075.91884365, -8775021.10436992, -8774964.99668543, 
        -8774907.74957743, -8774849.51995627, -8774790.4674253, 
        -8774730.7538434, -8774670.54288135, -8774609.9995732, 
        -8774549.28986396, -8774488.58015471, -8774428.03684657, 
        -8774367.82588451, -8774308.11230261, -8774249.05977164, 
        -8774190.83015048, -8774133.58304248, -8774077.47535799, 
        -8774022.66088426, -8773969.28986396, -8773917.50858334, 
        -8773867.4589713, -8773819.27821034, -8773773.09836058, 
        -8773729.04599778, -8773687.2418664, -8773647.80054867, 
        -8773610.83015048, -8773576.43200514, -8773544.70039557, 
        -8773515.7222959, -8773489.57713309, -8773466.33656922, 
        -8773446.06430505, -8773428.81590546, -8773414.6386471, 
        -8773403.57138886, -8773395.64446533, -8773390.87960364, 
        -8773389.28986396, 4574141.40786374, 4574080.6981545, 
        4574020.15484635, 4573959.94388429, 4573900.23030239, 
        4573841.17777142, 4573782.94815026, 4573725.70104226, 
        4573669.59335777, 4573614.77888404, 4573561.40786374, 
        4573509.62658312, 4573459.57697108, 4573411.39621012, 
        4573365.21636036, 4573321.16399756, 4573279.35986618, 
        4573239.91854845, 4573202.94815026, 4573168.55000492, 
        4573136.81839535, 4573107.84029568, 4573081.69513287, 
        4573058.454569, 4573038.18230483, 4573020.93390524, 4573006.75664689, 
        4572995.68938865, 4572987.76246511, 4572982.99760342, 
        4572981.40786374, 4572982.99760342, 4572987.76246511, 
        4572995.68938865, 4573006.75664689, 4573020.93390524, 
        4573038.18230483, 4573058.454569, 4573081.69513287, 4573107.84029568, 
        4573136.81839535, 4573168.55000492, 4573202.94815026, 
        4573239.91854845, 4573279.35986618, 4573321.16399756, 
        4573365.21636036, 4573411.39621012, 4573459.57697108, 
        4573509.62658312, 4573561.40786374, 4573614.77888404, 
        4573669.59335777, 4573725.70104226, 4573782.94815026, 
        4573841.17777142, 4573900.23030239, 4573959.94388429, 
        4574020.15484635, 4574080.6981545, 4574141.40786374, 
        4574202.11757298, 4574262.66088113, 4574322.87184318, 
        4574382.58542509, 4574441.63795606, 4574499.86757721, 
        4574557.11468521, 4574613.22236971, 4574668.03684343, 
        4574721.40786374, 4574773.18914435, 4574823.2387564, 
        4574871.41951736, 4574917.59936711, 4574961.65172991, 
        4575003.45586129, 4575042.89717903, 4575079.86757721, 
        4575114.26572255, 4575145.99733213, 4575174.9754318, 
        4575201.1205946, 4575224.36115847, 4575244.63342264, 
        4575261.88182223, 4575276.05908059, 4575287.12633883, 
        4575295.05326236, 4575299.81812405, 4575301.40786374, 
        4575299.81812405, 4575295.05326236, 4575287.12633883, 
        4575276.05908059, 4575261.88182223, 4575244.63342264, 
        4575224.36115847, 4575201.1205946, 4575174.9754318, 4575145.99733213, 
        4575114.26572255, 4575079.86757721, 4575042.89717903, 
        4575003.45586129, 4574961.65172991, 4574917.59936711, 
        4574871.41951736, 4574823.2387564, 4574773.18914435, 
        4574721.40786374, 4574668.03684343, 4574613.22236971, 
        4574557.11468521, 4574499.86757721, 4574441.63795606, 
        4574382.58542509, 4574322.87184318, 4574262.66088113, 
        4574202.11757298, 4574141.40786374), .Dim = c(121L, 2L
        ))), class = c("XY", "POLYGON", "sfg"))), class = c("sfc_POLYGON", 
    "sfc"), precision = 0, bbox = structure(c(xmin = -8775709.28986396, 
    ymin = 4572981.40786374, xmax = -8773389.28986396, ymax = 4575301.40786374
    ), class = "bbox"), crs = structure(list(input = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +R=6371007.181 +units=m +no_defs", 
        wkt = "PROJCRS[\"unknown\",\n    BASEGEOGCRS[\"unknown\",\n        DATUM[\"unknown\",\n            ELLIPSOID[\"unknown\",6371007.181,0,\n                LENGTHUNIT[\"metre\",1,\n                    ID[\"EPSG\",9001]]]],\n        PRIMEM[\"Greenwich\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8901]]],\n    CONVERSION[\"unknown\",\n        METHOD[\"Sinusoidal\"],\n        PARAMETER[\"Longitude of natural origin\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8802]],\n        PARAMETER[\"False easting\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8806]],\n        PARAMETER[\"False northing\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8807]]],\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(year = NA_integer_, 
locality_id = NA_integer_, observation_count = NA_integer_), class = "factor", .Label = c("constant", 
"aggregate", "identity")), row.names = c(NA, -1L), class = c("sf", 
"tbl_df", "tbl", "data.frame")), structure(list(year = "2011", 
    locality_id = "L1472874", observation_count = 0, geometry = structure(list(
        structure(list(structure(c(-7214135.48475349, -7214137.07449317, 
        -7214141.83935486, -7214149.7662784, -7214160.83353664, 
        -7214175.01079499, -7214192.25919458, -7214212.53145875, 
        -7214235.77202262, -7214261.91718543, -7214290.8952851, 
        -7214322.62689467, -7214357.02504001, -7214393.9954382, 
        -7214433.43675593, -7214475.24088731, -7214519.29325011, 
        -7214565.47309987, -7214613.65386083, -7214663.70347287, 
        -7214715.48475349, -7214768.85577379, -7214823.67024752, 
        -7214879.77793201, -7214937.02504001, -7214995.25466117, 
        -7215054.30719214, -7215114.02077404, -7215174.2317361, 
        -7215234.77504424, -7215295.48475349, -7215356.19446273, 
        -7215416.73777088, -7215476.94873293, -7215536.66231484, 
        -7215595.71484581, -7215653.94446696, -7215711.19157496, 
        -7215767.29925945, -7215822.11373318, -7215875.48475349, 
        -7215927.2660341, -7215977.31564615, -7216025.4964071, 
        -7216071.67625686, -7216115.72861966, -7216157.53275104, 
        -7216196.97406878, -7216233.94446696, -7216268.3426123, 
        -7216300.07422188, -7216329.05232154, -7216355.19748435, 
        -7216378.43804822, -7216398.71031239, -7216415.95871198, 
        -7216430.13597034, -7216441.20322858, -7216449.13015211, 
        -7216453.8950138, -7216455.48475349, -7216453.8950138, 
        -7216449.13015211, -7216441.20322858, -7216430.13597034, 
        -7216415.95871198, -7216398.71031239, -7216378.43804822, 
        -7216355.19748435, -7216329.05232154, -7216300.07422188, 
        -7216268.3426123, -7216233.94446696, -7216196.97406878, 
        -7216157.53275104, -7216115.72861966, -7216071.67625686, 
        -7216025.4964071, -7215977.31564615, -7215927.2660341, 
        -7215875.48475349, -7215822.11373318, -7215767.29925945, 
        -7215711.19157496, -7215653.94446696, -7215595.71484581, 
        -7215536.66231484, -7215476.94873293, -7215416.73777088, 
        -7215356.19446273, -7215295.48475349, -7215234.77504424, 
        -7215174.2317361, -7215114.02077404, -7215054.30719214, 
        -7214995.25466117, -7214937.02504001, -7214879.77793201, 
        -7214823.67024752, -7214768.85577379, -7214715.48475349, 
        -7214663.70347287, -7214613.65386083, -7214565.47309987, 
        -7214519.29325011, -7214475.24088731, -7214433.43675593, 
        -7214393.9954382, -7214357.02504001, -7214322.62689467, 
        -7214290.8952851, -7214261.91718543, -7214235.77202262, 
        -7214212.53145875, -7214192.25919458, -7214175.01079499, 
        -7214160.83353664, -7214149.7662784, -7214141.83935486, 
        -7214137.07449317, -7214135.48475349, 4014314.81839922, 
        4014254.10868998, 4014193.56538183, 4014133.35441977, 
        4014073.64083787, 4014014.5883069, 4013956.35868575, 
        4013899.11157775, 4013843.00389325, 4013788.18941952, 
        4013734.81839922, 4013683.0371186, 4013632.98750656, 
        4013584.8067456, 4013538.62689584, 4013494.57453304, 
        4013452.77040167, 4013413.32908393, 4013376.35868575, 
        4013341.9605404, 4013310.22893083, 4013281.25083116, 
        4013255.10566836, 4013231.86510448, 4013211.59284032, 
        4013194.34444073, 4013180.16718237, 4013169.09992413, 
        4013161.17300059, 4013156.40813891, 4013154.81839922, 
        4013156.40813891, 4013161.17300059, 4013169.09992413, 
        4013180.16718237, 4013194.34444073, 4013211.59284032, 
        4013231.86510448, 4013255.10566836, 4013281.25083116, 
        4013310.22893083, 4013341.9605404, 4013376.35868575, 
        4013413.32908393, 4013452.77040167, 4013494.57453304, 
        4013538.62689584, 4013584.8067456, 4013632.98750656, 
        4013683.0371186, 4013734.81839922, 4013788.18941952, 
        4013843.00389325, 4013899.11157775, 4013956.35868575, 
        4014014.5883069, 4014073.64083787, 4014133.35441977, 
        4014193.56538183, 4014254.10868998, 4014314.81839922, 
        4014375.52810846, 4014436.07141661, 4014496.28237867, 
        4014555.99596057, 4014615.04849154, 4014673.2781127, 
        4014730.52522069, 4014786.63290519, 4014841.44737892, 
        4014894.81839922, 4014946.59967984, 4014996.64929188, 
        4015044.83005284, 4015091.0099026, 4015135.0622654, 4015176.86639678, 
        4015216.30771451, 4015253.2781127, 4015287.67625804, 
        4015319.40786761, 4015348.38596728, 4015374.53113009, 
        4015397.77169396, 4015418.04395812, 4015435.29235772, 
        4015449.46961607, 4015460.53687431, 4015468.46379785, 
        4015473.22865954, 4015474.81839922, 4015473.22865954, 
        4015468.46379785, 4015460.53687431, 4015449.46961607, 
        4015435.29235772, 4015418.04395812, 4015397.77169396, 
        4015374.53113009, 4015348.38596728, 4015319.40786761, 
        4015287.67625804, 4015253.2781127, 4015216.30771451, 
        4015176.86639678, 4015135.0622654, 4015091.0099026, 4015044.83005284, 
        4014996.64929188, 4014946.59967984, 4014894.81839922, 
        4014841.44737892, 4014786.63290519, 4014730.52522069, 
        4014673.2781127, 4014615.04849154, 4014555.99596057, 
        4014496.28237867, 4014436.07141661, 4014375.52810846, 
        4014314.81839922), .Dim = c(121L, 2L))), class = c("XY", 
        "POLYGON", "sfg"))), class = c("sfc_POLYGON", "sfc"), precision = 0, bbox = structure(c(xmin = -7216455.48475349, 
    ymin = 4013154.81839922, xmax = -7214135.48475349, ymax = 4015474.81839922
    ), class = "bbox"), crs = structure(list(input = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +R=6371007.181 +units=m +no_defs", 
        wkt = "PROJCRS[\"unknown\",\n    BASEGEOGCRS[\"unknown\",\n        DATUM[\"unknown\",\n            ELLIPSOID[\"unknown\",6371007.181,0,\n                LENGTHUNIT[\"metre\",1,\n                    ID[\"EPSG\",9001]]]],\n        PRIMEM[\"Greenwich\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8901]]],\n    CONVERSION[\"unknown\",\n        METHOD[\"Sinusoidal\"],\n        PARAMETER[\"Longitude of natural origin\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8802]],\n        PARAMETER[\"False easting\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8806]],\n        PARAMETER[\"False northing\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8807]]],\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(year = NA_integer_, 
locality_id = NA_integer_, observation_count = NA_integer_), class = "factor", .Label = c("constant", 
"aggregate", "identity")), row.names = c(NA, -1L), class = c("sf", 
"tbl_df", "tbl", "data.frame")))


test.all = test.all %>%
  dplyr::bind_rows() %>% #bind the list into a data.frame
  sf::st_cast(to = "POINT") %>% #convert polygon to a list of points
  dplyr::mutate(
    X =  sf::st_coordinates(geometry)[,1], #retrieve X coord
    Y =  sf::st_coordinates(geometry)[,2]  #retrieve Y coord
  ) %>%
  sf::st_drop_geometry() #drop the geometry column

But I'd like too thetest.all in coordinates in a clockwise direction. Please, any help with it?


Solution

  • This should be possible by converting to polar coordinates, centered around each group's center (in this case I picked the median x/y).

    I use geom_path here since it plots in order of appearance (vs. geom_line, in order of the x variable).

    library(tidyverse)
    my_data <- tibble(group = sample(letters[1:3], 100, TRUE),
                      x = rnorm(100) + 2 * as.numeric(factor(group)),
                      y = rnorm(100))
    
    my_data |>
      mutate(across(x:y, median, .names = "{.col}_med"), .by = group) |> 
      mutate(theta = atan2(y - y_med, x - x_med)) |> 
      arrange(theta) |>
      ggplot(aes(x, y, group = group, color = group)) + 
      geom_point() +
      geom_path()
    

    enter image description here