Pergunta

Dada uma matriz de pontos, é fácil de desenhar uma linha com base nestes, por exemplo, usando a classe GraphicsPath.

Por exemplo, a seguinte matriz de pontos ...

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

... descreve uma linha que se assemelha a um Z.

Mas aqui vem o desafio; I necessário desenhar os cantos arredondados com um raio de, por exemplo 10 pixels. Por cantos quero dizer os pontos na linha que não são iniciar ou pontos finais. Neste caso existem dois cantos em (0,100) e (100,0).

Eu tenho jogado ao redor com Beziers, curvas e arcos, alguns dos quais podem ter a solução - eu simplesmente não têm sido capazes de encontrá-lo eu mesmo, no entanto, desde que eu tenho que ser capaz de lidar com linhas desenhadas em todos os ângulos, não apenas linhas horizontais ou verticais.

Como definir a LineJoin do objeto Pen para Round não é suficiente, uma vez que isso só mostra com canetas mais amplas.


Editar: Para esclarecer, eu estou bem ciente dos bezier, curva e arco capacidades da classe GraphicsPath. Estou à procura de alguns conselhos mais específicos em relação à construção do algoritmo que pode tomar qualquer número de pontos, e reuni-los com cantos arredondados.


Solução

eu uni a função seguinte que retorna um caminho que representa a linha, com os cantos arredondados. A função faz uso de uma função LengthenLine, que pode ser encontrada aqui .

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

Solução

curvas de Bezier são bastante simples de implementar:

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

Felizmente, você também tê-los como parte da classe GraphicsPath Se você quer omitir os detalhes:

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

E você também pode olhar para as estrias:

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

Outras dicas

Esta é a função que eu uso para desenhar um retângulo com cantos arredondados ... A partir desta você pode calcular o ângulo de cada linha.

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 isso ajuda você na parte mais difícil da trigonometria;)

Esta url tem uma descrição de como desenhar retângulos arredondados que podem ajudá-lo começar.

Mas eu acho que, se nada mais que você seria capaz de adicionar mais pontos ao seu caminho, para dar a ilusão de cantos arredondados. Então adicionar em vários pontos entre 0,0 e 100,0. Um exemplo poderia ser:

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

Eu não testei esse caminho de qualquer forma, apenas puxou alguns números que podem funcionar fora do ar:.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top