Geraden Strich zeichnen

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Geraden Strich zeichnen

    Hallo Com,

    ich habe auf meiner Form eine Picturebox in die man schon ganz normal zeichnen kann.Nun will ich das wenn in der CheckBox "Gerade" aktiviert wurde das der User nur einen geraden Strich zeichnen kann wie in Windows Paint.Wie geht das ?


    Regardz,

    iEi
    Hi
    Teile dir einfach den Winkel in 4-tel oder 8-tel ein, jenachdem, ob du diagonalen auch zulassen willst. Anschließend ermittelst du über arc cos und arc sin bzw. arc tan die Winkel relativ zum Ursprung, dividierst diese durch 4 bzw. 8, rundest, multiplizierst wieder mit 4 bzw. 8 und bildest anschließend wieder Sinus und Cosinus davon (hübsch unperformant btw., einfache If-Abfrage über Steigungsdreieck wäre schöner). Um arc cos und arc sin anwenden zu können, musst du übrigens quasi (P - U) / |P - U| berechnen, wobei P die Position der Maus ist und U die ursprüngliche Position der Maus. |P - U| ist die Länge des Verbindungsvektors zwischen P und U. Beachte, dass P = U unzulässig ist bzw. einen Sonderfall darstellen sollte.

    Gruß
    ~blaze~
    Vektoren kannst du dir so vorstellen, dass du den Raum in (in deinem Fall 2) Dimensionen aufteilst. So ist in deinem Fall die x-Achse (1, 0) und die y-Achse (0, 1). Ein allgemeiner Vektor hat somit folgende Darstellung: x * (1, 0) + y * (0, 1) = (x, y).
    Die Länge eines Vektors erhältst du über den Pythagoras:
    |(x, y)| = sqrt(x * x + y * y), wobei sqrt die Quadratwurzel ist.
    Beachte übrigens, dass man Vektoren meist in einer Spalte untereinander darstellt, also quasi

    Quellcode

    1. / x \
    2. ( )
    3. \ y /

    Es besteht übrigens ein Unterschied zwischen Punkten und Vektoren. Das darfst du aber gerne auch nachschauen, wenn's dich interessiert.
    Außerdem gilt noch, dass
    cos(alpha) = dot(a, b) / (|a|*|b|)
    mit a, b 2-dim. Vektoren (also in R^2), dot(a, b) = a1*b1+a2*b2 und alpha der Winkel zwischen a und b. Du musst aber aufpassen, der Cosinus ist punkt-symmetrisch zum Ursprung und keine bijektive Abbildung, was so viel heißt, wie, dass du aus gegebenem b in cos(a) = b nicht auf ein eindeutiges a schließen kannst, wenn a in [0, 2pi).
    Der Sinus würde sich übrigens aus dem Cosinus ergeben (Betrag des Kreuzproduktes ginge auch, ist aber Overkill, denk' ich), da eben gilt, dass (cos a)² + (sin a)² = 1, bzw. cos(a + 90°) = sin(a)

    Gruß
    ~blaze~
    Danke dir blaze nur leider bringt mich das nicht wirklich weiter.

    Nur kann man das im Picturebox1_MouseUp Event machen,so hab ich es für ein Rechteck gemacht:

    VB.NET-Quellcode

    1. If RectangleRadioButton.Checked Then
    2. endLocation = e.Location
    3. Dim s As Point
    4. s.X = endLocation.X - startLocation.X
    5. If s.X < 0 Then
    6. startLocation.X = endLocation.X
    7. End If
    8. s.Y = endLocation.Y - startLocation.Y
    9. If s.Y < 0 Then
    10. startLocation.Y = endLocation.Y
    11. End If
    12. s.X = Math.Abs(s.X)
    13. s.Y = Math.Abs(s.Y)
    14. g.DrawRectangle(PenPoint, New Rectangle(startLocation, s))
    15. End If
    @iEi: Schwebt Dir vor, einen geraden Strich wie bei Paint zu malen, also MouseDown als Startpunkt und MouseMove als Endpunkt und bei MouseUp wird der Endpunkt fixiert, also Startpunkt merken, bei MouseMove die aktuellen Koordinaten merken, das Bild invalidisieren und im Paint-Event als letztes (nach dem anderen allen) eine Linie vom Startpunkt zum aktuellen Punkt malen.
    Bei MouseUp Startpunkt und Endpunkt in die Liste der zu malenden Geraden aufnehmen (zu all dem anderen).
    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!
    Naja, hab' ich dir doch beschrieben. Erst hältst du den Ursprung (in MouseDown) in einer Variablen fest, z.B.

    VB.NET-Quellcode

    1. Private _origin As Point
    2. Private Sub _drawingSurface_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles _drawingSurface.MouseDown
    3. If (e.Buttons And MouseButtons.Left) = MouseButtons.Left Then
    4. _origin = e.Location
    5. End If
    6. End Sub
    7. Private Sub _drawingSurface_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles _drawingSurface.MouseUp
    8. If (e.Buttons And MouseButtons.Left) = MouseButtons.Left Then
    9. Dim offset As Size = New Size(e.X - _origin.X, e.Y - _origin.Y)
    10. 'jetz haste den Abstands"vektor" offset (vllt. schreibst du dir dafür noch eine extra Klasse?) und kannst die restlichen Operationen durchführen
    11. End If
    12. End Sub

    Damit du auch was machst, darfst das jetzt du machen ;). Mach's ggf. auch einfach mal mit einer Skizze und zeichne dir die Winkel ein, wenn du's dir nicht vorstellen kannst.

    Hm, "gerade" Linie kann ist ambig, insofern könnt's ja auch sein, dass das gar nicht so gemeint war. Ggf. reicht es auch einfach die beiden Punkte festzuhalten und in einer extra Klasse dann die Linie über DrawLine(pen, _origin, _destiniation) zu zeichnen. Ich hatte bei meinen obigen Formulierungen gedacht, dass es eine Strecke sein soll, die nur 90°-Winkel oder 45°-Winkel zulässt.
    Btw.: es ist eine Strecke.

    Gruß
    ~blaze~

    jocutus schrieb:

    Das geht doch - oder?
    Klar, MouseDown, MouseMove, MouseUp und Paint.
    2 Point-Variablen, Start und End, ein Flag, dass überhaupt gezeichnet werden soll. Den FRest bekommst Du allein raus. :D
    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 war etwas irritiert über die vielen Berechnungen, deshalb meine Nachfrage.
    Denn beim Drucken gehts ja auch mit 'Startpunkt' bis 'Endpunkt'.
    Das Leben ist nicht so kompliziert. Eine süsse Erinnerung tut's.
    Indiana Jocutus - Jäger des Variablen-Schatzes

    jocutus schrieb:

    Denn beim Drucken gehts ja auch mit 'Startpunkt' bis 'Endpunkt'.
    Ja, nur dass während des MouseMove dieser Endpunkt variabel ist und permanent verändert werden kann. Beim Drucken steht er fest.
    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!