opengl算法学习---点关于任意直线的对称点
设原点为\(P(x,y)\),对称点为\(P'(x',y')\),对直线y=mx+b,则两点的中点落在直线上
\[\Rightarrow \frac{y+y'}{2}=m(\frac{x+x'}{2})+b
\]
\[y'=m(x'+x)+2b-y
\]
过两点作一直线,则该直线垂直于y=mx+b
\[\Rightarrow \frac{y-y'}{x-x'}=-\frac{1}{m}
\]
\[y'=-\frac{1}{m}(x'-x)+y
\]
\[\Rightarrow
\left\{\begin{matrix}
y'=m(x'+x)+2b-y \\
y'=-\frac{1}{m}(x'-x)+y
\end{matrix}\right.
\]
\[\Rightarrow -\frac{1}{m}(x'-x)+y=m(x'+x)+2b-y
\]
\[x'-x-my=-m^{2}(x+x')-m(2b-y)
\]
\[(1+m^{2})x'=(1-m^{2})x-2m(b-y)
\]
\[x'=\frac{1-m^{2}}{1+m^{2}}x+\frac{2m}{1+m^{2}}y-\frac{2mb}{1+m^{2}}
\]
\[\Rightarrow y'=m(x+\frac{1-m^{2}}{1+m^{2}}x+\frac{2m}{1+m^{2}}y-\frac{2mb}{1+m^{2}})+2b-y
\]
\[y'=\frac{2m}{1+m^{2}}x+\frac{m^{2}-1}{1+m^{2}}y+\frac{2b}{1+m^{2}}
\]
\[\left\{\begin{matrix}
x'=\frac{1-m^{2}}{1+m^{2}}x+\frac{2m}{1+m^{2}}y-\frac{2mb}{1+m^{2}} \\
y'=\frac{2m}{1+m^{2}}x+\frac{m^{2}-1}{1+m^{2}}y+\frac{2b}{1+m^{2}}
\end{matrix}\right.
\Rightarrow
\]
\[p'=
\begin{bmatrix}
x'\\
y' \\
1
\end{bmatrix}
=
\frac{1}{1+m^{2}}
\begin{bmatrix}
1-m^{2} & 2m & -2mb\\
2m & m^{2}-1 & 2b\\
0 & 0 & 1+m^{2}
\end{bmatrix}
\cdot
\begin{bmatrix}
x\\
y \\
1
\end{bmatrix}
=T\cdot P
\]
当已知直线上两点\((x_{1},y_{1}),(x_{2},y_{2})\)
当\(x_{1}\neq x_{2}时\)
\[\Rightarrow
\left\{\begin{matrix}
m=\frac{y_{2}-y_{1}}{x_{2}-x_{1}} \\
b=\frac{x_{2}y_{1}-x_{1}y_{2}}{x_{2}-x_{1}}
\end{matrix}\right.
\]
\[p'=
\begin{bmatrix}
x'\\
y' \\
1
\end{bmatrix}
\]
\[=
\frac{1}{(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}}
\cdot
\]
\[\begin{bmatrix}
(x_{2}-x_{1})^{2}-(y_{2}-y_{1})^{2} & 2(x_{2}-x_{1})(y_{2}-y_{1}) & -2(y_{2}-y_{1})(x_{2}y_{1}-x_{1}y_{2})\\
2(x_{2}-x_{1})(y_{2}-y_{1}) & (y_{2}-y_{1})^{2}-(x_{2}-x_{1})^{2} & 2(x_{2}-x_{1})(x_{2}y_{1}-x_{1}y_{2})\\
0 & 0 & (x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}
\end{bmatrix}
\cdot
\begin{bmatrix}
x\\
y \\
1
\end{bmatrix}
\]
\[=T\cdot P
\]
当\(x_{1}= x_{2}时\)
两点关于直线\(x=x_{1}\)对称
所以
\[\Rightarrow
p'=
\begin{bmatrix}
x'\\
y' \\
1
\end{bmatrix}
=
\begin{bmatrix}
-1 & 0 & 2x_{1}\\
0 & 1 & 0\\
0 & 0 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
x\\
y \\
1
\end{bmatrix}
=T\cdot P
\]
由于两式在\(x_{1}=x_{2}\)下同时成立
所以
\[p'=
\begin{bmatrix}
x'\\
y' \\
1
\end{bmatrix}
\]
\[=
\frac{1}{(x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}}
\cdot
\]
\[\begin{bmatrix}
(x_{2}-x_{1})^{2}-(y_{2}-y_{1})^{2} & 2(x_{2}-x_{1})(y_{2}-y_{1}) & -2(y_{2}-y_{1})(x_{2}y_{1}-x_{1}y_{2})\\
2(x_{2}-x_{1})(y_{2}-y_{1}) & (y_{2}-y_{1})^{2}-(x_{2}-x_{1})^{2} & 2(x_{2}-x_{1})(x_{2}y_{1}-x_{1}y_{2})\\
0 & 0 & (x_{2}-x_{1})^{2}+(y_{2}-y_{1})^{2}
\end{bmatrix}
\cdot
\begin{bmatrix}
x\\
y \\
1
\end{bmatrix}
\]
\[=T\cdot P
\]
代码实现
#include <GL/gl.h>
#include <GL/glut.h>
#include <bits/stdc++.h>
using namespace std;
const double PI=acos(-1.0);
void init()
{
glClearColor (0.0, 1.0, 0.0, 0.0);
glMatrixMode (GL_PROJECTION);
gluOrtho2D (0, 200, 0, 200);
}
void calreflect(GLfloat &x,GLfloat &y,GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat xp,GLfloat yp)
{
GLfloat a=(x2-x1)*(x2-x1)-(y2-y1)*(y2-y1);
GLfloat b=2*(x2-x1)*(y2-y1);
GLfloat c=2*(y2-y1)*(x2*y1-x1*y2);
GLfloat d=2*(x2-x1)*(x2*y1-x1*y2);
GLfloat div=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
x=(a*xp+b*yp-c)/div;
y=(b*xp-a*yp+d)/div;
}
void drawline(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat xp,GLfloat yp,GLfloat fxp,GLfloat fyp)
{
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glColor3f(0.0,0.0,1.0);
glVertex2f(fxp,fyp);
glVertex2f(xp,yp);
glEnd();
}
void drawpoint(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat xp,GLfloat yp,GLfloat fxp,GLfloat fyp)
{
glPointSize(5);
glBegin(GL_POINTS);
glColor3f(0.0,0.0,0.0);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glColor3f(1.0,0.0,0.0);
glVertex2f(fxp,fyp);
glVertex2f(xp,yp);
glEnd();
}
void reflection(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat xp,GLfloat yp)
{
GLfloat fxp,fyp;
calreflect(fxp,fyp,x1,y1,x2,y2,xp,yp);
drawline(x1,y1,x2,y2,xp,yp,fxp,fyp);
drawpoint(x1,y1,x2,y2,xp,yp,fxp,fyp);
glFlush();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
reflection(30,50,160,170,110,65);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("a relection point");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}