Autor Beitrag
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 17:51 
Moin :)!

Ich baue grade meinen Complex Calculator aus und mit fällt auf, dass ich ein Zeigerdiagramm mit Strichen habe; ich möchte allerdings ein Zeigerdiagramm mit Zeigern, daher hätt ich gerne Pfeilspitzen... hab mich schon etwas mit den Winkelfunktionen gespielt, aber das brachte nichts.
Hier der Code, wo der "Pfeil" (ohne Spitze) gezeichnet wird. (w div 2, h div 2) ist der Koordinatenursprung.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
      for i := Low(vars) to High(vars) do begin
        //Zeiger
        Pen.Color := vars[i].Color;
        MoveTo(w div 2, h div 2); //Ursprung
        LineTo(Round(w div 2 + vars[i].Real * scalex), Round(h div 2 - vars[i].Img * scaley));
        //Pfeilspitze
        //???
        //Beschriftung
        Font.Color := Pen.Color;
        if vars[i].Real > 0 then //Positionsabhängig
          TextOut(Round(w div 2 + vars[i].Real * scalex) - TextWidth(vars[i].Name) - 10, Round(h div 2 - vars[i].Img * scaley) - TextHeight(vars[i].Name) div 2 {center}, vars[i].Name)
        else
          TextOut(Round(w div 2 + vars[i].Real * scalex) + 10, Round(h div 2 - vars[i].Img * scaley) - TextHeight(vars[i].Name) div 2 {center}, vars[i].Name)
        end;


Jemand eine Idee für die Pfeilspizen?

AXMD
sourcehunter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 482

Win XP | Suse 10.1
Delphi 2005 Pers.
BeitragVerfasst: Fr 04.03.05 18:18 
Probiers mal mit nem Polygon. So, dass du von der Spitze z.B. 10 "Pixel" zurückgehst und dann 5 zu jeder Seite senkrecht zur Linie.

_________________
Linux und OpenSource rulez!
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 18:21 
sourcehunter hat folgendes geschrieben:
Probiers mal mit nem Polygon. So, dass du von der Spitze z.B. 10 "Pixel" zurückgehst und dann 5 zu jeder Seite senkrecht zur Linie.


Das "senkrecht" ist ja mein eigentliches Problem. Woher weiß ich, wie ich zeichnen muss damit es genau senkrecht wird...

AXMD
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 18:28 
Sagen wir einfachheitshalber, dass deine Linie im Koordinatenursprung beginnt.
D.h. Linie von 0,0 bis X,Y

Die Linie senkrecht dazu ist dann 0,0 bis -Y,X. Wieso?
Das Skalarprodukt der beiden Vektoren (X,Y)*(-Y,X)=0 (und das ist die Definition von "senkrecht")
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 18:37 
Also ich leite das kurz her, damit die Anwendung klar ist.

Länge der Linie L := sqrt(X^2+Y^2);

Die untere Pfeilkante sei W Pixels und die Höhe H Pixels.

Der Schnittpunkt untere Pfeilkante mit Linie ist dann bei
PX := X-X/L*H;
PY := Y-Y/L*H;

Von dort aus möchtest du senkrecht dazu eine Linie zeichnen. Wie oben erwäht lautet die Einheitssenkrechte:
SX := -Y/L;
SY := X/L;

Die linke, untere Pfeilecke ist dann bei:
Punkt A: PX+SX*W/2 ; PY+SY*W/2
Die rechte, untere Pfeilecke bei:
Punkt B: PX-SX*W/2 ; PY-SY*W/2

Das zu zeichende Dreieck besteht also aus den 3 Punkten: Die Spitze, A und B
Ich probiers schnell aus und korrigiere das noch, wenn nötig.

//Edit: Scheint zu funktionieren :) Verschieben kannst du den Pfeil dann selbst :)
//Edit2: Hab noch ne kleine Modifikation gemacht, sodass die untere Kante nicht einfach gerade ist (sieht doof aus)
ausblenden Delphi-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:
procedure TForm1.Button1Click(Sender: TObject);
const
 H = 30; // Höhe an den Seiten
 C = 25; // Höhe am Rumpf (5 Pixel weniger)
 W = 20; // Breite
Var
 L, PX, PY, SX, SY, X, Y,
 X1,Y1,X2,Y2 : Extended;
begin
 X := 100;
 Y := 20;
 L := sqrt(X*X+Y*Y);
 PX := X-X/L*H;
 PY := Y-Y/L*H;
 SX := -Y/L;
 SY := X/L;
 with Canvas do
 begin
  X1 := PX+SX*W/2;
  Y1 := PY+SY*W/2;
  X2 := PX-SX*W/2;
  Y2 := PY-SY*W/2;
  MoveTo(0,0);
  LineTo(Trunc(X), Trunc(Y));
  Polygon([Point(Trunc(X), Trunc(Y)), Point(round(X1), round(Y1)),
           Point(Trunc(X-X/L*C), Trunc(Y-Y/L*C)), Point(round(X2), round(Y2))]);
 end;
end;


