求折线两侧平行线算法

发布于 2022-09-12 14:01:58 字数 183 浏览 23 评论 0

如下图所示:已知中间折线的坐标,求两侧平行线坐标的算法,感谢
折线数据结构:[{x,y},...]
image.png
image.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

于我来说 2022-09-19 14:01:58

不多废话,直接上代码

function dist2d(coord1, coord2) {
  let dx = coord1[0] - coord2[0];
  let dy = coord1[1] - coord2[1];
  return Math.sqrt(dx * dx + dy * dy)
}
function equals(coord1, coord2) {
  let equals = true;
  for (let i = coord1.length - 1; i >= 0; --i){
    if (coord1[i] != coord2[i]) {
      equals = false;
      break
    }
  }
  return equals
}
function offsetCoords(coords, offset) {
    var path = [];
    var N = coords.length-1;
    var max = N;
    var mi, mi1, li, li1, ri, ri1, si, si1, Xi1, Yi1;
    var p0, p1, p2;
    var isClosed = equals(coords[0],coords[N]);
    if (!isClosed) {
            p0 = coords[0];
            p1 = coords[1];
            p2 = [
                    p0[0] + (p1[1] - p0[1]) / dist2d(p0,p1) *offset,
                    p0[1] - (p1[0] - p0[0]) / dist2d(p0,p1) *offset
            ];
            path.push(p2);
            coords.push(coords[N])
            N++;
            max--;
    }
    for (var i = 0; i < max; i++) {
            p0 = coords[i];
            p1 = coords[(i+1) % N];
            p2 = coords[(i+2) % N];
            mi = (p1[1] - p0[1])/(p1[0] - p0[0]);
            mi1 = (p2[1] - p1[1])/(p2[0] - p1[0]);
            // Prevent alignements
            if (Math.abs(mi-mi1) > 1e-10) {
                    li = Math.sqrt((p1[0] - p0[0])*(p1[0] - p0[0])+(p1[1] - p0[1])*(p1[1] - p0[1]));
                    li1 = Math.sqrt((p2[0] - p1[0])*(p2[0] - p1[0])+(p2[1] - p1[1])*(p2[1] - p1[1]));
                    ri = p0[0] + offset*(p1[1] - p0[1])/li;
                    ri1 = p1[0] + offset*(p2[1] - p1[1])/li1;
                    si = p0[1] - offset*(p1[0] - p0[0])/li;
                    si1 = p1[1] - offset*(p2[0] - p1[0])/li1;
                    Xi1 = (mi1*ri1-mi*ri+si-si1) / (mi1-mi);
                    Yi1 = (mi*mi1*(ri1-ri)+mi1*si-mi*si1) / (mi1-mi);
                    // Correction for vertical lines
                    if(p1[0] - p0[0] == 0) {
                            Xi1 = p1[0] + offset*(p1[1] - p0[1])/Math.abs(p1[1] - p0[1]);
                            Yi1 = mi1*Xi1 - mi1*ri1 + si1;
                    }
                    if (p2[0] - p1[0] == 0 ) {
                            Xi1 = p2[0] + offset*(p2[1] - p1[1])/Math.abs(p2[1] - p1[1]);
                            Yi1 = mi*Xi1 - mi*ri + si;
                    }
                    path.push([Xi1, Yi1]);
            }
    }
    if (isClosed) {
            path.push(path[0]);
    } else {
            coords.pop();
            p0 = coords[coords.length-1];
            p1 = coords[coords.length-2];
            p2 = [
                    p0[0] - (p1[1] - p0[1]) / dist2d(p0,p1) *offset,
                    p0[1] + (p1[0] - p0[0]) / dist2d(p0,p1) *offset
            ];
            path.push(p2);
    }
    return path;
}

结果

offsetCoords([[0,0],[0,2],[3,2],[3,4],[-1,4],[-1,6],[5,8]], 1)
//[[1,0],[1,1],[4,1],[4,5],[0,5],[0,5.279240779943874],[5.316227766016838,7.051316701949486]]
offsetCoords([[0,0],[0,2],[3,2],[3,4],[-1,4],[-1,6],[5,8]], -1)
//[[-1,0],[-1,3],[2,3],[2,3],[-2,3],[-2,6.720759220056126],[4.683772233983162,8.948683298050513]]

再多废话两句,代码来自ol-ext,其他空间分析库也有相应代码,但原理都一样,比如truflineOffset

っ〆星空下的拥抱 2022-09-19 14:01:58

这个主要找各种转折点,然后顺序连线即可
起点和终点都算一种特殊转折点
这样每个线段也就有了对应的2条等距平行线的描述方程,相近的2条等距平行线有且只有1个交点,就是对应的等距平行线上的转折点。
上面2个图中,第一个图的处理其实不准确的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文