Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Funktionsplotter: Graph falsch herum (https://www.delphipraxis.net/149804-funktionsplotter-graph-falsch-herum.html)

HTC_Magic 30. Mär 2010 17:32


Funktionsplotter: Graph falsch herum
 
Hallo Leute :-D

Wir machen momentan im Infounterricht (Stufe 12)das Projekt Funktionsplotter, für Funktionen 3. Grades. Ich bin schon recht weit(genauer gesagt der der am weitesten ist im Kurs^^), und habe jetzt in den Ferien mal ein bisschen weiter gemacht. Nur habe ich momentan ein fettes Problem: Mein Graph ist immer falsch rum! Es muss sich irgendwo ein Minus eingeschlichen haben - aber ich find's nicht :wall:

Hier mal der Quelltext.
Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,Math;

type
  TFktPlotter = class(TForm)
    ImgGraph: TImage;
    ScrA: TScrollBar;
    ScrB: TScrollBar;
    ScrC: TScrollBar;
    ScrD: TScrollBar;
    LbA: TLabel;
    LbB: TLabel;
    LbC: TLabel;
    LbD: TLabel;
    BtZeichnen: TButton;
    LbTitel: TLabel;
    BtReset: TButton;
    BtBeenden: TButton;
    PnFkt: TPanel;
    LbFunktion: TLabel;
    PnWertA: TPanel;
    PnWertB: TPanel;
    PnWertC: TPanel;
    PnWertD: TPanel;
    Button1: TButton;
    ScrDef: TScrollBar;
    Label1: TLabel;
    PnWertDef: TPanel;
    procedure BtZeichnenClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure BtBeendenClick(Sender: TObject);
    procedure ScrAChange(Sender: TObject);
    procedure ScrBChange(Sender: TObject);
    procedure ScrCChange(Sender: TObject);
    procedure ScrDChange(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ScrDefChange(Sender: TObject);
    procedure BtResetClick(Sender: TObject);

  private
    { Private declarations }
    procedure ZeichneKS;
    procedure Initialisieren;
    procedure ZeichneGraph;
    procedure BeschriftungXAchse;
    //procedure BeschriftungYAchse;
    function XPix(xP:Extended):Integer;
    function YPix(yP:Extended):Integer;
    function f(x:Extended):Extended;
  public
    { Public declarations }
  end;

var
  FktPlotter: TFktPlotter;
  a,b,c,d,def: Extended;

implementation

{$R *.dfm}

procedure TFktPlotter.BtZeichnenClick(Sender: TObject);
begin
  Initialisieren;
  ZeichneKS;
  BeschriftungXAchse;
  //BeschriftungYAchse;
  ZeichneGraph;
end;

procedure TFktPlotter.Initialisieren;
begin
  //Variablen von Scrollbar beziehen
  a:=ScrA.Position/20;
  b:=ScrB.Position/20;
  c:=ScrC.Position/20;
  d:=ScrD.Position/20;
  // Schon eingführt, aber noch deaktiviert
  //def:=ScrDef.Position;
  def:=10;

  PnWertA.Caption:=FloatToStr(a);
  PnWertB.Caption:=FloatToStr(b);
  PnWertC.Caption:=FloatToStr(c);
  PnWertD.Caption:=FloatToStr(d);
  PnWertDef.Caption:=FloatToStr(def);

  LbFunktion.Caption:='f(x)='+FloatToStr(a)+'x³+'+FloatToStr(b)+'x²+'+FloatToStr(c)+'x+'+FloatToStr(d);
end;

procedure TFktPlotter.ZeichneKS;
begin
  ImgGraph.Canvas.Rectangle(0,0,imgGraph.Width-1,ImgGraph.Height-1);
  ImgGraph.Canvas.MoveTo(200,0);
  ImgGraph.Canvas.LineTo(200,400);
  ImgGraph.Canvas.MoveTo(0,200);
  ImgGraph.Canvas.LineTo(400,200);
end;

procedure TFktPlotter.FormActivate(Sender: TObject);
begin
  ZeichneKS;
end;

procedure TFktPlotter.BtBeendenClick(Sender: TObject);
begin
  close;
end;

function TFktPlotter.XPix(xP:Extended):Integer;
begin
  result:=round(200+xP*200/def)
end;

function TFktPlotter.YPix(yP:Extended):Integer;
begin
  result:=round(200+yP*200/def)
end;


function TFktPlotter.f(x:Extended):Extended;
begin
  result:=a*power(x,3)+b*power(x,2)+c*x+d
end;

procedure TFktPlotter.Zeichnegraph;
var
  xP,yP:Integer;
  x,y:Real;
begin
  x:=-1*(def);
  y:=f(x);
  xP:=XPix(x);
  yP:=yPix(y);
  ImgGraph.Canvas.MoveTo(xP,yP);
  x:=x+0.1;
  repeat
    begin
      y:=f(x);
      xP:=XPix(x);
      yP:=XPix(y);
      ImgGraph.Canvas.LineTo(xP,yP);
      x:=x+0.1
    end
  until x>def;
end;

procedure TFktPlotter.ScrAChange(Sender: TObject);
begin
  PnWertA.Caption:=FloatToStr(ScrA.Position/20);
end;

procedure TFktPlotter.ScrBChange(Sender: TObject);
begin
  PnWertB.Caption:=FloatToStr(ScrB.Position/20);
end;

procedure TFktPlotter.ScrCChange(Sender: TObject);
begin
  PnWertC.Caption:=FloatToStr(ScrC.Position/20);
end;

procedure TFktPlotter.ScrDChange(Sender: TObject);
begin
  PnWertD.Caption:=FloatToStr(ScrD.Position/20);
end;

procedure TFktPlotter.ScrDefChange(Sender: TObject);
begin
  PnWertDef.Caption:=FloatToStr(ScrDef.Position);
end;

procedure TFktPlotter.BeschriftungXAchse;
var
ONEstep,StandortX:extended;
ObenY,UntenY:Integer;
begin
  //Breite einer Einheit berechnen
  ONEstep:=200/def;
  StandortX:=200;
  //Y-Koordinaten für Strich
  ObenY:=195;
  UntenY:=205;
  //Bei (0|0) Anfangen, nach links arbeiten
  repeat
    ImgGraph.Canvas.MoveTo(trunc(StandortX),200);
    StandortX:=StandortX-ONEstep;
    ImgGraph.Canvas.MoveTo(trunc(StandortX),200);
    //Strich zeichnen
    ImgGraph.Canvas.LineTo(trunc(StandortX),ObenY);
    ImgGraph.Canvas.LineTo(trunc(StandortX),UntenY);
  until StandortX<0;
  StandortX:=200;
  //Bei (0|0) Anfangen, nach rechts arbeiten
  repeat
    ImgGraph.Canvas.MoveTo(trunc(StandortX),200);
    StandortX:=StandortX+ONEstep;
    ImgGraph.Canvas.MoveTo(trunc(StandortX),200);
    //Strich zeichnen
    ImgGraph.Canvas.LineTo(trunc(StandortX),ObenY);
    ImgGraph.Canvas.LineTo(trunc(StandortX),UntenY);
  until StandortX>400

end;

{procedure TFktPlotter.BeschriftungYAchse;
var
ONEstep,StandortY:extended;
LinksX,RechtsX:Integer;
begin
  //Breite einer Einheit berechnen
  ONEstep:=200/def;
  /////////////////////
  StandortY:=200;
  //X-Koordinaten für den Strich
  LinksX:=195;
  RechtsX:=205;
  //Bei (0|0) Anfangen, nach unten arbeiten
  repeat
    ImgGraph.Canvas.MoveTo(200,trunc(StandortY));
    StandortY:=StandortY-ONEstep;
    ImgGraph.Canvas.MoveTo(200,trunc(StandortY));
    //Strich zeichnen
    ImgGraph.Canvas.LineTo(LinksX,trunc(StandortY));
    ImgGraph.Canvas.LineTo(RechtsX,trunc(StandortY));
  until StandortY>400;
  /////////////////////
  StandortY:=200;
  //Bei (0|0) Anfangen, nach oben arbeiten
  repeat
    ImgGraph.Canvas.MoveTo(200,trunc(StandortY));
    StandortY:=StandortY+ONEstep;
    ImgGraph.Canvas.MoveTo(200,trunc(StandortY));
    //Strich zeichnen
    ImgGraph.Canvas.LineTo(LinksX,trunc(StandortY));
    ImgGraph.Canvas.LineTo(RechtsX,trunc(StandortY));
  until StandortY<0
  ///////////////////
end;        }

procedure TFktPlotter.Button1Click(Sender: TObject);
// Nur für Testzwecke, zum schnelleren Arbeiten
begin
  ScrC.Position:=20;
  ScrD.Position:=20;
  Initialisieren;
  ZeichneKS;
  BeschriftungXAchse;
  //BeschriftungYAchse;
  ZeichneGraph;
end;



procedure TFktPlotter.BtResetClick(Sender: TObject);
begin
  ScrA.Position:=0;
  ScrB.Position:=0;
  ScrC.Position:=0;
  ScrD.Position:=0;
  ScrDef.Position:=0;
  ZeichneGraph;
end;

end.
Nicht wundern, der Regler für den Definitionsbereich ist noch nicht implementiert, und beim zurücksetzten gibts auch noch nen Bug bei der Aktualisierung des Graphs, aber das egal.

Achja, ein weiteres Problem zeigt sich beim Beschriften der Y-Achse, habe da einfach die Prozedur von der Beschriftung der X-Achse umgeschrieben, aber irgendwie klappt es nicht! Das Programm hängt sich, wenn es mit kompiliert wird, auf! Die Beschriftung der X-Achse funktioniert einwandfrei...ich glaube ich hab da irgendwo einen Denkfehler :gruebel:

Könnt ihr da mal drüber gucken :) Das fuchst mich^^

grüße
HTC_Magic

BUG 30. Mär 2010 17:48

Re: Funktionsplotter: Graph falsch herum
 
Kann es sein, dass du nicht berücksichtigst, das bei Delphi bzw. Windows das Koordinatensystem auf dem Kopf steht?

Code:
0--------> x
|
|
|
v y
Wenn ich deinen Code richtig überblicke:
Delphi-Quellcode:
function TFktPlotter.YPix(yP:Extended):Integer;
begin
  result:= ImgGraph.Height-1 - round(200+yP*200/def);
end;
Und in der Schleife benutzt du yP:= XPix(y);, glaub nicht das das gewollt ist.

Matze 30. Mär 2010 17:49

Re: Funktionsplotter: Graph falsch herum
 
Hallo, herzlich Willkommen!

Ich habe gerade keine Zeit, den Source durch zu schauen, aber vielleicht ist das ja schon die Ursache:

Die Koordinate 0/0 eines Canvas liegt oben links (nicht unten links). Evtl. hast du das nicht berücksichtigt und musst die y-Werte nur entsprechend umrechnen:

Delphi-Quellcode:
yWert := yMax - yWert;
Grüße, Matze

Edit: Mist, da war ich zu langsam. ;)

