反射

最近学线性代数,想到了一种新的方法计算所有二维空间(可推广到n维)的线反射。相比较之前的旋转坐标系方法简单很多。

假设有直线[latex]l_1=\vec{P}_{0}+\vec{P}t[/latex]作为入射线,[latex]l_2=\vec{Q}_{0}+\vec{Q}d[/latex]作为介质,求反射线[latex]l_3=\vec{R}_{0}+\vec{R}s[/latex]。

[latex]l_1[/latex]到[latex]l_2[/latex]的投影为:
[latex]proj_{l_{2}}(l_1)=\vec{Q}(\vec{Q}^{T}\vec{Q})^{-1}\vec{Q}^{T}\vec{P}[/latex]

$latex R $可通过投影和P的关系求得:
$latex \vec{R}=2proj_{l_{2}}(l_1)-\vec{P} $

$latex \vec{R}_{0} $是$latex l_1$和$latex l_2$的交点(解出$latex t_0$和$latex d_0$从而得到$latex \vec{R}_{0} $):

$latex \left[\begin{array}{cc}\vec{P}&-\vec{Q}\end{array}\right] \left[\begin{array}{c}t_{0}\\d_{0}\end{array}\right]=\left[\begin{array}{c}\vec{Q}_{0}-\vec{P}_{0}\end{array}\right]$

[latex]\left[\begin{array}{c}t_{0}\\d_{0}\end{array}\right]=\left[\begin{array}{cc}\vec{P}&-\vec{Q}\end{array}\right]^{-1}\left[\begin{array}{c}\vec{Q}_{0}-\vec{P}_{0}\end{array}\right][/latex]

$latex \vec{R}_{0}=\vec{P}_{0}+\vec{P}t_{0}=\vec{Q}_{0}+\vec{Q}d_{0}$

下面是matlab代码,可以快速计算反射线。可以输入以标量或矢量模式输入直线。

display 'This program will calculate the reflection line equation by inputing two lines\n.';

%input with two methods
voa= input('Would you like to input using Vector[v] or Scalar[s] form? (v by default): ','s');

if voa=='s'

    pk=0;pb=0;qk=0;qb=0;
    display 'please input lines in such format y=k*x+b\n';
    pk=input('please input k for line1 (entering line): ');
    pb=input('please input b for line1 (entering line): ');
    qk=input('please input k for line2 (middle line): ');
    qb=input('please input b for line2 (middle line): ');

    %convert the line equations into vector format;
    p0=[0;pb];
    q0=[0;qb];
    p=[1;pk];
    q=[1;qk];
else
    display 'please input lines in such format [p0x;p0y]+[px;py]*t\n';
    p0x=input('please input p0x: ');
    p0y=input('please input p0y: ');
    px=input('please input px: ');
    py=input('please input py: ');
    q0x=input('please input q0x: ');
    q0y=input('please input q0y: ');
    qx=input('please input qx: ');
    qy=input('please input qy: ');

    %organize into vector form
    p0=[p0x;p0y];
    q0=[q0x;q0y];
    p=[px;py];
    q=[qx;qy];
end

%calculate using line projection
proj=q*inv(q'*q)*q'*p;
r=2*proj-p;

%calculate r0 by solving the matrix
tdmat=[p -q p0-q0];
rtdmat=rref(tdmat);
t=-rtdmat(1,3);
r0=p0+p*t;

%draw the lines
d=linspace(-20,20);
d1=zeros(1,100)+1;
l1=p0*d1+p*d;
l2=q0*d1+q*d;
l3=r0*d1+r*d;

figure;
plot(l1(1,:),l1(2,:));
hold;
plot(l2(1,:),l2(2,:),'g');
plot(l3(1,:),l3(2,:),'r');
axis equal;

%print result
if(voa=='s')
    rk=[r(2)/r(1)];
    rb=r0(2)-rk*r0(1);
    if rb>=0
        fprintf('this resulting line is y=%f*x+%f\n',rk,rb);
    else
        fprintf('this resulting line is y=%f*x%f\n',rk,rb);
    end
else
    fprintf('this resulting line is [%f;%f]+[%f;%f]*u\n',r0(1),r0(2),r(1),r(2));
end

 

“反射”上的10条回复

  1. 哈哈~我还记得这个问题呢!为什么R=2proj-P不是R=proj-P?比较笨,没懂= = 代数矩阵几分什么的强烈推荐maxima~可视化程度很高呵呵~

  2. proj-P是入射线到介质的差,介质要再加上这个差得到另一边和P等距的反射线,即2•proj-P。我去看看maxima~谢谢~

  3. 恩,我看了下maxima,功能好像和matlab都有吧~?matlab也有符号运算。不过是免费开源,这点非常欢迎~

  4. 我知道啊,功能matlab都有,而且maxima那种rref都不是内置的还要batch-file。maxima是最最最早期的,maple,mathematica什么的前身。就是我说可视化程度高,我不知道matlab行不行,特别是求不定积分什么的都能写成我们平常写得样子,大概就这点和免费是好处了吧,呵呵。

  5. 这样啊。。了解了。。其实可视化的话可以写段代码把输出转换成latex代码,让latex engine生成自然书写。我这篇日志就是为了可视化而用了latex。。

评论已关闭。