Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi TCanvas : Sinuskurve (https://www.delphipraxis.net/144883-tcanvas-sinuskurve.html)

Kännchen 18. Dez 2009 19:03


TCanvas : Sinuskurve
 
hi Leute. Bestimmt haben schon viele, viele unwissende Fragen zur Darstellung einer Sinusfunktion gestellt. Ich bin leider kein pro aber dafür Blond:D Mein Hauptproblem ist, dass die Sinuskurve nur als gestrichelte Linie oder Punkte dargestellt wird. Ok, eine Lösung hätte ich selber : Bogenmaß nutzen, spich Pie statt Grad. Aber wie genau setz ich das ein? Statt y=a*sin(b*x+c)+d lieber so ?? : y=a*sin(b*detograd(x)+c)+d ? oder y=a*sin(b*x*(Pie/180°)+c)+d ??? Leider hab ich kein Delphi auf meinem Rechner und kann somit nur theoretisch arbeiten. Könnte mir bitte jemand helfen?



Delphi-Quellcode:
procedure TForm1.BitBtn1Click(Sender: TObject);
var h,j,x,e1,e2,e3,e4:integer;
      a,b,c,d,y:real;
begin
     FOR j:=1 to 300 do
      begin
      form1.canvas.pixels[30,30+j]:=clblack;
      if j<=20 then
      begin
      form1.Canvas.Pixels[30-j,30+j]:=clblack;
      form1.Canvas.Pixels[50-j,50-j]:=clblack;
      end;
      end;
      for h:=1 to 550 do
      begin
      form1.canvas.pixels[20+h,320]:=clblack;
      if h<=20 then
      begin
      form1.canvas.pixels[570-h,320+h]:=clblack;
      form1.canvas.pixels[570-h,320-h]:=clblack;
      end;
      end;


      val(edit1.Text,a,e1);
      val(edit2.Text,b,e2);
      val(edit3.Text,c,e3);
      val(edit4.Text,d,e4);
      if (e1<>0) and (e2<>0) and (e3<>0) and (e4<>0) then
      begin
      application.MessageBox('Falsche Eingabe','Fehler',MB_ok);
      end
      else
      begin

         for x:=30 to 550 do
         begin
            y:=a*sin(b*x + c)+d;
            form1.Canvas.Pixels[30+round(100*y),320]:=clblack;
         end;
        end;  


end;
[edit=Luckie]Delphi Code Tags ergänzt. Mfg, Luckie[/edit]

Namenloser 18. Dez 2009 19:23

Re: TCanvas : Sinuskurve
 
Hallo,
Willkommen in der DP :dp:

Erstmal: Bitte benutze für Delphi-Code in deinen Beiträgen das [delphi ]-Tag, sonst ist es echt eine Qual, das zu lesen.

So ganz habe ich ehrlich gesagt beim ersten Lesen nicht verstanden, was der Kern deiner Frage ist - ich habe den Verdacht, dass du hier (evtl. unbewusst) mehrere Fragen gleichzeitig stellst. Versuche immer erst, deine Probleme in Teilprobleme zu zerlegen und dann für jede Frage einen eigenen Thread zu erstellen.

So, kommen wir erst mal zur Sache:
Zitat:

Mein Hauptproblem ist, dass die Sinuskurve nur als gestrichelte Linie oder Punkte dargestellt wird. Ok, eine Lösung hätte ich selber : Bogenmaß nutzen, spich Pie statt Grad. Aber wie genau setz ich das ein?
Ich weiß nicht, ob du hier wirklich die Ursache erkannt hast - du färbst für jeden X-Wert genau einen Pixel ein, wodurch du logischerweise Punkte und keine Linien erhältst - mit dem Bogenmaß hat das rein gar nichts zu tun. Am einfachsten löst du das Problem, indem du nicht auf Delphi-Referenz durchsuchenTCanvas.Pixels direkt zugreifst, sondern die Funktionen Delphi-Referenz durchsuchenTCanvas.MoveTo und Delphi-Referenz durchsuchenTCanvas.LineTo benutzt, um jeweils von einem Punkt zum nächsten eine Linie zu zeichnen.

Du wirst dir aber für dein Koordinatensystem eine andere Einheit als Pixel überlegen müssen - sonst hast du schon nach knapp 3 Pixeln eine 360°-Drehung gemacht. Dazu reicht es aber einfach aus, das Funktionsargument (b*x + c) für die Sinusfunktion durch einen konstanten Wert zu teilen - z.B. 10 - und anschließend das Ergebnis der Gesamtberechnung wieder mit diesem Faktor zu multiplizieren.

Noch eine Kleinigkeit: Es heißt Pi, nicht Pie. Ich war zuerst etwas verwirrt, weil Pie auch eine Methode von TCanvas ist, mit der sich "Tortenstücke" zeichnen lassen.

Kännchen 18. Dez 2009 19:53

Re: TCanvas : Sinuskurve
 
Ok - [delphi ]-Tag benutzen :) gemerkt! Alsooo : Leider darf ich nur Canvas.Pixels nutzen statt Cavas.Moveto und Canvas.Lineto, sonst hätte ich die ja genutz! Vllt entsteht ja deshalb diese gepunktete Linie, welche in keinsterweise einer Sinuskurve gleicht. Nur hab ich null Plan wie ich das löse. Zu der Einheit der x-Achse : wie leg ich am besten die Einheit fest? So das eben 0°- 360° auf meine 520 Pixel lange Linie passt? Geht es wenn ich in meiner For-Schleife die x-Werte durch 360° bzw Pi dividiere? ps: das mit dem Gradmaß in Bogenmaß umändern gab extra mein Informatiklehrer als Denkanstoß an. Leider nannte er nicht wie bzw wo man es nutzt.

