.NET GDI +: rounded drawing lines

Given an array of points, it is easy to draw a line based on these, for example. using the GraphicsPath class.

For example, the following array of points ...

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

... describes a line similar to Z.

But there is a challenge; I need to draw rounded corners with a radius, for example. 10 pixels. By corners, I mean points in a line that are not starting or ending points. In this case, there are two angles in (0,100)and (100,0).

I played with beziers, curves and arcs, some of which could hold the solution - I just could not find it, since I should be able to process lines drawn at all angles, not just horizontal or vertical lines.

Setting the LineJoinobject Penon is Roundinsufficient, since it is displayed only with wider handles.


Edit: To clarify, I am well aware of the possibilities of the bezier, curve, and arc of the GraphicsPath class. I am looking for more specific recommendations regarding the construction of an algorithm that can take any number of points, and scribble them along with rounded corners.


Decision

I put together the following function, which returns a path representing a line with rounded corners. The function uses the LengthenLine function, which can be found 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
source share
3 answers

, ... .

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

, ;)

+6

url , , .

, , . 0,0 100,0. :

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

I did not test this way in any way, just pulled out some numbers that might work from the air :).

0
source

Source: https://habr.com/ru/post/1724038/


All Articles