Entwickler-Ecke

Andere .NET-Sprachen - VB.net MandelBrotMenge


LINUS19 - So 15.04.18 01:33
Titel: VB.net MandelBrotMenge
Hallo,
ich wollte in VB.net die MandelBrotMenge zeichnen, nur wird nichts gezeichnet. Die Formel zur Überprüfung ob der Punkt in der MandelBrotMenge liegt müsste eigentlich stimmen.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
Public Class Form1

    Private formGraphics As System.Drawing.Graphics

    Private Property P_Position As Point = New Point(0, 0)
    Private Property P_Color As Color = Color.Black


    Public Sub New()
        ' Dieser Aufruf ist für den Designer erforderlich.
        InitializeComponent()
        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
        formGraphics = Me.CreateGraphics()
    End Sub


    ''' <summary>
    ''' Zeichne einen Punkt an der aktuelle Koordinate
    ''' </summary>
    ''' <param name="trans_x">X-Koordinate</param>
    ''' <param name="trans_y">Y-Koordinate</param>
    ''' <remarks></remarks>

    Private Sub SU_DrawPoint(trans_x As Double, trans_y As Double, P_Color As Color)
        Dim P_Pen = New Pen(Color.White)
        P_Pen.Color = P_Color
        formGraphics.DrawRectangle(P_Pen, New Rectangle(P_Position, New Size(1, 1)))
    End Sub

    Private Sub Button_Draw_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Dim Loc_Ergebnis As Integer = 0
        Dim Breite As Double
        Dim Hoehe As Double
        Dim x As Integer
        Dim y As Integer
        Dim Iterationen As Integer

        For Breite = -2 To 2 Step 0.005 '' 4/800

            For Hoehe = -1 To 1 Step 0.005  '' 2/400

                x = (Breite + 2) * 400
                y = (1 - Hoehe) * 200

                Loc_Ergebnis = inMandelBrotMenge(Breite, Hoehe, Iterationen)

                If (Iterationen <= 50) Then
                    SU_DrawPoint(x, y, Color.Green)
                End If

                If (Loc_Ergebnis = 1) Then

                    SU_DrawPoint(x, y, Color.Black)
                End If

            Next
        Next
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="x_pos"> x-Koordinate Punkt</param>
    ''' <param name="y_pos"> y-Koordinate Punkt </param>
    Private Function inMandelBrotMenge(x_pos As Double, y_pos As Double, ByRef Iterationen As Integer) As Integer

        Dim c As Double = 0
        Dim x As Double = 0
        Dim y As Double = 0
        Dim xn As Double
        Dim yn As Double

        Dim i As Integer = 0

        For i = 0 To 20 '' 20 Iterationen für jeden Punkt

            xn = x * x - y * y + x_pos
            yn = 2 * x * y + y_pos
            c = Math.Sqrt((xn * xn + yn * yn))

            x = xn
            y = yn

            If (c > 2) Then
                Return 0 '' nicht in MandelBrot
            End If

            If (c < 2) Then
                Return 1 '' in MandelBrot
            End If

        Next
    End Function

End Class


Delete - So 15.04.18 06:33

- Nachträglich durch die Entwickler-Ecke gelöscht -


Ralf Jansen - So 15.04.18 13:39

Den Code zum zeichnen solltest du auch in den Paint Event verschieben beziehungsweise, da du scheinbar direkt auf die Form zeichnest, die OnPaint Methode überschreiben. Windows kann deine Form zu beliebigen Zeitpunkten neu zeichnen. Dann wird OnPaint/Paint aufgerufen und nicht dein Code wodurch du einfach das Standard-Aussehen der Form gekommen würdest. Also Code verschieben. In Paint/OnPaint dann das vorhandene Graphics Object das du über die Parameter bekommst benutzen und kein neues erzeugen wie jetzt und dieses dann zum zeichnen benutzen. Dort wo du gerade zeichnest (Button_Draw_Click) solltest du nur Invalidate() aufrufen das das dann ein neuzeichnen anfordert wodurch die Paint/OnPaint Logik dann durchlaufen wird.


Th69 - So 15.04.18 13:57

Mein Standard-Link dazu: [Tutorial] Zeichnen in Windows-Forms-Programmen (Paint/OnPaint, PictureBox) [http://www.mycsharp.de/wbb2/thread.php?threadid=21782]


LINUS19 - Mo 16.04.18 17:39

Hallo,
ich habe jetzt noch ein paar Sachen verändert aber das Zeichnen funktioniert immer noch nicht und das Programm beendet sich mit:Das Programm "[10256] MandelBrotMenge.exe" wurde mit Code 0 (0x0) beendet.


user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
G
Die Variablen Hoehe und Breite haben bis dato keine Werte, auch wenn du es hier als Kommentar stehen hast.
Deine Methoden sind auf Englisch und die Variablen sind auf Deutsch. Du sollest dich für eins entscheiden



Was meinst du mit keine Werte? ich durchlaufe damit doch das Koordinatensystem und wandel es dann in das Fenster Koordinatensystem um. Die Variablen Namen sind gemischt, weil sie auf Englisch so vorgegebn waren.

Hier nochmal der veränderte Code: Hat noch wer einen Tipp wo noch Fehler sind?


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
Public Class Form1
    Private paintThread As System.Threading.Thread
    Private formGraphics As System.Drawing.Graphics
    Private run As Boolean = True

    Private Property P_Color As Color
    Private Property P_Pen As Pen

    Public Sub New()
        ' Dieser Aufruf ist für den Designer erforderlich.
        InitializeComponent()
        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
        formGraphics = Me.CreateGraphics()
    End Sub


    ''' <summary>
    ''' Zeichne einen Punkt an der angegebenen Koordinat
    ''' und mit der angegebenen Farbe
    ''' </summary>
    ''' <param name="trans_x">X-Koordinate</param>
    ''' <param name="trans_y">Y-Koordinate</param>
    ''' <remarks></remarks>

    Private Sub SU_DrawPointAt(trans_x As Integer, trans_y As Integer, P_Color As Color)
        Try
            Dim Loc_DrawToPoint As Point = New Point(trans_x, trans_y)
            P_Pen = New Pen(Color.White)
            P_Pen.Color = P_Color
            formGraphics.DrawRectangle(P_Pen, New Rectangle(Loc_DrawToPoint, New Size(1, 1)))
        Catch ex As Exception
        End Try

    End Sub

    Private Sub Button_Draw_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        MsgBox("Test")
        If paintThread Is Nothing Then paintThread = New Threading.Thread(AddressOf Draw)
        Try
            paintThread.Start()
        Catch ewe As Exception

        End Try

    End Sub
    ''' <summary>
    ''' Zeichne MandelBrotMenge
    ''' </summary>
    Private Sub Draw()
        If Me.InvokeRequired = True Then
            Me.EndInvoke(Me.BeginInvoke(New Action(AddressOf Draw)))
        Else
            Try
                Dim Loc_Ergebnis As Integer = 0

                Dim Breite As Double
                Dim Hoehe As Double
                Dim x As Integer
                Dim y As Integer
                Dim it As Integer = 0
                Dim counter As Integer = 0

                For Breite = -2 To 2 Step 0.005 '' 4/400
                    counter += 1
                    x = (2 + Breite) * 200
                    For Hoehe = -1 To 1 Step 0.005  '' 2/200
                        Loc_Ergebnis = inMandelBrotMenge(Breite, Hoehe, it)
                        y = (1 - Hoehe) * 200

                        If (Loc_Ergebnis = 1) Then
                            MsgBox("Test")
                            SU_DrawPointAt(x, y, Color.Black)

                        Else
                            If it <= 50 Then
                                SU_DrawPointAt(x, y, Color.Red)
                            Else
                                SU_DrawPointAt(x, y, Color.LimeGreen)
                            End If
                        End If

                        If (counter Mod 3 = 0) Then
                            Application.DoEvents()
                        End If

                        If run = False Then Exit For
                    Next
                    If run = False Then Exit For
                Next
            Catch ex As Exception

            End Try
        End If

    End Sub


Ralf Jansen - Mo 16.04.18 17:58

Du solltest a.) erstmal den Thread ausbauen und schauen was dann passiert. Das ganze GDI Graphics Subsystem ist nicht threadsicher.
Eigentlich gilt das gleich fürs gesamte Winforms. Zeichnen solltest du nur im Hauptthread. Alles andere, solange es nichts mit dem Anzeigen zu tun hat, kannst du in Thread auslagern.

Ansonsten solltest du deinen Code auch debuggen. Da solltest du näher an die Stelle mit dem Problem kommen als das dein Programm nur abschmiert.


Delete - Di 17.04.18 02:25

- Nachträglich durch die Entwickler-Ecke gelöscht -


LINUS19 - Di 17.04.18 16:19

Danke, jetzt funktioniert es. Es zeichnet nur sehr langsam was wahrscheinlich auch dadran liegt das ich es nicht in einem Thread ausgelagert habe. In Java dauert es nur eine Sekunde die MandelBrot Menge mit gleich vielen Iterationen zu erstellen.


Th69 - Di 17.04.18 17:33

Hast du etwa noch Application.DoEvents() in deiner Berechnung drin? Ansonsten zeige noch mal deine Berechnungsmethode.

Und das Auslagern in einen Thread ist hier nicht nötig.


LINUS19 - Di 17.04.18 19:34

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Hast du etwa noch Application.DoEvents() in deiner Berechnung drin? Ansonsten zeige noch mal deine Berechnungsmethode.


Ja, Application.DoEvents() ist noch drin.
Die Berechnung ob der Punkt in der MandelBrot Menge liegt habe ich nicht verändert.


Th69 - Mi 18.04.18 09:18

Ja und, warum? Wenn du dies entfernst, sollte die Methode schnell genug (ein paar Millisekunden) durchlaufen, um das Bild zu erzeugen (dann brauchst du auch keine Abfrage auf das Beenden der Berechnung).

Und wenn du SU_DrawPoint noch ein wenig optimierst, dann erst recht.
Benutze

VB.Net
1:
Dim P_Pen = Pens.White;                    

(s.a. mein Beitrag ("PS") in Mehrere erstellte Images flackern teilweise [https://www.entwickler-ecke.de/viewtopic.php?p=711938#711938] - jetzt schon ein 2. mal verlinkt ;- )

Und ist es Absicht, daß du nur ein 2-Farben Bild erzeugst (und keinen Verlauf)?

PS: Deine Methode inMandelBrotMenge ist auch eigenartig (beachte die Schleife und die beiden return-Anweisungen innerhalb).


LINUS19 - Fr 20.04.18 13:14

Hallo,
Applikation doEvents hatte ich nur drin damit, sich das Fenster noch verschieben lässt. Jetzt wo ich es rausgenommen habe läuft es deutlich schneller.

Die Funktion inManfelBrot habe ich auch noch Mal überarbeitet.