Namenloser 18. Dez 2009 20:09

Re: TCanvas : Sinuskurve
 
Zitat:

Zitat von Kännchen
Zu der Einheit der x-Achse : wie leg ich am besten die Einheit fest? So das eben 0°- 360° auf meine 520 Pixel lange Linie passt? Geht es wenn ich in meiner For-Schleife die x-Werte durch 360° bzw Pi dividiere? ps: das mit dem Gradmaß in Bogenmaß umändern gab extra mein Informatiklehrer als Denkanstoß an. Leider nannte er nicht wie bzw wo man es nutzt.

Also eigentlich hat das mit dem Bogenmaß nichts direkt zu tun, da ein Pixel ja nicht überall gleich groß und die Einheit daher sowieso willkürlich ist, aber du kannst natürlich pro Grad ein Pixel nehmen, sodass die Kurve sich dann genau nach 360 Pixeln wiederholt, statt schon nach 3. Wahrscheinlich will dein Lehrer darauf hinaus. Im Grunde ist die Umrechnung vom Grad- ins Bogenmaß nur ein einfacher Dreisatz, x*pi/180, wie du ja oben schon geschrieben hast. Alternativ kannst du die Funktion DegToRad() aus der Unit math verwenden. Natürlich musst du den Funktionswert noch mit dem gleichen Faktor skalieren, sonst ist deine Kurve verzerrt, sprich 360 Pixel breit aber nur 2 Pixel hoch.

Auch dann werden die Punkte zwar immer noch einzeln angezeigt werden, allerdings als erkennbare Kurve.

Wolfgang Mix 18. Dez 2009 20:13

Re: TCanvas : Sinuskurve
 
Dreisatz:

alpha(bogen)/alpha(grad) = 2 pi/360 Grad = pi/180 Grad

oder schau mal hier
Grüß

Wolfgang

isilive 20. Dez 2009 21:25

Re: TCanvas : Sinuskurve
 
Hab mir erlaubt deinen Code mal etwas einzurücken, damit man ihn besser lesen kann.

Delphi-Quellcode:
procedure TForm1.BitBtn1Click(Sender: TObject);
var h,j,x,e1,e2,e3,e4:integer;
      a,b,c,d,y:real;
begin
    FOR j:=1 to 300 do
      begin
      form1.canvas.pixels[30,30+j]:=clblack;
        if j<=20 then
          begin
          form1.Canvas.Pixels[30-j,30+j]:=clblack;
          form1.Canvas.Pixels[50-j,50-j]:=clblack;
          end;
      end;
    for h:=1 to 550 do
      begin
      form1.canvas.pixels[20+h,320]:=clblack;
        if h<=20 then
          begin
          form1.canvas.pixels[570-h,320+h]:=clblack;
          form1.canvas.pixels[570-h,320-h]:=clblack;
          end;
      end;
      val(edit1.Text,a,e1);
      val(edit2.Text,b,e2);
      val(edit3.Text,c,e3);
      val(edit4.Text,d,e4);
      if (e1<>0) and (e2<>0) and (e3<>0) and (e4<>0) then
          application.MessageBox('Falsche Eingabe','Fehler',MB_ok)
        else
          for x:=30 to 550 do
            begin
              y:=a*sin(b*x + c)+d;
              form1.Canvas.Pixels[30+round(100*y),320]:=clblack;
            end;
end;
Im Endeffekt geht es ja nur um diese Zeilen:
Delphi-Quellcode:
for x:=30 to 550 do
  begin
    y:=a*sin(b*x + c)+d;
    form1.Canvas.Pixels[30+round(100*y),320]:=clblack;
  end;
Wie Wolfgang und Namenlozer schon richtig geschrieben haben, muss du dir nur überlegen wie du
1) ein umgerechnetes x zum Einsetzten in die Formel kriegst
2) y skalieren muss damit das Ergebnis passt
3) hast du in Pixels [x,y] etwas stehen das ich nicht verstehe, das kann so nicht stimmen

Denkanstoss:
Delphi-Quellcode:
for x := 30 to 550 do
  begin
    x2 := x / faktor // (weil ich in die sinusformel nicht pixel sondern meinen normalen Wertebereich einsetze
    y := sin(x2);
    y := 100 - (y * streckfaktor);   // damit die sinuskurve auch höher als 1 pixel wird
    canvas.pixels [x,y] := clBlack;
  end
Gibt immer noch eine pixelige Kurve aber sollte funzen. Wenn du cool bist dann kommst du auf den Faktor nicht durch probieren sondern durch nachdenken. :mrgreen:
Weiters muss du aus y einen integer machen bevor du ihn in canvas.pixels verwendest. ZB so: canvas.pixels [x,round(y)] := clBlack;

Warum euer Lehrer euch nicht canvas.lineto verwenden lässt kann ich zwar nicht nachvollziehen, aber egal. Weiters könnte man noch andenken für x kleinere Schritte als 1 zu nehmen, dann würden auch entsprechend mehr Punkte erscheinen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz