【问题标题】:Offsetting a polyline in one direction向一个方向偏移多段线
【发布时间】:2021-12-24 08:46:00
【问题描述】:

我正在寻找一种方法来偏移通过 xy 坐标在一个方向(在 R 中)定义的任意曲线。我可以使用 {polyclip} 包在两个方向上偏移曲线。

library(polyclip)
#> polyclip 1.10-0 built from Clipper C++ version 6.4.0

# Make a curve
t <- seq(10, 0, by = -0.05)
curve <- data.frame(
  x = t * cos(t), y = t * sin(t)
)
plot(curve, type = 'l')

# Find offset
offset <- polylineoffset(curve, delta = 0.5, 
                         jointype = "round", endtype = "openbutt")[[1]]
offset <- as.data.frame(offset) # xy coordinates

lines(offset, col = "red")

因为曲线上的点比偏移量的delta 参数间隔更近,所以我可以通过找出一个点与下一个点之间的距离最大的位置来启发式地拆分偏移量。

distance <- c(0, sqrt(diff(offset$x)^2 + sqrt(diff(offset$y)^2)))
max_dist <- which.max(distance)

plot(curve, type = 'l')
lines(offset[1:(max_dist - 1), ], col = 3)
lines(offset[max_dist:nrow(offset), ], col = 4)

reprex package (v2.0.1) 于 2021 年 11 月 11 日创建

但是,我希望能够拆分偏移量,或者仅在一个方向上偏移,即使曲线上的点之间的距离比偏移距离更远。有没有办法在 R 中做到这一点?我没有与 {polyclip} 包结婚,使用另一个包的解决方案也可以。

【问题讨论】:

    标签: r geometry polyline


    【解决方案1】:

    不需要额外的包 Teunbrand - 这可以通过一个小的触发函数来完成:

    offset <- function(x, y, d) {
     angle <- atan2(diff(y), diff(x)) + pi/2
     angle <- c(angle[1], angle)
     data.frame(x = d * cos(angle) + x, y = d * sin(angle) + y)
    }
    

    所以,如果我们重新创建您的示例,我们有:

    t <- seq(10, 0, by = -0.05)
    
    curve <- data.frame(
      x = t * cos(t), y = t * sin(t)
    )
    
    plot(curve, type = 'l')
    

    我们可以添加一个偏移量:

    curve2 <- offset(curve$x, curve$y, 0.5)
    
    lines(curve2, col = "red")
    

    此函数的工作方式是使用atan2([delta y], [delta x]) 获取直线每个点的斜率角度,然后添加 90 度以找到与曲线垂直的直线的角度在那时候。最终找到沿这条线与原x、y坐标距离d的点,即(x + d * cos(angle), y + d * sin(angle))

    这可能最好以图形方式显示。这里的蓝线是函数offset计算的偏移量:

    segments(curve$x, curve$y, curve2$x, curve2$y, col = "blue")
    

    我们可以通过简单地传递一个负值d来向相反的方向偏移:

    lines(offset(curve$x, curve$y, -0.5), col = "forestgreen")
    

    我们需要了解定义偏移量的局限性,尤其是当偏移量与绘图的任何凹面部分相比较大时。例如,如果我们查看 -2 的偏移量,我们似乎在螺旋的中心有一个伪影:

    plot(curve, type = 'l')
    curve3 <- offset(curve$x, curve$y, -2)
    lines(curve3, col = "gray50")
    

    如果我们再次绘制偏移线段,我们可以看到为什么会发生这种情况:

    segments(curve$x, curve$y, curve3$x, curve3$y, col = "blue")
    

    本质上,如果你有一个紧凑的凹曲线和一个相当大的偏移量,那么偏移线就会交叉。这会产生一些与我们期望看到的“偏移路径”不太匹配的东西,但是如果不仔细定义偏移路径的含义以及我们想要的方式,就很难看到如何解决这个问题它出现在上述情况中。我的猜测是,最令人满意的解决方案是将d 缩小到否则会超过该点曲线半径的点,但我不会在这里实现,因为这只是一种选择,而且我我敢肯定那里有更好的。

    无论如何,这样做的好处之一是结果中的点数与输入的点数相同。这样可以轻松地将偏移量放入初始数据框中。方便构建新的几何图形!

    reprex package (v2.0.0) 于 2021 年 11 月 12 日创建

    【讨论】:

    • 感谢 Allan Cameron,通常非常有用的答案!还要感谢您不仅提供了一个有效的功能,而且还提供了解释,因为三角学不是我最擅长的(实际上我正在尝试用它来构建几何!)。
    • 我还发现使用M &lt;- atan2(diff(y, 2), diff(x, 2)) + pi/2; M &lt;- c(M[1], M, M[length(M)]) 可以很好地处理更简单的曲线,例如t &lt;- seq(0, 2 * pi, length.out = 7); x = cos(t); y = sin(t)(六边形)。
    猜你喜欢
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多