Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.5k views
in Technique[技术] by (71.8m points)

求折线两侧平行线算法

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

不多废话,直接上代码

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...