前面 GeoUtils 类可以很好的计算密闭多边形、矩形框出的区域面积,但没有解决折线自相交框出的区域面积计算。虽然折线自相交形成的区域框,绝大多数都可以用多边形区域框代替,但有时不免要用折线去形成一些特殊的区域框,而恰恰这些区域框又需要计算面积,这就形成了一个特殊需求。然而百度原生API以及各个开源库又都没有提供这种计算方法,于是就只能开发人员自己去解决了。 在度娘了几篇文章后,最终找到了一个计算方法,经实测效果不错,结果也比较精准。 // 计算图形面积 // path:[{lat:,lng:}],[{lat:,lng:}],[{lat:,lng:}] 路劲坐标点数组 computeSignedArea(path) { let radius = 6370996.81; // 地球平均半径 let len = path.length; if (len < 3) return 0; let total = 0; let prev = path[len - 1]; let prevTanLat = Math.tan((Math.PI / 2 - (prev.lat / 180) * Math.PI) / 2); let prevLng = (prev.lng / 180) * Math.PI; for (let i = 0; i < len; i++) { let tanLat = Math.tan( (Math.PI / 2 - (path[i].lat / 180) * Math.PI) / 2 ); let lng = (path[i].lng / 180) * Math.PI; total += this.polarTriangleArea(tanLat, lng, prevTanLat, prevLng); prevTanLat = tanLat; prevLng = lng; } return Math.abs(total * (radius * radius)); }, // 计算图形面积 polarTriangleArea(tan1, lng1, tan2, lng2) { let deltaLng = lng1 - lng2; let t = tan1 * tan2; return 2 * Math.atan2(t * Math.sin(deltaLng), 1 + t * Math.cos(deltaLng)); } 方法使用也比较简单,直接将自相交折线 各个点的坐标组成一个数组,传入 computeSignedArea(path) 即可。 由于方法返回的面积是以平方米作为单位的,所以需要处理下(毕竟地图区域那么大,以平方米计算,数字显得很大,但区域却不见得有多大,故用平方千米作为单位,以此来和我大中国960万平方千米比较,显得你这个区域有多大点) geoUtilsValue = this.computeSignedArea(overlayList) / 1000000 + "平方千米"; 以 沈阳故宫博物院为例,资料显示是六万多平方米(即0.06+平方千米),实际折线框图计算面积:0.0614平方千米,精确度还可以。
计算面积调用方法: // 计算面积 getSignedArea() { if ( this.circleObj || this.polygonObj || this.rectangleObj || this.polylineObj ) { if (this.circleObj) { // let geoUtilsValue = // this.getPolygonArea(this.circleObj.pointList) / 1000000 + // "平方千米"; // 多边形、矩形计算面积(除以1000000,将平方米换算成平方千米) // alert(geoUtilsValue); } if (this.polygonObj || this.rectangleObj) { // 多边形、矩形 密闭多边形 let overlayList = this.polygonObj ? this.polygonObj.pointList : this.rectangleObj.pointList; let geoUtilsValue = BMapLib.GeoUtils.getPolygonArea(overlayList) / 1000000 + "平方千米"; // 多边形、矩形计算面积(除以1000000,将平方米换算成平方千米) alert(geoUtilsValue); } // 判定折线对象是否存在 if (this.polylineObj) { // 折线自相交多边形 let pointList = this.polylineObj.pointList, pointListLeng = pointList.length; let firstPoint = pointList[0]; let lastPoint = pointList[pointListLeng - 1]; // 判定折线首尾点距离,首尾点距离不超过10米视为构成密闭图像区域,则可计算面积 if ( pointListLeng > 3 && BMapLib.GeoUtils.getDistance( // 计算两点之间的距离,两点坐标必须为经纬度 new BMap.Point(firstPoint.lng, firstPoint.lat), new BMap.Point(lastPoint.lng, lastPoint.lat) ) < 10 ) { let geoUtilsValue = this.computeSignedArea(this.polylineObj.pointList) / 1000000 + "平方千米"; // 多边形、矩形计算面积(除以1000000,将平方米换算成平方千米) alert(geoUtilsValue); } else { alert( pointListLeng > 3 ? "折线首尾坐标点相距太远,无法形成密闭图形区域" : "坐标点过少,无法构成密闭图形区域" ); } } this.clearOverlayObjAndLayer(); } else { if ( !( this.circleObj || this.polygonObj || this.rectangleObj || this.polylineObj ) ) { alert("请先绘制密闭图形或自相交折线图形!"); } } }, 参考博文链接:https://blog.csdn.net/qq_38615014/article/details/89207005 |
|