Trước tiên hãy làm một số phân tích.
Giả sử trong đa giác mật độ xác suất của nó là hàm tỷ lệ Khi đó hằng số tỷ lệ là nghịch đảo của tích phân so với đa giác,Pp(x,y).p
μ0,0(P)=∬Pp(x,y)dxdy.
Các khối tâm hệ thiên thể của đa giác là điểm tọa độ trung bình, tính bằng những khoảnh khắc đầu tiên của họ. Điều thứ nhất là
μ1,0(P)=1μ0,0(P)∬Pxp(x,y)dxdy.
Các tenxơ quán tính có thể được biểu diễn dưới dạng mảng đối xứng của các khoảnh khắc thứ hai được tính toán sau khi dịch đa giác để đặt barycenter của nó ở gốc: đó là ma trận của các khoảnh khắc thứ hai trung tâm
μ′k,l(P)=1μ0,0(P)∬P(x−μ1,0(P))k(y−μ0,1(P))lp(x,y)dxdy
trong đó nằm trong khoảng từ đến đến Bản thân tenor-- hay còn gọi là ma trận hiệp phương sai - là(k,l)(2,0)(1,1)(0,2).
I(P)=(μ′2,0(P)μ′1,1(P)μ′1,1(P)μ′0,2(P)).
Một PCA của mang lại các trục chính của đây là các hàm riêng của đơn vị được chia tỷ lệ theo giá trị riêng của chúng.I(P)P :P:
Tiếp theo, hãy tìm cách làm các phép tính. Bởi vì đa giác được trình bày dưới dạng một chuỗi các đỉnh mô tả ranh giới định hướng của nó nên việc gọi ra là điều tự nhiên∂P,
Định lý của Green: trong đó là một dạng được xác định trong một vùng lân cận của và∬Pdω=∮∂Pω
ω=M(x,y)dx+N(x,y)dyPdω=(∂∂xN(x,y)−∂∂yM(x,y))dxdy.
Chẳng hạn, với và mật độ ( tức là đồng nhất) chúng tôi có thể (bằng cách kiểm tra) chọn một trong số nhiều các giải pháp, chẳng hạn nhưdω=xkyldxdyp , ω ( x , y ) = - 1p,ω(x,y)=−1l+1xkyl+1dx.
Điểm của điều này là tích phân đường viền tuân theo các đoạn đường được xác định bởi chuỗi các đỉnh. Bất kỳ phân đoạn dòng nào từ vertex đến vertex đều có thể được tham số hóa bởi một biến thực trong biểu mẫuuvt
t→u+tw
trong đó là hướng đơn vị bình thường từ đếnDo đó, các giá trị của nằm trong khoảng từ đến Theo tham số này và là các hàm tuyến tính của và và là các hàm tuyến tính của Do đó, tích phân của tích phân đường viền trên mỗi cạnh trở thành hàm đa thức của được đánh giá dễ dàng cho nhỏ vàw∝v−uuv.t0|v−u|.xytdxdydt.t , k l .t,kl.
Việc thực hiện phân tích này cũng đơn giản như mã hóa các thành phần của nó. Ở mức thấp nhất, chúng ta sẽ cần một hàm để tích hợp một dạng đa thức trên một đoạn thẳng. Các hàm cấp cao hơn sẽ tổng hợp các hàm này để tính toán các khoảnh khắc thô và trung tâm để thu được barycenter và tenor quán tính, và cuối cùng chúng ta có thể vận hành trên tenxơ đó để tìm các trục chính (là các hàm riêng của nó). Các R
mã dưới đây thực hiện công việc này. Nó không giả vờ về hiệu quả: nó chỉ nhằm mục đích minh họa ứng dụng thực tế của phân tích đã nói ở trên. Mỗi chức năng là đơn giản và các quy ước đặt tên song song với các quy ước phân tích.
Bao gồm trong mã là một thủ tục để tạo các đa giác khép kín, được kết nối đơn giản, không tự giao nhau (bằng cách biến đổi ngẫu nhiên các điểm dọc theo một vòng tròn và bao gồm cả đỉnh bắt đầu làm điểm cuối cùng của nó để tạo ra một vòng khép kín). Tiếp theo đây là một vài câu lệnh để vẽ đa giác, hiển thị các đỉnh của nó, tiếp giáp với barycenter và vẽ các trục chính có màu đỏ (lớn nhất) và màu xanh lam (nhỏ nhất), tạo ra một hệ tọa độ hướng tích cực theo hướng đa giác.
#
# 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")