2013-02-13 117 views
4

我正在使用voronoi tessellations。我有不同的多边形代表曲面细分中的区域。voronoi tessellations的层次结构

以下几点用于绘制图中的曲面细分。

tessdata 
    [,1]  [,2] 
1 -0.4960583 -0.3529047 
2 -2.4986929 0.8897895 
3 3.6514561 -1.3533369 
4 -1.7263101 -5.5341202 
5 2.2140143 0.3883696 
6 -2.5208933 -1.4881461 
7 -3.2556913 4.4535629 
8 0.6423109 -2.8350062 
9 -0.4160715 1.2676151 
10 4.4059361 4.5641771 

使用tessdata作为输入来绘制镶嵌如下:

library(deldir) 
dd<-deldir(tessdata[,1], tessdata[,2]) 
plot(dd,wlines="tess") 

enter image description here

的Sammon坐标如下。

 [,1]  [,2] 
1 3.14162704 -1.45728604 
2 2.35422623 2.46437927 
3 -0.85051049 2.71503294 
4 1.94310458 -0.45936958 
5 0.08737757 3.74324701 
6 1.23007799 1.34443842 
7 0.01571924 2.19322032 
8 1.43320754 2.64818631 
9 -0.05463431 0.66980876 
10 1.51344967 5.03351176 

我想要构造输入坐标点坐标点的曲面细分。使用这些点的曲面细分应位于所示图中的一个区域内,因此,上述点应该缩放,或者我们可以在上图中的某个区域内限制曲面细分的绘图。

希望我已经涵盖了所有必要的数据。

P.S:

sammon的投影出现在“MASS”包中。 “deldir”包中的voronoi tessellations。

deldir函数输出的dirsgs参数将给出构成曲面细分中线条的点的坐标。

包图形的段函数可以用来连接坐标从dirsgs中提取出来的2个点。

+0

你是怎么尝试已经这样做? – juba 2013-02-13 18:36:27

+0

