![]() |
Windmühle, bei der die Flügelanzahl variabel ist
Ich bin zurzeit an einer Windmühle, bei dem die Postition, Flügelanzahl und Höhe der Mühle variabel ist. Das "Haus" der Mühle habe ich schon fertig, nur komme ich bei den variablen Flügeln nicht weiter:
Delphi-Quellcode:
Habt ihr Tipps bzw. Lösungen?
unit muehleU;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; const pi=3.1415; type TForm1 = class(TForm) Button1: TButton; Image1: TImage; procedure Button1Click(Sender: TObject); procedure Muehle(anzahl,hoehe,x,y:integer); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Muehle (4,150,50,50); end; procedure TForm1.Muehle (anzahl,hoehe,x,y:integer); var flange,nr,bm,x2,y2:integer; begin with Image1.Canvas do begin moveTo (x,y); rectangle (x,y,x+round(hoehe/5),hoehe); moveTo (x+(round(hoehe/5)DIV 2),y+10); x2:= x+(round(hoehe/5)DIV 2); y2:= y+10; flange:= hoehe DIV 2 ; bm:= round((2*pi) / anzahl); for nr:= 1 to anzahl do begin lineTo (round(flange*cos(bm*nr)+(hoehe DIV 10)),round(-flange*sin(bm*nr)+60)); moveTo (x2,y2); end; end; end; end. |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Ich denke, da kann man nur trigonometrisch rangehen. Also mit dem Anfangswinkel starten, den Endpunkt des Flügels ausrechnen (sin/cos), den Winkel ändern usw.
Delphi-Quellcode:
Hierbei wird der Winkel gegen den Uhrzeigersinn von der X-Achse aus gemessen.
FluegelEndPunkt.X:=Drehpunkt.X+Cos(Winkel)*Fluegelradius;
FluegelEndPunkt.Y:=Drehpunkt.Y+Sin(Winkel)*Fluegelradius; [edit]Wie kann man denn so blöd sein... Danke, Nikolas[/edit] |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Delphi-Quellcode:
Wobei Sinus und Cosinus auch noch mit dem Flügelradius multipliziert werden sollten, da man sonst nichts sieht.
FluegelEndPunkt.X:=Drehpunkt.X+Cos(Winkel);
FluegelEndPunkt.Y:=Drehpunkt.Y+Sin(Winkel); Den Winkel zwischen zwei Flügeln findest du dann einfach per Winkel=2pi/Flügelanzahl raus, wenn dein Flügel nicht nur aus einem Strich sondern aus einem Dreieck bestehen soll, wäre so was eine Möglichkeit:
Delphi-Quellcode:
Ich habe den Code nicht getestet, er dürfte aber recht gut sein, hoffe ich mal.
Winkel= 2pi/Flügelanzahl;
WinkelKlein = Winkel /3; x=100; y=100; (pen.)moveto(x,y); for i:=0 to Flügelanzahl do begin lineto(x+cos(winkel*i)*radius, y+sin(winkel*i)*radius); lineto(x+cos(winkel*i+winkelKlein)*radius, y+sin(winkel*i+winkelklein)*radius); lineto(x,y); end; |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Danke schon mal für eure Antworten :-D
Ich weiß nur nicht, wo ich jetzt den Code von Nikolas einbauen soll... Soll ich dafür die ganze Muehle Prozedure überschreiben? Und noch was: Winkel und WinkelKlein hab ich doch noch gar nicht definiert . . . Das kann doch gar nicht funktionieren, oder? :gruebel: |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Zitat:
Und die zweite Frage ist nicht wirklich ernst gemeint, oder?
Delphi-Quellcode:
Wenn du jetzt t und Omega gescheit setzt (z.B. in einem Timer) könntest du die Windmühle sogar zum rotieren bringen :)
Winkelstart=t*Omega;
Winkel = 2pi/Anzahl; WinkelAkt= Winkelstart; for i:=0 to Anzahl do begin lineto(x+cos(WinkelAkt)*radius, y+sin(WinkelAkt)*radius); lineto(x+cos(WinkelAkt+winkelKlein)*radius, y+sin(WinkelAkt+winkelklein)*radius); lineto(x,y); WinkelAkt += Winkel; end; |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Das wäre mein nächster Schritt :-D
Doch zunächst muss ich erstmal die Windräder hinkriegen. Und es will einfach nicht... :? Ich habe Apollonius Tipp befolgt, da meine Flügel keine Dreiecke, sondern einfach nur Striche sein sollen. Mein Programmcode sieht jetzt wie folgt aus:
Delphi-Quellcode:
unit muehleU;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; const pi=3.1415; type TForm1 = class(TForm) Button1: TButton; Image1: TImage; procedure Button1Click(Sender: TObject); procedure Muehle(anzahl,hoehe,x,y:integer); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Muehle (4,150,50,50); end; procedure TForm1.Muehle (anzahl,hoehe,x,y:integer); var flange,nr,bm,x2,y2, FluegelEndPunktX, FluegelEndPunktY:integer; begin with Image1.Canvas do begin moveTo (x,y); rectangle (x,y,x+round(hoehe/5),hoehe); moveTo (x+(round(hoehe/5)DIV 2),y+10); x2:= x+(round(hoehe/5)DIV 2); y2:= y+10; flange:= hoehe DIV 2 ; bm:= round((2*pi) / anzahl); for nr:= 1 to anzahl do begin FluegelEndPunktX:=(hoehe DIV 10)+round(Cos(bm*nr)); FluegelEndPunktY:=60+round(Sin(bm*nr)); //lineTo (round(flange*cos(bm*nr)+(hoehe DIV 10)),round(-flange*sin(bm*nr)+60)); lineTo (FluegelEndPunktX,FluegelEndPunktY); moveTo (x2,y2); end; end; end; end. |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Und warum befolgst du nicht mal meinen Tipp?
Greif dir einen taschenrechner und gib doch mal das hier ein: > FluegelEndPunktX:=(hoehe DIV 10)+round(Cos(bm*nr)); Was kommt da für ein Wert raus? Ist dieser Wert sinnvoll? |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Hi
Es ist relativ einfach, Windmühlenflügel zu programmieren. Überlegen wir, was notwendig ist: Ein Mittelpunkt, dazu eignet sich ein TPoint. Dieser Variablentyp beinhaltet einen x und einen y Wert. Z.B.
Delphi-Quellcode:
Nabe : TPoint (Global )
Delphi-Quellcode:
Zwei weitere Variablen machen Sinn
Nabe.x:=256; // Beispiel, so initialisierst du deinen Mittelpunkt im FormCreate
Nabe.y:=55;
Delphi-Quellcode:
Um eine Linie zu zeichnen benötigen wir nun einen Anfangspunkt und einen Endpunkt.
Gradzahl : Real; (Global) // veränderbare Winkelvariable für die Bewegung
AnzFluegel : Integer; (Global) // falls eine veränderbare Flügelzahl erwünscht.... Also, Anfang ist Mitte, Endpunkt ist Flügellänge und Winkel von Mitte. Daraus machen wir eine Funktion, in der wir diese Werte als Parameter übergeben und einen TPoint-Wert erhalten:
Delphi-Quellcode:
Nun die Zeichnung der Linie, am besten eine Procedur mit den Parametern Anfangspunk, Endpunkt und Farbe. Die Farbe brauchst du, um die alte Zeichnung wieder zu löschen. Nehmen wir an, du zeichnest auf einem grünen Untergrund. Eine Rote Linie ist sichtbar, eine grüne nicht...
Function TMyForm.Endpunkt( Radius: Integer; Winkel: Real; Zentrum : TPoint):TPoint;
Var xypunkt : TPoint; Begin xypunkt.x:=Trunc(Cos(DegToRad(Winkel))*(-Radius))+Zentrum.x; xypunkt.Y:=Trunc(Sin(DegToRad(Winkel))*(-Radius))+Zentrum.Y; Result:= xypunkt; End; Also
Delphi-Quellcode:
Eigentlich lassen sich jetzt schon die Programmzeilen testen, wenn ich z.B. über ein Button erst mal einen Endpunkt errechne und dann anschließend die Anzeige aufrufe. Du willst aber die Flügellänge und die Anzahl der Flügel selbst bestimmen. Nun gut, 2 Editfelder mit den Werten und nun geht es los.
Procedure TMyForm.ShowFluegel(Anfang,Ende: Tpoint; Farbe : TColor);
Begin MyForm.Canvas.Pen:Color:=Farbe; MyForm.Canvas.Moveto(Anfang.x, Anfang.Y); MyForm.Canvas.Lineto(Ende.x, Ende.Y); End; In die Ereignisroutine deines Tasters setzt du erst mal folgenden Code:
Delphi-Quellcode:
Nun kannst du mit Tastendrücken schrittweise prüfen, ob alles klappt. Ist es nach deinem Geschmack geraten, kannst du an die Automatisierung gehen. Nimm einen Timer und kopiere dein Button-Ereignisprogramm mit den Variablen hinein. Die Zuweisung der AnzFluegel-Variable löschst du im Timer Ereignis und im Button-Ereignis löscht du alles außer der Zuweisung der AnzFluegel-Variable.
Procedure TMyForm.MyButtonClick(Sender:Tobject);
Var i : Integer; Sektorwinkel : Real; Kreispunkt : Tpoint; Begin AnzFluegel :=StrToInt(Ed_Fluegel.Text); //Editfeld mit Namen ED_Fluegel // globale Variable setzen For i:=1 to AnzFluegel do // jeden einzelnen Flügel berechnen und darstellen Begin SektorWinkel:=360/Anzfluegel *i; // Winkel der einzelnen Flügel berechnen Sektorwinkel:=Sektorwinkel+GradZahl; // Irgendwann soll sich das Windrad ja drehen If SektorWinkel > 360 then Sektorwinkel:=Sektorwinkel-360; // wir bleiben bei 360 ° Kreis Kreispunkt :=EndPunkt(StrToInt(Ed_Fluegellaenge.Text),Sektorwinkel,Nabe); // separater Aufruf schafft Durchblick ShowFluegel(Nabe, Kreispunkt, ClGreen); // erst mal unsichtbar...... End; // I-Schleife Gradzahl:=Gradzahl+1; // Gradzahl erhöhen, >1 wird die Drehung schneller If GradZahl>360 then GradZahl:=1; // auf 360° begrenzen For i:=1 to AnzFluegel do // und jeden einzelnen Flügel berechnen und darstellen Begin SektorWinkel:=360/Anzfluegel *i; // Winkel der einzelnen Flügel berechnen Sektorwinkel:=Sektorwinkel+GradZahl; // Irgendwann soll sich das Windrad ja drehen If SektorWinkel > 360 then Sektorwinkel:=Sektorwinkel-360; // wir bleiben bei 360 ° Kreis Kreispunkt :=EndPunkt(StrToInt(Ed_Fluegellaenge.Text),Sektorwinkel,Nabe); ShowFluegel(Nabe, Kreispunkt, ClRed); // jetzt sichtbar...... End; // I-Schleife End; Feddisch........ Noch mal eine kurze Bemerkung zu fogenden Zeilen
Delphi-Quellcode:
Das geht auch ....
Kreispunkt :=EndPunkt(StrToInt(Ed_Fluegellaenge.Text),Sektorwinkel,Nabe); // separater Aufruf schafft Durchblick
ShowFluegel(Nabe, Kreispunkt, ClGreen); // erst mal unsichtbar......
Delphi-Quellcode:
Kreispunkt wird mit dem Funktionsaufruf ersetzt und erspart die Variable „Kreispunkt“
ShowFluegel(Nabe, EndPunkt(StrToInt(Ed_Fluegellaenge.Text), Sektorwinkel, Nabe), ClGreen);
Ist aber schlecht zu Kommentieren und für Anfänger nicht Gruß oldmax |
Re: Windmühle, bei der die Flügelanzahl variabel ist
Ich würde dringend empfehlen, folgende Funktionen zu verwenden:
![]() Damit wird das Zeichnen eines Flügels stark vereinfacht. 1.) ein Flügel ist ein Polygon und wird mit Canvas.Polygon(Points: array of TPoint) gezeichnet 2.) die Punkte des Flügel werden auf Karopapier so gezeichnet, dass der Drehpunkt auf (0,0) liegt 3.) jetzt braucht es 2 Operationen, um einen Flügel in beliebiger Richtung und Position zu zeichen 4.) mit Rotate2Darray() werden alle Punkte um den vorgegebenen Winkel gedreht 5.) mit Translate2Darray() wird der Drehpunkt des Flügels (der ja noch immer bei (0,0) liegt) in den Drehpunkt der Windmühle verschoben Diese Vorgehensweise hat viele Vorteile: * wiederverwendbar (taugt auch für Games, Spielkarten, ...) * flexibel (das Flügelprofil in Schritt 2.) kann völlig frei gestaltet werden) * sauber gekapselt (die ganze Mathematik liegt in Rotate2Darray() & Translate2Darray()) * mit etwas Zusatzaufwand kann man die ganze Zeichnung auch zoomen |
Re: Windmühle, bei der die Flügelanzahl variabel ist
So ... sry, dass ich erst jetzt antworte, aber mein Internet hat gestreikt :pale:
Ich habe es jetzt geschafft, die Flügel zu zeichnen, sodass sie in dem richtigen Winkel zueinander stehen. Doch wie könnte es anders sein: Die Drehung scheint noch nicht zu klappen... Die Idee zu der Drehung die ich hatte: die Mühleprozedur in eine TimerRoutine und dann mit Weiß übermalen. Danach den Winkel verändern und mit Schwarz malen. Danach wieder mit weiß, usw. Doch wie verändere ich den Winkel? Ich habe das Bogenmaß 2 pi genommen. Jetzt wollte ich einfach in der zeichenRoutine um ein Grad addieren. Doch es will nicht:
Delphi-Quellcode:
Ich hoffe ihr wollt mir noch helfen. Schließlich hab ich mich ja nicht gemeldet :pale:
unit muehleU;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; const pi=3.1415; type TForm1 = class(TForm) Button1: TButton; Image1: TImage; Edit1: TEdit; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Timer1: TTimer; Button6: TButton; procedure Button1Click(Sender: TObject); procedure Muehle(anzahl,hoehe,x,y:integer); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button6Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; v:integer; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var z:integer; begin z:= StrToInt(Edit1.Text); Muehle (z,150,50,50); end; procedure TForm1.Muehle (anzahl,hoehe,x,y:integer); var flange,nr,x2,y2,FluegelEndeX,FluegelEndeY:integer; begin with Image1.Canvas do begin moveTo (x,y); rectangle (x,y,x+round(hoehe/5),hoehe); moveTo (x+(round(hoehe/5)DIV 2),y+10); x2:= x+(round(hoehe/5)DIV 2); y2:= y+10; flange:= hoehe DIV 2 ; for nr:= 1 to anzahl do begin FluegelEndeX:= x2+round(flange*cos(nr*(2*pi+v)/anzahl)); FluegelEndeY:= y2+round(flange*sin(nr*(2*pi+v)/anzahl)); lineTo (FluegelEndeX,FluegelEndeY); moveTo (x2,y2); end; end; end; procedure TForm1.Button2Click(Sender: TObject); begin Muehle (2,150,50,50); end; procedure TForm1.Button3Click(Sender: TObject); begin Muehle (8,150,50,50); end; procedure TForm1.Button4Click(Sender: TObject); begin Muehle (20,150,50,50); end; procedure TForm1.Button5Click(Sender: TObject); begin Muehle (150,150,50,50); end; procedure TForm1.Timer1Timer(Sender: TObject); begin Image1.Canvas.Pen.Color:= clBlack; Muehle (8,150,50,50); Image1.Canvas.Pen.Color:= clWhite; Muehle (8,150,50,50); Image1.Canvas.Pen.Color:= clBlack; Muehle (8,150,50,50); end; procedure TForm1.Button6Click(Sender: TObject); begin Timer1.Enabled:= true; end; procedure TForm1.FormCreate(Sender: TObject); begin v:= 0 end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz