计算几何(二维),定理及证明(持续更新中..)

news2024/12/1 12:08:32

注:定理来自这篇博客,本文注重证明

向量基本运算

加法

向量 a ⃗ = ( x 1 , y 1 ) , b ⃗ = ( x 2 , y 2 ) \vec{a}=\left(x_1,y_1\right),\vec{b}=\left(x_2,y_2\right) a =(x1,y1),b =(x2,y2) a ⃗ + b ⃗ = ( x 1 + x 2 , y 1 + y 2 ) \vec{a}+\vec{b}=(x_1+x_2,y_1+y_2) a +b =(x1+x2,y1+y2)
向量在加法中可以理解为一种移动效果,所以向量加法可以理解为下图:
在这里插入图片描述

叉积

叉积的计算

向量 a ⃗ = ( x 1 , y 1 ) , b ⃗ = ( x 2 , y 2 ) \vec{a}=\left(x_1,y_1\right),\vec{b}=\left(x_2,y_2\right) a =(x1,y1),b =(x2,y2) a ⃗ × b ⃗ = x 1 y 2 − x 2 y 1 \vec{a}\times \vec{b}=x_1y_2-x_2y_1 a ×b =x1y2x2y1,证明如下:
首先,根据叉积的定义: a ⃗ × b ⃗ = ∣ a ⃗ ∣ ⋅ ∣ b ⃗ ∣ ⋅ sin ⁡ ( θ ) \vec{a}\times \vec{b}=\left|\vec{a}\right|\cdot|\vec{b}|\cdot \sin\left(\theta\right) a ×b =a b sin(θ) ∣ a ⃗ ∣ \left|\vec{a}\right| a 表示 a ⃗ \vec{a} a 的模长,也就是长度, θ \theta θ 表示从 a ⃗ \vec{a} a 旋转到 b ⃗ \vec{b} b 经过的角度,顺时针为正,逆时针为负)
定义 a r c t a n 2 ( x , y ) arctan2(x,y) arctan2(x,y) 表示从 ( 1 , 0 ) (1,0) (1,0) 顺时针旋转至 ( x , y ) (x,y) (x,y) 经过的角度(返回弧度,取值为 0 ∼ 2 π 0\sim 2\pi 02π
则原式可以表示为 x 1 2 + y 1 2 ⋅ x 2 2 + y 2 2 ⋅ sin ⁡ ( a r c t a n 2 ( x 2 , y 2 ) − a r c t a n 2 ( x 1 , y 1 ) ) \sqrt{x_1^2+y_1^2}\cdot\sqrt{x_2^2+y_2^2}\cdot\sin\left(arctan2\left(x_2,y_2\right)-arctan2(x_1,y_1)\right) x12+y12 x22+y22 sin(arctan2(x2,y2)arctan2(x1,y1))
根据 sin ⁡ ( a − b ) = sin ⁡ ( a ) cos ⁡ ( b ) − cos ⁡ ( a ) sin ⁡ ( b ) \sin(a-b)=\sin(a)\cos(b)-\cos(a)\sin(b) sin(ab)=sin(a)cos(b)cos(a)sin(b) 可得: 原式 = x 1 2 + y 1 2 ⋅ x 2 2 + y 2 2 ⋅ ( sin ⁡ ( a r c t a n 2 ( x 2 , y 2 ) ) cos ⁡ ( a r c t a n 2 ( x 1 , y 1 ) ) − cos ⁡ ( a r c t a n 2 ( x 2 , y 2 ) ) sin ⁡ ( a r c t a n 2 ( x 1 , y 1 ) ) ) 原式=\sqrt{x_1^2+y_1^2}\cdot\sqrt{x_2^2+y_2^2}\cdot\left(\sin(arctan2(x_2,y_2))\cos(arctan2(x_1,y_1))-\cos(arctan2(x_2,y_2))\sin(arctan2(x_1,y_1))\right) 原式=x12+y12 x22+y22 (sin(arctan2(x2,y2))cos(arctan2(x1,y1))cos(arctan2(x2,y2))sin(arctan2(x1,y1)))
由于每个表示为 ( x , y ) (x,y) (x,y) 的向量放到平面直角坐标系上后实际上为:
在这里插入图片描述
通过 a r c t a n 2 ( x 2 , y 2 ) arctan2(x_2,y_2) arctan2(x2,y2) 我们得到了 ∠ B A D \angle{BAD} BAD 所以 sin ⁡ ( a r c t a n 2 ( x 2 , y 2 ) ) = sin ⁡ ( ∠ B A D ) = B D A B = y x 2 + y 2 , cos ⁡ ( a r c t a n 2 ( x 2 , y 2 ) ) = cos ⁡ ( ∠ B A D ) = A D A B = x x 2 + y 2 \sin(arctan2(x_2,y_2))=\sin(\angle{BAD})=\frac{BD}{AB}=\frac{y}{\sqrt{x^2+y^2}},\cos(arctan2(x_2,y_2))=\cos(\angle{BAD})=\frac{AD}{AB}=\frac{x}{\sqrt{x^2+y^2}} sin(arctan2(x2,y2))=sin(BAD)=ABBD=x2+y2 y,cos(arctan2(x2,y2))=cos(BAD)=ABAD=x2+y2 x
所以: 原式 = x 1 2 + y 1 2 ⋅ x 2 2 + y 2 2 ⋅ ( y 2 x 2 2 + y 2 2 ⋅ x 1 x 1 2 + y 1 2 − x 2 x 2 2 + y 2 2 ⋅ y 1 x 1 2 + y 1 2 ) = x 1 2 + y 1 2 ⋅ x 2 2 + y 2 2 ⋅ x 1 y 2 − x 2 y 1 x 1 2 + y 1 2 ⋅ x 2 2 + y 2 2 = x 1 y 2 − x 2 y 1 \begin{aligned}原式&=\sqrt{x_1^2+y_1^2}\cdot\sqrt{x_2^2+y_2^2}\cdot\left(\frac{y_2}{\sqrt{x_2^2+y_2^2}}\cdot\frac{x_1}{\sqrt{x_1^2+y_1^2}}-\frac{x_2}{\sqrt{x_2^2+y_2^2}}\cdot\frac{y_1}{\sqrt{x_1^2+y_1^2}}\right) \\ &=\sqrt{x_1^2+y_1^2}\cdot\sqrt{x_2^2+y_2^2}\cdot\frac{x_1y_2-x_2y_1}{\sqrt{x_1^2+y_1^2}\cdot\sqrt{x_2^2+y_2^2}} \\ &=x_1y_2-x_2y_1 \end{aligned} 原式=x12+y12 x22+y22 (x22+y22 y2x12+y12 x1x22+y22 x2x12+y12 y1)=x12+y12 x22+y22 x12+y12 x22+y22 x1y2x2y1=x1y2x2y1

叉积的性质

画出 sin ⁡ x \sin x sinx 的曲线:
在这里插入图片描述
其正负性在 x = π , 2 π , 3 π , . . . . , n π x=\pi,2\pi,3\pi,....,n\pi x=π,2π,3π,...., 位置发生改变,这里的 x x x 使用了弧度表示,相当于角度每增加或减少 180 ° 180\degree 180° 发生一次改变。所以 a ⃗ × b ⃗ \vec{a}\times\vec{b} a ×b 的值当从 a ⃗ \vec{a} a 顺时针旋转至 b ⃗ \vec{b} b 经过的角度小于 180 ° 180\degree 180° 时为正,否则为负(相当于朝向 a ⃗ \vec{a} a 方向时 b ⃗ \vec{b} b 若在左侧则为正,否则为负,这个性质可以用来判断左右转),并且若角度为 0 ° 0\degree 180 ° 180\degree 180° 时为 0 0 0(这个性质可以用来判断共线)。

点积

向量 a ⃗ = ( x 1 , y 1 ) , b ⃗ = ( x 2 , y 2 ) \vec{a}=\left(x_1,y_1\right),\vec{b}=\left(x_2,y_2\right) a =(x1,y1),b =(x2,y2) a ⃗ ⋅ b ⃗ = x 1 x 2 + y 1 y 2 \vec{a}\cdot \vec{b}=x_1x_2+y_1y_2 a b =x1x2+y1y2,其证明方法与叉积大致相同,读者感兴趣的话可以自行证明,提示:

  1. 点积的定义: a ⃗ ⋅ b ⃗ = ∣ a ⃗ ∣ ⋅ ∣ b ⃗ ∣ ⋅ cos ⁡ ( θ ) \vec{a}\cdot \vec{b}=\left|\vec{a}\right|\cdot|\vec{b}|\cdot \cos\left(\theta\right) a b =a b cos(θ)
  2. cos ⁡ ( a − b ) = sin ⁡ ( a ) sin ⁡ ( b ) + cos ⁡ ( a ) cos ⁡ ( b ) \cos(a-b)=\sin(a)\sin(b)+\cos(a)\cos(b) cos(ab)=sin(a)sin(b)+cos(a)cos(b)

另外,点积的性质为当 − 90 < θ < 90 -90<\theta<90 90<θ<90 时值为负,当 90 < θ < 270 90<\theta<270 90<θ<270 − 270 < θ < − 90 -270<\theta<-90 270<θ<90 时值为正(判断有无掉头),当 x = 90 , − 90 , 270 , − 270 x=90,-90,270,-270 x=90,90,270,270 时值为 0 0 0 (判断垂直)。证明方法也类似于叉积,提示:

  1. cos ⁡ x \cos x cosx 的曲线:
    在这里插入图片描述

点与线

相交

判断线段是否相交

首先,感性理解一下,如果有两个线段相交,那么任意一条线段的两个端点一定在另一条线段的两侧,反之也成立(如下图)。

在这里插入图片描述
所以若将一条线段变成一个向量(一个端点指向另一端点),从终点向另外一条线段的两个端点走,必定一个向左拐,一个向右拐,所以叉积的正负性必定不同(如下图 C D ⃗ , D A ⃗ , D B ⃗ \vec{CD},\vec{DA},\vec{DB} CD ,DA ,DB C D ⃗ × D A ⃗ \vec{CD}\times\vec{DA} CD ×DA C D ⃗ × D B ⃗ \vec{CD}\times\vec{DB} CD ×DB 的正负性不同):
在这里插入图片描述
当然,也会出现特殊情况,就是两条线段重合:
在这里插入图片描述
此时,两线段相交,但叉积都为0(两向量方向相同或相反时叉积为0),但如果直接特判,依然会出问题,两线段共线:
在这里插入图片描述
上图中线段CD与线段 EF共线,会出现错误的判断。所以,还需进一步完善判断条件——加入快速排斥实验。
快速排斥实验,其目的是排除两线段共线但不相交的情况,即判断两个分别包含两线段的矩形是否有公共部分(如下图情况没有),只有出现了公共部分,两线段才可能相交。
在这里插入图片描述
这样下来,我们便解决了特殊情况,下面是代码:

#include<bits/stdc++.h>
namespace geometry
{
    using namespace std;
    struct Vector{//向量
        double x,y;
    };
    struct Point{//点
        double x,y;
    };
    struct Segment{//线段
        Point a,b;
    };
    struct Line{//直线
        Point a;
        Vector k;
    };
    double chk(double n)//判断n的正负性,n>0时返回1,n<0时返回-1,n=0时返回0
    {
        return (n>0?1:(n==0?0:-1));
    }
    double distance(Point a,Point b)//点之间的距离
    {
        return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
    }
    double operator *(Vector q,Vector h){//向量点乘
        return q.x*h.x+q.y*h.y;
    }
    Vector operator *(Vector q,double h){//向量扩大
        return (Vector){q.x*h,q.y*h};
    }
    Vector operator *(double q,Vector h){//向量扩大
        return (Vector){q*h.x,q*h.y};
    }
    Vector operator +(Vector q,Vector h){//向量加法
        return (Vector){q.x+h.x,q.y+h.y};
    }
    Point operator +(Point q,Vector h){//点加向量,实现位移
        return (Point){q.x+h.x,q.y+h.y};
    }
    Point operator -(Point q,Vector h){//点减向量,实现位移
        return (Point){q.x-h.x,q.y-h.y};
    }
    Vector operator -(Point q,Point h){//q-h,得到q->h的向量
        return (Vector){h.x-q.x,h.y-q.y};
    }
    double operator ^(Vector q,Vector h){//向量叉乘
        return q.x*h.y-q.y*h.x;
    }
    bool turn_left(Vector q,Vector h)//左转叉积大于0
    {
        return (q^h)>0;
    }
    bool turn_right(Vector q,Vector h)//右转叉积小于0
    {
        return (q^h)<0;
    }
    bool turn_back(Vector q,Vector h)//掉头点积小于0
    {
        return (q*h)<0;
    }
    bool vertical(Vector q,Vector h)//垂直点积等于0
    {
        return (q*h)==0;
    }
    bool segment_cross_check(Segment a,Segment b)//线段相交检测
    {
        if(min(a.a.x,a.b.x)>max(b.a.x,b.b.x)||min(a.a.y,a.b.y)>max(b.a.y,b.b.y)||min(b.a.x,b.b.x)>max(a.a.x,a.b.x)||min(b.a.y,b.b.y)>max(a.a.y,a.b.y))
            return false;//快速排斥实验
        double ans1=chk((a.a-a.b)^(b.a-a.a)),ans2=chk((a.a-a.b)^(b.b-a.a)),ans3=chk((b.a-b.b)^(a.a-b.a)),ans4=chk((b.a-b.b)^(a.b-b.a));
        return ans1!=ans2&&ans3!=ans4||ans1==0;//跨立实验
    }
}
using namespace std;
using namespace geometry;
int main()
{
    Segment a,b;
	cin>>a.a.x>>a.a.y>>a.b.x>>a.b.y>>b.a.x>>b.a.y>>b.b.x>>b.b.y;
	cout<<segment_cross_check(a,b);
	return 0;
}

直线相交

直线的表示

首先,介绍一下直线在计算几何中的常用表示方法:使用一个点和一个向量进行表示。
相信大家都学过一次函数,一次函数的格式为 y = k x + b ( k ≠ 0 ) y=kx+b(k\ne 0) y=kx+b(k=0),与一次函数的格式类似,这种方法的格式为 ( b x + x k x , b y + x k y ) (b_x+xk_x,b_y+xk_y) (bx+xkx,by+xky)(具体含义稍后解释)但 k , b k,b k,b 与一次函数中完全不同。
对于两个点 a , b a,b a,b 我们可以确定一条直线:
在这里插入图片描述
y = k x + b ( k ≠ 0 ) y=kx+b(k\ne 0) y=kx+b(k=0) 中, k k k 是直线的斜率,也就是 B y − A y B x − A x \frac{B_y-A_y}{B_x-A_x} BxAxByAy 。而在 ( b x + x k x , b y + x k y ) (b_x+xk_x,b_y+xk_y) (bx+xkx,by+xky) 中, k k k 是一个向量,从 A A A 指向 B B B 或从 B B B 指向 A A A x x x 为一个实数,用来控制向量的长度和方向,表示 x x x y y y 方向的位移。
在这里插入图片描述
如此,我们便可以表示出该直线上的所有点。
为什么要这样表示一条线段?其实理由有很多,而其中我认为最重要的是:使用向量表示的直线,无需特殊考虑x方向差为0的情况(除0),当然,它也让许多计算更加简便。

求交点

在这里插入图片描述
如何求出上图两条直线的交点?读者可以先自行思考,再往下翻。(本文只介绍几何做法,当然,也存在代数做法,感兴趣的话可以尝试自己寻找答案)

首先,过我们过 A , B A,B A,B 两点做平行于 C D CD CD 的直线:
在这里插入图片描述
容易发现,图中可以构造一对相似三角形(下图的 △ A B H , △ I A G \bigtriangleup ABH,\bigtriangleup IAG ABH,IAG),又因为 △ A B H \bigtriangleup ABH ABH 的斜边实际上就是向量 A B ⃗ \vec{AB} AB ,如果我们可以得到两三角形任意一边的比例,就可以得到向量 A I ⃗ \vec{AI} AI 。那么如何得到边的比例呢?
在这里插入图片描述
在过 A A A 的平行线上截取一段长度等于 C D ⃗ \vec{CD} CD 模长的线段,分别向上和向下构造两个平行四边形。
又 ∵ S 上 = ∣ C D ⃗ ∣ ⋅ B H , S 下 = ∣ C D ⃗ ∣ ⋅ A G 又\because S_上=|\vec{CD}|\cdot BH,S_下=|\vec{CD}|\cdot AG S=CD BH,S=CD AG
∴ S 上 : S 下 = B H : A G \therefore S_上:S_下=BH:AG SS=BH:AG
我们可以通过向量叉积求出两平行四边形的面积,之后便可得出比例求出交点。
在这里插入图片描述
现在,考虑符号。我们发现,对于一条同直线,可以表示它向量有两个方向, k k k − k -k k。下图是上图的另几个情况:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
经过计算可以发现,不管是哪一种情况, C D ⃗ × C A ⃗ \vec{CD}\times\vec{CA} CD ×CA C D ⃗ × A B ⃗ \vec{CD}\times\vec{AB} CD ×AB 如果符号相同,则 I = A − A B ⃗ ⋅ A G B H I=A-\vec{AB}\cdot\frac{AG}{BH} I=AAB BHAG 否则 I = A + A B ⃗ ⋅ A G B H I=A+\vec{AB}\cdot\frac{AG}{BH} I=A+AB BHAG,代码如下(前面已经给出的内容不再重复出现):

bool line_cross_check(Line a,Line b)
{
    return (a.k^b.k)!=0;//在同一平面内两直线不平行才相交
}
bool point_on_line(Point a,Line b)
{
    return ((b.a-a)^b.k)==0;//三点共线
}
Point line_cross_get_cross_point(Line a,Line b)
{
    Vector c=b.a-a.a;
    return a.a-(b.k^c)/(b.k^a.k)*a.k;//得到带符号的比例
}

这个方法不仅可以求出直线交点,加上一些判断,它也可以求出线段交点。

距离

点到直线的距离

实际上这个问题十分简单,我们已经知道了叉积的几何意义是求出两向量所确定的平行四边形的带符号面积,那么可以构造出下图所示的平行四边形:
在这里插入图片描述
利用叉积求出它的面积,再除以 ∣ K L ⃗ ∣ |\vec{KL}| KL ,可以得出 K L KL KL 边上的高,也就是 J J J 到直线 K L KL KL 的距离。
代码如下:

double distance_point_to_line(Point a,Line b)
{
    Vector c=b.a-a;
    return fabs((c^b.k)/distance(b.a,b.a+b.k));
}

点到线段的距离

与直线不同,线段是有长度限制的。所以一个点到一条线段的距离有两种情况:
在这里插入图片描述
首先,在线段两端点分别作两条垂直于该线段的直线,将平面分为绿色,红色和紫色三个部分。如果点出现在红色区域,距离相当于直接做垂线,计算方法同计算点到直线距离。
其实出现在绿色和紫色区域是等价的,其距离都是到线段两端点之一的距离(取最小值)。
那么如何判断出现再了哪一个区域?这时候,就要用到点积了!
在这里插入图片描述
根据点积的性质, A B ⃗ ⋅ B C ⃗ ≥ 0 \vec{AB}\cdot\vec{BC}\ge0 AB BC 0 说明从 A B ⃗ \vec{AB} AB 方向走到 B C ⃗ \vec{BC} BC 方向没有掉头,也就是点 C C C 位于紫色区域,否则位于红色区域,判断是否位于绿色区域也是同理(但 A B ⃗ \vec{AB} AB 方向需要改成 B A ⃗ \vec{BA} BA 方向)。那么下面就是代码:

double distance_point_to_segment(Point a,Segment b)
{
    if(chk((b.a-b.b)*(b.b-a))==chk((b.b-b.a)*(b.a-a)))//判断是否在红色区域中
        return distance_point_to_line(a,(Line){b.a,(b.b-b.a)});//在红色区域中,返回垂线段长度
    else
        return min(distance(a,b.a),distance(a,b.b));//不在红色区域中,返回到线段两端点的最近距离
}

垂足

点在直线上的垂足

我们需要求出一个垂直于向量 Q R ⃗ \vec{QR} QR 的向量 S T ⃗ \vec{ST} ST T T T 为直线 Q R QR QR 上一点),根据点积的性质可以列出方程 Q R ⃗ ⋅ S T ⃗ = 0 \vec{QR}\cdot\vec{ST}=0 QR ST =0
在这里插入图片描述
怎么解出一个向量?比较困难。我们可以尝试将 S T ⃗ \vec{ST} ST 换一种形式表示。
定义点 a ( x 1 , y 1 ) a(x_1,y_1) a(x1,y1) 减去点 b ( x 2 , y 2 ) b(x_2,y_2) b(x2,y2) 的结果为向量 c ⃗ = ( x 2 − x 1 , y 2 − y 1 ) \vec{c}=(x_2-x_1,y_2-y_1) c =(x2x1,y2y1) (从 a a a 连接到 b b b 的向量)。
所以 S T ⃗ = ( Q − S ) ⃗ + Q T ⃗ = ( Q − S ) ⃗ + x ⋅ Q R ⃗ \vec{ST}=\vec{(Q-S)}+\vec{QT}=\vec{(Q-S)}+x\cdot\vec{QR} ST =(QS) +QT =(QS) +xQR x x x 为一实数,在此处扩大或缩小向量 Q R ⃗ \vec{QR} QR )。
在这里插入图片描述
现在,需要使用点积的分配律继续下一步推导。先证明一下:
a ⃗ = ( x 1 , y 1 ) , b ⃗ = ( x 2 , y 2 ) , c ⃗ = ( x 3 , y 3 ) \vec{a}=(x_1,y_1),\vec{b}=(x_2,y_2),\vec{c}=(x_3,y_3) a =(x1,y1),b =(x2,y2),c =(x3,y3)
a ⃗ ⋅ ( b ⃗ + c ⃗ ) = a ⃗ ⋅ ( x 2 + x 3 , y 2 + y 3 ) ⃗ = x 1 ( x 2 + x 3 ) + y 1 ( y 2 + y 3 ) \vec{a}\cdot\left(\vec{b}+\vec{c}\right)=\vec{a}\cdot\vec{(x_2+x_3,y_2+y_3)}=x_1(x_2+x_3)+y_1(y_2+y_3) a (b +c )=a (x2+x3,y2+y3) =x1(x2+x3)+y1(y2+y3)
a ⃗ ⋅ b ⃗ + a ⃗ ⋅ c ⃗ = x 1 x 2 + y 1 y 2 + x 1 x 3 + y 1 y 3 = x 1 ( x 2 + x 3 ) + y 1 ( y 2 + y 3 ) \vec{a}\cdot\vec{b}+\vec{a}\cdot\vec{c}=x_1x_2+y_1y_2+x_1x_3+y_1y_3=x_1(x_2+x_3)+y_1(y_2+y_3) a b +a c =x1x2+y1y2+x1x3+y1y3=x1(x2+x3)+y1(y2+y3)
∴ a ⃗ ⋅ ( b ⃗ + c ⃗ ) = a ⃗ ⋅ b ⃗ + a ⃗ ⋅ c ⃗ \therefore \vec{a}\cdot\left(\vec{b}+\vec{c}\right)=\vec{a}\cdot\vec{b}+\vec{a}\cdot\vec{c} a (b +c )=a b +a c
好的,现在实践运用一下:
Q R ⃗ ⋅ ( ( Q − S ) ⃗ + ( x ⋅ Q R ⃗ ) ) = 0 Q R ⃗ ⋅ ( Q − S ) ⃗ + Q R ⃗ ( x ⋅ Q R ⃗ ) = 0 Q R ⃗ ⋅ ( Q − S ) ⃗ + x ⋅ Q R ⃗ ⋅ Q R ⃗ = 0 x ⋅ Q R ⃗ ⋅ Q R ⃗ = − Q R ⃗ ⋅ ( Q − S ) ⃗ x = − Q R ⃗ ⋅ ( Q − S ) ⃗ Q R ⃗ ⋅ Q R ⃗ \begin{aligned} \vec{QR}\cdot\left(\vec{\left(Q-S\right)}+\left(x\cdot\vec{QR}\right)\right)&=0 \\\vec{QR}\cdot\vec{\left(Q-S\right)}+\vec{QR}\left(x\cdot\vec{QR}\right)&=0 \\\vec{QR}\cdot\vec{\left(Q-S\right)}+x\cdot\vec{QR}\cdot\vec{QR}&=0 \\x\cdot\vec{QR}\cdot\vec{QR}&=-\vec{QR}\cdot\vec{\left(Q-S\right)} \\x&=-\frac{\vec{QR}\cdot\vec{\left(Q-S\right)}}{\vec{QR}\cdot\vec{QR}} \end{aligned} QR ((QS) +(xQR ))QR (QS) +QR (xQR )QR (QS) +xQR QR xQR QR x=0=0=0=QR (QS) =QR QR QR (QS)
现在,我们得出了向量 Q T ⃗ = x ⋅ Q R ⃗ \vec{QT}=x\cdot\vec{QR} QT =xQR ,定义点 a ( x , y ) a(x,y) a(x,y) 加上向量 b ⃗ = ( x 1 , y 1 ) \vec{b}=(x_1,y_1) b =(x1,y1) 的结果为点 c ( x + x 1 , y + y 1 ) c(x+x_1,y+y_1) c(x+x1,y+y1),所以 T = Q + Q T ⃗ = Q + x ⋅ Q R ⃗ T=Q+\vec{QT}=Q+x\cdot\vec{QR} T=Q+QT =Q+xQR ,代码如下:

