如何在屏幕上建立一个x、y、z坐标系…?
我想在窗体上建立一个 x/y/z的坐标系,然后我任意给个3维的顶点,能在这个坐标系中表示出来。或者给2个(x,y,z)的点,在坐标系中能连成线。

解决方案 »

  1.   

    x,y坐标系直接就是横竖的两条线段就可以了
    z坐标系是与x,y成135度角的线段。然后根据xyz的坐标计算出实际显示在屏幕上的坐标。const OX = 200; OY=200;//虚拟坐标系的屏幕坐标原点
    function GetPoint(x,y,z:integer):TPoint;
    begin
      //返回虚拟坐标在屏幕上的坐标
      Result.x := OX + x - integer(z * Sqrt(2) /2)
      Result.x := OY - y + integer(z * Sqrt(2) /2)
    end;
    {$R *.DFM}
      

  2.   

    先setWindowOrgEx,然后画 x,y轴
    然后根据x,z的角度来画Z轴然后剩下的就是sin()cos()了吧?
      

  3.   

    myling:
    看见你的1点信誉就有删除的冲动……
      

  4.   

    我来学习,希望蹭点分  ^_^procedure TForm1.fLine(x,y,z,x1,y1,z1:Integer);
    const
      MX : Integer = 100;
      MY : Integer = 300;
    var
      rx,ry,rx1,ry1: Integer;
    begin
      y := - y;
      y1 := - y1;
      rx := x + trunc(z * sqrt(2)/2);
      ry := y - trunc(z * sqrt(2)/2);
      rx1 := x1 + trunc(z1 * sqrt(2)/2);
      ry1 := y1 - trunc(z1 * sqrt(2)/2);
      with Canvas do
      begin
        pen.Color := clBlack;
        MoveTo(x + MX, y + MY);
        LineTo(rx + MX , ry + MY);
        MoveTo(x1 + MX, y1 + MY);
        LineTo(rx1 + MX , ry1 + MY);    MoveTo(MX,MY);
        LineTo(MX, MY - 1000);
        MoveTo(MX, MY);
        LineTo(MX + 1000, MY);
        pen.Style := psDashDot;
        MoveTo(MX, MY);
        LineTo(MX + 1000, MY - 1000);
        pen.Style := psSolid;
        pen.Color := clblue;
        MoveTo(x + MX, y + MY);
        LineTo(x1 + MX, y1 + MY);
        pen.Color := clRed;
        MoveTo(rx + MX, ry + MY);
        LineTo(rx1 + MX, ry1 + MY);
      end;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
      self.Refresh;
      fline(100,100,strtoint(edit1.text),100,200,strtoint(edit2.text));
    end;
      

  5.   

    to 风舞轻扬) 
       如果我们从正面看过去的话,z就不是和y,x成135度啊。
      如果z是向上的,x向右,y是垂直显示器平面朝里面的,那么这个3维护坐标怎么建立呢?
      

  6.   

    用OPENGL吧:http://218.56.11.178:8020/web/index.aspx-》软件基地-》源码-》delphi/kylix->OpenGL演示例子
      

  7.   

    MoveTo(rx + MX, ry + MY);
    LineTo(rx1 + MX, ry1 + MY);
    是最基本的,不会不会吧?
      

  8.   

    z坐标角度只要明白一个其他的就应该不是问题,我用的z与x,y都成45的
    你把虚线当y,y当z 就应该是你要的
      

  9.   

    to ,九品御厨-进军嵌入式) 
    不是不会moveto,lineto,而是不知道怎么将3d的效果转换到2d平面上来。
    谢谢推荐,你的网站我经常有去看看。我现在要实现这些功能,然后做成activeform在ie中画图,我试过opengl在ie里画不出来(可能是我设置有误吧),但是用canvas就能画出来。opengl和canvas在delphi下都可以画出来,做成activeform后,opengl就不可以了
      

  10.   

    -》软件基地-》源码-》delphi/kylix->OpenGL演示例子
    运行后,我鼠标失灵
    -_|||
      

  11.   

    x向右,y向里,z向上:const OX = 200; OY=200;//虚拟坐标系的屏幕坐标原点
    function GetPoint(x,y,z:integer):TPoint;
    begin
      //返回虚拟坐标在屏幕上的坐标
      Result.x := OX + x + integer(y * Sqrt(2) /2)
      Result.y := OY - z - integer(y * Sqrt(2) /2)
    end;
    只是简单的数学变换而已。
      

  12.   

    to 风舞轻扬) 
       谢谢你的回答,我看过了,你写的程序现在是y和x,z成45度角的。这个是我们用笔在纸上画是这样的,但是严格意义上来说,我们在3维中正面看一个东西,假设z向上,x向右,y向里面的话,如果是正面看一个个东西的话,y的值应该始终为0(看不到的,被x挡住了),假设在xy平面有个正方形,我们看到的只是一条线而已 ,这时为了让眼睛能看到这个正方形,我们必须将yz平面绕x轴旋转,然后可能再将xy平面绕着z轴旋转,这样才能达到眼睛能看到的效果,那么你给的那个例子仅仅是一个特例,它到底绕x旋转了多少,然后又绕z轴旋转了多少呢?就不知道了。
       如果是按上面这种方法建立起来的3维坐标系,那应该是很灵活的一个坐标系了。我们可以意的旋转,然后给个3d点,换算出来,才是真正的3d点。
       我讲的清楚不清楚,是不是将问题复杂化了,希望大家帮帮忙。
      

  13.   

    风老大
    嘿嘿
    没想到现在的俺到了这种境界————男人看见俺也会冲动
    真受不了,嘿嘿,你可一定要把持住呀,否则……lincanwen(密码错误)
    为什么你们都把Z轴向上?不符合平时的思维呀
    高中学的可是y轴向上的说
      

  14.   

    MoveTo(rx + MX, ry + MY);
    LineTo(rx1 + MX, ry1 + MY);
    应该就能搞定了吧
      

  15.   

    你是说任意旋转xyz轴吗?
    这也可以有一个简单的公式算出来的。(如果不用专门API的话,效率上会慢一些)
    但是如果你的要求很复杂的话,建议你学习OPENGL或者DIRECTX。
      

  16.   

    谢谢大家帮忙。
    to 风舞轻扬):
       谢谢你。我的意思就是要能任意旋转xyz轴,因为问题很简单,只是画几条直线而已,所以,如果用Opengl or Directx,就显的很浪费cpu资源了,所以划不来用。
       “这也可以有一个简单的公式算出来的。(如果不用专门API的话,效率上会慢一些)”,不知道你说的这句话能不能说清楚点呢?谢谢。to 阿德) :
       谢谢关心本贴。因为在3D坐标中,好象是x水平,z竖直向上,y垂直显示器朝里或朝外吧。
      

  17.   

    有个例子,很不正规,但能实现两个坐标系之间的巨阵转换
    人眼和坐标动的效果,应该能满足你的要求
    要得化留个mail
      

  18.   

    这个我不会 hehe^^ 没有做过这方面的开发,帮你up吧你的问题不就是传说中的 三维坐标系与二维坐标系的转换吧..... hehe^^搬个板凳开始学习了
      

  19.   

    to (你的笑对我很重要):
       谢谢,我的email: [email protected],希望能给我一份,谢谢。to CDSoftwareWj(95927) :
        呵呵,没错,就是想实现三维坐标系与二维坐标系的转换,这个问题很老吗?我怎么搜索以前的贴子都没有啊。
      

  20.   

    以向右为0度:const OX = 200; OY=200;//虚拟坐标系的屏幕坐标原点
    function GetPoint(x,y,z:integer, Ax,Ay,Az:double):TPoint;
    //ax,ay,az是x,y,z轴在屏幕上的角度:
    begin
      //返回虚拟坐标在屏幕上的坐标
      Result.x := OX + x * cos(ax) + y*cos(ay) +z*cos(az)
      Result.y := OY -( x * sin(ax) + y*sin(ay) +z*sin(az))
    end;
      

  21.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls, Math;type
      TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        Button1: TButton;
        Button2: TButton;
        Edit3: TEdit;
        Label3: TLabel;
        Edit2: TEdit;
        Label2: TLabel;
        EdtX: TEdit;
        EdtY: TEdit;
        EdtZ: TEdit;
        Label1: TLabel;
        Label4: TLabel;
        Label5: TLabel;
        Button3: TButton;
        RadioGroup1: TRadioGroup;
        function ChangePoint(x,y,z:Integer):TPoint;
        function GeneratePoint(x,y,z:Integer):TPoint;
        procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure Button3Click(Sender: TObject);
        procedure RadioGroup1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      orgX,orgY:Integer;  //原点坐标
      xAngle,yAngle:single; //x旋转角度,y旋转角度
      xStart,yStart:integer; //计算每次鼠标拖动的起点位置
      bRate:Boolean;         //是否进行旋转操作。
      
    const uAngle = pi / 180;implementation{$R *.dfm}function TForm1.ChangePoint(x, y, z: Integer): TPoint;
    var x1,y1,z1:integer;
        len:integer;
    begin
    //
        len:=abs(y-orgY);
        if xAngle = pi / 2 then
        begin
           x1:=orgX + x;
           y1:=orgY;
        end
        else
        begin
           y1:=orgY - round(len / (1 + tan(xAngle)));
           x1:=orgX + round(len / (1 + tan(xAngle)) * tan(xAngle));
        end;    len:=abs(y1 - orgY);
        if yAngle = pi / 2 then
        begin
           x1:=orgX;
           y1:=orgY - y;
        end
        else
        begin
           y1:=orgY - round(len / (1 + tan(xAngle)) * tan(yAngle));
           //x1:=orgX + round(len / (1 + tan(xAngle)) * tan(xAngle));
        end;    result.X := x1;
        result.Y := y1;
    end;
      

  22.   

    function TForm1.GeneratePoint(x, y, z: Integer): TPoint;
    var x1,y1,z1:integer;
        ylen:integer;
    begin
    {=========================================================
    计算公式:
        X = (orgX + x) + [(ylen) * sin(xAngle)]
        Y = (orgY - y) - [(ylen) * cos(xAngle) * sin(yAngle)] - abs(z - orgY) * cos(yAngle)
    ==========================================================}
        yAngle:=uAngle * StrToFloat(Trim(Edit2.Text));
        xAngle:=uAngle * StrToFloat(Trim(Edit3.Text));
        ylen := y;
    //    x1 := (orgX) + Round((x + (ylen) * sin(xAngle)) * cos(xAngle));   //旋转Z轴时,X值改变
        x1 := (orgX + x) + Round((ylen) * sin(xAngle));                     //旋转Z轴时,X值不变
        Y1 := (orgY) - Round((ylen) * cos(xAngle) * sin(yAngle)) - Round(z * cos(yAngle));
        Result.X := x1;
        Result.Y := y1;    
    end;procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
        xStart := X;
        yStart := Y;
        bRate := True;
    end;procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    var i:integer;
    begin
        if (not bRate) or (y = yStart) then exit;
        bRate := False;    if abs(y - yStart)>abs(x - xStart) then
        begin
           i := trunc((y - yStart) / 50);
           i := (strtoint(Edit2.Text) + i);
           if i< 0 then
              i := 0
           else if i>90 then
              i :=90;
           Edit2.Text := FloatToStr(i);
        end
        else
        begin
           i := trunc((x - xStart) / 50);
           i := (strtoint(Edit3.Text) + i);
           if i< -90 then
              i := -90
           else if i>90 then
              i :=90;
           Edit3.Text := FloatToStr(i);
        end;
        Button3.Click;
    end;procedure TForm1.Button3Click(Sender: TObject);
    var MyPoint:TPoint;
        TxtFile:TextFile;
        s,tmpStr:String;
        x1,y1,z1,position,Pos1,i,j:Integer;
        Points:Array of Array of Integer;
    begin
        Try
           { AssignFile(TxtFile,'D:\Point.txt');
            Reset(TxtFile);
            Readln(TxtFile,s);   }        if RadioGroup1.ItemIndex = 1 then
                s:='(700,0,0)(0,600,0)(0,0,600)' +
                   '(100,90,20)(140,150,0)(210,160,30)(260,200,58)(365,210,10)(440,180,51)(520,200,7)(570,240,0)(640,320,0)(605,450,0)(610,520,0)' +
                   '(100,90,160)(140,150,100)(210,160,140)(260,200,200)(365,210,110)(440,180,180)(520,200,130)(570,240,160)(640,320,70)(605,450,190)(610,520,100)'
            else
                s:='(700,0,0)(0,600,0)(0,0,600)' +
                   '(300,100,20)(400,140,0)(460,220,30)(490,310,58)(380,470,51)(290,490,7)(210,440,0)(140,385,0)(110,295,0)(140,200,0)(300,100,20)' +
                   '(300,100,200)(400,140,80)(460,220,150)(490,310,198)(380,470,198)(290,490,125)(210,440,108)(140,385,90)(110,295,118)(140,200,130)(300,100,200)';
            if Trim(s) <> '' then
               s := ')' + s + '(';
            PaintBox1.Refresh;
            position := Pos(')(',s);
            j:=High(Points);
            while position > 0 do
            begin
                s := Copy(s,Position + 2,Length(s) - (Position + 1));
                tmpStr := Copy(s,1,Pos(')(',s) - 1);
                if Trim(tmpStr)<>'' then
                begin
                   tmpStr := tmpStr + ',';
                   i := 0;
                   Pos1 := Pos(',',TmpStr);
                   inc(j);
                   SetLength(Points,j + 1,3);
                   while Pos1 > 0 do
                   begin
                       Points[j][i] := StrToInt(Trim(Copy(tmpStr,1,Pos1 - 1)));
                       TmpStr := Copy(TmpStr,Pos1 + 1,Length(TmpStr) - Pos1);
                       Pos1 := Pos(',',TmpStr);
                       inc(i);
                   end;
                end;
                Position := Pos(')(',s);
            end;
            PaintBox1.Canvas.Pen.Style := psSolid;
            PaintBox1.Canvas.Pen.Color:=clblack;
            PaintBox1.Canvas.Pen.Width:=1;
            for i := 0 to 2 do  //画坐标轴
            begin
                MyPoint := GeneratePoint(Points[i][0],Points[i][1],Points[i][2]);
                PaintBox1.Canvas.MoveTo(orgX,orgY);
                PaintBox1.Canvas.LineTo(MyPoint.X,MyPoint.Y);
            end;        PaintBox1.Canvas.Pen.Style := psDot; 
            PaintBox1.Canvas.Pen.Width:=StrToInt(EdtX.Text);
            for i := 3 to 13 do  //画底
            begin
                MyPoint := GeneratePoint(Points[i][0],Points[i][1],Points[i][2]);
                if i=3 then
                   PaintBox1.Canvas.MoveTo(MyPoint.X,MyPoint.Y);
                PaintBox1.Canvas.LineTo(MyPoint.X,MyPoint.Y);
            end;
                    
            PaintBox1.Canvas.Pen.Color:=clgreen;
            for i := 3 to 13 do  //画等值线
            begin
                MyPoint := GeneratePoint(Points[i][0],Points[i][1],Points[i][2] + 50);
                if i=3 then
                   PaintBox1.Canvas.MoveTo(MyPoint.X,MyPoint.Y);
                PaintBox1.Canvas.LineTo(MyPoint.X,MyPoint.Y);
            end;        PaintBox1.Canvas.Pen.Style := psDashDot;
            PaintBox1.Canvas.Pen.Color:=clred;
            for i := 14 to 24 do //画高
            begin
                MyPoint := GeneratePoint(Points[i][0],Points[i][1],Points[i][2]);
                if i=14 then
                   PaintBox1.Canvas.MoveTo(MyPoint.X,MyPoint.Y);
                PaintBox1.Canvas.LineTo(MyPoint.X,MyPoint.Y);
            end;        PaintBox1.Canvas.Pen.Color:=clblack;
            PaintBox1.Canvas.Pen.Width:=2;
            for i := 3 to 13 do //画底和高的连线
            begin
                MyPoint := GeneratePoint(Points[i][0],Points[i][1],Points[i][2]);
                PaintBox1.Canvas.MoveTo(MyPoint.X,MyPoint.Y);
                MyPoint := GeneratePoint(Points[i + 11][0],Points[i + 11][1],Points[i + 11][2]);
                PaintBox1.Canvas.LineTo(MyPoint.X,MyPoint.Y);
            end;    finally
           // CloseFile(TxtFile);
        end;end;procedure TForm1.RadioGroup1Click(Sender: TObject);
    begin
        Button3.Click;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin  
            orgX:=100;
            orgY:=680;  //设置原点位置        xAngle:=0;
            yAngle:=0;  //设置旋转角度
    end;end.
      

  23.   

    窗体文件:
    object Form1: TForm1
      Left = 57
      Top = 201
      Width = 907
      Height = 433
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      WindowState = wsMaximized
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object PaintBox1: TPaintBox
        Left = 0
        Top = 0
        Width = 899
        Height = 406
        Cursor = crHandPoint
        Align = alClient
        OnMouseDown = PaintBox1MouseDown
        OnMouseUp = PaintBox1MouseUp
      end
      object Label3: TLabel
        Left = 323
        Top = 10
        Width = 32
        Height = 13
        Caption = 'xAngle'
      end
      object Label2: TLabel
        Left = 220
        Top = 10
        Width = 31
        Height = 13
        Caption = 'yangle'
      end
      object Label1: TLabel
        Left = 433
        Top = 12
        Width = 5
        Height = 13
        Caption = 'x'
      end
      object Label4: TLabel
        Left = 502
        Top = 12
        Width = 5
        Height = 13
        Caption = 'y'
      end
      object Label5: TLabel
        Left = 575
        Top = 12
        Width = 5
        Height = 13
        Caption = 'z'
      end
      object Button1: TButton
        Left = 0
        Top = 0
        Width = 65
        Height = 25
        Caption = 'reset'
        TabOrder = 0
      end
      object Button2: TButton
        Left = 64
        Top = 0
        Width = 75
        Height = 25
        Caption = 'Draw'
        TabOrder = 1
      end
      object Edit3: TEdit
        Left = 363
        Top = 6
        Width = 59
        Height = 21
        TabOrder = 2
        Text = '30'
      end
      object Edit2: TEdit
        Left = 260
        Top = 6
        Width = 51
        Height = 21
        TabOrder = 3
        Text = '60'
      end
      object EdtX: TEdit
        Left = 441
        Top = 8
        Width = 57
        Height = 21
        TabOrder = 4
        Text = '5'
      end
      object EdtY: TEdit
        Left = 511
        Top = 8
        Width = 57
        Height = 21
        TabOrder = 5
      end
      object EdtZ: TEdit
        Left = 584
        Top = 8
        Width = 57
        Height = 21
        TabOrder = 6
      end
      object Button3: TButton
        Left = 138
        Top = 0
        Width = 75
        Height = 25
        Caption = 'Button3'
        TabOrder = 7
        OnClick = Button3Click
      end
      object RadioGroup1: TRadioGroup
        Left = 648
        Top = -1
        Width = 137
        Height = 33
        Caption = 'RadioGroup1'
        Columns = 2
        ItemIndex = 0
        Items.Strings = (
          '图A'
          '图B')
        TabOrder = 8
        OnClick = RadioGroup1Click
      end
    end