2013-02-13 4 views
4

Я работаю с voronoi тесселяции. У меня разные полигоны, представляющие области в тесселяции.иерархия в вороной тесселяции

Приведенные ниже рисунки используются для рисования тесселяции на рисунке.

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

координаты Сэммона ниже.

 [,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 

Я хочу построить тесселяции, для которых вводятся координатные точки sammon. Тесселяция с использованием этих точек должна находиться в пределах одной из областей показанного рисунка, и для этого вышеуказанные точки следует масштабировать или мы можем ограничить график тесселяции в пределах одной из областей на приведенном выше рисунке.

Надеюсь, я коснулся всех необходимых данных.

P.S: проекция

Сэммона поставляется в пакете "MASS". voronoi тесселяции из пакета "deldir".

аргумент dirsgs выход функции deldir даст координаты точек, образующих линии в тесселяции.

сегментная функция графической упаковки может использоваться для объединения двух точек, координаты которых извлекаются из dirsgs.

+0

И что вы пытаетесь сделать уже? – juba

+0

Возможный дубликат [вывод проекции sammon внутри полигона] (http://stackoverflow.com/questions/14853503/sammon-projection-output-within-a-polygon) – juba

+0

Вы говорите, что знаете, как ограничить тесселяцию, так что ваш вопрос только, как масштабировать точки Саммона в один из полигонов? – Gregor

ответ

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, равным (или близким к нулю). Чтобы избежать этого, мы можем добавить штраф, если лямбда невелика.

# 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

+0

и линии тесселяции внутри плитки вытянуты за пределами плитки. Есть ли способ ограничить их, чтобы они были полностью внутри. – dp758

+0

Я обновил свой ответ, чтобы показать, как сдвинуть и перемасштабировать точки, в случае, если вы хотите их всех, и их точное положение не имеет значения. Обрезание графика (тесселяции) на многоугольник (ячейка) не является простым, по крайней мере, базовой графикой. –