Homepage von Thomas Schwobe
Home Software Quelltext Impressum Datenschutzerklärung

Quelltext:

unit ChartUnit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    TrackBar3: TTrackBar;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
    procedure TrackBar3Change(Sender: TObject);
  private
    procedure Rotate(alpha, beta, gamma: Integer);
  public
    
  end;

  TVector = array of Extended;

  TMatrix = record
    cols: Integer;
    rows: Integer;
    data: array of TVector;
  end;

  TPoint3D = record
    X, Y, Z: Extended;
  end;

var
  Form1: TForm1;

  P0, Pox, Poy, Poz, Px, Py, Pz: TPoint3D;
  oData, Data: array of array of TPoint3D;
  
implementation

{$R *.dfm}

function clearmatrix: TMatrix;
begin
  result.cols:=0;
  result.rows:=0;
  result.data:=nil;
end;

function creatematrix(cols, rows: Integer): TMatrix;
var i, j: Integer;

begin
  result.cols:=cols;
  result.rows:=rows;
  SetLength(result.data, cols);

  for i:=0 to cols-1 do
  begin
    SetLength(result.data[i], rows);

    for j:=0 to rows-1 do
      result.data[i, j]:=0;
  end;
end;

procedure destroymatrix(var mx: TMatrix);
var i: Integer;

begin
  for i:=0 to mx.cols-1 do
    Finalize(mx.data[i]);

  Finalize(mx.data);

  mx:=clearmatrix;
end;

procedure fillmatrix(var mx: TMatrix; value: Extended);
var i, j: Integer;

begin
  for j:=0 to mx.rows-1 do
    for i:=0 to mx.cols-1 do
      mx.data[i, j]:=value;
end;

function multmatrix(mxA, mxB: TMatrix): TMatrix;
var ai, aj, bi, bj: Integer;

begin
  result:=clearmatrix;

  if (mxA.cols<>mxB.rows) then
    Exit;

  result:=creatematrix(mxB.cols, mxA.rows);

  fillmatrix(result, 0);

  for aj:=0 to mxA.rows-1 do
    for bi:=0 to mxB.cols-1 do
      for ai:=0 to mxA.cols-1 do //weil: mxA.cols=mxB.rows
      begin
        bj:=ai;
        result.data[bi, aj]:=result.data[bi, aj]+mxA.data[ai, aj]*mxB.data[bi, bj];
      end
end;

//

function XSin(angle: Extended): Extended;
begin
  result:=Sin((angle*Pi)/180);
end;

function XCos(angle: Extended): Extended;
begin
  result:=Cos((angle*Pi)/180);
end;

function Point3D(X, Y, Z: Extended): TPoint3D;
begin
  result.X:=X;
  result.Y:=Y;
  result.Z:=Z;
end;

function RotateMatrix(X, Y, Z: Extended; alpha: Extended): TMatrix;
begin
  result:=creatematrix(4, 4);
                  
  with result do
  begin
    data[0, 0]:=Sqr(X)*(1-XCos(alpha))+XCos(alpha);
    data[0, 1]:=X*Y*(1-XCos(alpha))+Z*XSin(alpha);
    data[0, 2]:=X*Z*(1-XCos(alpha))-Y*XSin(alpha);
    data[0, 3]:=0;

    data[1, 0]:=X*Y*(1-XCos(alpha))-Z*XSin(alpha);
    data[1, 1]:=Sqr(Y)*(1-XCos(alpha))+XCos(alpha);
    data[1, 2]:=Y*Z*(1-XCos(alpha))+X*XSin(alpha);
    data[1, 3]:=0;

    data[2, 0]:=X*Z*(1-XCos(alpha))+Y*XSin(alpha);
    data[2, 1]:=Y*Z*(1-XCos(alpha))-X*XSin(alpha);
    data[2, 2]:=Sqr(Z)*(1-XCos(alpha))+XCos(alpha);
    data[2, 3]:=0;

    data[3, 0]:=0;
    data[3, 1]:=0;
    data[3, 2]:=0;
    data[3, 3]:=1;
  end;
end;

function XRotateMatrix(alpha: Extended): TMatrix;
begin
  result:=creatematrix(4, 4);

  with result do
  begin
    data[0, 0]:=1;
    data[0, 1]:=0;
    data[0, 2]:=0;
    data[0, 3]:=0;

    data[1, 0]:=0;
    data[1, 1]:=XCos(alpha);
    data[1, 2]:=-XSin(alpha);
    data[1, 3]:=0;

    data[2, 0]:=0;
    data[2, 1]:=XSin(alpha);
    data[2, 2]:=XCos(alpha);
    data[2, 3]:=0;

    data[3, 0]:=0;
    data[3, 1]:=0;
    data[3, 2]:=0;
    data[3, 3]:=1;
  end;
