在画三维立体图之前,主要是先要找到二维和三维的对应关系,这是转化的关键。
关键代码如下:
S[i].x=P[i][1]+sqrt(2)/3.0*(-P[i][0]);
S[i].y=P[i][2]+sqrt(2)/3.0*(-P[i][0]);
一、建立边表结构,在同一屏幕上完成三视图和正等轴测投影图
//消隐之前
//编译环境:Visual C++ 6.0,EasyX_20190219(beta)
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define max 50
#include<iostream>
#include<math.h>
using namespace std;
#define pi 3.14159
using namespace std;
double ja=35.3;//54.7
double rad=(double)ja*pi/(double)180.0;
double Dpoint[][4]={
{0,0,84,1},{110,0,84,1},{110,0,20,1},{140,0,20,1},
{140,0,0,1},{140,80,0,1},{0,80,0,1},{0,80,54,1},
{0,60,54,1},{0,60,84,1},{20,60,84,1},{20,20,84,1},
{110,20,84,1},{110,20,20,1},{60,20,20,1},{60,80,20,1},
{40,80,54,1},{40,60,54,1},{140,80,20,1},{0,0,0,1}
};
//下标从0开始
int ring[]={
0,1,12,11,10,9,//0-5
2,3,18,15,14,13,//6-11
8,17,16,17,//12-15
1,2,13,12,//16-19
3,4,5,18,//20-23
11,14,15,16,17,10,//24-29
11,12,13,14,//30-33
15,18,5,6,7,16,//34-39
9,10,17,8,//40-43
0,9,8,7,6,19,//44-49
0,19,4,3,2,1,//50-55
4,19,6,5//56-59
};
//构成面的顶点
int surface[12][2]={
{0,5},{6,11},{12,15},{16,19},{20,23},{24,29},
{30,33},{34,39},{40,43},{44,49},{50,55},{56,59}
};
//主视图
int XOZ_ring[]={
1,2,14,10,
0,7,16,10,
3,15,17,7,6,4
};
int XOZ_surface[3][2]={
{0,3},{4,7},{8,13}
};
//侧视图
int YOZ_ring[]={
0,2,13,12,
11,10,8,7,15,13,
3,4,5,15
};
int YOZ_surface[3][2]={
{0,3},{4,9},{10,13}
};
//俯视图
int XOY_ring[]={
2,0,9,10,11,12,
3,5,15,14,12,2,
14,15,16,17,10,11,
16,7,9,17
};
int XOY_surface[4][2]={
{0,5},{6,11},{12,17},{18,21}
};
//正等轴投影
int XYZ_ring[]={
3,4,5,18,
5,6,7,16,15,18,
2,3,18,15,14,13,
1,2,13,12,
11,12,13,14,
10,11,14,15,16,17,
7,8,17,16,
8,9,10,17,
0,1,12,11,10,9
};
int XYZ_surface[9][2]={
{0,3},{4,9},{10,15},{16,19},{20,23},{24,29},{30,33},{34,37},{38,43}
};
//三维坐标转换为右手坐标系的二维坐标
void transfer(double P[max][4], int n, POINT S[])
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<3;j++)
{
S[i].x=P[i][1]+sqrt(2)/3.0*(-P[i][0]);
S[i].y=P[i][2]+sqrt(2)/3.0*(-P[i][0]);
}
}
}
//主视图:XOZ面的投影变换,将Z的值给二维坐标的y
void XOZ_Projection(double P[max][4], int n, POINT S[])
{
double T[max][4];//新生成的投影面上的点
int i,j,k;
int TV[4][4]={ {1,0,0,0},{0,0,0,0},{0,0,1,0},{0,0,0,1} };
for(i=0;i<n;i++)
{
for(j=0;j<4;j++)
{ T[i][j]=0;
for(k=0;k<4;k++)
{T[i][j]+=P[i][k]*TV[k][j];}
}
}
for(i=0;i<n;i++)
{
S[i].x=T[i][0];
S[i].y=T[i][2];
}
}
//侧视图:YOZ面的投影变换,将y的值给二维坐标的x, z的值给二维坐标的y
void YOZ_Projection(double P[max][4], int n, POINT S[])
{
double T[max][4];//新生成的投影面上的点
int i,j,k;
int TW[4][4]={ {0,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1} };
for(i=0;i<n;i++)
{
for(j=0;j<4;j++)
{ T[i][j]=0;
for(k=0;k<4;k++)
{T[i][j]+=P[i][k]*TW[k][j];}
}
}
for(i=0;i<n;i++)
{
S[i].x=T[i][1];
S[i].y=T[i][2];
}
}
//俯视图:XOY面的投影变换,将y的值给二维坐标的y, x的值给二维坐标的x
void XOY_Projection(double P[max][4], int n, POINT S[])
{
double T[max][4];//新生成的投影面上的点
int i,j,k;
int TH[4][4]={ {1,0,0,0},{0,1,0,0},{0,0,0,0},{0,0,0,1} };
for(i=0;i<n;i++)
{
for(j=0;j<4;j++)
{ T[i][j]=0;
for(k=0;k<4;k++)
{T[i][j]+=P[i][k]*TH[k][j];}
}
}
for(i=0;i<n;i++)
{
S[i].x=T[i][0];
S[i].y=T[i][1];
}
}
//正等轴投影图:绕Z轴正向旋转α角 ,再绕X轴反向旋转β角,将三维形体向XOZ平面作正投影得到正轴测投影的投影变换矩阵
//三维形体向XOZ平面作正投影,将Z的值给二维坐标的y
void XYZ_Projection(double P[max][4], int n, POINT S[])
{
double T[max][4];//新生成的投影面上的点
int i,j,k;
double TT[4][4]={
{cos(rad),0,-sin(rad)*sin(rad),0},
{-sin(rad),0,-cos(rad)*sin(rad),0},
{0,0,cos(rad),0},
{0,0,0,1}
};
for(i=0;i<n;i++)
{
for(j=0;j<4;j++)
{ T[i][j]=0;
for(k=0;k<4;k++)
{T[i][j]+=P[i][k]*TT[k][j];}
}
}
for(i=0;i<n;i++)
{
S[i].x=T[i][0];
S[i].y=T[i][2];
}
}
int main()
{
initgraph(800,550);
setorigin(220,350);
setaspectratio(1,-1);
line(0,0,180,0);
line(0,0,0,120);
line(0,0,-95,-95);
int i,j,index,k;
POINT points[20];
POINT points1[10];
setcolor(RED);
transfer(Dpoint,20,points);
//画三维立体图
for(i=0;i<12;i++){
k=0;
for(j=surface[i][0];j<=surface[i][1];j++)
{
index=ring[j];
points1[k].x=points[index].x;
points1[k].y=points[index].y;
k++;
}
polygon(points1,k);
}
setcolor(YELLOW);
//画主视图
XOZ_Projection(Dpoint,20,points);
for(i=0;i<3;i++){//3个面
k=0;
for(j=XOZ_surface[i][0];j<=XOZ_surface[i][1];j++)
{
index=XOZ_ring[j];
points1[k].x=-points[index].x;
points1[k].y=points[index].y+230;
k++;
}
polygon(points1,k);
}
//侧视图
YOZ_Projection(Dpoint,20,points);
for(i=0;i<3;i++){//3个面
k=0;
for(j=YOZ_surface[i][0];j<=YOZ_surface[i][1];j++)
{
index=YOZ_ring[j];
points1[k].x=points[index].x+20;
points1[k].y=points[index].y+230;
k++;
}
polygon(points1,k);
}
//俯视图
XOY_Projection(Dpoint,20,points);
for(i=0;i<4;i++){//4个面
k=0;
for(j=XOY_surface[i][0];j<=XOY_surface[i][1];j++)
{
index=XOY_ring[j];
points1[k].x=-points[index].x;
points1[k].y=-points[index].y+210;
k++;
}
polygon(points1,k);
}
//正等轴投影图
XYZ_Projection(Dpoint,20,points);
for(i=0;i<12;i++){
k=0;
for(j=surface[i][0];j<=surface[i][1];j++)
{
index=ring[j];
points1[k].x=-points[index].x+250;
points1[k].y=-(-points[index].y+100)+200;
k++;
}
polygon(points1,k);
}
_getch();
closegraph();
return 0;
}
效果演示:
二、给定点的三维坐标值,建立面表、环表、顶点表三表结构,画出三维物体的消隐图
//消隐之后
//编译环境:Visual C++ 6.0,EasyX_20190219(beta)
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define max 50
#include<iostream>
#include<math.h>
using namespace std;
#define pi 3.14159
using namespace std;
double ja=35.3;//54.7
double rad=(double)ja*pi/(double)180.0;
double Dpoint[][4]={
{0,0,84,1},{110,0,84,1},{110,0,20,1},{140,0,20,1},
{140,0,0,1},{140,80,0,1},{0,80,0,1},{0,80,54,1},
{0,60,54,1},{0,60,84,1},{20,60,84,1},{20,20,84,1},
{110,20,84,1},{110,20,20,1},{60,20,20,1},{60,80,20,1},
{40,80,54,1},{40,60,54,1},{140,80,20,1},{0,0,0,1}
};
//下标从0开始
int ring[]={
0,1,12,11,10,9,//0-5
2,3,18,15,14,13,//6-11
8,17,16,17,//12-15
1,2,13,12,//16-19
3,4,5,18,//20-23
11,14,15,16,17,10,//24-29
11,12,13,14,//30-33
15,18,5,6,7,16,//34-39
9,10,17,8,//40-43
0,9,8,7,6,19,//44-49
0,19,4,3,2,1,//50-55
4,19,6,5//56-59
};
//构成面的顶点
int surface[12][2]={
{0,5},{6,11},{12,15},{16,19},{20,23},{24,29},
{30,33},{34,39},{40,43},{44,49},{50,55},{56,59}
};
//消影
int ring1[]={
3,4,5,18,
5,6,7,16,15,18,
2,3,18,15,14,13,
1,2,13,12,
11,12,13,14,
10,11,14,15,16,17,
7,8,17,16,
8,9,10,17,
0,1,12,11,10,9
};
int surface1[9][2]={
{0,3},{4,9},{10,15},{16,19},{20,23},{24,29},{30,33},{34,37},{38,43}
};
//三维坐标转换为右手坐标系的二维坐标
void transfer(double P[max][4], int n, POINT S[]){
int i,j;
for(i=0;i<n;i++){
for(j=0;j<3;j++){
S[i].x=P[i][1]+sqrt(2)/3.0*(-P[i][0]);
S[i].y=P[i][2]+sqrt(2)/3.0*(-P[i][0]);
}
}
}
//正等轴投影图
void XYZ_Projection(double P[max][4], int n, POINT S[]){
double T[max][4];//新生成的投影面上的点
int i,j,k;
double TT[4][4]={
{cos(rad),0,-sin(rad)*sin(rad),0},
{-sin(rad),0,-cos(rad)*sin(rad),0},
{0,0,cos(rad),0},
{0,0,0,1}
};
for(i=0;i<n;i++){
for(j=0;j<4;j++){
T[i][j]=0;
for(k=0;k<4;k++)
{T[i][j]+=P[i][k]*TT[k][j];}
}
}
for(i=0;i<n;i++){
S[i].x=T[i][0];
S[i].y=T[i][2];
}
}
int main()
{
initgraph(800,550);
setorigin(220,350);
setaspectratio(1,-1);
line(0,0,180,0);
line(0,0,0,120);
line(0,0,-95,-95);
int i,j,index,k;
POINT points[20];
POINT points1[10];
setcolor(RED);
transfer(Dpoint,20,points);
//未消影之前的三维立体图
for(i=0;i<12;i++){
k=0;
for(j=surface[i][0];j<=surface[i][1];j++){
index=ring[j];
points1[k].x=points[index].x;
points1[k].y=points[index].y;
k++;
}
polygon(points1,k);
}
//画三维立体消影图
setcolor(YELLOW);
for(i=0;i<9;i++){
k=0;
for(j=surface1[i][0];j<=surface1[i][1];j++){
index=ring1[j];
points1[k].x=points[index].x+250;
points1[k].y=points[index].y;
k++;
}
polygon(points1,k);
}
setcolor(BLUE);
//正等轴投影图
XYZ_Projection(Dpoint,20,points);
for(i=0;i<9;i++){
k=0;
for(j=surface1[i][0];j<=surface1[i][1];j++){
index=ring1[j];
points1[k].x=-points[index].x+200;
points1[k].y=-(-points[index].y+100)+300;
k++;
}
polygon(points1,k);
}
_getch();
closegraph();
return 0;
}
效果演示:
红色为原图,黄色为消影之后的三维立体图,蓝色为消影后的正等轴侧投影图。