.NET GDI +:角の丸い線を描く
-
05-07-2019 - |
質問
点の配列を考えると、これらに基づいて線を描くのは簡単です。 GraphicsPathクラスを使用します。
たとえば、次のポイントの配列...
[0]: (0,0)
[1]: (100,0)
[2]: (0,100)
[3]: (100,100)
... Zに似た行を記述します。
しかし、ここに課題があります。例えば半径が丸い角を描く必要があります。 10ピクセル。コーナーとは、開始点でも終了点でもないライン内のポイントを意味します。この場合、(0,100)
と(100,0)
に2つのコーナーがあります。
ベジェ、曲線、円弧をいじってみましたが、そのうちのいくつかは解決策を保持している可能性があります-すべての角度で描かれた線を処理する必要があるため、私はまだ自分で見つけることができませんでした、水平線や垂直線だけではありません。
Pen
オブジェクトの LineJoin
を Round
に設定するだけでは十分ではありません。これは幅の広いペンでのみ表示されるためです。
編集:明確にするために、GraphicsPathクラスのベジェ、曲線、および円弧の機能をよく知っています。私は、任意の数のポイントを取り、それらを丸い角でつなぐことができるアルゴリズムを構築することに関して、より具体的なアドバイスを探しています。
解決策
角の丸い線を表すパスを返す次の関数をまとめました。この関数は、ここで見つけることができるLengthenLine関数を使用しますa>。
protected GraphicsPath GetRoundedLine(PointF[] points, float cornerRadius)
{
GraphicsPath path = new GraphicsPath();
PointF previousEndPoint = PointF.Empty;
for (int i = 1; i < points.Length; i++)
{
PointF startPoint = points[i - 1];
PointF endPoint = points[i];
if (i > 1)
{
// shorten start point and add bezier curve for all but the first line segment:
PointF cornerPoint = startPoint;
LengthenLine(endPoint, ref startPoint, -cornerRadius);
PointF controlPoint1 = cornerPoint;
PointF controlPoint2 = cornerPoint;
LengthenLine(previousEndPoint, ref controlPoint1, -cornerRadius / 2);
LengthenLine(startPoint, ref controlPoint2, -cornerRadius / 2);
path.AddBezier(previousEndPoint, controlPoint1, controlPoint2, startPoint);
}
if (i + 1 < points.Length) // shorten end point of all but the last line segment.
LengthenLine(startPoint, ref endPoint, -cornerRadius);
path.AddLine(startPoint, endPoint);
previousEndPoint = endPoint;
}
return path;
}
解決
ベジェ曲線の実装は非常に簡単です:
http://www.codeproject.com/KB/recipes/BezirCurves.aspx
幸いなことに、これらの詳細を省略したい場合は、GraphicsPathクラスの一部としても使用できます。
http://msdn.microsoft .com / en-us / library / system.drawing.drawing2d.graphicspath.addbezier.aspx
そして、スプラインを調べることもできます:
http://msdn.microsoft .com / en-us / library / system.drawing.drawing2d.graphicspath.addcurve.aspx
他のヒント
これは、角が丸い長方形を描くために使用する関数です... これから、各線の角度を計算できます。
Public Sub DrawRoundRect(ByVal g As Graphics, ByVal p As Pen, ByVal x As Single, ByVal y As Single, ByVal width As Single, ByVal height As Single, ByVal radius As Single)
Dim gp As GraphicsPath = New GraphicsPath
gp.AddLine(x + radius, y, x + width - (radius * 2), y)
gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90)
gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2))
gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90)
gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height)
gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90)
gp.AddLine(x, y + height - (radius * 2), x, y + radius)
gp.AddArc(x, y, radius * 2, radius * 2, 180, 90)
gp.CloseFigure()
g.DrawPath(p, gp)
gp.Dispose()
End Sub
これが三角法の難しい部分に役立つことを期待してください;)
こののURLには、丸みを帯びた長方形を描画する方法の説明があります。開始します。
しかし、他に何もない場合は、パスにポイントを追加して、丸い角の錯覚を与えることができると思います。したがって、0,0から100,0の間にいくつかのポイントを追加します。例は次のとおりです。
(0,0) (90,0) (95,5) (95,10) (0,100)
このパスをテストしたことはありませんが、空中に機能する可能性のある数値をいくつか引き出しただけです。