欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计算机图形学:多边形裁剪算法-Sutherland—Hodgman算法

程序员文章站 2024-03-16 20:03:10
...

 

/*
1、顶点Pi在内侧,前一顶点Pi-1也在内侧,则将Pi纳入新的顶点序列;
2、顶点Pi在内侧,前一顶点Pi-1在外侧,则先求交点Q,再将Q、Pi依次纳入新的顶点序列;
3、顶点Pi在外侧,前一顶点Pi-1在内侧,则先求交点Q,再将Q纳入新的顶点序列;
4、顶点Pi与前一顶点Pi-1均在外侧,则顶点序列中不增加新的顶点。
*/

/*
函数定义在CPolygon类中;
数组pt存放原多边形的顶点;
n为多边形的顶点个数,第一个顶点和最后一个顶点相同,因此实际多边形的顶点个数为n-1。
*/
void CPolygon::SutherlandHodgman(double wxl, double wyt, double wxr, double wyb)//裁剪边界:左、上、右、下
{
	CP2 B[100], C[100];   //定义两个临时数组,用于每次裁剪后新生成的多边形顶点
	UINT m_nA, m_nB;
	int x, y;
	long tem1, tem2;
	int i;

	//原始多边形顶点个数
	//原始多边形顶点数组的第一个顶点和最后一个顶点相同,因此实际顶点个数为n-1
	m_nA = n-1;    
	m_nB = 0;      //新生成多边形顶点个数
	
	//左边界---------------------------------------------
	for (i = 0; i < m_nA; i++) {
		if (pt[i].x < wxl&&pt[i + 1].x < wxl) { //多边形两个顶点都在外部
			continue;
		}
		else if (pt[i].x >= wxl && pt[i + 1].x >= wxl) { //多边形两个顶点都在内部,保留第一个点
			/*
			    因为每个保留的点在数组中只出现一次,且下一次判断时第二个端点一定会要取到
			因此只保留两个点中的第一个
			*/
			B[m_nB].x = pt[i].x;
			B[m_nB].y = pt[i].y;
			m_nB++;
		}
		else if (pt[i].x < wxl && pt[i + 1].x >= wxl) { //两个端点起点在外部,终点在内部
			//求交点,然后交点送入临时数组
			x = wxl; 
			y = (wxl - pt[i].x) * (pt[i + 1].y - pt[i].y) / (pt[i + 1].x - pt[i].x) + pt[i].y;//y = x*dy/dx+y0
			
			B[m_nB].x = x;
			B[m_nB].y = y;
			m_nB++;
		}
		else if (pt[i].x >= wxl && pt[i + 1].x < wxl) { //两个端点起点在内部,终点在外部
			//求交点,起点和交点送入临时数组

			//保留起点
			B[m_nB].x = pt[i].x;
			B[m_nB].y = pt[i].y;
			m_nB++;

			//保留交点
			x = wxl;
			y = (wxl - pt[i].x) * (pt[i + 1].y - pt[i].y) / (pt[i + 1].x - pt[i].x) + pt[i].y;

			B[m_nB].x = x;
			B[m_nB].y = y;
			m_nB++;
		}
	}

	//把第一个点的数据拷贝到最后,形成第一次裁剪后的多边形
	if (i == m_nA) {
		B[m_nB] = B[0];
	}
	

	//上边界-------------------
	m_nA = 0;
	for (i = 0; i < m_nB; i++) {
		if (B[i].y < wyt&&B[i + 1].y < wyt) {  //两个都在边界上方(外部)
			continue;
		}
		else if (B[i].y >= wyt && B[i + 1].y >= wyt) { //都在上边界下方,保留起点
			C[m_nA].x = B[i].x;
			C[m_nA].y = B[i].y;
			m_nA++;
		}
		else if (B[i].y < wyt && B[i + 1].y >= wyt) { //起点在上,终点在下,保留交点
			y = wyt;
			x = (wyt - B[i].y) * (B[i + 1].x - B[i].x) / (B[i + 1].y - B[i].y) + B[i].x;//x = y*dx/dy+x0;

			C[m_nA].x = x;
			C[m_nA].y = y;
			m_nA++;
		}
		else if (B[i].y >= wyt && B[i + 1].y < wyt) {////起点在下,终点在上,保留起点、交点
			//保留起点
			C[m_nA].x = B[i].x;
			C[m_nA].y = B[i].y;
			m_nA++;

			//保留交点
			y = wyt;
			x = (wyt - B[i].y) * (B[i + 1].x - B[i].x) / (B[i + 1].y - B[i].y) + B[i].x;

			C[m_nA].x = x;
			C[m_nA].y = y;
			m_nA++;
		}
	}
	//形成第二次裁剪多边形
	if (i == m_nB) {
		C[m_nA] = C[0];
	}

	//右边界----------------------------------------------
	m_nB = 0;
	for (i = 0; i < m_nA; i++) {
		if (C[i].x > wxr && C[i + 1].x > wxr) {  //都在右边界右方
			continue;
		}
		else if (C[i].x <= wxr && C[i + 1].x <= wxr) {//都在右边界左方,保留起点
			B[m_nB].x = C[i].x;
			B[m_nB].y = C[i].y;
			m_nB++;
		}
		else if (C[i].x > wxr && C[i + 1].x <= wxr) { //起点在右方,终点在左方,保留交点
			x = wxr;
			y = C[i].y - (C[i].x - wxr) * (C[i + 1].y - C[i].y) / (C[i + 1].x - C[i].x);//y = y0-x*dy/dx;

			B[m_nB].x = x;
			B[m_nB].y = y;
			m_nB++;
		}
		else if (C[i].x <= wxr && C[i + 1].x > wxr) { //起点在左方,终点在右方,保留起点、交点
			//保留起点
			B[m_nB].x = C[i].x;
			B[m_nB].y = C[i].y;
			m_nB++;

			//保留交点
			x = wxr;
			y = C[i].y - (C[i].x - wxr) * (C[i + 1].y - C[i].y) / (C[i + 1].x - C[i].x);
			
			B[m_nB].x = x;
			B[m_nB].y = y;
			m_nB++;
		}
	}
	//三次裁剪后的新多边形
	if (i == m_nA) {
		B[m_nB] = B[0];
	}

	//下边界---------------------------------
	m_nA = 0;
	for (i = 0; i < m_nB; i++) {
		if (B[i].y > wyb && B[i + 1].y > wyb) {  //都在下边界下方
			continue;
		}
		else if (B[i].y <= wyb && B[i + 1].y <= wyb) { //都在下边界上方,保留起点
			C[m_nA].x = B[i].x;
			C[m_nA].y = B[i].y;
			m_nA++;
		}
		else if (B[i].y > wyb && B[i + 1].y <= wyb) { //起点在下方,终点在上方,保留交点
			y = wyb;
			x = B[i].x - (B[i].y - wyb) * (B[i + 1].x - B[i].x) / (B[i + 1].y - B[i].y);//x = x0-y*dx/dy;

			C[m_nA].x = x;
			C[m_nA].y = y;
			m_nA++;
		}
		else if (B[i].y <= wyb && B[i + 1].y > wyb) { //起点在上方,终点在下方,保留起点、交点
			//保留起点
			C[m_nA].x = B[i].x;
			C[m_nA].y = B[i].y;
			m_nA++;

			//保留交点
			y = wyb;
			x = B[i].x - (B[i].y - wyb) * (B[i + 1].x - B[i].x) / (B[i + 1].y - B[i].y);

			C[m_nA].x = x;
			C[m_nA].y = y;
			m_nA++;
		}
	}
	//形成裁剪后的多边形
	if (i == m_nB) {
		C[m_nA] = C[0];
	}

	//把新多边形顶点放回原多边形顶点数组
	pt = new CP2[m_nA+1];
	for (int i = 0; i <= m_nA; i++) {
		pt[i].x = C[i].x;
		pt[i].y = C[i].y;
	}
	n = m_nA+1;
}