我试图找出拐点,即直线上的曲线的起点和终点。如果查看图像,绿线可能是道路或溪流,黑点是曲线的起点和终点。
自动生成这些点的高级步骤是什么?我有ArcGIS Desktop,并且对ArcObjects非常方便。
我试图找出拐点,即直线上的曲线的起点和终点。如果查看图像,绿线可能是道路或溪流,黑点是曲线的起点和终点。
自动生成这些点的高级步骤是什么?我有ArcGIS Desktop,并且对ArcObjects非常方便。
Answers:
当曲线由线段组成时,这些线段的所有内部点都是拐点,这并不有趣。取而代之的是,曲线应被认为是那些线段的顶点所近似的。通过将分段的两次可微分曲线样条化,然后可以计算曲率。严格来说,拐点就是曲率为零的地方。
在该示例中,存在一些曲率几乎为零的较长拉伸。这表明指示的点应近似于低曲率区域的这种延伸的末端。
因此,有效的算法将对顶点进行样条运算,沿着密集的中间点集计算曲率,确定接近零曲率的范围(使用对“接近”意味着的合理估计),并标记这些范围的端点。
这里是工作R
代码来说明这些想法。让我们从表示为坐标序列的线串开始:
xy <- matrix(c(5,20, 3,18, 2,19, 1.5,16, 5.5,9, 4.5,8, 3.5,12, 2.5,11, 3.5,3,
2,3, 2,6, 0,6, 2.5,-4, 4,-5, 6.5,-2, 7.5,-2.5, 7.7,-3.5, 6.5,-8), ncol=2, byrow=TRUE)
分别对x和y坐标进行样条化以实现曲线的参数化。(该参数将称为time
。)
n <- dim(xy)[1]
fx <- splinefun(1:n, xy[,1], method="natural")
fy <- splinefun(1:n, xy[,2], method="natural")
插补样条线以进行绘图和计算:
time <- seq(1,n,length.out=511)
uv <- sapply(time, function(t) c(fx(t), fy(t)))
我们需要一个函数来计算参数化曲线的曲率。它需要估计样条曲线的一阶和二阶导数。对于许多样条曲线(例如三次样条曲线),这是一个简单的代数计算。 R
自动提供前三个导数。(在其他环境中,可能需要数字计算导数。)
curvature <- function(t, fx, fy) {
# t is an argument to spline functions fx and fy.
xp <- fx(t,1); yp <- fy(t,1) # First derivatives
xpp <- fx(t,2); ypp <- fy(t,2) # Second derivatives
v <- sqrt(xp^2 + yp^2) # Speed
(xp*ypp - yp*xpp) / v^3 # (Signed) curvature
# (Left turns have positive curvature; right turns, negative.)
}
kappa <- abs(curvature(time, fx, fy)) # Absolute curvature of the data
我建议根据曲线的范围估算零曲率的阈值。至少这是一个很好的起点;应该根据曲线的曲率进行调整(即,对于更长的曲线应增加)。以后将根据曲率将其用于为图着色。
curvature.zero <- 2*pi / max(range(xy[,1]), range(xy[,2])) # A small threshold
i.col <- 1 + floor(127 * curvature.zero/(curvature.zero + kappa))
palette(terrain.colors(max(i.col))) # Colors
现在已经对顶点进行了样条化并计算了曲率,剩下的只是找到拐点。为了显示它们,我们可以绘制顶点,绘制样条曲线并在其上标记拐点。
plot(xy, asp=1, xlab="x",ylab="y", type="n")
tmp <- sapply(2:length(kappa), function(i) lines(rbind(uv[,i-1],uv[,i]), lwd=2, col=i.col[i]))
points(t(sapply(time[diff(kappa < curvature.zero/2) != 0],
function(t) c(fx(t), fy(t)))), pch=19, col="Black")
points(xy)
空心点是其中的原始顶点,xy
黑色点是使用此算法自动识别的拐点。由于无法可靠地在曲线的端点处计算曲率,因此这些点没有特别标记。
您可以使用“ 增密”工具。在这种情况下,您选择按角度进行增密,然后选择直线上可接受的最大角度。然后将结果线应用于顶点处的工具“ 分割线”。最后,删除shape_length小于最小道路长度的线。
在这张照片中,我们看到三个步骤:
1-使用角度使线致密。我使用10度作为参数,我们使用了分割线。在图片中,曲线处于初始阶段。
arcpy.Densify_edit("line" , "ANGLE" , "","",10)
arcpy.SplitLine_management("line" , "line_split")
2-选择没有shape_length冗余的线段。正如我们在表中看到的,我没有选择那些多余的长度。然后,将它们选择到新的要素类中。
arcpy.Select_analysis("line_split" , "line_split_selected")
3-我们提取了位于线条边缘的顶点,这些顶点是拐点。
arcpy.FeatureVerticesToPoints_management("line_split_selected" , "line_split_pnt" , "DANGLE")
您可以使用与原始行具有最大偏移量的Generalize工具作为参数,因此可以选择适合您情况的偏移量。
如果我们将原始行命名为“ line_cur”,而将广义行命名为“ line_gen”,则可以将“ line_cur”剪切为“ line_gen”。结果将是“ line_cur”的直线段。然后,我们可以通过使用sql查询删除一些非常短的路段来进行清理,该查询选择的Shape_length大于最小路段的长度。