Как найти расстояние от точки до линии (зная все точки)? - PullRequest
3 голосов
/ 31 марта 2020

У меня есть линия, состоящая из двух точек BA и точки P. Я хотел бы найти расстояние от P до перпендикуляра BA и параллели BA. Знаете ли вы, есть ли какая-нибудь рабочая группа, занимающаяся этим в R или Matlab? Я прилагаю картинку, чтобы ее было легче понять.

Эскиз приведен ниже: enter image description here

Ответы [ 2 ]

3 голосов
/ 31 марта 2020

Вы можете попробовать приведенный ниже код, где имена функций perp_dist и xparal обозначают перпендикулярно AB и расстояниям по оси X

R версия

perp_dist <- function(P,A,B) {
  norm(pracma::cross(c(P-A,0),c(B-A,0)),"2")/norm(B-A,"2") # use cross product of vectors to calculate the distance 
}

xparal_dist <- function(P,A,B) {
  AB <- B-A
  perp_dist(P,A,B)*ifelse(AB[2]==0,1,sqrt(1+(AB[1]/AB[2])**2))
}

Пример

A <- c(1,3)
B <- c(5,10)
P <- c(7,7)
perp_dist(P,A,B)
xparal_dist(P,A,B)

, что дает

> perp_dist(P,A,B)
[1] 0.6933752

> xparal_dist(P,A,B)
[1] 0.8333333

версия Matlab

function d = perp_dist(P,A,B) 
  d = norm(cross([P-A,0],[B-A,0]))/norm(B-A); % use cross product of vectors to calculate the distance 
end

function d = xparal_dist(P,A,B)
  AB = B-A;
  if AB(2)==0
    f = 1;
  else
    f = sqrt(1+(AB(1)/AB(2))^2);
  end
  d = perp_dist(P,A,B)*f;
end

Пример

A = [0,0];
B = [6,9];
P = [2.5,2.5];
perp_dist(P,A,B)
xparal_dist(P,A,B)

такое, что

>> perp_dist(P,A,B)
ans =  0.6934

>> xparal_dist(P,A,B)
ans =  0.8333

Обновление (язык R) :

Если у вас есть A, B и P в виде data.frame, например,

set.seed(1)
A <- data.frame(X = rnorm(5),Y = rnorm(5))
B <- data.frame(X = rnorm(5),Y = rnorm(5))
P <- data.frame(X = rnorm(5),Y = rnorm(5))

, затем вы можете использовать Vectorize для ваших фреймов данных, то есть

dperp <- Vectorize(perp_dist)(data.frame(t(P)),data.frame(t(A)),data.frame(t(B)))
dxparal <- Vectorize(xparal_dist)(data.frame(t(P)),data.frame(t(A)),data.frame(t(B)))

, так что

> dperp
       X1        X2        X3        X4        X5 
0.1916007 0.3101444 2.2245761 1.2821965 0.2617655 
> dxparal
        X1         X2         X3         X4         X5 
 0.5619376  0.3351336  3.2146859 19.9448870  0.3494685 

Update 2 ( Версия R)

Если вы хотите рассчитать расстояние, параллельное оси Y, вы можете использовать следующий код (версия MATLAB аналогична)

yparal_dist <- function(P,A,B) {
  AB <- B-A
  perp_dist(P,A,B)*ifelse(AB[1]==0,1,sqrt(1+(AB[2]/AB[1])**2))
}
2 голосов
/ 31 марта 2020

Кодирование функции напрямую из формулы учебника.

dist_point2line <- function(P, A, B){
    dx <- B[1] - A[1]
    dy <- B[2] - A[2]
    numer <- abs(dy*P[1] - dx*P[2] + B[1]*A[2] - B[2]*A[1])
    denom <- sqrt(dx^2 + dy^2)
    d <- numer/denom
    inv_cos_ang <- if(dy == 0) 1 else sqrt(1 + (dx/dy)^2)
    p <- d*inv_cos_ang
    list(dist = d, parallel = p)
}

Проверка с расстоянием от начала координат до линии, проходящей через (0, 1) и (1, 0). Результат равен sqrt(2)/2, а расстояние, параллельное оси x, равно 1.

sqrt(2)/2
#[1] 0.7071068

dist_point2line(c(0, 0), c(1, 0), c(0, 1))
#$dist
#[1] 0.7071068
#
#$parallel
#[1] 1

Другой пример взят из @ ThomasIsCoding answer, Обратите внимание, что результаты различны, этот правильный 0,8.

plot(1, type = "n", xlim = c(0, 8), ylim = c(0, 11))
points(P[1], P[2], col = "red")
points(A[1], A[2])
points(B[1], B[2])
segments(A[1], A[2], B[1], B[2])
abline(h = P[2])

enter image description here

Редактировать

После запроса OP, чтобы функция вычисляла расстояние, параллельное y ось, вот новая версия вышеупомянутой функции.

dist_point2line <- function(P, A, B){
  dx <- B[1] - A[1]
  dy <- B[2] - A[2]
  numer <- abs(dy*P[1] - dx*P[2] + B[1]*A[2] - B[2]*A[1])
  denom <- sqrt(dx^2 + dy^2)
  d <- numer/denom
  inv_cos_ang <- if(dy == 0) 1 else sqrt(1 + (dx/dy)^2)
  inv_sin_ang <- if(dx == 0) 1 else sqrt(1 + (dy/dx)^2)
  px <- d*inv_cos_ang
  py <- d*inv_sin_ang
  list(dist = d, parallel = c(xdist = px, ydist = py))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...