Gruss,
Simon


Zuletzt bearbeitet von delfiphan am Fr 04.03.05 18:53, insgesamt 1-mal bearbeitet
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 18:51 
Danke dir vielmals, ich werd's mal ausprobieren...

AXMD
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:05 
Nein, es funktioniert nicht ganz. Der Code funzt bei mir (angepasst) seltsamerweise nur im vierten Quadranten richtig...

user defined image

AXMD
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 19:06 
Komisch. Hast du die Funktion richtig erweitert? Hier die backfertige Version:
ausblenden Delphi-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:
Procedure DrawArrow(Canvas : TCanvas; PX1,PY1,PX2,PY2 : Integer);
const
 H = 30;          // Höhe an den Seiten
 C = H * 6 div 7; // Höhe am Rumpf (ein wenige kürzer)
 W = H * 2 div 3; // Breite (Pfeil ist ein bisschen höher als breit)
Var
 L, PX, PY, X, Y : Extended;
begin
 X := PX2-PX1;
 Y := PY2-PY1;
 L := sqrt(X*X+Y*Y);
 PX := X*(1-H/L);
 PY := Y*(1-H/L);
 with Canvas do
 begin
  MoveTo(PX1,PY1); LineTo(PX2,PY2);
  Polygon([Point(PX2, PY2),
           Point(Round(PX1+PX-Y/L*W/2), Round(PY1+PY+X/L*W/2)),
           Point(Trunc(PX1+X-X/L*C), Trunc(PY1+Y-Y/L*C)),
           Point(Round(PX1+PX+Y/L*W/2), round(PY1+PY-X/L*W/2))]);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 DrawArrow(Canvas, 200,30,100,100);
end;
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:17 
Also ich glaub heut kapier ich's irgendwie nicht :gruebel:

Wenn ich deine Funktion so aufrufe DrawArrow(Canvas, 0, 0, x, y); wobei x und y die Endpunkte meines "Pfeils" (Strichs ;)) sind funzts gar nicht (keine Pfeile, nirgendwo).
Oder hab ich da was falsch gemacht?

AXMD
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 19:20 
Funzt nichts? Du siehst nichts?
DrawArrow(Image1.Canvas, X1,Y1,X2,Y2) zeichnet einen Pfeil von (X1,Y1) bis (X2,Y2). Die Pfeilspitze ist bei (X2,Y2)

Ich habe die Funktion in allen Richtungen getestet... Bei mir geht's.


Zuletzt bearbeitet von delfiphan am Fr 04.03.05 19:22, insgesamt 1-mal bearbeitet
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:22 
Hier mal der ganze Code... dein Code zeichnet bei mir leider gar nichts.

ausblenden volle Höhe Delphi-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:
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  w, h: Integer; //Breite und Höhe
  scalex, scaley: Double; //Skalierungsfaktoren
  tempvars: Array of Double;
  i: Integer;
  x, y: Integer;
