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