# [几何] 计算任意多边形的面积、中心、重心

30 篇文章 0 订阅
13 篇文章 1 订阅
1 篇文章 0 订阅


/**
* 获取不规则多边形几何中心点
*
* @param mPoints
* @return
*/
public static LatLng getCenterPoint(List<LatLng> mPoints) {
// 1 自己计算
LatLngBounds.Builder boundsBuilder = LatLngBounds.builder();
for (LatLng ll : mPoints)
boundsBuilder.include(ll);
return boundsBuilder.build().getCenter();
}

计算不规则任意多边形的重心：

    /**
* 获取不规则多边形重心点
*
* @param mPoints
* @return
*/
public static LatLng getCenterOfGravityPoint(List<LatLng> mPoints) {
double area = 0.0;//多边形面积
double Gx = 0.0, Gy = 0.0;// 重心的x、y
for (int i = 1; i <= mPoints.size(); i++) {
double iLat = mPoints.get(i % mPoints.size()).latitude;
double iLng = mPoints.get(i % mPoints.size()).longitude;
double nextLat = mPoints.get(i - 1).latitude;
double nextLng = mPoints.get(i - 1).longitude;
double temp = (iLat * nextLng - iLng * nextLat) / 2.0;
area += temp;
Gx += temp * (iLat + nextLat) / 3.0;
Gy += temp * (iLng + nextLng) / 3.0;
}
Gx = Gx / area;
Gy = Gy / area;
return new LatLng(Gx, Gy);
}


    public class LatLng {
public final double latitude;
public final double longitude;
}

/**
* 经纬度范围类
*
*
* @author maple
*/
class LatLngBounds constructor(
private val southwest: LatLng,// 左下角 点
private val northeast: LatLng // 右上角 点
) {

val center: LatLng
get() {
// 计算中心点纬度
val centerLat = (this.southwest.latitude + this.northeast.latitude) / 2.0
// 计算中心点经度
val neLng = this.northeast.longitude // 右上角 经度
val swLng: Double = this.southwest.longitude // 左下角 经度
val centerLng: Double = if (swLng <= neLng) {
(neLng + swLng) / 2.0
} else {
(neLng + 360.0 + swLng) / 2.0
}
return LatLng(centerLat, centerLng)
}

// 某个点是否在该范围内（包含边界）
fun contains(point: LatLng): Boolean {
return latContains(point.latitude) && this.lngContains(point.longitude)
}

// 某个纬度值是否在该范围内（包含边界）
private fun latContains(lat: Double): Boolean {
return this.southwest.latitude <= lat && lat <= this.northeast.latitude
}

// 某个经度值是否在该范围内（包含边界）
private fun lngContains(lng: Double): Boolean {
return if (this.southwest.longitude <= this.northeast.longitude) {
this.southwest.longitude <= lng && lng <= this.northeast.longitude
} else {
this.southwest.longitude <= lng || lng <= this.northeast.longitude
}
}

// 小数据量可以使用该方法，大数据量建议使用Builder中的include()
fun including(point: LatLng): LatLngBounds {
val swLat = Math.min(this.southwest.latitude, point.latitude)
val neLat = Math.max(this.northeast.latitude, point.latitude)
var neLng = this.northeast.longitude
var swLng = this.southwest.longitude
val pLng = point.longitude
if (!this.lngContains(pLng)) {
if (zza(swLng, pLng) < zzb(neLng, pLng)) {
swLng = pLng
} else {
neLng = pLng
}
}
return LatLngBounds(LatLng(swLat, swLng), LatLng(neLat, neLng))
}

/**
* LatLngBounds生成器
*/
class Builder {
private var swLat = 1.0 / 0.0   // 左下角 纬度
private var swLng = 0.0 / 0.0   // 左下角 经度
private var neLat = -1.0 / 0.0  // 右上角 纬度
private var neLng = 0.0 / 0.0   // 右上角 经度

fun include(point: LatLng): Builder {
this.swLat = Math.min(this.swLat, point.latitude)
this.neLat = Math.max(this.neLat, point.latitude)
val pLng = point.longitude
if (java.lang.Double.isNaN(this.swLng)) {
this.swLng = pLng
} else {
if (lngContains(pLng)) {
return this
}
if (zza(this.swLng, pLng) < zzb(this.neLng, pLng)) {
this.swLng = pLng
return this
}
}
this.neLng = pLng
return this
}

// 某个经度值是否在该范围内（包含边界）
private fun lngContains(lng: Double): Boolean {
return if (this.swLng <= this.neLng) {
this.swLng <= lng && lng <= this.neLng
} else {
this.swLng <= lng || lng <= this.neLng
}
}

fun build(): LatLngBounds {
// Preconditions.checkState(!java.lang.Double.isNaN(this.swLng), "no included points")
return LatLngBounds(LatLng(this.swLat, this.swLng), LatLng(this.neLat, this.neLng))
}
}

companion object {
fun builder(): Builder {
return Builder()
}

// 前者 - 后者
private fun zza(var0: Double, var2: Double): Double {
return (var0 - var2 + 360.0) % 360.0
}

// 后者 - 前者
private fun zzb(var0: Double, var2: Double): Double {
return (var2 - var0 + 360.0) % 360.0
}
}

}


e.g：在计算一个点比较多的Polygon的范围时，建议使用Builder中的include()方法。

• 9
点赞
• 68
收藏
• 打赏
• 32
评论
11-25
04-04 1万+
12-14 306
10-22 1万+
03-22 9012
01-13 953
08-08 1667
07-23 2565
03-02 1928
07-12 61
03-10 1万+
05-04 793
05-27 2万+
08-08 629

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

Maple_Shao

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。