HTC_Magic 30. Mär 2010 17:59

Re: Funktionsplotter: Graph falsch herum
 
Liste der Anhänge anzeigen (Anzahl: 1)
doch, das mit dem amerikanischen Koordinaten System hab ich berücksichtigt...der fehler liegt wohl bei dem yP:= XPix(y) :lol: Cool! Da bestätigt sich wieder die aussage das 4 augen mehr als 2 sehen :-D

Werde es gleich mal ändern und neu kompilieren...

Hatte vergessen die .exe anzuhängen, falls es noch wen interessiert....

Habt ihr auch eine Idee bezügl. der Beschriftung?

HTC_Magic 12. Apr 2010 17:59

Re: Funktionsplotter: Graph falsch herum
 
der graph ist immer noch falsch herum :wall: ich kapier es nicht...da ist nirgendwo ein minus :mrgreen:
und die beschriftung auf der y-Achse geht auch noch nicht-.-

Hat keiner noch einen bzw. den Fehler gefunden?

greetz
HTC_magic

Wolfgang Mix 12. Apr 2010 18:33

Re: Funktionsplotter: Graph falsch herum
 
Schicke einmal bitte das ganze Projekt als ZIP,
dann lässt sich der Fehler leichter einkreisen.

BUG 12. Apr 2010 18:47

Re: Funktionsplotter: Graph falsch herum
 
Zitat:

Zitat von BUG
Delphi-Quellcode:
function TFktPlotter.YPix(yP:Extended):Integer;
begin
  result:= ImgGraph.Height-1 - round(200+yP*200/def);
end;

Hattest du das mal ausprobiert? Ich bin immer noch der Meinung, dass das helfen würde.
Es fehlt sozusagen das Minus.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:42 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