end;

function YRotateMatrix(alpha: Extended): TMatrix;
begin
  result:=creatematrix(4, 4);

  with result do
  begin
    data[0, 0]:=XCos(alpha);
    data[0, 1]:=0;
    data[0, 2]:=XSin(alpha);
    data[0, 3]:=0;

    data[1, 0]:=0;
    data[1, 1]:=1;
    data[1, 2]:=0;
    data[1, 3]:=0;

    data[2, 0]:=-XSin(alpha);
    data[2, 1]:=0;
    data[2, 2]:=XCos(alpha);
    data[2, 3]:=0;

    data[3, 0]:=0;
    data[3, 1]:=0;
    data[3, 2]:=0;
    data[3, 3]:=1;
  end;
end;

function ZRotateMatrix(alpha: Extended): TMatrix;
begin
  result:=creatematrix(4, 4);

  with result do
  begin
    data[0, 0]:=XCos(alpha);
    data[0, 1]:=-XSin(alpha);
    data[0, 2]:=0;
    data[0, 3]:=0;

    data[1, 0]:=XSin(alpha);
    data[1, 1]:=XCos(alpha);
    data[1, 2]:=0;
    data[1, 3]:=0;

    data[2, 0]:=0;
    data[2, 1]:=0;
    data[2, 2]:=1;
    data[2, 3]:=0;

    data[3, 0]:=0;
    data[3, 1]:=0;
    data[3, 2]:=0;
    data[3, 3]:=1;
  end;
end;

function Point3DToPoint2D(X, Y, Z: Extended): TPoint; overload;
begin
  result.x:=Round(1000*X/(1000+Z));
  result.y:=Round(1000*Y/(1000+Z));
end;
 
function Point3DToPoint2D(Point3D: TPoint3D): TPoint; overload;
begin
  result.x:=Round(1000*Point3D.X/(1000+Point3D.Z));
  result.y:=Round(1000*Point3D.Y/(1000+Point3D.Z));
end;

procedure Line(Canvas: TCanvas; pt1, pt2: TPoint);
begin
  Canvas.MoveTo(pt1.x, pt1.y);
  Canvas.LineTo(pt2.x, pt2.y);
end;

procedure TForm1.FormCreate(Sender: TObject);
var x, y, z: Integer;

begin
  P0:=Point3D(0,0,0);
  Pox:=Point3D(100,0,0);
  Poy:=Point3D(0,100,0);
  Poz:=Point3D(0,0,100);
  Px:=Point3D(100,0,0);
  Py:=Point3D(0,100,0);
  Pz:=Point3D(0,0,100);

  Randomize;

  SetLength(oData, 25);
  SetLength(Data, 25);

  for z:=0 to 24 do
  begin
    SetLength(oData[z], 25);
    SetLength(Data[z], 25);

    for x:=0 to 24 do
    begin
      if x=0 then
      begin
        if z=0 then
          Data[z, x]:=Point3D(x*4, Random(80), z*4)
        else
          Data[z, x]:=Point3D(x*4, Data[z-1, x].Y+Min(100, (Random(10)-5)), z*4);
      end
      else
        Data[z, x]:=Point3D(x*4, Data[z, x-1].Y+Min(100, (Random(10)-5)), z*4);

      oData[z, x]:=Data[z, x];
    end;
  end;
end;

procedure TForm1.FormPaint(Sender: TObject);
var x, y, z: Integer;
    pt0, ptx, pty, ptz: TPoint;

begin
  SetMapMode(Canvas.handle, MM_ISOTROPIC);
  SetWindowExtEx(Canvas.handle, ClientWidth, ClientHeight, nil); //darzustellende Punkte x,y
  SetViewportExtEx(Canvas.handle, ClientWidth, -ClientHeight, nil); //kippen
  SetViewportOrgEx(Canvas.handle, ClientWidth div 2, ClientHeight div 2, nil); //Nullpunkt

  pt0:=Point3DToPoint2D(P0);
  ptx:=Point3DToPoint2D(Px);
  pty:=Point3DToPoint2D(Py);
  ptz:=Point3DToPoint2D(Pz);

  Canvas.Pen.Color:=clBlack;

  Line(Canvas, pt0, ptx); Canvas.TextOut(ptx.x, ptx.y, 'X');
  Line(Canvas, pt0, pty); Canvas.TextOut(pty.x, pty.y, 'Y');
  Line(Canvas, pt0, ptz); Canvas.TextOut(ptz.x, ptz.y, 'Z');

  for z:=0 to 24 do
  begin
    Canvas.Pen.Color:=RGB($FF, $FF-z*5, z*5);

    for x:=0 to 23 do
      Line(Canvas, Point3DToPoint2D(Data[z, x]), Point3DToPoint2D(Data[z, x+1]));
  end;
