求折线两侧平行线算法

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

阅读 118
评论
    2 个回答
    • 13.4k

    不多废话,直接上代码

    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

      • 3.4k

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

        撰写回答

        登录后参与交流、获取后续更新提醒

        相似问题
        推荐文章