我们先来看在坐标系下三角形的面积计算
A(x1, y1),B(x2, y2), C(x3, y3)这三点,向量AB我记为a,向量AC我记为b,S_ABC = 1/2 absin<a, b>,a = (x, y), b = (m, n),代入:
a = (x2-x1, y2-y1),b = (x3-x1, y3-y1)
则 x = x2-x1, y = y2-y1, m = x3-x1, n = y3-y1;
则 S_ABC = 1/2|x1y2+x2y3+x3y1-x1y3-x3y2-x2y1|
实际上更好的办法是用三阶行列式写出来(只怪本人还未学线性代数):
在这里我并没有规定方向,所以需要加上绝对值。实际上,如果是逆时针方向则为正,顺势针方向则为负,我们在这里可以将它称为有向面积:
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int x1, y1, x2, y2, x3, y3;
double S;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
S = 0.5 * fabs(x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x3 * y2 - x2 * y1);
printf("%.2lf\n", S);
return 0;
}
那对于多边形呢?实际上我们看,一个多边形也可以进行拆分成若干三角形,三角形面积的累加就为多变形的面积,如图:
在这里我们可以起一个起点,比如S点,那么多边形SABCDE可以化成SBA、SCB、SDC、SED四个三角形的面积之和,假设S(x0, y0),A(x1, y1)、B(x2, y2)、C(x3, y3)、D(x4, y4)、E(x5, y5),在这里我们取逆时针方向(因为为正),利用上面的三阶行列式及其展开:
然后我们再来求加和,可以得到:
发现什么特点了吗?是不是交错相乘相减再求累加和,但是在这里需要注意最后一项是首尾坐标,在这里是S(x0, y0)和E(x5, y5)点,被减去,我们可以得到一个公式:
S =
∑
i
=
0
n
−
1
x
i
y
(
i
+
1
)
−
x
(
i
+
1
)
y
i
\sum_{i=0}^{n-1} x_iy_(i+1)-x_(i+1)y_i
∑i=0n−1xiy(i+1)−x(i+1)yi-(x0yn-1-xn-1y0)
代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int i, n, a[100][2];
double S;
printf("请问有多少个顶点?\n");
cin >> n;
for (i = 0; i < n; i++)
{
cin >> a[i][0] >> a[i][1];
}
S = 0;
for (i = 0; i < n - 1; i++)
{
//按照逆时针方向旋转
S += 0.5 * (a[i][0] * a[i + 1][1] - a[i + 1][0] * a[i][1]);
}
S += 0.5 * (a[0][0] * a[n - 1][1] - a[n - 1][0] * a[0][1]);
printf("面积为:\n");
printf("%.2f\n", S);
return 0;
}
在这里无论是凸多边形还是凹多边形,都可以采用这样的方式去求解,因为当你规定逆时针方向时,实际上的面积是为有向面积,此时,你在顺势针方向上读时的面积为负则恰好减去原来多的一块面积,所以也可也采用此方法。
听说也可以采用皮克定理来做,有兴趣的同学可以看一看,只做借鉴。