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

二维空间点到直线垂足计算公式推导及Java实现——学习笔记

程序员文章站 2022-04-02 21:27:13
...

二维空间点到直线垂足计算公式推导及Java实现

前言

简单的公式推导,大概是高中程度的知识了。不管以前学的好不好,很久不用的东西,一上手还是有点懵的。推导一遍也是为了加深记忆。

公式推导

首先我们知道直线上两点p1,p2
p1:(x1,y1) p_1:(x_1,y_1)p2:(x2,y2) p_2:(x_2,y_2)
和直线外一点p3
p3:(x3,y3) p_3:(x_3,y_3)
现在我们要求p3在直线p1p2上的垂足p4
p4:(x4,y4) p_4:(x_4,y_4)
可知直线p1p2垂直于直线p3p4,根据向量垂直的关系我们可以知道:
(x1x2)(x3x4)+(y1y2)(y3y4)=0(1) (x_1-x_2)(x_3-x_4)+(y_1-y_2)(y_3-y_4)=0\quad\quad(1)
同时由于p1,p2,p4三点共线,可假设系数u使得:
{x4=x1+u(x1x2)y4=y1+u(y1y2)(2) \begin{cases} \quad x_4=x_1+u(x_1-x_2)\\ \quad y_4=y_1+u(y_1-y_2) \end{cases}\quad\quad\quad(2)
将式子(2)带入(1)中,可以解得:
u=(x1x2)(x3x1)+(y1y2)(y3y1)(x1x2)2+(y1y2)2(3) u=\frac{(x_1-x_2)(x_3-x_1)+(y_1-y_2)(y_3-y_1)} {(x_1-x_2)^2+(y_1-y_2)^2}\quad(3)
再将求得的u带回(2)中,就得到了垂足。

代码实现

private Point getFoot(Point p1,Point p2,Point p3){
        Point foot=new Point();
        
        float dx=p1.x-p2.x;
        float dy=p1.y-p2.y;
        
        float u=(p3.x-p1.x)*dx+(p3.y-p1.y)*dy;
        u/=dx*dx+dy*dy;
        
        foot.x=(int)(p1.x+u*dx);
        foot.y=(int)(p1.y+u*dy);
        
        return foot;
    }

代码很简单,不解释了,参照上面推导的式子(2)和式子(3)

画蛇添足

这里多提一点。实际运用中,有的时候需要的只是把点映射在一条线段上,这时会出现一种情况,就是我们计算得到的垂足p4不在线段p1p2上,此时我们需要把p4映射到线段的两个端点(即p1p2)上。针对此情况修改代码:

private Point getFoot(Point p1,Point p2,Point p3){
        Point foot=new Point();

        float dx=p1.x-p2.x;
        float dy=p1.y-p2.y;

        float u=(p3.x-p1.x)*dx+(p3.y-p1.y)*dy;
        u/=dx*dx+dy*dy;

        foot.x=(int)(p1.x+u*dx);
        foot.y=(int)(p1.y+u*dy);

        float d=Math.abs((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.x-p2.y));
        float d1=Math.abs((p1.x-foot.x)*(p1.x-foot.x)+(p1.y-foot.y)*(p1.x-foot.y));
        float d2=Math.abs((p2.x-foot.x)*(p2.x-foot.x)+(p2.y-foot.y)*(p2.x-foot.y));

        if(d1>d||d2>d){
            if (d1>d2)  return p2;
            else return p1;
        }

        return foot;
    }
相关标签: 数学