向量法计算多边形面积
計算多邊形面積的方法為將多邊形分解成多個三角形,然后把這些三角形的面積相加。三角形面積為兩邊向量叉積除以2。
這是Java代碼,目前是第3版?,已經(jīng)盡可能優(yōu)化了,相比初版有25%的性能提升。
/*** 平面多邊形面積算法3,用原點為基點(不需要從圖形邊線上取點)<br/>* 多計算一條線段,但減少了每一步的兩次減法(起于原點的向量等于節(jié)點的坐標(biāo)),使誤差減小,每一步的計算量減少。* * @return 正方向(x軸向y軸旋轉(zhuǎn)方向)圈成的面積(如果有反方向的圈,則面積會被抵消,導(dǎo)致結(jié)果小于直觀觀測的面積或為負(fù)數(shù))*/private static final double getPolygonAreaMethodC(double... points) {if (points.length < 6) {// 無法構(gòu)成多邊形return 0;}final int pointArrayLength = points.length & (~1);// final int pointCount = pointArrayLength / 2;double area = 0.0;double dx1, dy1;double dx2, dy2;// 從原點到該點的向量dx1 = points[pointArrayLength - 2];dy1 = points[pointArrayLength - 1];for (int i = 0; i < pointArrayLength;) {// 從原點到該點的向量dx2 = points[i++];dy2 = points[i++];// 三角形的面積2倍,平行四邊形面積。為提高性能,不在循環(huán)中進行面積減半final double subArea = dx1 * dy2 - dx2 * dy1;// 由jvm進行智能內(nèi)聯(lián),分出這一步不會影響性能area += subArea;// 向量傳遞dx1 = dx2;dy1 = dy2;}// 最后統(tǒng)一除以2,提高性能return area / 2;}除了可以用來計算面積,還可以進行分布式計算π。把半徑R的圓分解成很多邊的多邊形,每臺計算機只計算其中的一部分。然后將每臺計算機算出的面積相加得到面積S。π=S/(R^2)。這只是一種用法,事實上并不建議用此方法計算π。最好的辦法仍然是可迭代的,所以分布式計算π并沒有優(yōu)勢。
下面是C++的版本,也是初版,作為參考。
/*** 平面多邊形面積** @return*/ double getPolygonArea(double *points, int length) {if (length < 6) {// 無法構(gòu)成多邊形return 0;}double area = 0.0;double x0 = points[0], y0 = points[1];double dx1, dy1;double dx2, dy2;dx1 = points[2] - x0;dy1 = points[3] - y0;for (int i = 4; i < length - 1; i += 2) {dx2 = points[i] - x0;dy2 = points[i + 1] - y0;double subArea = (dx1 * dy2 - dx2 * dy1) / 2.0;area += subArea;dx1 = dx2;dy1 = dy2;}return area; }Java并發(fā)版本(有依賴項,不可直接使用)。
依賴項1:ParallelTask.parallelFor其實是線程池。第一個參數(shù)0代表WorkSteal線程池。第二個參數(shù)代表Lambda執(zhí)行的次數(shù),一般取CPU核心數(shù)。Lambda的參數(shù)threadOrder代表此Lambda所在線程啟動的順序。靜態(tài)的方法parallelFor代表內(nèi)部生成線程池,并在返回之前關(guān)閉和等待線程池任務(wù)結(jié)束。ParallelTask是一個實現(xiàn)了十幾種動態(tài)與靜態(tài)parallelFor的大文件,不方便上傳。
依賴項2:StaticSystemUtils.getCPUCoreCount就是Runtime.avaliableProcesses()。StaticSystemUtils是一個獲取系統(tǒng)信息的大文件,不方便上傳。
依賴項3:StaticMathUtils.sum就是一個求和函數(shù)。StaticMathUtils是一個包含數(shù)十種算術(shù)方法,幾千行的大文件,不方便上傳。
/*** 平面多邊形面積算法3,用原點為基點(不需要從圖形邊線上取點)<br/>* 多計算一條線段,但減少了每一步的兩次減法(起于原點的向量等于節(jié)點的坐標(biāo)),使誤差減小,每一步的計算量減少。* * @return 正方向(x軸向y軸旋轉(zhuǎn)方向)圈成的面積(如果有反方向的圈,則面積會被抵消,導(dǎo)致結(jié)果小于直觀觀測的面積或為負(fù)數(shù))*/public static final double getPolygonAreaParallel(double... points) {if (points.length < 6) {// 無法構(gòu)成多邊形return 0;}final int pointArrayLength = points.length & (~1);final int pointCount = pointArrayLength / 2;double area = 0.0;final int taskCount = Math.min(StaticSystemUtils.getCPUCoreCount(), pointCount);final double[] eachArea = new double[taskCount];ParallelTask.parallelFor(0, taskCount, threadOrder -> {final int from = (int) ((long) threadOrder * pointArrayLength / taskCount) & (~1);final int to = (int) ((long) (threadOrder + 1) * pointArrayLength / taskCount) & (~1);double threadArea = 0.0;double dx1, dy1;double dx2, dy2;// 從原點到該點的向量if (threadOrder == 0) {dx1 = points[pointArrayLength - 2];dy1 = points[pointArrayLength - 1];} else {dx1 = points[from - 2];dy1 = points[from - 1];}for (int i = from; i < to;) {// 從原點到該點的向量dx2 = points[i++];dy2 = points[i++];// 三角形的面積2倍,平行四邊形面積。為提高性能,不在循環(huán)中進行面積減半final double subArea = dx1 * dy2 - dx2 * dy1;// 由jvm進行智能內(nèi)聯(lián),分出這一步不會影響性能threadArea += subArea;// 向量傳遞dx1 = dx2;dy1 = dy2;}eachArea[threadOrder] = threadArea;});area = StaticMathUtils.sum(eachArea);// 最后統(tǒng)一除以2,提高性能return area / 2;}?
總結(jié)
以上是生活随笔為你收集整理的向量法计算多边形面积的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: databricks spark 读取p
- 下一篇: 无言如是说-舒羽