计算多边形的面积
“数性至朴,算学是天下最诚实的东西,一加一永远是二,五乘四永远是二十,而十二自实永远是一百四十四。”
这世上,人心比算学更复杂。人际关系让人疲惫,还是数学比较单纯。这是我在电视剧《显微镜下的大明:丝绢案》中看到的,“人心叵测,难以琢磨,而数性至朴,从不虚饰,数与数之间的关联,就好比天上的星宿一样,万年难易,只要你掌握了其中的运转之妙,计算之理,便可以俯仰天地,上下求索”,帅家默说,“这便是我所求的道,任凭数字无穷无尽,任凭难题变化莫测,吾以一道而御之。也许在你看来,这只是一间装满了断烂朝报的破屋子,可在我看来,这是直通仙府的大道,我在其中神游天外,上穷碧落下黄泉,无数的景致只在一念之间,何其的快活。”
我留意到剧中有一个丈量妖田的算法————推步聚顶之术,于是心血来潮研究了一下,总结几种计算多边形面积的方法。
算法一: 三角剖分法
这个算法使用了多边形三角剖分的思想来计算多边形的面积。具体来说,它将多边形划分为若干个三角形,然后计算每个三角形的面积,最后将所有三角形的面积相加得到多边形的面积。
具体实现步骤如下:
-
首先,将多边形的顶点按照顺序排列。
-
从任意一个顶点开始,顺次连接所有相邻的顶点,形成若干个三角形。
-
对于每个三角形,使用海龙公式(海伦公式)计算其面积。海龙公式的计算公式为:
S = √[p(p-a)(p-b)(p-c)]
其中,S 表示三角形的面积,a、b、c 分别为三角形的三条边的长度,p 表示半周长,即 (a+b+c)/2。
-
将所有三角形的面积相加,即可得到多边形的面积。
在实现时,我们可以用一个循环遍历多边形的每个顶点,计算每个三角形的面积,并将其加入总面积中。具体地,我们可以计算以当前顶点和相邻的两个顶点构成的三角形面积,再累加到总面积中。
需要注意的是,这个算法要求多边形的顶点按照顺序排列。如果顺序不正确,计算结果将不正确。
// 三角剖分法的时间复杂度通常为 O(n log n) 或 O(n^2)
func polygonArea(x, y []float64) float64 {
n := len(x)
area := 0.0
for i := 0; i < n; i++ {
j := (i + 1) % n
area += x[i] * y[j] - x[j] * y[i]
}
area = math.Abs(area) / 2.0
// Triangulate the polygon
triArea := 0.0
for i := 1; i < n-1; i++ {
triArea += triangleArea(x[0], y[0], x[i], y[i], x[i+1], y[i+1])
}
return triArea
}
func triangleArea(x1, y1, x2, y2, x3, y3 float64) float64 {
a := math.Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))
b := math.Sqrt((x2-x3)*(x2-x3) + (y2-y3)*(y2-y3))
c := math.Sqrt((x3-x1)*(x3-x1) + (y3-y1)*(y3-y1))
s := (a + b + c) / 2.0
return math.Sqrt(s * (s - a) * (s - b) * (s - c))
}
计算三角形面积可以使用叉积来实现,即 S = 0.5 * (x1y2 - x2y1 + x2y3 - x3y2 + … + xny1 - x1yn),其中 x 和 y 分别表示多边形顶点的 x 坐标和 y 坐标。
叉积是向量运算中的一种,用于计算两个向量构成的平行四边形的面积、方向和法线。叉积也称为叉积积、矢量积或向量积。
两个向量 a 和 b 的叉积记为 a × b,其结果是一个新的向量,其大小等于 a 和 b 所在平行四边形的面积,方向垂直于 a 和 b 所在平面,且满足右手定则。右手定则是一个基本规律,它规定:将右手伸开,将大拇指指向向量 a 的方向,食指指向向量 b 的方向,那么中指所指的方向就是 a × b 的方向。
计算 a 和 b 叉积的公式为:
a × b = ∣ a ∣ ∣ b ∣ s i n θ n a × b =|a||b|sinθn