1. 程式人生 > 其它 >學習筆記——計算幾何

學習筆記——計算幾何

前言

高中數學必修二內容,基本理論見 oiwiki

向量及其基本運算

先上程式碼:

struct Node{
    double x,y;Node(){}
    Node(double _x,double _y){x=_x;y=_y;}
    void input(){scanf("%lf%lf",&x,&y);}
    Node friend operator+(Node a,Node b){return Node(a.x+b.x,a.y+b.y);
    Node friend operator-(Node a,Node b){return Node(a.x-b.x,a.y-b.y);}
    double friend operator*(Node a,Node b){return a.x*b.x+a.y*b.y;}//點積
    double friend operator^(Node a,Node b){return a.x*b.y-b.x-a.y;}//叉積
    void rot(double a){
        double x1=x*cos(a)-y*sin(a);
        double y1=y*cos(a)+x*sin(a);
        x=x1;y=y1;
    }
};

定義一個向量

根據向量的座標表示,可以用 \((x,y)\) 來表示一個向量。

struct Node{
    double x,y;Node(){}
    Node(double _x,double _y){x=_x;y=_y;}
    void input(){scanf("%lf%lf",&x,&y);}
};

向量加減

由於我們用座標表示一個向量,那麼兩個向量相加減實際上就是對應座標的加減。

Node friend operator+(Node a,Node b){
    return Node(a.x+b.x,a.y+b.y);
}
Node friend operator-(Node a,Node b){
    return Node(a.x-b.x,a.y-b.y);
}

向量點積

我們都知道 \(\vec{a}\cdot\vec{b}=|\vec{a}||\vec{b}|\cos\theta\)。其中 \(|\vec{a}|=\sqrt{x_a^2+y_a^2}\)\(|\vec{b}|=\sqrt{x_b^2+y_b^2}\),然後根據餘弦定理:\(d_{AB}^2=|\vec{a}|^2+|\vec{b}|^2-2|\vec{a}||\vec{b}|\cos\theta=(x_a-x_b)^2+(y_a-y_b)^2\),可以得到:\(-2|\vec{a}||\vec{b}|\cos\theta=-2x_ax_b-2y_ay_b\)\(|\vec{a}||\vec{b}|\cos\theta=x_ax_b+y_ay_b\)

所以 \(\vec{a}\cdot\vec{b}=x_ax_b+y_ay_b\)

double friend operator*(Node a,Node b){
    return a.x*b.x+a.y*b.y;
}

向量叉積

我們都知道 \(|\vec{a}\times\vec{b}|=|\vec{a}||\vec{b}|\sin\theta\)

我們都知道叉積有幾何意義就是兩條向量圍成的三角形面積的兩倍。

看張圖,可以發現所謂三角形面積的兩倍就是圖中黃色的面積。而黃色的面積就是 \(x_by_a-x_ay_b\),由於 \(\vec{a}\times\vec{b}\) 的結果根據右手螺旋定則是負的,所以叉積的表示式就是 \(|\vec{a}\times\vec{b}|=x_ay_b-x_by_a\)

叉積的用處還是非常多的。

double friend operator^(Node a,Node b){
    return a.x*b.y-b.x-a.y;
}

向量旋轉

嫖一張圖:

展開得:

\[\vec{b}=(l(\cos\theta\cos\alpha-\sin\theta\sin\alpha),l(\sin\theta\cos\alpha+\cos\theta\sin\alpha)) \]\[=(l\cos\theta\cos\alpha-l\sin\theta\sin\alpha,l\sin\theta\cos\alpha+l\cos\theta\sin\alpha) \]\[=(x\cos\alpha-y\sin\alpha,y\cos\alpha+x\sin\alpha) \]
void rot(double a){
    double x1=x*cos(a)-y*sin(a);
    double y1=y*cos(a)+x*sin(a);
    x=x1;y=y1;
}

直線及定義

先上程式碼:

struct Line{
    Node s,e;Line(){}
    Line(Node _s,Node _e){s=_s;e=_e}
    
}
少年的悲哀,畢竟是易消的殘雪。