.NET GDI +: рисование линий со скругленными углами - PullRequest
3 голосов
/ 26 ноября 2009

Учитывая массив точек, на их основе легко нарисовать линию, например, используя класс GraphicsPath.

Например, следующий массив точек ...

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

... описывает линию, которая напоминает Z.

Но здесь возникает проблема; Мне нужно нарисовать закругленные углы с радиусом, например 10 пикселей. Под углами я подразумеваю точки на линии, которые не являются начальными или конечными точками. В этом случае есть два угла на (0,100) и (100,0).

Я поиграл с Безье, кривыми и дугами, некоторые из которых могли бы содержать решение - я просто пока не смог найти его сам, так как я должен уметь обрабатывать линии, нарисованные во всех углах, не только горизонтальные или вертикальные линии.

Установка LineJoin объекта Pen на Round недостаточна, поскольку это отображается только с более широкими ручками.


Редактировать: Чтобы прояснить, я хорошо знаю о возможностях Безье, кривой и дуги класса GraphicsPath. Я ищу более конкретный совет относительно построения алгоритма, который может взять любое количество точек и связать их вместе с закругленными углами.


Решение

Я собрал следующую функцию, которая возвращает путь, представляющий линию с закругленными углами. Функция использует функцию LengthenLine, которую можно найти здесь .

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 ]

6 голосов
/ 27 ноября 2009

Это функция, которую я использую, чтобы нарисовать прямоугольник с закругленными углами ... Исходя из этого, вы можете рассчитать угол каждой линии.

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

Надеюсь, это поможет вам в сложной части тригонометрии;)

2 голосов
/ 27 ноября 2009

Кривые Безье довольно просты в реализации:

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

0 голосов
/ 27 ноября 2009

Этот URL содержит описание того, как рисовать скругленные прямоугольники, которые могут помочь вам начать.

Но я бы подумал, что если бы вы не смогли добавить больше точек на ваш путь, чтобы создать иллюзию закругленных углов. Поэтому добавьте в несколько точек от 0,0 до 100,0. Примером может быть:

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

Я никоим образом не проверял этот путь, просто вытащил несколько цифр, которые могут сработать:).

...