.NET GDI+;:用圆角画线

.NET GDI+;:用圆角画线,.net,gdi+,drawing,rounded-corners,graphicspath,.net,Gdi+,Drawing,Rounded Corners,Graphicspath,给定一组点,可以很容易地基于这些点绘制一条线,例如使用GraphicsPath类 例如,下面的点数组 [0]: (0,0) [1]: (100,0) [2]: (0,100) [3]: (100,100) …描述了一条类似于Z的线 但挑战来了;我需要绘制半径为10像素的圆角。所谓角点,我指的是线中不是起点或终点的点。在这种情况下,在(0100)和(100,0)处有两个角 我已经尝试过贝塞尔曲线、曲线和圆弧,其中一些可能适用于解决方案——我自己还没有找到它,因为我必须能够处理以所有角度绘制的线,

给定一组点,可以很容易地基于这些点绘制一条线,例如使用GraphicsPath类

例如,下面的点数组

[0]: (0,0)
[1]: (100,0)
[2]: (0,100)
[3]: (100,100)
…描述了一条类似于Z的线

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

我已经尝试过贝塞尔曲线、曲线和圆弧,其中一些可能适用于解决方案——我自己还没有找到它,因为我必须能够处理以所有角度绘制的线,而不仅仅是水平线或垂直线

Pen
对象的
LineJoin
设置为
Round
是不够的,因为这只适用于较宽的笔


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


解决方案 我将下面的函数放在一起,它返回一条表示带圆角的线的路径。该函数使用一个lengthline函数,可以找到该函数

protectedgraphicsPath GetRoundedLine(点F[]点,浮动半径)
{
GraphicsPath路径=新的GraphicsPath();
PointF previousEndPoint=PointF.Empty;
对于(int i=1;i1)
{
//缩短起点并为除第一条线段外的所有线段添加贝塞尔曲线:
点F角点=起始点;
延长线(端点,参考起点,-转角半径);
点F控制点1=转角点;
点F控制点2=转角点;
延长线(先前端点,参考控制点1,-转角半径/2);
延长线(起点,参考控制点2,-转角半径/2);
AddBezier(上一个端点、控制点1、控制点2、起始点);
}
if(i+1
url描述了如何绘制圆角矩形,这可能有助于您开始

但我认为,如果没有其他东西,你可以在你的道路上增加更多的点,给人一种圆角的错觉。所以在0,0和100,0之间加上几个点。例如:

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


我没有以任何方式测试该路径,只是从空中提取了一些数字:)。

这是我用来绘制圆角矩形的函数。。。 由此可以计算每条线的角度

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

希望这能帮助你学习更难的三角学;)

贝塞尔曲线的实现非常简单:

幸运的是,如果您想省略血淋淋的细节,GraphicsPath类中也包含了它们:

您还可以查看样条曲线:


这可能没有帮助,但如果您可以使用WPF,这将非常容易。在gdi+中也非常容易。当然,您可以用r2之类的变量替换radius*2,使其更清晰+不管怎样:)是的。。。我以前做过,它确实需要一些重构:顺便说一句,Bernhof可能希望使用仅使用2个点的样条曲线(我认为是AddCurve)并利用张力来获得一个精细的半径,而不是AddArc()函数。然后,唯一真正需要计算的是两个点的坐标(x减去两个方向上的垂直线)。正如我在文章中提到的,我已经对这些点进行了研究。我一直在寻找一些更具体的建议,不过还是要谢谢你:)你知道样条曲线和贝塞尔曲线的区别吗?通过正确设置控制点,你可以很容易地让它们顺利连接。是的,我知道区别。在我的例子中,线条必须始终笔直,除了角落。Beziers和curves有一个习惯,就是在一定程度上扭曲/弯曲线条的其余部分,这可能是因为我发现正确设置控制点并不容易。啊,但是你的问题应该很容易解决!直线段使用法线,角点使用贝塞尔曲线。请记住,控制点将与曲线导数的直线相匹配。您可能希望将它们都放在整个矩形的角处。请看这里:这里和这里了解更多信息。这可能给了我继续下去所需的线索。谢谢你的链接,如果我遇到更多麻烦,我会发布一个新问题:)
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