Interpolation einer Kurve

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Memo.

    Interpolation einer Kurve

    Hallo,

    ich beschäftige mich seit einger Zeit mit 3-D Landschaften und möchte ein Perlin-Noise generieren ^^
    (Ich suche keinen Code dafür - ich will ihn selber schreiben. Aus Übungszwecken :D )

    Hier tritt das Problem der "Interpolation" auf. Soviel ich verstanden habe ist das das "glätten" einer Kurve.
    Ich orientiere mich derzeit an folgender Seite: freespace.virgin.net/hugo.elias/models/m_perlin.htm (Abschnitt: Cosine Interpolation)

    Hab das ganze kurzerhand in VB umgesetzt (hoffentlich richtig :S )

    VB.NET-Quellcode

    1. Function Interpolate(p1 As PointF, p2 As PointF, x As Integer) As Integer
    2. Dim ft = x * Math.PI
    3. Dim f = (1 - Math.Cos(ft)) / 2
    4. Return p1.Y * (1 - f) + p2.Y * f
    5. End Function


    Ganzer Code (halbings schön dokumentiert ;))
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private values As New List(Of Integer) 'Y-Werte (gleichmäßig verteilt!)
    3. Private original As PointF()
    4. Private r As New Random(Now.Millisecond)
    5. Private Sub btn_seed_Click(sender As System.Object, e As System.EventArgs) Handles btn_seed.Click
    6. '5 zufällige Werte generieren
    7. values.Clear()
    8. For index = 1 To 8
    9. values.Add(r.Next(0, pb_ausgabe.Height))
    10. Next
    11. original = MakePoints() 'Zum Vergleich
    12. 'Punkte darstellen
    13. MakeBitmap()
    14. End Sub
    15. Private Sub btn_interpolate_Click(sender As System.Object, e As System.EventArgs) Handles btn_interpolate.Click
    16. 'Alle Punkte interpolieren
    17. Dim old_points = MakePoints()
    18. Dim new_values As New List(Of Integer)
    19. For index = 0 To values.Count - 2 'Weniger 2, da der letzte Punkt keinen Punkt rechts von ihm hat
    20. Dim currentX = (old_points(index).X + old_points(index + 1).X) / 2 'X-Koordinate für neuen Punkt berechnen
    21. new_values.Add(Interpolate(old_points(index), old_points(index + 1), currentX)) 'Interpolieren und in Liste einfügen
    22. Next
    23. 'Punkte mischen
    24. For index = 0 To values.ToArray.Count - 2
    25. values.Insert(index + 1, new_values(index))
    26. Next
    27. 'Punkte darstellen
    28. MakeBitmap()
    29. End Sub
    30. Private Sub MakeBitmap()
    31. Dim bmp As New Bitmap(pb_ausgabe.Width, pb_ausgabe.Height) 'Bitmap zum anzeigen
    32. 'Punkte generieren
    33. Dim points = MakePoints()
    34. 'Punkte zeichnen
    35. Using g = Graphics.FromImage(bmp)
    36. g.Clear(Color.White)
    37. g.DrawCurve(Pens.Red, original)
    38. g.DrawLines(Pens.Blue, points)
    39. End Using
    40. 'Anzeigen
    41. pb_ausgabe.Image = bmp
    42. End Sub
    43. Function MakePoints() As PointF()
    44. Dim points As New List(Of PointF)
    45. Dim f = pb_ausgabe.Width / values.Count 'Abstand zwischen einzelnen Punkten
    46. Dim x_val As Single = 0 'Aktuelle X-Position
    47. For Each y_val In values
    48. points.Add(New PointF(x_val, y_val))
    49. x_val += f
    50. Next
    51. Return points.ToArray()
    52. End Function
    53. Function Interpolate(p1 As PointF, p2 As PointF, x As Integer) As Integer
    54. Dim ft = x * Math.PI
    55. Dim f = (1 - Math.Cos(ft)) / 2
    56. Return p1.Y * (1 - f) + p2.Y * f
    57. End Function
    58. End Class


    Screenshots: (blau: meine Berechnung) (rot: DrawCurve)



    Liegt der Fehler jetzt in der Berechnung oder an mir? 8|
    Die geglättete rote Kurve ist ja wohl bei beiden gleich, da hast Du wohl einfach den Befehl Neu Berechnen vergessen aufzurufen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Memo schrieb:

    Die blaue Kurve soll sich der roten annähern
    Was soll eigentlich passieren?
    Du gibst eine blaue Kurve als Punktwolke vor und suchst eine rote glatte gefittete Kurve
    oder
    Du hast eine rote glatte Kurve und suchst sinnvolle (äquidistante) Stützstellen, um sie mit wenigen Punkten zu approximieren?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So wie Du das geschrieben hast macht das keinen Sinn. :S
    - blaue Punktwolke vorgeben
    - Die blaue soll sich der roten annähern
    Dann wäre ja die rote Kurve eine zufällige oder eine göttliche Kurve (zunächst) ohne Bezug zur blauen Kurve. ?(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    OK.
    Was soll denn "Interpolate" genau machen?
    Kannst Du das mal bitte verbal beschreiben?
    Und gib Deinem Code Option Strict On.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich weiß, was Interpolation ist. Du sollst Dein Problem selbst beschreiben, damit Du es auch verstehst.
    Ersetz mal Deinen Code-Snippet in der btn_interpolate_Click durch diesen hier:

    VB.NET-Quellcode

    1. 'Punkte mischen
    2. For index As Integer = 0 To values.ToArray.Length - 2
    3. values.Insert(2 * index + 1, new_values(index))
    4. Next
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!