komische Linien beim Zeichnen – woran liegt's?

  • VB.NET
  • .NET (FX) 4.5–4.8

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

    komische Linien beim Zeichnen – woran liegt's?

    Hallo zusammen,

    ich habe mir eine Klasse geschrieben, die mir Punkte auf einer Kugeloberfläche speichert. Wenn ich diese Kugel (erst einmal in 2D) zeichne, will ich alle paar Höhenpixel eine andere Farbe nehmen. Leider läuft das schief. Woran liegt's? Ich habe bereits ausprobiert:
    1.) Step der For loop auf 0.25 -> Programm rattert ewig... Zeichnung wird nicht besser
    2.) Step der For loop auf 0.5 -> Zeichnung ist schlecht wie im angehängten Bild
    3.) Step der For loop auf 1 -> Zeichnung ist (logischerweise) schlechter (mehr Löcher an den Rändern etc).

    Dies ist die Class_HalfSphere.vb


    Spoiler anzeigen

    VB.NET-Quellcode

    1. #Disable Warning IDE1006 ' Benennungsstile
    2. Imports System.Windows.Media.Media3D
    3. Public NotInheritable Class Class_HalfSphere
    4. Public Phi As UInt16 = 0US
    5. Public Theta As UInt16 = 0US
    6. Public ReadOnly Liste_mit_allen_Vektoren As New List(Of Vector3D)
    7. Private ReadOnly Liste_thetas As New List(Of Double)
    8. Private ReadOnly Liste_phis As New List(Of Double)
    9. Public Sub New(ByVal Radius As Double)
    10. For _phi As Double = 0.0 To 359.0 Step 0.5
    11. For _theta As Double = 0.0 To 90.0 Step 0.5
    12. Liste_mit_allen_Vektoren.Add(New Vector3D(
    13. Radius * Math.Cos(_phi * Math.PI / 180.0) * Math.Sin(_theta * Math.PI / 180.0),
    14. Radius * Math.Sin(_phi * Math.PI / 180.0) * Math.Sin(_theta * Math.PI / 180.0),
    15. Radius * Math.Cos(_theta * Math.PI / 180.0))
    16. )
    17. Liste_thetas.Add(_theta)
    18. Liste_phis.Add(_phi)
    19. Next
    20. Next
    21. End Sub
    22. 'Private Function unitV(ByVal par As Double, ByVal xx As Double, ByVal yy As Double, ByVal zz As Double) As Double
    23. ' Return par / Math.Sqrt(Math.Pow(xx, 2.0) + Math.Pow(yy, 2.0) + Math.Pow(zz, 2.0))
    24. 'End Function
    25. Public Function getVector() As Vector3D
    26. Dim Value As Vector3D
    27. For i As Integer = 0 To Liste_mit_allen_Vektoren.Count - 1 Step 1
    28. If Liste_phis(i) = CDbl(Phi) AndAlso Liste_thetas(i) = CDbl(Theta) Then
    29. Value = Liste_mit_allen_Vektoren(i)
    30. Return Value
    31. End If
    32. Next
    33. Return Value
    34. End Function
    35. End Class
    36. #Enable Warning IDE1006 ' Benennungsstile



    und dies die Form1.vb

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Windows.Media.Media3D
    2. Public NotInheritable Class FormMain
    3. Private ReadOnly Deu As New System.Globalization.CultureInfo("de-DE")
    4. Private half_sphere As Class_HalfSphere
    5. Private program_has_finished_loading As Boolean = False
    6. Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    7. Me.BackColor = Color.FromArgb(171, 207, 181)
    8. PictureBox1.BackColor = Color.White
    9. End Sub
    10. Private Sub FormMain_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    11. Select Case e.KeyCode
    12. Case Keys.NumPad8
    13. If half_sphere.Theta > 0US Then
    14. half_sphere.Theta -= 1US
    15. Vektor_finden()
    16. End If
    17. Case Keys.NumPad2
    18. If half_sphere.Theta < 90US Then
    19. half_sphere.Theta += 1US
    20. Vektor_finden()
    21. End If
    22. Case Keys.NumPad4
    23. If half_sphere.Phi < 360US Then
    24. half_sphere.Phi += 1US
    25. Vektor_finden()
    26. End If
    27. If half_sphere.Phi = 360US Then half_sphere.Phi = 0US
    28. Case Keys.NumPad6
    29. If half_sphere.Phi > 0US Then
    30. half_sphere.Phi -= 1US
    31. Vektor_finden()
    32. End If
    33. Case Else
    34. Exit Select
    35. End Select
    36. TextBox_theta.Text = half_sphere.Theta.ToString(Deu).PadLeft(2, "0"c) & " °"
    37. TextBox_phi.Text = half_sphere.Phi.ToString(Deu).PadLeft(2, "0"c) & " °"
    38. End Sub
    39. Private Sub FormMain_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
    40. half_sphere = New Class_HalfSphere(190.0)
    41. program_has_finished_loading = True
    42. End Sub
    43. Private Sub Vektor_finden()
    44. Dim meingefundenerVektor As Vector3D = half_sphere.getVector()
    45. TextBox_x.Text = Math.Round(meingefundenerVektor.X, 3).ToString(Deu)
    46. TextBox_y.Text = Math.Round(meingefundenerVektor.Y, 3).ToString(Deu)
    47. TextBox_z.Text = Math.Round(meingefundenerVektor.Z, 3).ToString(Deu)
    48. End Sub
    49. Private Sub PictureBox1_DoubleClick(sender As Object, e As EventArgs) Handles PictureBox1.DoubleClick
    50. PictureBox1.Invalidate()
    51. End Sub
    52. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    53. If Not program_has_finished_loading Then Return
    54. If e.Graphics Is Nothing Then Return
    55. e.Graphics.TranslateTransform(CSng(PictureBox1.Size.Width / 2.0), CSng(PictureBox1.Size.Height / 2.0))
    56. e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    57. e.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    58. e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
    59. e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
    60. For i As Integer = 0 To half_sphere.Liste_mit_allen_Vektoren.Count - 1 Step 3
    61. If CInt(half_sphere.Liste_mit_allen_Vektoren(i).Z) Mod 30 = 0 Then
    62. Using PenGruen As New Pen(Color.FromArgb(0, 173, 0), 1.0F)
    63. e.Graphics.DrawLine(
    64. PenGruen,
    65. 0.0F,
    66. 0.0F,
    67. CSng(half_sphere.Liste_mit_allen_Vektoren(i).X),
    68. CSng(-half_sphere.Liste_mit_allen_Vektoren(i).Z))
    69. End Using
    70. Else
    71. Using PenBlau As New Pen(Color.FromArgb(0, 204, 255), 1.0F)
    72. e.Graphics.DrawLine(
    73. PenBlau,
    74. 0.0F,
    75. 0.0F,
    76. CSng(half_sphere.Liste_mit_allen_Vektoren(i).X),
    77. CSng(-half_sphere.Liste_mit_allen_Vektoren(i).Z)) 'Negatives Vorzeichen weil y in VB.net nach unten positiv läuft.
    78. End Using
    79. End If
    80. Next
    81. End Sub
    82. End Class



    Viele Grüße
    Bartosz

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()

    Bartosz schrieb:

    ich habe mir eine Klasse geschrieben, die mir Punkte auf einer Kugeloberfläche speichert.
    Alle Punkte? Das sind sehr sehr viele.
    Na ich vermute mal, nur eine bestimmte Anzahl davon.
    Verrätst du uns diese Anzahl?

    Ansonsten sieht mir dein Code so aus, als ob du Linien malst vom Mittelpunkt zu diesen Vektor-Punkten.
    Die Linien werden sich logischerweise gegenseitig übermalen, wenn sie dicht genug beieinander liegen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @Bartosz Momentan malst Du in Kugelkoordinaten (theta und phi), die auf der Oberfläche verschieden dicht liegen.
    Überlege Dir eine Koordinatentransformation, wo Du die Punkte in kartesisdchen Koordinaten setzen kannst (x, y), auf jedes Pixel einen Punkt.
    Dann wird Deine Fläche optimal dicht gezeichnet.
    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!
    @ϕconst Die Zeile habe ich etxra eingefügt, damit alle 30 Höhenpixel eine grüne Linie statt einer blauen gezeichnet wird. Wie man im Bild sieht, klappt das ab der Mitte nicht mehr. Die Linien gehen schräg hoch. Das ist eines der Probleme. Ich wüsste gern, woran das liegt.

    @ErfinderDesRades Beim For-Schleifen-Step von 1 ergibt sich 91 * 360 = 32760. Bei Step 0,5 das vierfache. "Ansonsten sieht mir dein Code so aus, als ob du Linien malst vom Mittelpunkt zu diesen Vektor-Punkten." Richtig.

    @RodFromGermany Ich stelle die Vektoren mithilfe von Kugelkorrdinaten auf, ja, aber ich wandle noch in der Klasse um auf x, y und z und zeichne sie mit x und z ? Was meintest du?

    Bartosz schrieb:

    VB.NET-Quellcode

    1. For _phi As Double = 0.0 To 359.0 Step 0.5
    2. For _theta As Double = 0.0 To 90.0 Step 0.5
    3. ' ...
    Lass diese beiden Schleifen über x und y gehen.
    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!

    ErfinderDesRades schrieb:

    Die Linien werden sich logischerweise gegenseitig übermalen, wenn sie dicht genug beieinander liegen.

    Bartosz schrieb:

    32760
    Das sind in der Tat sehr viele Linien auf kleiner Fläche.
    Die übermalen sich also gegenseitig, und was letztendlich zur Ansicht kommt hängt von der Reihenfolge ab, in der welche Linien zu welchem Punkt hin gemalt werden.
    Extrem unwirtschaftlich, und auch optisch wird kaum etwas bei rauskommen können, was man erwartet (was immer man erwartet).

    Kläre zunächstmal deine Erwartung, was denn zur Ansicht kommen soll.
    Dann überleg dir, welche Punkt-Auswahl dafür geeignet ist, und wie zu zeichnen. Das malen einer Linie vom 0-Punkt zum VektorPunkt finde ich höchst fragwürdig.

    Aber wie gesagt: Kläre zunächstmal deine Erwartung, was denn zur Ansicht kommen soll.
    @ErfinderDesRades Ich möchte eine vollwertige Halbkugel erstellen. Das habe ich auch in der Klasse so programmiert. Ich wollte die Halbkugel gestern nur mal eben schnell zeichnen. Du hast wie gesagt Recht, man braucht nicht alles zeichnen, sondern nur ein paar der vielen Linien, weil man ja in 2D "platt draufguckt". Aber jetzt einfach Graphics.FillArc() nutzen, halte ich für falsch. Ist geschummelt.

    Es funktioniert jetzt

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    2. If Not program_has_finished_loading OrElse e.Graphics Is Nothing Then
    3. Return
    4. End If
    5. e.Graphics.TranslateTransform(CSng(PictureBox1.Size.Width / 2.0), CSng(PictureBox1.Size.Height / 2.0))
    6. e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    7. e.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    8. e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
    9. e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
    10. For i As Integer = 0 To half_sphere.Liste_mit_allen_Vektoren.Count - 1 Step 1
    11. If half_sphere.Liste_phis(i) = 0.0 OrElse half_sphere.Liste_phis(i) = 180.0 Then
    12. Using PenBlau As New Pen(Color.FromArgb(0, 204, 255), 1.0F)
    13. e.Graphics.DrawLine(
    14. PenBlau,
    15. 0.0F,
    16. 0.0F,
    17. CSng(half_sphere.Liste_mit_allen_Vektoren(i).X),
    18. CSng(-half_sphere.Liste_mit_allen_Vektoren(i).Z))
    19. If CInt(half_sphere.Liste_mit_allen_Vektoren(i).Z) Mod 30 = 0 Then
    20. Using PenGruen As New Pen(Color.FromArgb(0, 173, 0), 1.0F)
    21. e.Graphics.DrawLine(
    22. PenGruen,
    23. 0.0F,
    24. CSng(-half_sphere.Liste_mit_allen_Vektoren(i).Z),
    25. CSng(half_sphere.Liste_mit_allen_Vektoren(i).X),
    26. CSng(-half_sphere.Liste_mit_allen_Vektoren(i).Z))
    27. End Using
    28. End If
    29. End Using
    30. End If
    31. Next
    32. End Sub



    mit

    VB.NET-Quellcode

    1. For _phi As Double = 0.0 To 359.0 Step 1.0
    2. For _theta As Double = 0.0 To 90.0 Step 0.125

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()