먼저 몇 가지 분석을 해보자.
다각형 에서 확률 밀도는 비례 함수 비례 상수 는 다각형에 대한 의 적분의 역수입니다.피p ( x , y) .피
μ0 , 0( P) =∬피p ( x , y) d xdy.
다각형 의 중심 은 첫 번째 모멘트로 계산 된 평균 좌표 점입니다. 첫 번째는
μ1 , 0( P) =1μ0 , 0( P)∬피엑스p ( x , y) d xD Y.
관성 텐서는 원점에 그 중심 좌표를 넣어 다각형 번역 후 계산 번째 모멘트의 대칭 배열로 표현 될 수있다 : 즉, 행렬의 중심부 번째 순간
μ'k , l( P) =1μ0 , 0( P)∬피( x −μ1 , 0( P) )케이( y−μ0 , 1( P) )엘p ( x , y) d xD Y
여기서 은 에서 에서 텐서 itself-- 일명 공분산 행렬은 -입니다( k , l )( 2 , 0 )( 1 , 1 )( 0 , 2 ) .
나는( P) = (μ'2 , 0( P)μ'1 , 1( P)μ'1 , 1( P)μ'0,2(P)).
의 PCA는 주축 을 산출합니다 이들은 고유 값으로 스케일 된 단위 고유 벡터입니다.I(P)P:
다음으로 계산 방법을 알아 보겠습니다. 다각형은 방향 경계 설명하는 일련의 꼭짓점으로 표시되므로 호출하는 것이 당연합니다.∂P,
녹색 정리 : 여기서 는 및 근처에 정의 된 단일 형식입니다.∬Pdω=∮∂Pω
ω=M(x,y)dx+N(x,y)dyPdω=(∂∂xN(x,y)−∂∂yM(x,y))dxdy.
예를 들어, 및 일정한 ( 즉 , 균일 한) 밀도 검사를 통해 여러 가지 중 하나를 선택할 수 있습니다 와 같은 솔루션dω=xkyldxdyp,ω(x,y)=−1l+1xkyl+1dx.
요점은 형상 적분이 정점 시퀀스에 의해 결정된 선분을 따른다는 것입니다. 정점 에서 정점 까지의 모든 선분 은 형식 의 실수 변수 에 의해 매개 변수화 될 수 있습니다uvt
t→u+tw
여기서 는 에서 로의 단위 법선 방향입니다따라서 의 값 범위는 에서 이 매개 변수화에서 와 는 선형 함수 이고 와 는 의 선형 함수입니다 따라서 각 모서리에 걸친 적분의 적분은 다항식 함수 가됩니다.w∝v−uuv.t0|v−u|.xytdxdydt.t, 작은 것으로 쉽게 평가됩니다 k 과 l.
이 분석을 구현 하는 것은 구성 요소를 코딩하는 것만 큼 간단합니다. 가장 낮은 수준에서 우리는 선분에 다항식 한 형태를 통합하는 함수가 필요합니다. 더 높은 수준의 함수는 이들을 모아 중심 및 관성 텐서를 얻기 위해 원시 및 중심 모멘트를 계산하며, 마지막으로 텐서에서 작동하여 주 축 (축척 된 고유 벡터)을 찾을 수 있습니다. R
수행 아래 코드이 작동합니다. 그것은 효율성을 강조하지 않습니다. 그것은 전술 한 분석의 실제 적용만을 설명하기위한 것입니다. 각 기능은 간단하며 명명 규칙은 분석 기능과 유사합니다.
이 코드에는 유효한 폐쇄 형, 간단하게 연결된 비 자체 교차 다각형을 생성하는 절차가 포함되어 있습니다 (원형을 따라 점을 임의로 변형하고 시작 정점을 최종 점으로 포함하여 폐쇄 루프를 생성 함). 다음은 폴리곤을 플로팅하고 정점을 표시하고 바리 센터에 인접하며 주축을 빨간색 (최대) 및 파란색 (최소)으로 표시하여 다각형 중심의 양의 방향 좌표계를 작성하는 몇 가지 명령문입니다.
#
# Integrate a monomial one-form x^k*y^l*dx along the line segment given as an
# origin, unit direction vector, and distance.
#
lintegrate <- function(k, l, origin, normal, distance) {
# Binomial theorem expansion of (u + tw)^k
expand <- function(k, u, w) {
i <- seq_len(k+1)-1
u^i * w^rev(i) * choose(k,i)
}
# Construction of the product of two polynomials times a constant.
omega <- normal[1] * convolve(rev(expand(k, origin[1], normal[1])),
expand(l, origin[2], normal[2]),
type="open")
# Integrate the resulting polynomial from 0 to `distance`.
sum(omega * distance^seq_along(omega) / seq_along(omega))
}
#
# Integrate monomials along a piecewise linear path given as a sequence of
# (x,y) vertices.
#
cintegrate <- function(xy, k, l) {
n <- dim(xy)[1]-1 # Number of edges
sum(sapply(1:n, function(i) {
dv <- xy[i+1,] - xy[i,] # The direction vector
lambda <- sum(dv * dv)
if (isTRUE(all.equal(lambda, 0.0))) {
0.0
} else {
lambda <- sqrt(lambda) # Length of the direction vector
-lintegrate(k, l+1, xy[i,], dv/lambda, lambda) / (l+1)
}
}))
}
#
# Compute moments of inertia.
#
inertia <- function(xy) {
mass <- cintegrate(xy, 0, 0)
barycenter = c(cintegrate(xy, 1, 0), cintegrate(xy, 0, 1)) / mass
uv <- t(t(xy) - barycenter) # Recenter the polygon to obtain central moments
i <- matrix(0.0, 2, 2)
i[1,1] <- cintegrate(uv, 2, 0)
i[1,2] <- i[2,1] <- cintegrate(uv, 1, 1)
i[2,2] <- cintegrate(uv, 0, 2)
list(Mass=mass,
Barycenter=barycenter,
Inertia=i / mass)
}
#
# Find principal axes of an inertial tensor.
#
principal.axes <- function(i.xy) {
obj <- eigen(i.xy)
t(t(obj$vectors) * obj$values)
}
#
# Construct a polygon.
#
circle <- t(sapply(seq(0, 2*pi, length.out=11), function(a) c(cos(a), sin(a))))
set.seed(17)
radii <- (1 + rgamma(dim(circle)[1]-1, 3, 3))
radii <- c(radii, radii[1]) # Closes the loop
xy <- circle * radii
#
# Compute principal axes.
#
i.xy <- inertia(xy)
axes <- principal.axes(i.xy$Inertia)
sign <- sign(det(axes))
#
# Plot barycenter and principal axes.
#
plot(xy, bty="n", xaxt="n", yaxt="n", asp=1, xlab="x", ylab="y",
main="A random polygon\nand its principal axes", cex.main=0.75)
polygon(xy, col="#e0e0e080")
arrows(rep(i.xy$Barycenter[1], 2),
rep(i.xy$Barycenter[2], 2),
-axes[1,] + i.xy$Barycenter[1], # The -signs make the first axis ..
-axes[2,]*sign + i.xy$Barycenter[2],# .. point to the right or down.
length=0.1, angle=15, col=c("#e02020", "#4040c0"), lwd=2)
points(matrix(i.xy$Barycenter, 1, 2), pch=21, bg="#404040")