Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Kreis auf Canvas zeichen
suga2001 - Mi 14.01.09 17:32
Titel: Kreis auf Canvas zeichen
ich möchte einen Kreis zeichen und dazu habe ich unterschiedliche Varianten ausprobiert
Als Ellipse gings am einfachste :D , nun bin ich aber hängen geblieben, hab schon einiges gelesen aber irgendwie kommt trotzdem nicht das gewünschte Ergebnis dabei raus.
Das ist mein Quelltext um einen Kreis anhand von sin und cos zu zeichen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| i:=Image1; r:=90; for j := 0 to 360 do begin x:=cos(DegToRad(j)) * r + i.Width / 2; y:=sin(DegToRad(j)) * r + i.Height / 2; i.Canvas.Lineto(Round(x), Round(y)); end; end; |
funktioniert auch ganz gut, wenn da nicht eine störende Linie entstehen würde. Ich gehe davon aus, dass der Punkt, wo die Linie endet und zum "Kreis" wird, durch meine Gleichung vorher angegeben wird. Stimmt das? :?: Ich möchte diese Linie aber nicht gezeichnet haben. Benutze ich ein moveto, wird gar kein Kreis mehr gezeichnet.
Möchte ich nun einen Kreis über r²=x² + y² und stelle mir das nach x oder y um, dann wird nur ein sekrechter Strich gezeichnet.
Dazu mein Quellcode:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| r:integer; x,y:real;
begin
r:=90;
y := (sqrt(sqr(r) - (sqr(x)))); x := (sqrt(sqr(r) - (sqr(y)))); Image1.Canvas.Lineto(round(x),round(y)); |
auf was bezieht sich x und y? Vielleicht hab ich ja an etwas nicht gedacht? :oops:
Danke schon mal im Voraus :roll:
jaenicke - Mi 14.01.09 17:42
Warum benutzt du denn nicht einfach die vorgefertigte Methode? Ich meine, gibt es einen Grund oder willst du das nur aus Interesse machen? ;-)
suga2001 hat folgendes geschrieben : |
Möchte ich nun einen Kreis über r²=x² + y² und stelle mir das nach x oder y um, dann wird nur ein sekrechter Strich gezeichnet. |
Mehr zeichnest du ja auch nicht.
suga2001 hat folgendes geschrieben : |
Delphi-Quelltext 1:
| Image1.Canvas.Lineto(round(x),round(y)); | |
Wie meinst du das also? Ist dir nicht klar was LineTo macht? Das zeichnet ja nur einen Strich... :gruebel:
// EDIT:
Ach ja:
suga2001 hat folgendes geschrieben : |
funktioniert auch ganz gut, wenn da nicht eine störende Linie entstehen würde. Ich gehe davon aus, dass der Punkt, wo die Linie endet und zum "Kreis" wird, durch meine Gleichung vorher angegeben wird. Stimmt das? :?: Ich möchte diese Linie aber nicht gezeichnet haben. Benutze ich ein moveto, wird gar kein Kreis mehr gezeichnet. |
Am Anfang ist ja der Zeichenstift schon auf der Zeichenfläche. Nämlich bei (0,0). Wenn du dann das erste LineTo machst, dann wird von dort zu den angegebenen Koordinaten die Linie gezeichnet. (Und danach dann zwischen den berechneten Punkten des Kreises, wie es sein soll.)
Du musst zuerst mit MoveTo zu der ersten Koordinate des Kreises gehen und kannst dann von dort aus anfangen zu zeichnen. ;-)
suga2001 - Mi 14.01.09 18:19
Danke, hat mir schon weitergeholfen. :D
das tue ich doch mit dem code
Delphi-Quelltext
1:
| Image1.Canvas.MoveTo(r+i.Width,r+i.Height); |
Dann habe ich aber statt dem Lineto von 0,0 kommend nun den Lineto von der anderen Seite unten meines Canvas kommend. :?
mit
Delphi-Quelltext
1:
| i.Canvas.Lineto(Round(x), Round(y)); |
Zeichne ich doch jeweils von Punkt zu Punkt über 360° meine Punkte, oder?
jaenicke - Mi 14.01.09 18:40
suga2001 hat folgendes geschrieben : |
das tue ich doch mit dem code
Delphi-Quelltext 1:
| Image1.Canvas.MoveTo(r+i.Width,r+i.Height); |
Dann habe ich aber statt dem Lineto von 0,0 kommend nun den Lineto von der anderen Seite unten meines Canvas kommend. :? |
Ja, klar. Überlege dir einmal wo die Koordinaten sind, die du dort angibst...
(i ist das Image in rot, der Punkt ist die Koordinate wo du den Stift hinbewegst...)
Du musst zu dem Punkt auf dem Kreis, von dem aus dann weitergezeichnet werden soll.
suga2001 hat folgendes geschrieben : |
mit
Delphi-Quelltext 1:
| i.Canvas.Lineto(Round(x), Round(y)); |
Zeichne ich doch jeweils von Punkt zu Punkt über 360° meine Punkte, oder? |
Ja, von der aktuellen Stiftposition zu der neuen angegebenen. Die neue Stiftposition ist dann an dem neuen Punkt.
suga2001 - Mi 14.01.09 18:51
so, nun hab ich den Strich immerhin schon im Kreis, als Radius, sozusagen :lol: ist doch schon mal was :wink:
wie bekomme ich den nun weg? er wird doch immer gezeichnet, weil ich das doch schließlich mit angegeben habe, oder?
jaenicke - Mi 14.01.09 19:05
Naja, ich glaube es ist besser, wenn ich es direkt schreibe:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| i := Image1; r := 90; x := cos(DegToRad(0)) * r + i.Width / 2; y := sin(DegToRad(0)) * r + i.Height / 2; i.Canvas.MoveTo(Round(x), Round(y));
for j := 1 to 360 do begin x := cos(DegToRad(j)) * r + i.Width / 2; y := sin(DegToRad(j)) * r + i.Height / 2; i.Canvas.Lineto(Round(x), Round(y)); end; end; |
So gehst du zuerst zum ersten Punkt, den du natürlich genauso wie in der Schleife berechnen kannst, bevor du die Linie zum nächsten Punkt ziehst.
Den Punkt kannst du natürlich auch einfacher berechnen, ich wollte dir nur deutlich machen wie das Prinzip ist.
suga2001 - Mi 14.01.09 19:16
guuuuuuuuut, schick.das geht... ich danke dir für die tolle Hilfe :D
suga2001 - Mi 14.01.09 20:17
Wenn ich diesen Kreis nun auch noch ausmalen möchte, mir einer mir vorgegeben Farbe, bleibt meins immer weiß, also so, wie ichs gezeichnet hatte. an welcher stelle der Prozedur muss ich denn
Delphi-Quelltext
1: 2:
| Canvas.Brush.Color := clGreen; |
Eine Frehlermeldung bekomme ich nicht. Kann ich das nicht mit in die Prozedur reinschreiben, in der mein kreis gezeichnet wird? so, gleich zum Anfang nach dem ersten begin in dem o.g Quellcode??
Oder muss ich dazu extra einen Button machen, der das denn ausmalt, und denn denn mein brush.color einfach????
jaenicke - Mi 14.01.09 20:36
So wie du jetzt zeichnest zeichnest du nur Linien, d.h. du musst das Füllen selbst machen. Deshalb wiederhole ich meine Frage: Musst du das so kompliziert machen bzw. willst du das so machen?
Schließlich kann man einen Kreis auch direkt mit einem einzigen Befehl (Ellipse) zeichnen und dann wird auch Brush automatisch zum Füllen benutzt.
suga2001 - Do 15.01.09 12:20
Sorry, ich war noch so in dem ganzen mathematischen drinn, dass ich das einfach kopiert und auf meinen Button gesetzt habe. :lol:
Mit einer Elipse gehts ja wesentlich schneller.
Aber das einfache
Delphi-Quelltext
1: 2:
| image1.Canvas.Ellipse(0,0,180,180); Canvas.Brush.Color := clGreen; |
funktioniert nicht. Auch nicht,wenn ich es davor setzte. Meine Hilfedatei von Delphi geht auch nicht, da ich Vista64 benutzte, es startet immer nur die windows-Hilfe...
jaenicke - Do 15.01.09 12:40
Weil du dich einmal aufs Canvas des Formulars (ohne image1.) und einmal auf das des Images beziehst... ;-)
Ansonsten ist die umgekehrte Reihenfolge dann richtig, du musst natürlich die Farbe zuerst setzen.
suga2001 - Do 15.01.09 12:43
hab ich gemacht. Einmal möchte ich es mit floodfill füllen und einmal mit brush.
Floodfill funktioniert wunderbar.
Delphi-Quelltext
1:
| Canvas.FloodFill(90,90,clBlack,fsBorder); |
ich muss das aber irgendwie wieder löschen. benutze ich
canvas.Free , stürtzt mir das programm ab :(
ich muss den farbwert ja irgendwie wieder zurücksetzten, damit ich den einmal grün für floodfill und einmal blau für brush machen kann...
jaenicke - Do 15.01.09 12:48
Mit Canvas.Free entfernst du das Objekt Canvas aus dem Speicher. Dann ist es weg. Das ist wie wenn du im Auto sagst "Lenkrad nach links drehen", "Lenkrad aus dem Fenster wegschmeißen", "Lenkrad nach rechts drehen" (welches Lenkrad?). ;-)
Was Floodfill macht ist dir klar? :gruebel:
suga2001 - Do 15.01.09 13:14
Delphi-Quelltext
1: 2:
| Image1.Canvas.Brush.Color:=clred; image1.Canvas.Ellipse(0,0,180,180); |
klappt auch :D
Danke schön :wink:
Horst_H - Do 15.01.09 13:31
Hallo,
ich hätte nicht gedacht, dass ein Eigenbau so schnell ist.
Aber brush kann ja mehr und zudem zeichne ich nicht den äusseren Rand in der passenden Farbe.
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:
| procedure canvasfilledCircle(can:TCanvas;MittelPunkt:Tpoint;radius:integer); var x,y,dy : integer; tmpColour : Tcolor; begin tmpColour := can.Pen.Color; can.Pen.Color := can.Brush.Color; radius := radius-1; with can do begin for dy := -radius to radius do begin x := round(sqrt(sqr(radius)-sqr(dy))); moveto(Mittelpunkt.x-x, Mittelpunkt.y+dy); Lineto(Mittelpunkt.x+x, Mittelpunkt.y+dy); end; end; can.Pen.Color := tmpColour; end;
procedure TForm1.Button1Click(Sender: TObject); var i : integer; t1,t0: dword; begin t0:= gettickcount; for i := 1 to 5000 do begin Form1.canvas.Brush.Color := random(high(TColor)); canvasfilledCircle(Form1.canvas,Point(150,200),70); end; t1:= gettickcount; memo1.Lines.Add(Format('Eigenbau %d',[t1-t0]));
t0:= gettickcount; for i := 1 to 5000 do begin Form1.canvas.Brush.Color := random(high(TColor)); Form1.canvas.ellipse(150-70,200-70,150+70,200+70); end; t1 := gettickcount; memo1.Lines.Add(Format('Ellipse %d',[t1-t0])); end; |
Gruß Horst
Henneberg - Di 30.11.10 17:18
ok ich hab dann jetzt nur noch eine frage
ich hab es nach langen versuchen nun endlich auch daheim geschafft und wollte nun noch ausprobieren ob ich denn die koordinaten bzw den radius selbst eingeben kann(im edit)
und da müsste ich noch wissen wofür welche varaible steht
image1.Canvas.Ellipse(0,0,180,180);
also bei mir image1.Canvas.Ellipse(x,y,m,n);
danke im vorraus
henneberg
bummi - Di 30.11.10 17:26
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var x,y,m,n:Integer; begin If TryStrToInt(Edit1.text,x) and TryStrToInt(Edit2.text,y) and TryStrToInt(Edit3.text,m) and TryStrToInt(Edit4.text,n) then begin end else Showmessage('Ungültige Eingabe'); |
Henneberg - Di 30.11.10 17:33
Naia ne..
ich meine z.B. welche variable steht für den mittelpunkt
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Button1Click(Sender: TObject); var x,y,m,n:integer; begin x:=StrToInt (Edit1.Text); y:=StrToInt (Edit2.Text); m:=StrToInt (Edit3.Text); n:=StrToInt (Edit4.Text); image1.Canvas.Ellipse(x,y,m,n); end; |
ich habs jetzt mal so gemacht und durch versuchen herausgefinden das bei mir x für die breite und y für die länge steht aber was bestimmen jetzt m und n? bzw kann ich hierbei überhaupt angeben wo der kreis liegt?
danke im vorraus
henneberg
Moderiert von
Martok: Delphi-Tags eingefügt
bummi - Di 30.11.10 17:49
Du gibst das umgebende Rechteck an, den Mittelpunkt kannst du Dir herausrechnen, wenn Du es anders eingeben willst rückwärts rechnen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!