凸多边形的线消隐算法(C++实现)计算机图形学作业

//实验名称:带有线消隐的三维物体投影绘制
//功       能:对于用户输入的三维物体空间信息与选择的投影面(三个坐标面之一),绘制该三维物体在该投影面上的带消隐的投影图
//编译环境:Visual Studio 2022,EasyX_20220116
#include<iostream>
#include<graphics.h>
#include<conio.h>
#include<vector>
using namespace std;

//定义一个结构体表示面表的结点,结点中存储该面所对应的开始结点和结束结点在边表中的下标
struct Face
{
	unsigned start = 0;
	unsigned end = 0;
};

//定义一个点类表示三维坐标系中的坐标点,并定义一个构造函数
struct Point
{
	int x;
	int y;
	int z;

	explicit Point(const int& x = 0, const int& y = 0, const int& z = 0) :x(x), y(y), z(z) {}
};

//消隐投影的主要函数,可以处理不同的三维物体在三个坐标面上的投影图,因此是一个通用函数
void Blanking(void)
{
	//由用户输入的多面体面数创立一个边表
	unsigned FaceNum;
	cout << "请输入该多面体的面数:";
	cin >> FaceNum;
	Face* FaceArray = new Face[FaceNum];

	//由用户输入的多面体顶点数创立一个顶点表,用于存储多面体的每一个顶点
	unsigned PointNum;
	cout << "请输入多面体的顶点数:";
	cin >> PointNum;
	Point* PointArray = new Point[PointNum];
	cout << "请分别输入这些顶点的空间坐标(x,y,z)" << endl;
	for (unsigned i = 0; i < PointNum; i++)
	{
		cin >> PointArray[i].x >> PointArray[i].y >> PointArray[i].z;
	}
	//输出一次点表,方便用户在后续步骤中找出对应点的下标
	cout << "各个顶点及其对应下标如下所示:" << endl;
	for (unsigned i = 0; i < PointNum; i++)
	{
		cout << "下标: " << i << "\t 坐标: " << PointArray[i].x << " " << PointArray[i].y << " " << PointArray[i].z << endl;
	}
	//由于事先难以确定边的总数,因此考虑用向量vector代替数组来表示边表,边表中存储边所对应的点在点表中的下标
	vector<int>SideArray;
	for (unsigned i = 0; i < FaceNum; i++)
	{
		FaceArray[i].start = SideArray.size();
		unsigned SideNum;
		cout << "请输入第" << i + 1 << "个面的边数:";
		cin >> SideNum;
		cout << "请按照顺序输入构成这些边的顶点在顶点表中的下标:";
		for (unsigned j = 0; j < SideNum; j++)
		{
			unsigned pos;
			cin >> pos;
			SideArray.push_back(pos);
		}
		FaceArray[i].end = SideArray.size() - 1;
	}
	//到此为止,三个表:点表、边表和面表都创建完成并完成了初始化工作
	int ProjectionFace;
	//由用户选择想要的消隐投影面
	cout << "单链三表结构建立完成,请选择投影面(1表示xOz面,2表示yOz面,3表示xOy面):";
	cin >> ProjectionFace;
	initgraph(1000, 700);
	//进行一次坐标系转换,由于计算机中的坐标系的原点在屏幕左上角且纵轴方向与数学中纵轴方向相反,因此进行转换,并在画布上绘制出坐标轴
	line(0, 350, 1000, 350);
	line(500, 0, 500, 700);
	setcolor(RED);
	if (ProjectionFace == 1)//第一种情况,投影面为xOz面
	{
		for (unsigned i = 0; i < FaceNum; i++)
		{
			//由于投影面为xOz面,因此纵坐标可以忽略不计,先从点表中取出该面对应的所有点
			int x1 = PointArray[SideArray[FaceArray[i].start]].x;
			int z1 = PointArray[SideArray[FaceArray[i].start]].z;

			int x2 = PointArray[SideArray[FaceArray[i].start + 1]].x;
			int z2 = PointArray[SideArray[FaceArray[i].start + 1]].z;

			int x3 = PointArray[SideArray[FaceArray[i].start + 2]].x;
			int z3 = PointArray[SideArray[FaceArray[i].start + 2]].z;

			//计算判定值,由判定值的正负即可确定该面对于观察者是否可见
			int Eflag = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2);
			if (Eflag > 0)//如果判定值大于零,说明该面对于观察者可见,进行如下操作
			{
				unsigned PointN = FaceArray[i].end - FaceArray[i].start + 1;
				POINT* p = new POINT[PointN];
				//对该面上的点进行投影操作,并转换坐标系
				for (unsigned j = FaceArray[i].start; j <= FaceArray[i].end; j++)
				{
					p[j - FaceArray[i].start].x = PointArray[SideArray[j]].x + 500;
					p[j - FaceArray[i].start].y = 350 - PointArray[SideArray[j]].z;
				}
				//求出投影点后按照原有的拓扑关系对点进行连线操作
				for (unsigned j = 0; j < PointN - 1; j++)
				{
					line(p[j].x, p[j].y, p[j + 1].x, p[j + 1].y);
				}
				line(p[PointN - 1].x, p[PointN - 1].y, p[0].x, p[0].y);
			}
		}
		_getch();
	}
	else if (ProjectionFace == 2)//第二种情况,投影面为yOz面,操作方法与之前类似
	{
		for (unsigned i = 0; i < FaceNum; i++)
		{
			int y1 = PointArray[SideArray[FaceArray[i].start]].y;
			int z1 = PointArray[SideArray[FaceArray[i].start]].z;

			int y2 = PointArray[SideArray[FaceArray[i].start + 1]].y;
			int z2 = PointArray[SideArray[FaceArray[i].start + 1]].z;

			int y3 = PointArray[SideArray[FaceArray[i].start + 2]].y;
			int z3 = PointArray[SideArray[FaceArray[i].start + 2]].z;

			int Eflag = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2);
			if (Eflag > 0)
			{
				unsigned PointN = FaceArray[i].end - FaceArray[i].start + 1;
				POINT* p = new POINT[PointN];
				for (unsigned j = FaceArray[i].start; j <= FaceArray[i].end; j++)
				{
					p[j - FaceArray[i].start].x = PointArray[SideArray[j]].y + 500;
					p[j - FaceArray[i].start].y = 350 - PointArray[SideArray[j]].z;
				};
				for (unsigned j = 0; j < PointN - 1; j++)
				{
					line(p[j].x, p[j].y, p[j + 1].x, p[j + 1].y);
				}
				line(p[PointN - 1].x, p[PointN - 1].y, p[0].x, p[0].y);
			}
		}
		_getch();
	}
	else if (ProjectionFace == 3)//第三种情况,投影面为xOy面,操作方法与之前类似
	{
		for (unsigned i = 0; i < FaceNum; i++)
		{
			int x1 = PointArray[SideArray[FaceArray[i].start]].x;
			int y1 = PointArray[SideArray[FaceArray[i].start]].y;

			int x2 = PointArray[SideArray[FaceArray[i].start + 1]].x;
			int y2 = PointArray[SideArray[FaceArray[i].start + 1]].y;

			int x3 = PointArray[SideArray[FaceArray[i].start + 2]].x;
			int y3 = PointArray[SideArray[FaceArray[i].start + 2]].y;

			int Eflag = (y2 - y1) * (x3 - x2) - (x2 - x1) * (y3 - y2);
			if (Eflag > 0)
			{
				unsigned PointN = FaceArray[i].end - FaceArray[i].start + 1;
				POINT* p = new POINT[PointN];
				for (unsigned j = FaceArray[i].start; j <= FaceArray[i].end; j++)
				{
					p[j - FaceArray[i].start].x = PointArray[SideArray[j]].x + 500;
					p[j - FaceArray[i].start].y = 350 - PointArray[SideArray[j]].y;
				};
				for (unsigned j = 0; j < PointN - 1; j++)
				{
					line(p[j].x, p[j].y, p[j + 1].x, p[j + 1].y);
				}
				line(p[PointN - 1].x, p[PointN - 1].y, p[0].x, p[0].y);
			}
		}
		_getch();
	}
	return;
}

