将线旋转到真北或垂直

我有一个数据集,其中包含多条对角线,我想将这些线旋转到垂直或正北,以便正确显示x轴数据。我已经看过Rodrigues公式,但是这让我望而却步,并且想知道它们是否是我可以使用的R包。请参见下面的示例,我将需要旋转它。

library(sf)
library(ggplot2)

ex<-structure(list(OBJECTID = c(10526,10913),geometry = structure(list(
    structure(c(-103.47406,-103.46268,31.47367,31.48499),.Dim = c(2L,2L),class = c("XY","LInesTRING","sfg")),structure(c(-103.46525,-103.4788333,31.4879722000001,31.4748056),"sfg"))),n_empty = 0L,crs = structure(list(
    epsg = 4267L,proj4string = "+proj=longlat +datum=NAD27 +no_defs"),class = "crs"),class = c("sfc_LInesTRING","sfc"),precision = 0,bbox = structure(c(xmin = -103.4788333,ymin = 31.47367,xmax = -103.46268,ymax = 31.4879722000001),class = "bbox"))),row.names = c(NA,-2L),sf_column = "geometry",agr = structure(c(OBJECTID = NA_integer_),.Label = c("constant","aggregate","identity"),class = "factor"),class = c("sf","tbl_df","tbl","data.frame"))

ggplot(ex)+geom_sf()

附上我的追求图

将线旋转到真北或垂直

谢谢!

hailang_163 回答:将线旋转到真北或垂直

在假设所有直线平行的情况下,旋转点是所有直线的重心,

  1. 找到线的质心
  2. 找到线与正北之间的方位
  3. 围绕质心旋转每个坐标
  4. 完成。
library(sf)
library(sfheaders)
library(ggplot2)
library(geosphere)

## get the centre of the lines
centre <- sf::st_centroid( sf::st_union( ex ) )

## remove class so we just have coordinates as a vector
centre <- unclass( centre[[1]] )

## get each coordinate of the lines. These will each be rotated
coords <- sf::st_coordinates( ex )

## to know the angle of rotation,we need to know due-north from a given point
## under the assumption all lines are parallel,we just need the bearing between the 
## start of a line and the end
##
## you're using lon / lat values,so we can use geosphere package to get the bearing
bearing <- geosphere::bearing(
  p1 = coords[1,c("X","Y")],p2 = coords[2,"Y")]
  )


theta <- bearing * pi / 180 ## in radians

#' rotate
#' function to rotate x and y coordinates around a point
#' theta - angle of rotation
#' p - point(s) to rotate
#' centre - centre point
rotate <- function( theta,p,centre ) {
  new_x <- cos( theta ) * ( p[,1] - centre[1] ) - sin( theta ) * ( p[,2] - centre[2] ) + centre[1]
  new_y <- sin( theta ) * ( p[,1] - centre[1] ) + cos( theta ) * ( p[,2] - centre[2] ) + centre[2] 
  return( matrix( c( new_x,new_y ),ncol = 2 ) ) 
}

## calculate the rotated points
coords_new <- rotate( theta,coords,centre )

## we've kept order in tact,so we can cbind the L1 id back on
coords_new <- cbind( coords_new,coords[,"L1"])

## new sf object (using library(sfheaders) )
sf_new <- sfheaders::sf_linestring( obj = coords_new,linestring_id = 3)
sf::st_crs( sf_new ) <- sf::st_crs( ex )

## plot to verify
ggplot() + geom_sf( data = sf_new ) + 
  geom_sf( data = ex ) + 
  geom_sf( data = sf::st_centroid( sf::st_union( ex ) ) )

enter image description here

本文链接:https://www.f2er.com/3070083.html

大家都在问