[多边形内的[sammon投影输出]可能的重复](http://stackoverflow.com/questions/14853503/sammon-projection-output-within-a-polygon) – juba 2013-02-13 18:37:58

+0

你说你知道如何限制曲面细分,所以是你的问题是如何将Sammon点放大到其中一个多边形? – Gregor 2013-02-13 18:51:22

回答

6

如果你想限制第二套点 到镶嵌, 可以使用tile.list的瓷砖之一,有每个图块的描述, 然后检查哪些点在这种瓷砖 (有有很多功能可以这样做: 在下面的例子中,我用secr::pointsInPolygon)。

# Sample data 
x <- matrix(rnorm(20), nc = 2) 
y <- matrix(rnorm(1000), nc=2) 

# Tessellation 
library(deldir) 
d <- deldir(x[,1], x[,2]) 
plot(d, wlines="tess") 

# Pick a cell at random 
cell <- sample(tile.list(d), 1)[[1]] 
points(cell$pt[1], cell$pt[2], pch=16) 
polygon(cell$x, cell$y, lwd=3) 

# Select the points inside that cell 
library(secr) 
i <- pointsInPolygon(
    y, 
    cbind( 
    c(cell$x,cell$x[1]), 
    c(cell$y,cell$y[1]) 
) 
) 
points(y[!i,], pch=".") 
points(y[i,], pch="+") 

# Compute a tessellation of those points 
dd <- deldir(y[i,1], y[i,2]) 
plot(dd, wlines="tess", add=TRUE) 

Tessellation inside a cell of another tessellation

相反,如果你想翻译和重新调整的点 放到合适的瓷砖,这是棘手。

我们需要以某种方式估算如何远离瓷砖的要点是: 为此,让我们从一个点定义几个若干辅助功能来计算, 第一的距离段, 然后从距离指向多边形的点。

distance_to_segment <- function(M, A, B) { 
    norm <- function(u) sqrt(sum(u^2)) 
    lambda <- sum((B-A) * (M-A))/norm(B-A)^2 
    if(lambda <= 0) { 
    norm(M-A) 
    } else if(lambda >= 1) { 
    norm(M-B) 
    } else { 
    N <- A + lambda * (B-A) 
    norm(M-N) 
    } 
} 
A <- c(-.5,0) 
B <- c(.5,.5) 
x <- seq(-1,1,length=100) 
y <- seq(-1,1,length=100) 
z <- apply(
    expand.grid(x,y), 
    1, 
    function(u) distance_to_segment(u, A, B) 
) 
par(las=1) 
image(x, y, matrix(z,nr=length(x))) 
box() 
segments(A[1],A[2],B[1],B[2],lwd=3) 

library(secr) 
distance_to_polygon <- function(x, poly) { 
    closed_polygon <- rbind(poly, poly[1,]) 
    if(pointsInPolygon(t(x), closed_polygon)) 
    return(0) 
    d <- rep(Inf, nrow(poly)) 
    for(i in 1:nrow(poly)) { 
    A <- closed_polygon[i,] 
    B <- closed_polygon[i+1,] 
    d[i] <- distance_to_segment(x,A,B) 
    } 
    min(d) 
} 
x <- matrix(rnorm(20),nc=2) 
poly <- x[chull(x),] 
x <- seq(-5,5,length=100) 
y <- seq(-5,5,length=100) 
z <- apply(
    expand.grid(x,y), 
    1, 
    function(u) distance_to_polygon(u, poly) 
) 
par(las=1) 
image(x, y, matrix(z,nr=length(x))) 
box() 
polygon(poly, lwd=3) 

现在,我们可以寻找形式

x --> lambda * x + a 
y --> lambda * y + b 

的改造最小化的(平方的总和)距离多边形。 这实际上是不够的:我们很可能最终得到比例因子 lambda等于(或接近)零。 为了避免这种情况,我们可以添加一个惩罚,如果lambda小。

# Sample data 
x <- matrix(rnorm(20),nc=2) 
x <- x[chull(x),] 
y <- matrix(c(1,2) + 5*rnorm(20), nc=2) 
plot(y, axes=FALSE, xlab="", ylab="") 
polygon(x) 

# Function to minimize: 
# either the sum of the squares of the distances to the polygon, 
# if at least one point is outside, 
# or minus the square of the scaling factor. 
# It is not continuous, but (surprisingly) that does not seem to be a problem. 
f <- function(p) { 
    lambda <- log(1 + exp(p[1])) 
    a <- p[2:3] 
    y0 <- colMeans(y) 
    transformed_points <- t(lambda * (t(y)-y0) + a) 
    distances <- apply(
    transformed_points, 
    1, 
    function(u) distance_to_polygon(u, x) 
) 
    if(all(distances == 0)) - lambda^2 
    else      sum(distances^2) 
} 
# Minimize this function 
p <- optim(c(1,0,0), f)$par 
# Compute the optimal parameters 
lambda <- log(1 + exp(p[1])) 
a <- p[2:3] 
y0 <- colMeans(y) 
# Compute the new coordinates 
transformed_points <- t(lambda * (t(y)-y0) + a) 
# Plot them 
segments(y[,1], y[,2], transformed_points[,1], transformed_points[,2], lty=3) 
points(transformed_points, pch=3) 
library(deldir) 
plot( 
    deldir(transformed_points[,1], transformed_points[,2]), 
    wlines="tess", add=TRUE 
) 

Shifting and rescaling a set of points to put them inside a polygon

+0

@ Vincent Zoonekynd谢谢,这很好。你的答案帮了很大忙。但我有一个小问题。我知道如何查找点是否在多边形中。我想要的是如何按照所有点适合多边形的方式来缩放我所有的点。 – dp758 2013-02-14 06:18:02

+0

并且瓦片内细分的线条延伸到瓦片之外。有没有办法限制他们,使他们完全在里面。 – dp758 2013-02-14 06:24:39

+0

我已经更新了我的答案,同时也展示了如何移动和重新调整点数,以防万一您想要所有这些点,并且它们的确切位置并不重要。 将曲线图(曲面细分)剪切成多边形(单元格) 并不简单,至少在基本图形上。 – 2013-02-14 12:10:15