Autor Beitrag
Krefti
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Fr 25.08.06 09:10 
guten morgen zusammen..

mein problem ist folgendes: Ich zeichne auf einem image ein Rechteck und eine Linie in der mitte als x-achse. die länge und höhe des Rechtecks kann variabel eingegeben werden.

im Ursprung dieses Koordinatensystems wird ein Sinus gezeichnet, dessen Amplitude und Periodenzahl man auch variabel eingeben kann. jetzt möchte ich den sinus je nachdem was eingegeben worden ist passend strecken oder stauchen, dass er genau in das rechteck reinpasst.

hier mal mein code den ich bis jetzt habe..schaut vielleicht ein bischen chaotisch aus, aber ich bin no am anfagn :wink:
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:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    edLaenge: TEdit;
    Label2: TLabel;
    edHoehe: TEdit;
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    edPeriode: TEdit;
    edAmplitude: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Malebild(Canvas1:TCanvas);
    procedure Button2Click(Sender: TObject);
    procedure edLaengeKeyPress(Sender: TObject; var Key: Char);
    procedure edHoeheKeyPress(Sender: TObject; var Key: Char);
    procedure Button3Click(Sender: TObject);
    procedure edPeriodeKeyPress(Sender: TObject; var Key: Char);
    procedure edAmplitudeKeyPress(Sender: TObject; var Key: Char);


  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;
  const Pi=3.1415926535897932385;
var
  Form1: TForm1;

implementation

{$R *.dfm}


