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;
}

posted @ 2020-05-03 15:48  springfield_psk  阅读(911)  评论(0编辑  收藏  举报