Point foot_point(Point a,Line b)
{
    return b.a-b.k*(b.k*(a-b.a)/(b.k*b.k));//推导过程长,但结论简单
}

点对于一条直线的对称点

对于一条直线对称的两个点到这一条直线的距离相等。也就是说,当我们找到了这个点在直线上的垂足,再将它们相连得到向量,并且将其扩大一倍后加上原始点后,所得到的点就是所求得的对称点(见下图)。
在这里插入图片描述
代码:

Point symmetric_point(Point a,Line b)
{
    Point c=foot_point(a,b);//得到垂足
    return a+2*(a-c);//得到对称点
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/768316.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

P7 第二章 电阻电路的等效变换

1、等效变换应用举例 化简套路&#xff1a; 电压源与其串联的电阻&#xff0c;可以等效为电流源并联电阻&#xff0c;然后电流源就可以拿去合并电路中的&#xff0c;与之并联的电流&#xff0c;电阻则可以拿去合并与之并联的电阻。 公式法&#xff1a; 就是根据端的电压与端的…

第一节 C++ 变量

文章目录 1. Visual Studio Community 安装1.1. Visual Studio 介绍1.2. Visual Studio的安装1.3 Visual Studio创建与使用1.3.1 创建一个工程项目1.3.2 新建一个C文件1.3.3 编写执行文件 2. Dev-C 安装(初学者建议使用)2.1 Dev-C 介绍2.2 Dev-C 安装2.3 Dev-C 快捷键使用 3. 认…

数学建模常用模型(九) :偏最小二乘回归分析

数学建模常用模型&#xff08;九&#xff09; &#xff1a;偏最小二乘回归分析 偏最小二乘回归&#xff08;Partial Least Squares Regression&#xff0c;PLS Regression&#xff09;是一种常用的统计建模方法&#xff0c;用于解决多元线性回归中自变量间高度相关的问题。在偏…

【java】三大容器类(List、Set、Map)的常用实现类的特点

三大容器类&#xff08;List、Set、Map&#xff09;的常用实现类的特点 简介 本文总结三大容器类&#xff08;List、Set、Map&#xff09;的常用实现类&#xff08;ArrayList、Vector、LinkedList、HashSet、HashMap、HashTable&#xff09;的特点 一、List部分 1、ArrayLi…

C# DlibDotNet 人脸识别、人脸68特征点识别、人脸5特征点识别、人脸对齐,三角剖分,人脸特征比对

人脸识别 人脸68特征点识别 人脸5特征点识别 人脸对齐 三角剖分 人脸特征比对 项目 VS2022.net4.8OpenCvSharp4DlibDotNet Demo下载 代码 using DlibDotNet.Extensions; using DlibDotNet; using System; using System.Collections.Generic; using System.ComponentModel; …

学堂在线数据结构(上)(2023春)邓俊辉 课后作业错题整理

The reverse number of a sequence is defined as the total number of reversed pairs in the sequence, and the total number of element comparisons performed by the insertion sort in the list of size n is: 一个序列的逆序数定义为该序列中的逆序对总数&#xff0c;…

transformer Position Embedding

这是最近一段很棒的 Youtube 视频&#xff0c;它深入介绍了位置嵌入&#xff0c;并带有精美的动画&#xff1a; Transformer 神经网络视觉指南 -&#xff08;第 1 部分&#xff09;位置嵌入 让我们尝试理解计算位置嵌入的公式的“sin”部分&#xff1a; 这里“pos”指的是“单词…

自定义view(一)----自定义TextView

自定义view也算是Android的一大难点&#xff0c;里面涉及到很多值得学习的地方&#xff0c;我会在接下来写一系列文章去介绍它&#xff0c;本篇文章以自定义一个TextView为例。 View的构造方法 自定义view之前我们先了解view的四个构造方法&#xff0c;自定义view无非就是新建一…

R语言逻辑回归(Logistic Regression)、回归决策树、随机森林信用卡违约分析信贷数据集...

原文链接&#xff1a;http://tecdat.cn/?p23344 本文中我们介绍了决策树和随机森林的概念&#xff0c;并在R语言中用逻辑回归、回归决策树、随机森林进行信用卡违约数据分析&#xff08;查看文末了解数据获取方式&#xff09;&#xff08;点击文末“阅读原文”获取完整代码数据…

MVSNet、PatchMatchNet中的 eval.sh文件超参数解释

下面以PatchMatchNet为例, 打开PatchMatchNet程序中的 eavl.sh文件, 可以看到文件设置了数据集路径,及超参数设置(超参数,也可以不写,会使用默认参数) 上图中各参数意思如下: 执行文件python eval.py; 数据集加载方方式使用dtu_yao_eval ; batch_size=1 ,视图数N设…

【C++】命名空间 ( namespace )

目录搁这 什么是命名空间命名空间的作用如何定义命名空间命名空间的种类如何使用命名空间内的成员作用域限定符命名空间展开命名空间全部展开命名空间部分展开 总结 什么是命名空间 命名空间是一种用来避免命名冲突的机制&#xff0c;它可以将一段代码的名称隔离开&#xff0c…

中国地图使用心得

中国地图使用心得 注册地图是注册在echarts对象上而非 自己构建的echarts dom上、。 请求本地json文件 ​ vue项目的public打包时不会动&#xff0c;所以线上和本地地址直接指向了public同级目录&#xff0c;请求时直接相对路径 绘制中国地图时&#xff0c;如何在各个省会地方…

「深度学习之优化算法」(十三)蝙蝠算法

1. 蝙蝠算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读)   蝙蝠算法(Bat Algorithm)是受蝙蝠回声定位的特性启发而提出的新兴算法,提出时间是2010年,虽然距今(2020)有近10年,但与其它的经典算法相比仍算一个新算法。算法也已有一定规模的研究和应用,但仍…

