Pregunta

Dado un conjunto de puntos, es fácil dibujar una línea basada en estos, por ejemplo. utilizando la clase GraphicsPath.

Por ejemplo, la siguiente matriz de puntos ...

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

... describe una línea que se parece a una Z.

Pero aquí viene el desafío; Necesito dibujar esquinas redondeadas con un radio de, por ejemplo. 10 píxeles. Por esquinas me refiero a los puntos en la línea que no son puntos de inicio o final. En este caso, hay dos esquinas en (0,100) y (100,0) .

He jugado un poco con beziers, curvas y arcos, algunos de los cuales podrían contener la solución. Aún no he podido encontrarla, ya que tengo que ser capaz de manejar líneas dibujadas en todos los ángulos. no solo líneas horizontales o verticales.

Establecer el LineJoin del objeto Pen en Round no es suficiente, ya que esto solo se muestra con plumas más amplias.


Editar: Para aclarar, soy consciente de las capacidades de curva, curva y arco de la clase GraphicsPath. Estoy buscando algunos consejos más específicos con respecto a la construcción del algoritmo que puede tomar cualquier número de puntos, y encadenarlos con esquinas redondeadas.


Solución

Reuní la siguiente función que devuelve una ruta que representa la línea con esquinas redondeadas. La función utiliza una función LengthenLine, que se puede encontrar en aquí .

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;
}
¿Fue útil?

Solución

Las curvas de Bezier son bastante sencillas de implementar:

http://www.codeproject.com/KB/recipes/BezirCurves.aspx

Afortunadamente, también los tienes como parte de la clase GraphicsPath si quieres omitir los detalles sangrientos:

http://msdn.microsoft .com / en-us / library / system.drawing.drawing2d.graphicspath.addbezier.aspx

Y también puedes mirar en splines:

http://msdn.microsoft .com / en-us / library / system.drawing.drawing2d.graphicspath.addcurve.aspx

Otros consejos

Esta es la función que uso para dibujar un rectángulo con esquinas redondeadas ... a partir de esto puedes calcular el ángulo de cada línea.

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

Espero que esto te ayude en la parte más difícil de la trigonometría;)

Esta url tiene una descripción de cómo dibujar rectángulos redondeados que podrían ayudarte empezar.

Pero creo que si nada más pudieras agregar más puntos a tu camino, para dar la ilusión de esquinas redondeadas. Así que sume varios puntos entre 0,0 y 100,0. Un ejemplo podría ser:

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

No he probado ese camino de ninguna manera, solo saqué algunos números que podrían salir del aire :).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top