# 內外積在程式中的應用 先複習 * $\vec{AB}=(x2−x1 ,y2 ​−y1​)$ * 內積: $\vec{a}\cdot\vec{b} = a_xb_x+a_yb_y$ * 外積: $\vec{a}\times\vec{b} = a_xb_y-a_yb_x$ :::warning 需要至少三個點才能形成兩個向量 ::: ## 內積(Dot Product) 可以用來求角度或判斷夾角是銳角、直角或鈍角 | 判斷 | 結果 | | --------------------------- | -- | | ( $\vec{a}\cdot\vec{b}$ > 0 ) | 銳角 | | ( $\vec{a}\cdot\vec{b}$ = 0 ) | 直角 | | ( $\vec{a}\cdot\vec{b}$ < 0 ) | 鈍角 | 由角度的關係可以知道兩向量的方向關係: * **夾角為銳角**( $0^{\circ }\le\theta <90^{\circ }$):內積為正值,表示兩個向量方向大致`相同`。 * **夾角為鈍角**( $90^{\circ }\le\theta <180^{\circ }$):內積為正值,表示兩個向量方向大致`相反`。 * **夾角為直角** ($\theta =90^{\circ }$):內積為零,表示兩個向量互相`垂直`。 ## 外積 在幾何中(3D),向量的定義為`公垂向量`,他會垂直 $\vec{a}$ 與 $\vec{b}$ ,但在平面中,沒有地方儲存Z軸,所以會運算結果會是一個正負數,用來代表左右轉還是迴轉。 > a = (1, 0) // 指向 x 軸正方向 b = (0, 1) // 指向 y 軸正方向 外積: $a×b=(1)(1)−(0)(0)=+1$ 代表「z 軸正方向」,也就是「逆時針」旋轉 -> 左轉。 所以正負號可判斷旋轉方向: * $> 0$ → 左轉 * $< 0$ → 右轉 * $= 0$ → 共線(迴轉或原地不動) :::warning 要注意外積=0的時候可能是原地不動,迴轉的條件是兩方向相反(透過內積求得方向) ::: | 類型 | 用法 | 判斷依據 | | ----- | --------- | ----------- | | 判斷轉向 | 外積 | 正負號 | | 判斷夾角 | 內積 | 正負號 | | 計算面積 | 外積絕對值 / 2 | 幾何面積 | | 多邊形方向 | 外積和的符號 | 正→逆時針、負→順時針 | | 判斷正交 | 內積 = 0 | 垂直 | # 實作 競賽中會透過Struct這個資料結構來快速存取x,y值。 ```cpp= struct Point { double x, y; }; int main() { Point a = {3, 4}; Point b = {1, 2}; cout << a.x+b.x;//4 } ``` 當然也可以透過以下寫法: 更快速的存取其他運算。 ```cpp= struct Point { double x, y; // 向量加法 Point operator+(const Point &other) const { return {x + other.x, y + other.y}; } // 向量減法 Point operator-(const Point &other) const { return {x - other.x, y - other.y}; } // 內積 double dot(const Point &other) const { return x * other.x + y * other.y; } // 外積 double cross(const Point &other) const { return x * other.y - y * other.x; } }; ``` ```cpp= Point a = {3, 4}, b = {1, 2}; cout << a.dot(b) << endl; // 內積 cout << a.cross(b) << endl; // 外積 ``` ## 實際演練 [2023/06 APCS 實作題](/Y5GdYfwnQ4Kbw3H8bJTkaw) - 第一題: 路徑偵測