【LLM系列之LLaMA2】LLaMA 2技术细节详细介绍!

Llama 2 发布&#xff01; Meta 刚刚发布了 LLaMa 2&#xff0c;它是 LLaMA 的下一代版本&#xff0c;具有商业友好的许可证。&#x1f92f;&#x1f60d; LLaMA 2 有 3 种不同的尺寸&#xff1a;7B、13B 和 70B。 7B & 13B 使用与 LLaMA 1 相同的架构&#xff0c;并且是商…

年CTF—初五

0x00 前言 CTF 加解密合集&#xff1a;CTF 加解密合集 0x01 题目 神秘人送来了半个世纪前的无线电信号&#xff0c;但是只能分别出以下的密文&#xff1a; YDHML_QKA_PDK_HVD_NAHI_OQ_K_GR 据说上面的无线电信号代表的是中文&#xff0c;由红岸基地发往半人马星系 半个世纪过…

数据容器入门(set)

集合的定义&#xff1a; 语法&#xff1a;变量名称 {元素&#xff0c;元素&#xff0c;元素.........元素} 定义空集合&#xff1a; 变量名称 set&#xff08;&#xff09; set {“abc”&#xff0c;123&#xff0c;“def”} 集合的特点&#xff1a; 可以容纳多个数据可以容…

数据结构01-线性结构-链表栈队列-栈篇

文章目录 参考&#xff1a;总结大纲要求线性结构-栈回文匹配小猫钓鱼的故事 参考&#xff1a; 线性结构-栈 总结 本系列为C数据结构系列&#xff0c;会介绍 线性结构&#xff0c;简单树&#xff0c;特殊树&#xff0c;简单图等。本文为线性结构部分。 大纲要求 线性结构 【…

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数)

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数) 文章目录 回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(不调用工具箱函数)预测效果基本介绍程序设计参考资料 预测效果 基本介绍 GRU神经网络是LSTM神经网络的一种变体&#xff0c;LSTM 神经网 …

集合面试题--二叉树,红黑树,散列表

目录 二叉树 二叉搜索树 时间复杂度 总结 红黑树 红黑树特质 复杂度 总结 散列表 散列函数 哈希冲突 散列冲突-链表法&#xff08;拉链&#xff09; 时间复杂度 ​总结 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是…