百度地图 - 基础学习(8): 折线构成闭合图形面积计算
前面 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
赞 (0)
