我在将3D坐标转换为2D时遇到问题,然后在C.中打印等轴测投影中的所有点
我试过这个:
u = x / z;
v = y / z;
但是当z=0时,我的函数进入一个无限循环。
我也在谷歌上找到了一些东西,但这对负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)在左上角。
听起来像是在混合概念。只有当您认为3D原点是您的相机,z=1平面是您的屏幕时,除以第三坐标才有意义。在这种情况下,z=0的点被投影到无穷大。通常,您有一个视图截头体来剪裁这样的无限坐标。如果您的输入被期望为z=0,那么这是不可行的。
在任何情况下,它都不是等角的,因为z轴扮演的角色与所有其他轴不同。等距投影是平行投影的一种特殊情况,而你的除法表示中心投影,除非它是平面投影变换后的去均匀化步骤。
对于等距投影,我建议您尝试以下方法:
u = x*cos(α) + y*cos(α+120°) + z*cos(α-120°)
v = x*sin(α) + y*sin(α+120°) + z*sin(α-120°)
尽管对于C,你必须转换成弧度。α会旋转你的视图,选择你想对齐的东西。如果你选择α作为30°的倍数,你会得到相当好的数字,只涉及一个简单的平方根。sin/cos对简单地描述了彼此相距120°的三个单位长度的矢量。使用这些作为三维单位向量的图像。如果你愿意的话,你也可以把它写成矩阵乘以向量乘法。
以下是维基百科页面上关于等距投影的数学方程的非优化实现
它可以归结为以下功能:
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 %gn",u[i][j],v[i][j],z[i][j]);
}
}
fclose(fp);
}
它生成一个包含u v z
的文件data.dat
。它可以由gnuplot软件显示,方法是按照gnuplot中的第一个答案:当第三列等于零时,如何使点变成一种颜色,否则变成另一种颜色?gnuplot命令是:
plot[-7:10][-5:15] "data.dat" u 1:2:( $3 ) with points pt 7 ps 3 palette