.NET GDI +:绘制带圆角的线条

时间:2009-11-26 20:48:37

标签: .net gdi+ drawing rounded-corners graphicspath

给定一系列点,很容易根据这些点绘制一条线,例如:使用GraphicsPath类。

例如,以下数组......

[0]: (0,0)
[1]: (100,0)
[2]: (0,100)
[3]: (100,100)

...描述了一个类似于Z的行。

但接下来是挑战;我需要绘制半径为例如圆角的圆角。 10个像素。在角落,我指的是线条中不是起点或终点的点。在这种情况下,(0,100)(100,0)有两个角落。

我玩过beziers,曲线和弧线,其中一些可能解决方案 - 我自己还没有找到它,因为我必须能够处理从各个角度绘制的线条,不只是水平线或垂直线。

LineJoin对象的Pen设置为Round是不够的,因为这只会显示更宽的笔。


编辑:为了澄清,我很清楚GraphicsPath类的bezier,曲线和弧功能。我正在寻找一些关于构建可以采用任意数量点的算法的更具体的建议,并将它们与圆角串在一起。


解决方案

我把以下函数放在一起,它返回一个表示带圆角的线的路径。该函数使用了一个LengthenLine函数,可以找到here

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;
}

3 个答案:

答案 0 :(得分:6)

这是我用来绘制圆角矩形的函数... 从这里你可以计算出每条线的角度。

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

希望这能帮助你完成三角学中较难的部分;)

答案 1 :(得分:2)

Bezier曲线非常简单易用:

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

答案 2 :(得分:0)

This url描述了如何绘制可能有助于您开始的圆角矩形。

但我认为,如果没有其他任何你可以在你的道路上添加更多的点,给出圆角的错觉。所以在0,0和100,0之间添加几个点。一个例子可能是:

(0,0) (90,0) (95.5) (95,10) (0100)

我没有以任何方式测试过这条路径,只是提取了一些可能无法解决的数字:)。