end;

procedure TForm1.Rotate(alpha, beta, gamma: Integer);
var x, y, z: Integer;
    Rx, Ry, Rz, Rt, Rm, Xm, Xim, Ym, Yim, Zm, Zim: TMatrix;

    procedure FillM(var M: TMatrix; P: TPoint3D);
    begin
      M.data[0, 0]:=P.X;
      M.data[0, 1]:=P.Y;
      M.data[0, 2]:=P.Z;
      M.data[0, 3]:=0;
    end;

    function TurnP(P: TPoint3D): TPoint3D;
    var M, Mi: TMatrix;
    
    begin
      M:=creatematrix(1, 4);
      FillM(M, P);
      Mi:=multmatrix(Rm, M);

      result:=Point3D(Mi.data[0,0],Mi.data[0,1],Mi.data[0,2]);

      destroymatrix(M);
      destroymatrix(Mi);
    end;

begin
  Rx:=XRotateMatrix(-alpha);
  Ry:=YRotateMatrix(beta);
  Rz:=ZRotateMatrix(gamma);

  Rt:=multmatrix(Rx, Ry);
  Rm:=multmatrix(Rt, Rz);

  Px:=Pox;
  Py:=Poy;
  Pz:=Poz;

  Px:=TurnP(Px);
  Py:=TurnP(Py);
  Pz:=TurnP(Pz);

  for z:=0 to 24 do
    for x:=0 to 24 do
      Data[z, x]:=oData[z, x];

  for z:=0 to 24 do
    for x:=0 to 24 do
      Data[z, x]:=TurnP(Data[z, x]);

  destroymatrix(Rx);
  destroymatrix(Ry);
  destroymatrix(Rz);
  destroymatrix(Rt);
  destroymatrix(Rm);

  Invalidate;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  Label1.Caption:='X: '+inttostr(TrackBar1.Position);
  Rotate(TrackBar1.Position, TrackBar2.Position, TrackBar3.Position);
end;

procedure TForm1.TrackBar2Change(Sender: TObject);
begin
  Label2.Caption:='Y: '+inttostr(TrackBar2.Position);
  Rotate(TrackBar1.Position, TrackBar2.Position, TrackBar3.Position);
end;

procedure TForm1.TrackBar3Change(Sender: TObject);
begin
  Label3.Caption:='Z: '+inttostr(TrackBar3.Position);
  Rotate(TrackBar1.Position, TrackBar2.Position, TrackBar3.Position);
end;

end.
 


object Form1: TForm1
  Left = 226
  Top = 103
  Caption = 'Form1'
  ClientHeight = 601
  ClientWidth = 854
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OnCreate = FormCreate
  OnPaint = FormPaint
  TextHeight = 13
  object Label1: TLabel
    Left = 32
    Top = 8
    Width = 7
    Height = 13
    Caption = 'X'
  end
  object Label2: TLabel
    Left = 32
    Top = 128
    Width = 7
    Height = 13
    Caption = 'Y'
  end
  object Label3: TLabel
    Left = 32
    Top = 248
    Width = 7
    Height = 13
    Caption = 'Z'
  end
  object TrackBar1: TTrackBar
    Left = 24
    Top = 24
    Width = 25
    Height = 97
    Max = 360
    Orientation = trVertical
    TabOrder = 0
    TickMarks = tmBoth
    TickStyle = tsNone
    OnChange = TrackBar1Change
  end
  object TrackBar2: TTrackBar
    Left = 24
    Top = 144
    Width = 25
    Height = 97
    Max = 360
    Orientation = trVertical
    TabOrder = 1
    TickMarks = tmBoth
    TickStyle = tsNone
    OnChange = TrackBar2Change
  end
  object TrackBar3: TTrackBar
    Left = 24
    Top = 264
    Width = 25
    Height = 97
    Max = 360
    Orientation = trVertical
    TabOrder = 2
    TickMarks = tmBoth
    TickStyle = tsNone
    OnChange = TrackBar3Change
  end
end

© 2025 by Thomas Schwobe