int main(void)
{
	Blanking();
	return 0;
}
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于图形 的二次图形消隐和相关文档 长方体的自隐藏线消隐上机指导 1. 实验目的与要求:掌握长方体的表面模型的建立;掌握三维图形的显示流程;掌握长方体自消隐算法。 2. 实验步骤: (1)长方体表面模型的定义 三维齐次坐标结构的定义,面结构的定义,面结构中添加可见性属性;顶点表的定义,面表、与顶点表的关系。 (2)几何变换的实现 分别对顶点进行绕X轴旋转和绕Y轴旋转,旋转角度为参数,以实现轴测投影。 (3)消隐 计算每个面的外法向量,与视向量进行点积,给该面的可见性属性赋值。 (4)投影变换的实现 平行投影中正投影的投影变换公式及矩阵,要求以XOY平面为投影平面,Z轴正方向为视线方向。 (3)窗口-视区变换的实现 窗口大小的选取——一般将所有图形都取在窗口内;注意投影变换时投影平面的选取,投影平面上的坐标与视区坐标x,y的对应。 (4)图形显示 显示面表中的每一个面,对于不可见面用虚线绘制该面各边,对于可见面用实线绘制各边。 3. 具体任务 在已给出程序Draw3D2中,在视图类中分别添加绕X轴旋转和绕Y轴旋转的函数void RotateX(int angle)和void RotateY(int angle);在视图类中添加计算外法向量的函数HOMOCOORD GetN(HOMOCOORD p1, HOMOCOORD p2, HOMOCOORD p3),其返回值为外法向量。注意面结构中添加的可见性属性,注意显示图形时对于不可见和可见面的处理。 4. 说明 绕X轴的旋转变化的公式实现: 考虑到旋转变化不影响w分量,可得 其他变换类似。对顶点表每个顶点进行更新。 计算外法向量函数的: P1,p2,p3为面上逆时针依次相连的三个顶点,由此外法向量N=(p2-p1)×(p3-p2); 若令x1=p2.x-p1.x, y1=p2.y-p1.y, z1=p2.z-p1.z; x2=p3.x-p2.x, y2=p3.x-p2.x, z2=p3.x-p2.x; 则外法向量可以由下列行列式求出 即

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值