如何将一组点坐标从凹壳转换为R中的多边形?

时间:2016-03-09 14:06:10

标签: r maps coordinates polygon

我有一个alphahull::ashape()结果,我需要使用spatstat::owin()转换后续空间分析。有一个优雅的解决方案如何从凹形船体订购点并将形状转换为owin对象或任何Spatial*对象?对于假设矩阵coords中的有序点,多边形定义为:

geo.owin=try(owin(poly=list(x=coords[,1],y=coords[,2])),silent=T)
if(class(geo.owin)=="try-error") geo.owin=owin(poly=list(x=rev(coords[,1]),y=rev(coords[,2])))

这是不可能的。 ashape()$edges矩阵包含可以绘制为看起来像多边形的点的坐标,并且此处提供矩阵。但是,这些点没有按照不同的绘图颜色和箭头方向进行排序。

# data
okraj = matrix(c(23.8808, 18.0106, 23.8808, 1.8265, 1.8266, 1.8265, 18.0106, 39.5352, 39.5352, 39.5352, 13.5519, 27.9675, 3.8102, 4.8269, 8.8236, 52.7248, 45.3385, 52.7248, 50.9600, 50.9600, 50.9600, 45.3385, 39.9042, 39.9042, 39.9042, 49.1204, 41.8421, 47.1450, 44.9423, 46.0246, 13.5519, 27.9675, 32.1116, 1.8266, 4.5644, 3.8102, 17.5557, 39.5840, 32.1116, 29.2158, 4.5644, 29.2158, 4.8269, 8.8236, 17.5557, 49.1204, 41.8421, 41.3710, 50.9600, 49.8638, 47.1450, 45.5063, 39.8987, 41.3710, 40.0750, 49.8638), ncol=4, dimnames=list(NULL,c("x1","y1","x2","y2")))

# draw polygon from arrows
farby=colorRampPalette(c("lightblue","black"))(nrow(okraj))
plot(0,type="n",xlim=range(okraj[,c(1,3)]),ylim=range(okraj[,c(2,4)]),xlab="",ylab="")
for(i in 1:nrow(okraj)){
    arrows(okraj[i,"x1"],okraj[i,"y1"],okraj[i,"x2"],okraj[i,"y2"],col=farby[i],length=.1,lwd=2)
}

Concave hull with unordered points

通过其他问题搜索,返回ordered pointsconvex not concave shapesCpythonLua种语言解决方案的解决方案。我当前的代码搜索矩阵中的连接点,并在解释alpha形状边缘坐标时遇到的每个问题使用if()条件(原谅天真编码)。

# function finding a row, which contains the connecting data
find.connection=function(bod, temp){
    # test whether a connection exists in the first set of point coordinates
    riadok1=ifelse(length(which(temp[,1]==bod[1]))==0,NA,which(temp[,1]==bod[1]))
    riadok2=ifelse(length(which(temp[,2]==bod[2]))==0,NA,which(temp[,2]==bod[2]))
    # test for a connection in the second set of coordinates
    if(is.na(riadok1)){
        riadok1=ifelse(length(which(temp[,3]==bod[1]))==0,NA,which(temp[,3]==bod[1]))
        riadok2=ifelse(length(which(temp[,4]==bod[2]))==0,NA,which(temp[,4]==bod[2]))
    }
    # check multiple values in x or y coordinates and select a row where both occur
    if(riadok1==riadok2){
        riadok=riadok1
    } else {
        riadky1=ifelse(length(which(temp[,3]==bod[1]))==0,NA,which(temp[,3]==bod[1]))
        riadky2=ifelse(length(which(temp[,4]==bod[2]))==0,NA,which(temp[,4]==bod[2]))
        riadok=intersect(riadky1,riadky2)
    }
    return(riadok)
}

# setting up the variable with ordered points
coords=c(okraj[1,c("x2","y2")])
coords=rbind(coords,c(okraj[1,c("x1","y1")]))

# current working point and a matrix subset, in which to search for a connection
bod=okraj[1,1:2]
temp=okraj[-1,]

# consecutively search for connecting points
for(j in 1:nrow(okraj)){

    if(any(is.na(match(bod,temp)))){
        message(paste("Problem with: ", bod,", row: ",j ))
        next
    }

    bod2=NA # next ordered point
    smer=0 # controls the set of coordinates to use for a connection

    for(x in 1:2){
        riadok=find.connection(bod=bod,temp=temp)
        # my solution to the current crash point can be implemented here
        if(is.na(riadok)) bod2=NA
        # select correct value for the connecting point from the two sets of coordinates
        else bod2=temp[riadok,c(x+smer,x+smer+1)]
        if(all(bod==bod2)) bod2=temp[riadok,c(x+2,x+3)]
        if(any(is.na(bod2))){
            smer=1
            next
        } else { break }
    }

    # store the connecting point and move to the next
    coords=rbind(coords,bod2)
    bod=bod2

    # caveats for the last row in the matrix
    if(!is.null(dim(temp))) temp = temp[-riadok,]
    if(is.null(dim(temp))){
        if(all(coords[1,]==coords[nrow(coords),])){
            break
        }
        if(which(temp==bod[1])==1){
            coords=rbind(coords,temp[3:4])
            break
        } else { 
            coords=rbind(coords,temp[1:2])
            break
        }
    }
}

适用于某些数据集。这里,样本数据集包含一个端点okraj[8,3:4],它不连接到矩阵中的任何其他内容,代码崩溃。我的解决方案是跳过该行,然后再次尝试。

if(is.na(riadok)){
    bod2=NA
    temp=temp[-riadok,]
    bod=coords[nrow(coords),]
    next
}

但是,该解决方案需要删除一行数据,这是错误的。您对将alpha形状转换为映射对象的系统解决方案的帮助将非常感激。

编辑:

关于removing holes from polygons的问题从@Spacedman使用rgeos例程得到了答案。如何用这里的例子中的无序点来解决我的问题呢?

0 个答案:

没有答案