{------------------------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
begin

    If (edLaenge.Text=''or (edHoehe.Text=''then
      begin
           showmessage('Sie müssen Länge und Höhe eingeben');
           exit;
      end;
       image1.Picture:=nil;
       MaleBild(Image1.Canvas);
end;
{------------------------------------------------------------------------------}
Procedure TForm1.MaleBild(Canvas1:TCanvas);
var
   offx,
   pixelProZoll:Integer;
   pixelpromm:single;
   laenge,hoehe,amplitude,periode: integer;

   x,y,y1,x1,dx : real;
   xx,yy : integer;

   TheRect: TRect;
begin
     laenge:=0;
     hoehe:=0;
     periode:=0;
     amplitude:=0;  
     laenge    := StrToInt(edLaenge.Text);
     hoehe     := StrToInt(edhoehe.Text);
     periode   := StrToInt(edPeriode.Text);
     amplitude := StrToInt(edAmplitude.Text);

     with Canvas1 do begin
        PixelProZoll:=GetDeviceCaps(Canvas1.Handle, LOGPIXELSX);
        PixelProMM:=pixelprozoll/25.4;
        Offx:=GetDeviceCaps(Canvas1.Handle, PHYSICALOFFSETX);

        Pen.Color:=clBlack;
        MoveTo(Round(100*PixelProMM),Round(100*PixelProMM));
        Rectangle(Rect(Round(50*PixelProMM)-offx,
                       Round(25*PixelProMM),
                       Round((50+laenge)*PixelProMM-offx),
                       Round((25+hoehe)*PixelProMM)));

        MoveTo(Round(50*PixelProMM)-offx,Round((25+hoehe/2)*PixelProMM));
        LineTo(Round((50+laenge)*PixelProMM-offx),Round((25+hoehe/2)*PixelProMM));
        x:=0;                              // anfangswert für x= 0
        dx:=0.001;                         // bei der schleife x immer um 0.001 erhöhen

        While x<=(periode * 2 * Pi) do      // so lange bis x die anzahl der perioden mal 2*Pi erreicht hat
          begin
            y:=amplitude * sin(-x);        // errechnung des y wertes
            y1:=y*25+Round((25+hoehe/2)*PixelProMM);     // berrechnung der y koordinate
            x1:=x*25+Round(50*PixelProMM);               // berrechnung der x koordinate
            yy:=trunc(y1);                               // umwandeln der gleitkommazahl in eine ganzzahl
            xx:=trunc(x1);                               // umwandeln der gleitkommazahl in eine ganzzahl
            Pixels[xx,yy]:=clred;                        // das jeweilige pixel rot färben
            x:=x+dx;                                     // den x wert + delta x erhöhen
           end;
         end;
end;
{------------------------------------------------------------------------------}
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;                                                   // programm beenden
end;
{------------------------------------------------------------------------------}
procedure TForm1.edLaengeKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',  #8]) then begin                //man darf nur zahlen eingeben
       showmessage('Sie dürfen nur Zahlen eingeben!');
         key := #0;
         exit;
     end;
end;
{------------------------------------------------------------------------------}

procedure TForm1.edHoeheKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',  #8]) then begin                //man darf nur zahlen eingeben
       showmessage('Sie dürfen nur Zahlen eingeben!');
         key := #0;
         exit;
     end;
end;
{------------------------------------------------------------------------------}
procedure TForm1.edPeriodeKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',  #8]) then begin                 //man darf nur zahlen eingeben
       showmessage('Sie dürfen nur Zahlen eingeben!');
         key := #0;
         exit;
     end;
end;
{------------------------------------------------------------------------------}
procedure TForm1.edAmplitudeKeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in ['0'..'9',  #8]) then begin               //man darf nur zahlen eingeben
       showmessage('Sie dürfen nur Zahlen eingeben!');
         key := #0;
         exit;
     end;
end;
{------------------------------------------------------------------------------}
procedure TForm1.Button3Click(Sender: TObject);
begin
   Printer.BeginDoc;                                          // Druck dokument beginnen
   with printer do begin
      MaleBild(Printer.Canvas);                               // die bild malen funktion auf das gerät drucker zeichnen
   end;
   Printer.EndDoc;                                            // druck dokument beenden
end;
{------------------------------------------------------------------------------}
end.



Moderiert von user profile iconChristian S.: Topic aus VCL (Visual Component Library) verschoben am Fr 25.08.2006 um 09:16
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 27.08.06 00:15 
Wenn die linke-obere Ecke des Rechtecks bei (x0,y0) ist und das Rechteck die Breite/Höhe (w,h) hat sollte die Transformation irgendwie so aussehen (inklusive auf den Kopf gestellt):
(-sin((x-x0)/w*2*pi)+1)/2*h+y0
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Mo 28.08.06 08:42 
vielen dank für die antwort..des hat mir schon sehr weitergeholfen.

in y-richtung füllt der sinus das rechteck aus, aber in x-richtung wird er ganz normal gezeichnet.
im moment zeichnet er so viele Perioden, bis er das ende des rechtecks erreicht hat..wie kann ich die den sinuns in x-richtung strecken oder stauchen??
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:
Procedure TForm1.MaleBild(Canvas1:TCanvas);
var
   offx,
   pixelProZoll:Integer;
   pixelpromm:single;
   laenge,hoehe,periode,amplitude: integer;

   x,y,y1,x1,dx,x0,y0 : real;
   xx,yy : integer;

   TheRect: TRect;
begin
     laenge:=0;
     hoehe:=0;
     periode:=0;
     amplitude:=0;
     laenge    := StrToInt(edLaenge.Text);
     hoehe     := StrToInt(edhoehe.Text);
     periode   := StrToInt(edPeriode.Text);
     amplitude := StrToInt(edAmplitude.Text);

     with Canvas1 do begin
        PixelProZoll:=GetDeviceCaps(Canvas1.Handle, LOGPIXELSX);
        PixelProMM:=pixelprozoll/25.4;
        Offx:=GetDeviceCaps(Canvas1.Handle, PHYSICALOFFSETX);

        Pen.Color:=clBlack;
        Rectangle(Rect(Round(0)-offx,
                       Round(0),
                       Round((laenge)*PixelProMM-offx),
                       Round((hoehe)*PixelProMM)));

        MoveTo(Round(0)-offx,Round((hoehe/2)*PixelProMM));
        LineTo(Round((laenge)*PixelProMM-offx),Round((hoehe/2)*PixelProMM));
        x:=0;                              // anfangswert für x= 0
        dx:=0.001;                         // bei der schleife x immer um 0.001 erhöhen
        x0:=0;
        y0:=0;
        While x<=(laenge*PixelProMM) do      // er zeichnet so viele Perioden, bis er das ende des rechtecks erreicht hat
          begin
            y:=(-sin((x-x0)/laenge*2*pi))/2*hoehe*PixelproMM+y0+hoehe/2*PixelProMM;        // errechnung des y wertes
            y1:=y;     // berrechnung der y koordinate
            x1:=x;     // berrechnung der x koordinate
            yy:=trunc(y1);                               // umwandeln der gleitkommazahl in eine ganzzahl
            xx:=trunc(x1);                               // umwandeln der gleitkommazahl in eine ganzzahl
            Pixels[xx,yy]:=clred;                        // das jeweilige pixel rot färben
            x:=x+dx;                                     // den x wert + delta x erhöhen
           end;
         end;
end;
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 28.08.06 20:42 
Ich dachte der Sinus soll genau ins Rechteck passen? Ich hab dich wohl falsch verstanden.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Di 29.08.06 08:32 
der sinus soll der variabel eingegebenen größe des rechteck angepasst werden..
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 29.08.06 10:22 
Dazu solltest Du Dir eine Abbildungsfunktionen schreiben.

Erstmal befindet sich dein Rechteck irgendwo auf dem Canvas (RX,RY) und hat irgendwelche Abmessungen (RW und RH). Das ist dein 'ViewPoint'. Dann soll die Vertikal von yMin bis yMax, und die Horizontale von Xmin bis XMax laufen. Das sind deine Achsen (oder auch 'real world').

Du brauchst also eine Funktion, die dir zu real world Koordinaten die genaue Pixelposition auf dem Canvas ausrechnet. Dann kannst Du ganz bequem zeichnen.

Mal sehen (Umrechnen P_real (X_real, Y_real) ==> P_pixel (X_pixel, Y_pixel):
ausblenden Quelltext
1:
2:
X_pixel = RX + RW*(X_real - Xmin)/(Xmax - Xmin)
Y_pixel = RY + RH*(Y_real - Ymin)/(Ymax - YMin)

Das sollte doch so funktionieren. Schreib Dir am Besten eine Klasse:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
TPlotter = Class (TCanvas)
Public
  Procedure SetViewPort (XOffset, YOffset, XWidth, YHeight : Cardinal);
  Procedure Axis (Xmin, Xmax, Ymin, Ymax : Extended);
  Procedure Move (X,Y : Extended);
  Procedure Draw (X,y : Extended);
End;


Damit kannst Du dann wunderbar zeichnen.
...
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  myPlotter := TPlotter (MyPaintBox.Canvas); // Geht das so?
  myPlotter.SetViewPort (10,15300,150); // Rechteck an (10,15) und 300x150 pxl groß
  myPlotter.Axis (0,100,-1,1);
  For x:=0 to 1000 do
    if x=0 then 
      myPlotter.move (x, sin(x)) 
    else
      myPlotter.draw (x, sin(x));
...

Das ist doch einfach, oder? Nur die 'Move' und 'Draw' Methoden musst du Dir noch definieren.

_________________
Na denn, dann. Bis dann, denn.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Do 09.11.06 15:32 
habs inzwischen selbst gelöst..