Domanda

Data una serie di punti, è facile tracciare una linea basata su questi, ad es. usando la classe GraphicsPath.

Ad esempio, la seguente matrice di punti ...

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

... descrive una linea che ricorda una Z.

Ma ecco che arriva la sfida; Devo disegnare angoli arrotondati con un raggio di es. 10 pixel. Per angoli intendo i punti nella linea che non sono punti di inizio o di fine. In questo caso ci sono due angoli in (0,100) e (100,0) .

Ho giocato con bezier, curve e archi, alcuni dei quali potrebbero contenere la soluzione: non sono ancora riuscito a trovarlo da solo, poiché devo essere in grado di gestire le linee tracciate in tutti gli angoli, non solo linee orizzontali o verticali.

L'impostazione del LineJoin dell'oggetto Pen su Round non è sufficiente, dal momento che viene mostrato solo con penne più larghe.


Modifica: Per chiarire, sono ben consapevole delle capacità di bezier, curve e arco della classe GraphicsPath. Sto cercando qualche consiglio più specifico riguardo alla costruzione dell'algoritmo che può prendere un numero qualsiasi di punti e metterli insieme con angoli arrotondati.


Soluzione

Metto insieme la seguente funzione che restituisce un percorso che rappresenta la linea con angoli arrotondati. La funzione utilizza una funzione LengthenLine, che può essere trovata qui .

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;
}
È stato utile?

Soluzione

Le curve di Bezier sono piuttosto semplici da implementare:

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

Fortunatamente li hai anche come parte della classe GraphicsPath se vuoi omettere i dettagli cruenti:

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

E puoi anche esaminare le spline:

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

Altri suggerimenti

Questa è la funzione che utilizzo per disegnare un rettangolo con angoli arrotondati ... da questo puoi calcolare l'angolo di ogni linea.

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

Spero che questo ti aiuti nella parte più difficile della trigonometria;)

Questo URL ha una descrizione di come disegnare rettangoli arrotondati che potrebbero aiutarti iniziare.

Ma penso che se non altro potessi aggiungere più punti al tuo percorso, per dare l'illusione di angoli arrotondati. Quindi aggiungi diversi punti tra 0,0 e 100,0. Un esempio potrebbe essere:

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

Non ho testato quel percorso in alcun modo, ho solo tirato fuori alcuni numeri che potrebbero funzionare dal nulla :).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top