二維坐標系中的點積、叉積、多邊形面積
點積定義
設有向量 \(\vec{a}\) 和 \(\vec{b}\) ,定義點積 \(\vec{a}\cdot \vec{b}\) 為 實數 ,其值為 向量 \(\vec{a}\) 在向量 \(\vec{b}\) 上投影的長度乘以向量 \(\vec{b}\) 的模
點積性質
滿足交換律,結合律
點積計算
直接計算
坐標系中計算
放在坐標系中,設 \(\vec{a} = (x_{1},\ y_{1}),\ \vec{b} = (x_{2},\ y_{2})\)
那么 \(\vec{a}\cdot \vec{b} = x_{1}x_{2} + y_{1}y_{2}\)
叉積定義
設有向量 \(\vec{a}\) 和 \(\vec{b}\) ,定義叉積 \(\vec{a}\times \vec{b}\) 為新的 向量。
其模長為 \(\vec{a}\) 和 \(\vec{b}\) 所圍成的平行四邊形面積。
方向與 \(\vec{a}\) 和 \(\vec{b}\) 均垂直。
若 \(\vec{b}\) 在 \(\vec{a}\) 逆時針方向,即呈現左手系,那么 \(\vec{a}\times \vec{b}\) 為正;反之為負。
叉積性質
叉積模即為平行四邊形面積,所以在直角坐標系中求一個三角形的面積可以用叉積來計算,即
叉積不滿足交換律,因為方向會發生變化,即
二維叉積模的計算
直接計算
坐標系中計算
放在坐標系中,設 \(\vec{a} = (x_{1},\ y_{1}),\ \vec{b} = (x_{2},\ y_{2})\)
經過推導得到 \(|\vec{a} \times \vec{b}| = |x_{1}y_{2} - x_{2}y_{1}|\)
去掉絕對值便得到 有向面積
若值為正,說明 \(\vec{b}\) 在 \(\vec{a}\) 逆時針方向;若值為負,說明說明 \(\vec{b}\) 在 \(\vec{a}\) 順時針方向。
多邊形面積計算
基本思想是把多邊形划分成多個三角形,然后叉積計算面積。這個思想對於凹凸多邊形都成立。
記多邊形頂點逆時針排列為 \(P_{0},\ P_{1},\ ..,\ P_{n - 1}\)
為了方便計算,選取坐標原點 \(O(0,\ 0)\) 作為源點,逐一計算 \(\vec{OP_{i}}\times \vec{OP_{i + 1}}\) ,累計求和即可。
公式為
當 \(i = n - 1\) 時,下一個坐標要回到 \((x_{0}, y_{0})\) ,這里可以特判,也可以取模運算。
復雜度 \(O_{n}\)
由於叉積面積的有向性,多余的面積會被抵消掉,所以這個算法是正確的,此處省略嚴格證明。
\(code\)
int n;
struct Cor
{
int x, y;
}cor[105];
inline int read()
{
char c = getchar();
int ans = 0, f = 1;
while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
return ans * f;
}
int main()
{
while(scanf("%d", &n) && n) {
for(int i = 0; i < n; ++i)
cor[i].x = read(), cor[i].y = read();
double ans = 0.0;
for(int i = 0; i < n; ++i){
ans += 0.5 * (cor[i % n].x * cor[(i + 1) % n].y - cor[i % n].y * cor[(i + 1) % n].x);
}
printf("%.1f\n", ans);
}
return 0;
}