使用加权最小二乘法逼近的三维矢量交叉

时间:2018-01-09 22:28:08

标签: r least-squares line-intersection

我想在3D空间中找到与多个线/矢量最近的交点,但我想根据每个矢量的长度来加权每个矢量的影响(它的长度越大,其影响越大)。我正在使用R. The answer to this question完美地找到与多个向量最接近的交点,但缺少加权分量。我在哪里需要插入权重矩阵?

This(4 th 幻灯片)建议在哪里,但我没有成功找到这部分在Dan的代码中的位置(我使用线性代数的方式太少而无法完全理解发生了什么事。)

关于线 - 线交叉的理论可以在answerWikipedia找到。

以下是我在R中的Dan MATLAB code的翻译:

XYZ_intersect <- function(XYZ_start, XYZ_end)
{
# XYZ_start: matrix n x 3 containing starting XYZ coordinates
# XYZ_end: matrix n x 3 containing ending XYZ coordinates

direction_vectors <- XYZ_end - XYZ_start
length_vectors <- matrix(sqrt(.rowSums(direction_vectors^2, dim(direction_vectors)[1], 3)))
normalized_vectors <- direction_vectors / (length_vectors %*% matrix(1, ncol = 3))    
weights <- length_vectors / sum(length_vectors)

Nx <- normalized_vectors[,1, drop = FALSE]
Ny <- normalized_vectors[,2, drop = FALSE]
Nz <- normalized_vectors[,3, drop = FALSE]

Sxx <- sum(Nx^2 - 1)
Syy <- sum(Ny^2 - 1)
Szz <- sum(Nz^2 - 1)
Sxy <- sum(Nx*Ny)
Sxz <- sum(Nx*Nz)
Syz <- sum(Ny*Nz)

symmetric <- matrix(c(Sxx,Sxy,Sxz,Sxy,Syy,Syz,Sxz,Syz,Szz), nrow = 3)

Cx <- sum(XYZ_start[,1, drop = FALSE]*(Nx^2 - 1) + XYZ_start[,2, drop = FALSE]*(Nx*Ny) + XYZ_start[,3, drop = FALSE]*(Nx*Nz))
Cy <- sum(XYZ_start[,1, drop = FALSE]*(Nx*Ny) + XYZ_start[,2, drop = FALSE]*(Ny^2 - 1) + XYZ_start[,3, drop = FALSE]*(Ny*Nz))
Cz <- sum(XYZ_start[,1, drop = FALSE]*(Nx*Nz) + XYZ_start[,2, drop = FALSE]*(Ny*Nz)  + XYZ_start[,3, drop = FALSE]*(Nz^2 - 1))

C <- matrix(c(Cx,Cy,Cz))
XYZ_intersect <- t(solve(symmetric,C))
return(XYZ_intersect)
}

所以,如果我有四个向量描述为:

#     (X0,Y0,Z0,X1,Y1,Z1)
vec1 <- c(0,0,1,3,3,6)
vec2 <- c(3,0,2,3,4,8)
vec3 <- c(0,3,3,4,3,9)
vec4 <- c(2,3,2,4,3,7)

XYZ_start <- matrix(c(vec1[1:3], vec2[1:3], vec3[1:3], vec4[1:3]), ncol = 3, byrow = TRUE)
XYZ_end <- matrix(c(vec1[4:6], vec2[4:6], vec3[4:6], vec4[4:6]), ncol = 3, byrow = TRUE)

XYZ_intersect(XYZ_start, XYZ_end)
#         [,1]     [,2]     [,3]
#[1,] 3.132048 3.063237 6.522456

在这种情况下,我想给出以下权重:

weights
#          [,1]
#[1,] 0.2487194
#[2,] 0.2735124
#[3,] 0.2735124
#[4,] 0.2042558

1 个答案:

答案 0 :(得分:0)

最后,有血有肉的人帮助了我。必须在每个总和中添加权重矩阵:

XYZ_intersect <- function(XYZ_start, XYZ_end)
{
  # XYZ_start: matrix n x 3 containing starting XYZ coordinates
  # XYZ_end: matrix n x 3 containing ending XYZ coordinates

  direction_vectors <- XYZ_end - XYZ_start
  length_vectors <- matrix(sqrt(.rowSums(direction_vectors^2, dim(direction_vectors)[1], 3)))
  normalized_vectors <- direction_vectors / (length_vectors %*% matrix(1, ncol = 3))    
  weights <- length_vectors / sum(length_vectors)

  Nx <- normalized_vectors[,1, drop = FALSE]
  Ny <- normalized_vectors[,2, drop = FALSE]
  Nz <- normalized_vectors[,3, drop = FALSE]

  Wxx <- weights * (Nx^2 - 1)
  Wyy <- weights * (Ny^2 - 1)
  Wzz <- weights * (Nz^2 - 1)
  Wxy <- weights * Nx * Ny
  Wxz <- weights * Nx * Nz
  Wyz <- weights * Ny * Nz

  Sxx <- sum(Wxx)
  Syy <- sum(Wyy)
  Szz <- sum(Wzz)
  Sxy <- sum(Wxy)
  Sxz <- sum(Wxz)
  Syz <- sum(Wyz)

  symmetric <- matrix(c(Sxx,Sxy,Sxz,Sxy,Syy,Syz,Sxz,Syz,Szz), nrow = 3)

  Cx <- sum(XYZ_start[,1, drop = FALSE] * Wxx + XYZ_start[,2, drop = FALSE] * Wxy + XYZ_start[,3, drop = FALSE] * Wxz)
  Cy <- sum(XYZ_start[,1, drop = FALSE] * Wxy + XYZ_start[,2, drop = FALSE] * Wyy + XYZ_start[,3, drop = FALSE] * Wyz)
  Cz <- sum(XYZ_start[,1, drop = FALSE] * Wxz + XYZ_start[,2, drop = FALSE] * Wyz + XYZ_start[,3, drop = FALSE] * Wzz)

  C <- matrix(c(Cx,Cy,Cz))
  XYZ_intersect <- t(solve(symmetric,C))
  return(XYZ_intersect)
}

因此,使用我的四个向量,结果是:

XYZ_intersect(XYZ_start, XYZ_end)
#         [,1]     [,2]     [,3]
#[1,] 3.092853 3.069695 6.556273