Gra*_*ton 6 c# c++ geometry clipper nettopologysuite
我有一条多段线,我想沿着这些点在一个方向上进行可变宽度偏移。我该怎么做?对于折线,我只需要支持直线,不需要支持曲线或圆弧。
多段线可以是闭合的,也可以是开放的,并且偏移仅在一个方向上——为了便于讨论,我们假设它在左侧方向。
上图
几乎概括了我想要做的事情;唯一的问题是,它在整个折线中是统一的偏移,因此我想要可变的偏移。
这个问题比乍看起来要棘手得多。有一些库并没有完全做到这一点。让我们一一分析一下。
Clipper 可以处理多边形缓冲区,这意味着在两个方向上创建偏移线,最后围绕该线形成多边形。所以不适合我的需求。此外,它不处理变量缓冲。
快船队开发者在论坛上对此进行了一些讨论,但遗憾的是没有任何结果。
NetTopologySuite有一个VariableBuffer类,它可以处理可变偏移量。但不幸的是,NetTopologySuite 只能处理多边形缓冲(将一条线转换为包含该线的多边形),而不能处理折线偏移(其中折线在单个方向上偏移)。
另外,似乎使用上述方法 NetTopologySuite 会在两个方向上“炸毁”多边形,并且需要设置BufferParameters.IsSingleSided=true
以便具有单边多边形偏移,但目前还不清楚如何将其与 结合使用VariableBuffer
。
Cavalier countours与大多数库不同,它只能在一个方向上进行折线偏移(这就是我想要的),这样就不会形成多边形。这就是我想要的,但不幸的是,它不能进行可变宽度偏移。
似乎没有简单的方法可以做到这一点。有什么想法可以做到这一点吗?
欢迎任何基于 C#、C++ 或 C 库构建的解决方案。
事实上,对于可变偏移量,问题会更加复杂。在具有单个偏移的情况下,点 p 到折线的距离定义为折线到 p 的最近点的距离(参见https://github.com/jbuckmccready/CavalierContours/blob中的pointValidForOffset示例) /master/include/cavc/polylineoffset.hpp)
对可变偏移量的概括并不明显。
对于简单折线(无曲线),一个简单的解决方案是:设F为初始折线。
要绘制远离变量 offset 的折线G :如果将代码放在http://paperjs.org/“Sketch ”中,则此代码有效,结果如下:
/* Computes a polyline with a fixed offset (red)
* and another with a variable size offset (green)
*/
const points = [
new Point(30, 40),
new Point(100, 80),
new Point(200, 60),
new Point(250, 50),
new Point(300, 70),
new Point(350, 90),
new Point(400, 60),
new Point(450, 50),
new Point(500, 70),
new Point(550, 90),
];
let poly1 = new Path();
poly1.strokeColor = 'black';
points.forEach(p => poly1.add(p));
const fixOffs = 5;
const offsets = [
10, 20, 30, 20, 10, 10, 20, 20, 30, 30];
let fix = [];
let variable = [];
const size = points.length;
for(let i=0; i<size; ++i){
let tangent;
if(i===0){ // if first point
tangent = points[1] - points[0];
}else if(i+1===size){ // if last point
tangent = points[i] - points[i-1];
}else{ // mean of segment before and segment after point i
tangent = (points[i] - points[i-1]) * 0.5 +
(points[i+1] - points[i]) * 0.5;
}
let normal = new Point(-tangent.y, tangent.x); // perpendicular vector
normal = normal / normal.length; // normalize
fix.push(points[i] + normal * fixOffs);
variable.push(points[i] + normal * offsets[i]);
}
let polyFix = new Path();
polyFix.strokeColor = 'red';
fix.forEach(p => polyFix.add(p));
let polyVar = new Path();
polyVar.strokeColor = 'green';
variable.forEach(p => polyVar.add(p));
Run Code Online (Sandbox Code Playgroud)