对称算法(计算机图形学)

#include<iostream>
#include<gl/glut.h>
using namespace std;

/*
    对于任意直线的二维图形对称变化的实验,要求输入的直线是任意直线,直线的端点只能由键盘输入或者鼠标拾取,
	要做对称变换的图形也是一个任意图形(至少应是一个任意多边形)。

	对称变换,先分析如何使用一系列简单变换来构造题目要求的复合变换。本体要实现的变换可以用如下一组变换组合来实现:
	① 将直线任一点移至与坐标原点重合
	② 将平移后的直线绕原点旋转至与某一坐标轴重合
	③ 将题目要求的对称变换转为实现已知图形关于上述坐标轴的对称变换
	④ 按逆序求上述①、②变换的逆变换
	⑤ 将上述矩阵依次相乘得到最终的复合变换矩阵

则某一多边形关于任意直线的对称变换就转变为将该多边形的各顶点与上述求得的复合变换进行矩阵乘法,求得变换后的新多边形的各个顶点坐标。
*/

void Initial(void)
{
	glClearColor(1.0f,1.0f,1.0f,1.0f);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0,200.0,0.0,150.0);
}

class CPoint
{
	public:
	int x;
	int y;

	CPoint(){}

	CPoint(int x1,int y1)
	{
		x=x1;
		y=y1;
	}

	static CPoint ZeroMoveToXY(CPoint p, CPoint XY);//原始坐标向屏幕坐标XY的平移
	static CPoint ToZero(CPoint p);//关于原点对称
	static CPoint XYMoveToZero(CPoint p, CPoint XY);//XY坐标向屏幕坐标的平移
	static CPoint Charge_AllLine(CPoint p, CPoint line_start, CPoint line_end);//关于Ax+By+C = 0对称
};


CPoint CPoint::ZeroMoveToXY(CPoint p, CPoint XY)
{
	//原始坐标向屏幕坐标XY的平移
	CPoint result;
	int change[3][3] = {{1,0,0},{0,1,0},{-XY.x,-XY.y,1}};
	int p1[3] = {0,0,0};

	for (int j = 0;j < 3;j++)
	{
	   p1[j]=p.x * change[0][j] + p.y * change[1][j] + change[2][j];
	}

	result.x = p1[0];
	result.y = p1[1];

	return result;
}


CPoint CPoint::ToZero(CPoint p)
{
	//关于原点对称
	CPoint result;
	int change[3][3] = {{-1,0,0},{0,-1,0},{0,0,1}};
	int p1[3] = {0,0,0};

	for (int j = 0;j < 3;j++)
	{
    	p1[j]=p.x * change[0][j] + p.y * change[1][j] + change[2][j];
	}

	result.x = p1[0];
	result.y = p1[1];

	return result;
}


CPoint CPoint::XYMoveToZero(CPoint p, CPoint XY)
{
	//XY坐标向屏幕坐标的平移
	CPoint result;
	int change[3][3] = {{1,0,0},{0,1,0},{XY.x,XY.y,1}};
	int p1[3] = {0,0,0};

	for (int j = 0;j < 3;j++)
	{
	   p1[j]=p.x * change[0][j] + p.y * change[1][j] + change[2][j];
	}

	result.x = p1[0];
	result.y = p1[1];

	return result;
}


CPoint CPoint::Charge_AllLine(CPoint p, CPoint line_start, CPoint line_end) 
{//关于Ax+By+C = 0对称
	double A,B,C;
	if(line_start.x == line_end.x)
	{
	    A = 1;B = 0;C = -line_start.x;
	}
	else 
	if(line_start.y == line_end.y)
	{
     	A = 0;B = 1;C = -line_start.y;
	}
	else
	{
		A = line_end.y - line_start.y;
		B = -(line_end.x - line_start.x);
		C = -line_start.x*(line_end.y-line_start.y)+line_start.y*(line_end.x - line_start.x);
	}

	CPoint result;

	float Y_f = (-A*B*p.x + A*A*p.y - B*C)/(B*B+A*A);
	float X_f = (-A*B*p.y + B*B*p.x - A*C)/(B*B+A*A);

	CPoint xy,m1,m2;
	xy.x=X_f;
	xy.y = Y_f;

	m1 = CPoint::ZeroMoveToXY(p, xy);
	m2 = CPoint::ToZero(m1);

	result = XYMoveToZero(m2, xy);

	return result;
}


void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f,0.0f,0.0f);
	glBegin(GL_LINES);
	int n,x,y,i;

	cout<<"请输入对称图形的顶点数:"<<endl;
	cin>>n;

	CPoint *p=new CPoint[n];
	for(i=0;i<n;i++)
	{
		cout<<"请输入第"<<i+1<<"个顶点坐标"<<endl; cin>>x>>y;
		p[i].x=x;
		p[i].y=y;

		if(i==0||i==1)
		{
	    	glVertex2i(p[i].x,p[i].y);
		}
		else 
		if(i==n-1)
		{
			glVertex2i(p[i-1].x,p[i-1].y);
			glVertex2i(p[i].x,p[i].y);
			glVertex2i(p[i].x,p[i].y);
			glVertex2i(p[0].x,p[0].y);
		}
		else
		{
			glVertex2i(p[i-1].x,p[i-1].y);
			glVertex2i(p[i].x,p[i].y);
		}
	}

	cout<<"请输入对称直线的两个顶点:"<<endl; 
	CPoint *p2=new CPoint[2];

	for(i=0;i<2;i++)
	{
		cout<<"请输入第"<<i+1<<"个顶点坐标"<<endl; cin>>x>>y;
		p2[i].x=x;
		p2[i].y=y;
		glVertex2i(p2[i].x,p2[i].y);
		
	}
	for(i=0;i<n;i++)
	{
		p[i]=CPoint::Charge_AllLine(p[i], p2[0], p2[1]);
		if(i==0||i==1)
		{
	    	glVertex2i(p[i].x,p[i].y);
		}
		else if(i==n-1)
		{
			glVertex2i(p[i-1].x,p[i-1].y);
			glVertex2i(p[i].x,p[i].y);
			glVertex2i(p[i].x,p[i].y);
			glVertex2i(p[0].x,p[0].y);
		}
		else
		{
			glVertex2i(p[i-1].x,p[i-1].y);
			glVertex2i(p[i].x,p[i].y);
		}
	}

	glEnd();
	glFlush();
}

int main(int argc,char*argv[])
{
	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); 
	glutInitWindowSize(400,300);
	glutInitWindowPosition(0,0);
	glutCreateWindow("矩形");
	glutDisplayFunc(Display);
	Initial();
	glutMainLoop();
	return 0;
}

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值