在 R 中有没有办法找到点和线段之间的垂直距离?

问题描述 投票:0回答:2

这个问题在这里回答了,但是没有用R语言回答。我是编码的新手,所以我一直无法弄清楚如何将已接受答案的 C++ 代码“翻译”成 R 代码。

与链接问题一样,我的线段由两个端点定义:A (x1,y1) 和 B (x2,y2)。我试图找到这条线段和点 C (x3,y3) 之间的最短(即垂直)距离。下面是一些示例代码,说明点“C”应该与线段有最短距离,但点“C1”不应该。

A <- c(2, 4)
B <- c(8, 16)
C <- c(3, 11)
C1<- c(11, 16)

plot(1, type = "n", xlim = c(0, 25), ylim = c(0, 25))
points(C[1], C[2], col = "red")
points(C1[1], C1[2], col = "blue")
points(A[1], A[2])
points(B[1], B[2])
segments(A[1], A[2], B[1], B[2])

提前感谢您的帮助!

我知道我必须删除分号和类类型才能“翻译”成 R,但我认为主要问题之一是找出与 C++ 代码中使用的 vec2 类型相当的类类型。

r geometry distance line-segment
2个回答
1
投票

你在找这样的东西吗?

A <- c(2, 4)
B <- c(8, 16)
C <- c(3, 11)
C1<- c(11, 16)

library(sf)
library(sfheaders)

myline <- sf_linestring(matrix(c(A,B), ncol = 2))
mypoint <- sf_point(matrix(c(C,C1), ncol = 2))

st_length(st_nearest_points(mypoint, myline))
#[1] 0.2425356 7.0000000

视觉确认

library(ggplot2)
ggplot() + 
  geom_sf(data = myline, color = "green") +
  geom_sf(data = mypoint, color = "blue") +
  geom_sf(data = st_nearest_points(mypoint, myline), color = "magenta")


1
投票

这主要是 javascript 答案的一个端口,尽管我已经让它更适合 R。特别是,它使用向量作为参数,就像 C++ 答案(

vec2
只是意味着一个二维向量),而不是提供个人
x
y
点。为此,我使用
x
y
值定义了您的观点:

A <- c(x = 2, y = 4)
B <- c(x = 8, y = 16)
C <- c(x = 3, y = 11)
C1 <- c(x = 11, y = 16)

你可以这样称呼它:

pDistance(start_point = C, segment_p1 = A, segment_p2 = B) 
# Closest point is on segment
# [1] 2.236068
pDistance(start_point = C1, segment_p1 = A, segment_p2 = B) 
# Closest point is: B
# [1] 3

我们可以用每个点的输出绘制一个半径的圆来检查答案:

pDistance <- function(start_point, segment_p1, segment_p2) {
    dist_p1 <- start_point - segment_p1
    dist_p2 <- segment_p2 - segment_p1

    args <- as.list(match.call())

    dot <- sum(dist_p1 * dist_p2)
    len_sq <- sum(dist_p2^2)

    param <- -1
    if (len_sq != 0) { # in case of 0 length line
        param <- dot / len_sq
    }

    if (param < 0) {
        message("Closest point is: ", args$segment_p1)
        xx <- segment_p1["x"]
        yy <- segment_p1["y"]
    } else if (param > 1) {
        message("Closest point is: ", args$segment_p2)
        xx <- segment_p2["x"]
        yy <- segment_p2["y"]
    } else {
        message("Closest point is on segment")
        xx <- segment_p1["x"] + param * dist_p2["x"]
        yy <- segment_p1["y"] + param * dist_p2["y"]
    }

    dx <- unname(start_point["x"] - xx)
    dy <- unname(start_point["y"] - yy)
    sqrt(dx * dx + dy * dy)
}

我用

plotrix
将圆圈添加到您的情节中:

plotrix::draw.circle(C["x"], C["y"], pDistance(C, A, B))
plotrix::draw.circle(C1["x"], C1["y"], pDistance(C1, A, B))

实际功能没有使用任何额外的包

© www.soinside.com 2019 - 2024. All rights reserved.