begin
  with PaintBox1.Canvas do begin
    //Breite und Höhe speichern
    w := PaintBox1.Width;
    h := PaintBox1.Height;
    //Draw background
    Brush.Style := bsSolid;
    Brush.Color := clWhite;
    Pen.Color := clWhite;
    Rectangle(0, 0, w, h);
    Brush.Style := bsClear;
    Pen.Color := clBlack;
    //Imaginäre Achse
    MoveTo(w div 2, 0);
    LineTo(w div 2, h);
    //Reale Achse
    MoveTo(0, h div 2);
    LineTo(w, h div 2);
    //Skalierungsfaktor (x) bestimmen
    SetLength(tempvars, Length(vars) + 1);
    for i := Low(vars) to High(vars) do
      tempvars[i] := Abs(vars[i].Real);
    tempvars[Length(vars)] := Abs(loesung.Real);
    scalex := MaxValue(tempvars); //Größten Realteil bestimmen (Betrag!)
    SetLength(tempvars, 0);
    if scalex = 0 then
      scalex := 100;
    scalex := (w div 2 - 10) / scalex; //10px Abstand
    //Skalierungsfaktor (y) bestimmen
    SetLength(tempvars, Length(vars) + 1);
    for i := Low(vars) to High(vars) do
      tempvars[i] := Abs(vars[i].Img);
    tempvars[Length(vars)] := Abs(loesung.Img);
    scaley := MaxValue(tempvars); //Größten Imaginärteil bestimmen (Betrag!)
    SetLength(tempvars, 0);
    if scaley = 0 then
      scaley := 100;
    scaley := (h div 2 - 10) / scaley; //10px Abstand
    //1 (x) einzeichnen
    MoveTo(Round(w div 2 + scalex), h div 2 - 5);
    LineTo(Round(w div 2 + scalex), h div 2 + 5);
    TextOut(Round(w div 2 + scalex) - 2, h div 2 + 8, '1');
    //1 (y) einzeichnen
    MoveTo(w div 2 + 5, Round(h div 2 - scaley));
    LineTo(w div 2 - 5, Round(h div 2 - scaley));
    TextOut(w div 2 - 14, Round(h div 2 - scaley) - 5, '1');
    //Zeiger zeichnen
    try
      //Zeiger zeichnen
      for i := Low(vars) to High(vars) do begin
        //Zeiger
        Pen.Color := vars[i].Color;
        MoveTo(w div 2, h div 2); //Ursprung
        LineTo(Round(w div 2 + vars[i].Real * scalex), Round(h div 2 - vars[i].Img * scaley));
        //Pfeilspitze
        x := Round(w div 2 + vars[i].Real * scalex);
        y := Round(h div 2 - vars[i].Img * scaley);
        DrawArrow(Canvas, 0, 0, x, y);
        //Beschriftung
        Font.Color := Pen.Color;
        if vars[i].Real > 0 then //Positionsabhängig
          TextOut(Round(w div 2 + vars[i].Real * scalex) - TextWidth(vars[i].Name) - 10, Round(h div 2 - vars[i].Img * scaley) - TextHeight(vars[i].Name) div 2 {center}, vars[i].Name)
        else
          TextOut(Round(w div 2 + vars[i].Real * scalex) + 10, Round(h div 2 - vars[i].Img * scaley) - TextHeight(vars[i].Name) div 2 {center}, vars[i].Name)
        end;
      //Ergebnis zeichnen
      Pen.Color := loesung.Color;
      MoveTo(w div 2, h div 2); //Ursprung
      LineTo(Round(w div 2 + loesung.Real * scalex), Round(h div 2 - loesung.Img * scaley));
      //Beschriftung
      Font.Color := Pen.Color;
      if loesung.Real > 0 then //Positionsabhängig
        TextOut(Round(w div 2 + loesung.Real * scalex) - TextWidth(loesung.Name) - 10, Round(h div 2 - loesung.Img * scaley) - TextHeight(loesung.Name) div 2 {center}, loesung.Name)
      else
        TextOut(Round(w div 2 + loesung.Real * scalex) + 10, Round(h div 2 - loesung.Img * scaley) - TextHeight(loesung.Name) div 2 {center}, loesung.Name)
    except
      TextOut(100, 100, 'Ungültige Eingabe');
      end;
    end;
end;


AXMD
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 19:24 
Statt diese Zeilen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
        MoveTo(w div 2, h div 2); //Ursprung  
        LineTo(Round(w div 2 + vars[i].Real * scalex), Round(h div 2 - vars[i].Img * scaley));  
        //Pfeilspitze  
        x := Round(w div 2 + vars[i].Real * scalex);  
        y := Round(h div 2 - vars[i].Img * scaley);  
        DrawArrow(Canvas, 0, 0, x, y);        //Beschriftung

Nur das hier:
ausblenden Delphi-Quelltext
1:
 DrawArrow(PaintBox1.Canvas,   w div 2, h div 2,   Round(w div 2 + vars[i].Real * scalex), Round(h div 2 - vars[i].Img * scaley));					
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:29 
Es ändert sich was.... jetzt ist gar kein Pfeil mehr da...

ausblenden Delphi-Quelltext
1:
2:
3:
x := Round(w div 2 + vars[i].Real * scalex);
y := Round(h div 2 - vars[i].Img * scaley);
DrawArrow(Canvas, w div 2, h div 2, x, y);


Ergibt (Lösung wird separat gezeichnet!)

user defined image

:gruebel: AXMD
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:32 
:autsch:

Die PaintBox vergessen... *argx* :autsch:

Danke dir vielmals, kommst in die Danksagungen im Readme und bei deiner Funktion kommt ein entsprechender Comment in den Code ;)

Btw: könnt ich den Code vielleicht ohne dem Verbindungsstrich zwischen den beiden Enden haben :mrgreen:
Also

/|\
|
|

statt

/|\
-|-
|

Thx
AXMD


Zuletzt bearbeitet von AXMD am Fr 04.03.05 19:34, insgesamt 1-mal bearbeitet
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Fr 04.03.05 19:32 
Kopier einfach mal die obere Zeile.
Wichtig: Paintbox1.Canvas
sonst wird implizit Form1.Canvas angenommen!

//Edit: Okay, dann ist ja gut :)
Wegen der Funktion musste mich nicht gleich auflisten (kannst aber, wenn du willst :))
So ich muss jetzt raus.. Schönen Abend noch :)
*und weg

//Edit2: Und hiermit gebe ich dir die Erlaubnis mit dem Code zu tun was du willst ;)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  Polygon([Point(PX2, PY2),
           Point(Round(PX1+PX-Y/L*W/2), Round(PY1+PY+X/L*W/2)),
           Point(PX2, PY2),
           Point(Round(PX1+PX+Y/L*W/2), round(PY1+PY-X/L*W/2))]);

*wirklich weg :wink2:
AXMD Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Fr 04.03.05 19:50 
Vielen lieben Dank nochmal.

Readme hat folgendes geschrieben:
Ein herzliches Dankeschön geht an "delphifan" für die Hilfestellung beim Implementieren der Pfeilspitzen ;).


Thx
AXMD