Announcement

Collapse
No announcement yet.

Einen Pfeil in Canvas zeichnen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Einen Pfeil in Canvas zeichnen

    Hallo zusammen,<br>
    Ich möchte einen Makierungspfeil in TCanvas zeichnen wobei die Spitze x1,x2 von MouseDown ist. Meine Idee war folgende <br>
    <PRE>
    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    x1:=x;
    y1:=y;
    end;

    procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    With Form1 do
    begin
    // Zeichne die Spitze
    Canvas.Brush.Color := clTeal;
    Canvas.Polygon([Point(x1,y1),Point(?,?),Point(?,?)]);
    <b>// Wie ist die berechnung von ?</b>
    // Dann eine Linie von der Spitze bis MouseUp
    Canvas.MoveTo(x1,y1);
    Canvas.LineTo(x,y);
    end;
    end;
    </pre><br>
    Hat jemand eine Idee ?

  • #2
    <pre>

    <code><font size=2 face="Courier New">Du nimmst ein TForm mit einer TPaintBox1
    <br>
    <b>var
    </b>S,E: TPoint;
    <br>
    <b>procedure </b>TForm3.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    <b>const
    </b>PfeilLength = <font color="#0000FF">40</font>; <font color="#008080"><i>// Länge des Pfeiles in Pixel
    </i></font>PfeilWinkel = <font color="#0000FF">90</font>; <font color="#008080"><i>// der Pfeil ist im Winkel von 90 Grad spitz
    </i></font><b>var
    </b>Alpha,SinAlpha,CosAlpha: Double;
    C,A,B: Double;
    P1,P2: TPoint;
    <b>begin
    with </b>PaintBox1, Canvas <b>do
    begin
    </b><font color="#008080"><i>// lösche vorhergehende zeichnung
    </i></font>Pen.Color := Color;
    MoveTo(S.X, S.Y);
    LineTo(E.X, E.Y);
    Brush.Color := Color;
    FillRect(Bounds(S.X -<font color="#0000FF">50</font>, S.Y - <font color="#0000FF">50</font>, <font color="#0000FF">100</font>, <font color="#0000FF">100</font>));
    <br>
    <font color="#008080"><i>// S = Startpunkt, E = Endpunkt der Linie
    </i></font>S := Point(Width <b>shr </b><font color="#0000FF">1</font>, Height <b>shr </b><font color="#0000FF">1</font>);
    E := Point(X, Y);
    <b>if </b>(S.X = E.X) <b>and </b>(S.Y = E.Y) <b>then </b>Exit; <font color="#008080"><i>// wichtig, ansonsten Division durch Null
    <br>
    // zeichne weiße Linie
    </i></font>Pen.Color := clWhite;
    MoveTo(S.X, S.Y);
    LineTo(E.X, E.Y);
    <br>
    <font color="#008080"><i>// berechne A,B,C die Strecken eines rechtwinkligen Dreieckes C = Hypotenuse
    </i></font>A := S.X - E.X;
    B := S.Y - E.Y;
    C := Sqrt(A * A + B * B); <font color="#008080"><i>// c² = (a² + b²)^0.5
    <br>
    // wende Strahlensatz an
    </i></font>A := A * PfeilLength / C;
    B := B * PfeilLength / C;
    <br>
    <font color="#008080"><i>// Zeige den Punkt A,B
    </i></font>Pixels[Round(S.X - A), Round(S.Y - B)] := clRed;
    <br>
    <font color="#008080"><i>// berechne 1. linken Punkt des Pfeiles, er ist im Winkel von -PfeilWinkel / 2
    // Grad vom Punkt (A,B) versetzt, wir nutzen eine Koordinaten-Rotation um S
    </i></font>Alpha := -PfeilWinkel * PI / <font color="#0000FF">360</font>;
    SinAlpha := Sin(Alpha);
    CosAlpha := Cos(Alpha);
    <br>
    P1.X := Trunc(S.X - (CosAlpha * A - SinAlpha * B) + <font color="#0000FF">0.5</font>);
    P1.Y := Trunc(S.Y - (SinAlpha * A + CosAlpha * B) + <font color="#0000FF">0.5</font>);
    <br>
    <font color="#008080"><i>// berechne 2. rechten Punkt des Pfeiles
    </i></font>Alpha := +PfeilWinkel * PI / <font color="#0000FF">360</font>;
    SinAlpha := Sin(Alpha);
    CosAlpha := Cos(Alpha);
    <br>
    P2.X := Trunc(S.X - (CosAlpha * A - SinAlpha * B) + <font color="#0000FF">0.5</font>);
    P2.Y := Trunc(S.Y - (SinAlpha * A + CosAlpha * B) + <font color="#0000FF">0.5</font>);
    <br>
    <font color="#008080"><i>// zeichne einen Kreisausschnitt
    </i></font>Brush.Color := clBlue;
    Pie(S.X - PfeilLength, S.Y - PfeilLength, S.X + PfeilLength, S.Y + PfeilLength,
    P2.X, P2.Y, P1.X, P1.Y);
    <br>
    <font color="#008080"><i>// zeichne Polygon
    </i></font>Brush.Color := clRed;
    Polygon([S, P1, P2]);
    <b>end</b>;
    <b>end</b>;
    <br>
    Gruß Hagen
    </font>
    </code></pre&gt

    Comment


    • #3
      Die Punkte S,E sollten natürlich Felder des TForms sein, ich habe sie nur hier als global definiert damit Du den Quelltext direkt nutzen kannst. Da wir PaintBox1.OnMouseMove() nutzen wird die weiße Linie von der Mitte der PaintBox zum Mausezeiger gezeichnet und diesem bei Bewegung folgen. Im Mittelpunkt der Paintbox wird nun der Pfeil gezeichnet. Im obigen Code ist die Spitze 90 Grad spitz und er hat eine Länge von 40 Pixeln. Gezeichnet werden zwei Versionen, einmal in Blau das Polygon = rechtwinkliges Dreieck und in Rot ein Kreisausschnitt.<br>

      Die Mathematik ist recht simpel aufgebaut. Zuerst ermitteln wir per Strahlensatz den Punkt auf der Linie der 40 Pixel vom Start, also Mitte der PaintBox, entfernt ist. Dieser Punkt (A,B) relativ zu S wird als roter Pixel gezeichnet. Dann rotieren wir diesen Punkt um S, jeweils um -45 Grad nach links und +45 Grad nach rechts. Somit haben wir unsere Endpunkte des Pfeiles berechnet.<br>

      Es gibt noch einfachere bzw. optimiertere Wege, deren Mathematik ist aber nicht so einfach zu verstehen.<br>

      Gruß Hage

      Comment


      • #4
        <pre>

        <code><font size=2 face="Courier New">Hier noch ein Source der an beiden Enden der Linie einen Pfeil zeichnet.
        <br>
        Gruß Hagen
        <br>
        <br>
        <b>procedure </b>PfeilLinie(Canvas: TCanvas; S,E: TPoint; PfeilLength: Integer; PfeilAngle: Double);
        <br>
        <b>procedure </b>Pfeil(Canvas: TCanvas; S, E: TPoint; Length: Integer; Angle: Double);
        <b>var
        </b>Alpha,SinAlpha,CosAlpha: Double;
        C,A,B: Double;
        P1,P2: TPoint;
        <b>begin
        </b><font color="#008080"><i>// berechne A,B,C die Strecken eines rechtwinkligen Dreieckes C = Hypotenuse
        </i></font>A := S.X - E.X;
        B := S.Y - E.Y;
        C := Sqrt(A * A + B * B); <font color="#008080"><i>// c² = (a² + b²)^0.5
        <br>
        // wende Strahlensatz an
        </i></font>A := A * Length / C;
        B := B * Length / C;
        <br>
        <font color="#008080"><i>// Zeige den Punkt A,B
        // Pixels[Round(S.X - A), Round(S.Y - B)] := clRed;
        <br>
        // berechne 1. linken Punkt des Pfeiles, er ist im Winkel von -PfeilWinkel / 2
        // Grad vom Punkt (A,B) versetzt, wir nutzen eine Koordinaten-Rotation um S
        </i></font>Alpha := -Angle * PI / <font color="#0000FF">360</font>;
        SinAlpha := Sin(Alpha);
        CosAlpha := Cos(Alpha);
        <br>
        P1.X := Trunc(S.X - (CosAlpha * A - SinAlpha * B) + <font color="#0000FF">0.5</font>);
        P1.Y := Trunc(S.Y - (SinAlpha * A + CosAlpha * B) + <font color="#0000FF">0.5</font>);
        <br>
        <font color="#008080"><i>// berechne 2. rechten Punkt des Pfeiles
        </i></font>Alpha := +Angle * PI / <font color="#0000FF">360</font>;
        SinAlpha := Sin(Alpha);
        CosAlpha := Cos(Alpha);
        <br>
        P2.X := Trunc(S.X - (CosAlpha * A - SinAlpha * B) + <font color="#0000FF">0.5</font>);
        P2.Y := Trunc(S.Y - (SinAlpha * A + CosAlpha * B) + <font color="#0000FF">0.5</font>);
        <br>
        <font color="#008080"><i>// zeichne einen Kreisausschnitt
        </i></font>Canvas.Pie(S.X - Length, S.Y - Length, S.X + Length, S.Y + Length,
        P2.X, P2.Y, P1.X, P1.Y);
        <b>end</b>;
        <br>
        <b>begin
        with </b>Canvas <b>do
        begin
        </b>MoveTo(S.X, S.Y);
        LineTo(E.X, E.Y);
        Pfeil(Canvas, S, E, PfeilLength, PfeilAngle);
        Pfeil(Canvas, E, S, PfeilLength, PfeilAngle);
        <b>end</b>;
        <b>end</b>;
        <br>
        <b>var
        </b>S,E: TPoint;
        <br>
        <b>procedure </b>TForm3.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
        <b>begin
        with </b>PaintBox1, Canvas <b>do
        begin
        </b><font color="#008080"><i>// lösche vorhergehende zeichnung
        </i></font>Pen.Color := Color;
        MoveTo(S.X, S.Y);
        LineTo(E.X, E.Y);
        Brush.Color := Color;
        FillRect(Bounds(S.X -<font color="#0000FF">50</font>, S.Y - <font color="#0000FF">50</font>, <font color="#0000FF">100</font>, <font color="#0000FF">100</font>));
        FillRect(Bounds(E.X -<font color="#0000FF">50</font>, E.Y - <font color="#0000FF">50</font>, <font color="#0000FF">100</font>, <font color="#0000FF">100</font>));
        <br>
        <font color="#008080"><i>// S = Startpunkt, E = Endpunkt der Linie
        </i></font>S := Point(Width <b>shr </b><font color="#0000FF">1</font>, Height <b>shr </b><font color="#0000FF">1</font>);
        E := Point(X, Y);
        <b>if </b>(S.X = E.X) <b>and </b>(S.Y = E.Y) <b>then </b>Exit; <font color="#008080"><i>// wichtig, ansonsten Division durch Null
        <br>
        </i></font>Pen.Color := clWhite;
        Brush.Color := clRed;
        PfeilLinie(Canvas, S, E, <font color="#0000FF">32</font>, <font color="#0000FF">64</font>);
        <b>end</b>;
        <b>end</b>;
        </font>
        </code></pre&gt

        Comment


        • #5
          Klasse Hagen,<br>wie immer bist du der Experte für Mathe angelegenheiten, ich hab leider in der Schule nie aufgepasst :-)))<br&gt

          Comment


          • #6
            5. Klasse Mathe glaub ich, ist also schon 20 Jahre her, oh Gott oh Gott. Ich liebe solche kleinen Aufgaben, das frischt das Wissen auf und entspannt :

            Comment


            • #7
              :v

              Comment

              Working...
              X