在等轴投影中将3D坐标转换为2D

时间:2015-02-19 13:31:42

标签: c math graphics

我无法将3D坐标转换为2D,然后在C中以等轴投影打印所有点。

我试过了:

u = x / z;
v = y / z;

但是当z = 0时,我的函数进入无限循环。

我也在google上发现了一些东西,但这不适用于负Z(当Z> 0时需要颠簸,Z< 0时需要凹坑)

这是我的工作方式。我的函数获取一个看起来像这样的文件

0 0 0 0 0 0 0 0 0 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 -5 -5 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 9 9 9 9 9 9 9 9 0
0 0 0 0 0 0 0 0 0 0

数字表示z坐标,原点(0; 0; 0)表示左上角。

2 个答案:

答案 0 :(得分:3)

听起来像是在混合概念。如果您将3D原点视为您的相机,并将z = 1平面视为您的屏幕,则除以第三个坐标才有意义。在这种情况下,z = 0的点将被投影到无穷大。通常你有一个视图frustrum来剪辑这样的无限坐标。如果你的输入预计有z = 0,那么那就不行了。

并且在任何情况下,它都不是isometric,因为z轴与所有其他轴的角色不同。等长投影是平行投影的一种特殊情况,而你的划分则表示中心投影,除非它是平面投影变换后的非均匀化步骤。

对于等轴测投影,我建议您尝试以下方法:

u = x*cos(α) + y*cos(α+120°) + z*cos(α-120°)
v = x*sin(α) + y*sin(α+120°) + z*sin(α-120°)

虽然对于C你必须转换为弧度。 α将旋转您的视图,然后选择您想要对齐的东西。如果你选择α作为30°的倍数,你会得到相当不错的数字,只涉及一个简单的平方根。 sin / cos对简单地描述了三个彼此成120°的单位长度矢量。您可以将它们用作3D单位矢量的图像。如果您愿意,也可以将其写为矩阵时间向量乘法。

答案 1 :(得分:1)

这是wikipedia page about isometric projection

上找到的数学方程式的非优化实现

归结为以下功能:

int toIsometric2D(double x, double y,double z, double *u, double*v){
    *u=(x-z)/sqrt(2);
    *v=(x+2*y+z)/sqrt(6);
    return 0;
}

编译以下代码:gcc main.c -o main -lm

#include <stdio.h>
#include <math.h>


int toIsometric2D(double x, double y,double z, double *u, double*v){
    *u=(x-z)/sqrt(2);
    *v=(x+2*y+z)/sqrt(6);
    return 0;
}

int main(){
    int n=10;
    double z[n][n];
    int i,j;

    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            z[i][j]=0;
        }
    }

    for(i=2;i<8;i++){
        for(j=2;j<8;j++){
            z[i][j]=9;
        }
    }

    for(i=4;i<6;i++){
        for(j=4;j<6;j++){
            z[i][j]=-5;
        }
    }

    double u[n][n];
    double v[n][n];

    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            toIsometric2D(i, j,z[i][j], &u[i][j],&v[i][j]);
        }
    }

    //print to file -> gnuplot

    FILE* fp;
    fp=fopen("data.dat","w");
    for(i=0;i<9;i++){
        for(j=0;j<9;j++){
            fprintf(fp,"%g %g %g\n",u[i][j],v[i][j],z[i][j]);
        }
    }

    fclose(fp);
}

它会生成一个文件data.dat,其中包含u v z。它可以通过gnuplot软件按照How to make points one color when a third column equals zero, and another color otherwise, in Gnuplot?的第一个答案显示.gnuplot命令是:

plot[-7:10][-5:15] "data.dat" u 1:2:( $3 ) with points pt 7 ps 3 palette