如下图所示:已知中间折线的坐标,求两侧平行线坐标的算法,感谢折线数据结构:[{x,y},...]
不多废话,直接上代码
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,其他空间分析库也有相应代码,但原理都一样,比如truf的lineOffset
ol-ext
truf
lineOffset
这个主要找各种转折点,然后顺序连线即可起点和终点都算一种特殊转折点这样每个线段也就有了对应的2条等距平行线的描述方程,相近的2条等距平行线有且只有1个交点,就是对应的等距平行线上的转折点。上面2个图中,第一个图的处理其实不准确的。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
暂无简介
文章 0 评论 0
接受
发布评论
评论(2)
不多废话,直接上代码
结果
再多废话两句,代码来自
ol-ext
,其他空间分析库也有相应代码,但原理都一样,比如truf
的lineOffset
这个主要找各种转折点,然后顺序连线即可
起点和终点都算一种特殊转折点
这样每个线段也就有了对应的2条等距平行线的描述方程,相近的2条等距平行线有且只有1个交点,就是对应的等距平行线上的转折点。
上面2个图中,第一个图的处理其实不准确的。