我正在尝试解决以下问题R
:
我有一个由包含两个分量 x 和 y 的列表 l 定义的多边形对象。顺序定义了多边形的边。
例如 :
l=list(
x=c(-1.93400738955091,0.511747161547164,1.85047596846401,-1.4963460488281,-1.31613255558929,-0.0803828876660542,1.721752044722,-0.724002506376074,-2.08847609804132,2.13366860069641),
y=c(-1.02967154136169,1.53216851658359,-1.39564869249673,-1.21266011692921,1.6419616619241,-1.87141898897228,0.946605074767527,1.49557080147009,0.324443917837958,-0.517303529772633)
)
plot(l,type="b",pch=16)
points(l$x[c(10,1)],l$y[c(10,1)],type="b",pch=16)
现在我感兴趣的是只保留这个多边形的外边界(而不是凸包)。下图突出了我想保留的点
points(
x=c(-1.13927707377209,-1.31613255249992,-1.3598262571216,0.511747159281619,0.264900107013767,0.671727215417383,-0.724002505140328,-1.93400738893304,-1.4811931364624,-1.45298543105533,-2.08847609804132,-1.40787406113029,-1.3598262571216,0.278826441754518,1.85047596733123,1.48615105742673,1.48615105742673,2.13366860069641,1.38016944537233,1.38016944537233,1.17232981688283,1.17232981688283,1.72175204307433,0.671727215417383,-1.496346, -0.08038289, -0.2824999),
y=c(1.13914087952916,1.64196166071069,0.949843643913108,1.53216851597378,1.27360509238768,1.18229006681548,1.49557080106148,-1.02967154055378,-0.972634663817139,-0.525818314106921,0.324443915423533,0.188755761926866,0.949843643913108,-1.30971824545964,-1.3956486896768,-0.59886540309968,-0.59886540309968,-0.517303527559411,-0.367082245352325,-0.367082245352325,0.0874657083966551,0.0874657083966551,0.94660507315481,1.18229006681548,-1.21266,-1.871419,-1.281255),
pch=16,
col="red",
cex=0.75
)
我真的不知道是否有工具可以轻松做到这一点。我找到的最接近的是包中的polysimplify
函数polyclip
,它标识了我需要的所有点,但也输出了一些我不需要的点(线段相交的内部点)。
我实际上找到了一个解决方案(如下)。以下功能可以满足我的要求,但我不确定它为什么起作用(以及它是否可能会失败)。
实际上下面的函数正确地识别了我想要的点,但是以错误的顺序输出它们,所以它对我来说仍然没用......
polygon.clean<-function(poly){
require(polyclip)
poly.cleaned=polysimplify(poly)
x=unlist(sapply(poly.cleaned,function(x)x$x))
y=unlist(sapply(poly.cleaned,function(x)x$y))
x.src=x[!x%in%x[duplicated(x)]]
y.src=y[!y%in%y[duplicated(y)]]
poly.cleaned=poly.cleaned[sapply(poly.cleaned,function(poly.sub,x,y){
any(poly.sub$x%in%x&poly.sub$y%in%y)
},x=x.src,y=y.src)]
x=unlist(sapply(poly.cleaned,function(x){
res=x$x
if(length(res)==4){
res=vector()
}
res
}))
y=unlist(sapply(poly.cleaned,function(x){
res=x$y
if(length(res)==4){
res=vector()
}
res
}))
x=c(x,x.src)
y=c(y,y.src)
tester=duplicated(x)&duplicated(y)
x=x[!tester]
y=y[!tester]
list(x=x,y=y)
}
plot(l,type="b",pch=16)
points(l$x[c(10,1)],l$y[c(10,1)],type="b",pch=16)
points(polygon.clean(l),pch=16,cex=0.75,col="red")