最近项目用到:在不规则任意多边形的中心点加一个图标。(e.g: xx地区发生暴雪,暴雪区域是多边形,给多边形中心加一个暴雪的图标)

之前的设计是,计算不规则多边形范围矩形bounds的中心点。这个比较简单,对于一些圆,矩形,凸多边形都比较适合。但是遇到凹多边形就会出现问题,比如一个月牙型的不规则多边形,bounds的中心点,就落到月牙外了。就有点难以接受了。

经过讨论,决定将中心改为重心。

下面上代码,

计算不规则任意多边形的中心:

/*** 获取不规则多边形几何中心点** @param mPoints* @return*/public static LatLng getCenterPoint(List<LatLng> mPoints) {// 1 自己计算// 2 使用Google map API提供的方法(推荐)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、yfor (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);}

其中LatLng类就是一个包含经纬度点的简单类。可以自己创建一个包含 x ,y 的类代替。

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

好多人说不知道LatLngBounds类的具体实现,其实这是Google map包中的一个类,内部功能很简单,就是提供了一个构造器Builder可以不断的往里面添加经纬度点LatLng,不断计算更新Bounds范围和center中心点。

下面贴上整理后的LatLngBounds类,可以减去导入Google map包的麻烦

/*** 经纬度范围类** 复写com.google.android.gms.maps.model.LatLngBounds中核心方法** @author maple*/
@Deprecated("条件允许,请使用com.google.android.gms.maps.model.LatLngBounds")
class LatLngBounds constructor(private val southwest: LatLng,// 左下角 点private val northeast: LatLng // 右上角 点
) {val center: LatLngget() {// 计算中心点纬度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.longitudevar swLng = this.southwest.longitudeval pLng = point.longitudeif (!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.longitudeif (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 = pLngreturn this}}this.neLng = pLngreturn 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}}}

注意⚠️:LatLngBounds中including()方法  和  Builder中include()方法在具体实现上是相同,但是LatLngBounds每次都会new一个新的对象,所以不适合大批量数据时使用。

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

Demo地址:https://github.com/shaoshuai904/GoogleMap_Demo

通过这张图,就可以发现中心和重心的区别

     

项目实际表现:

     

[几何] 计算任意多边形的面积、中心、重心相关推荐

  1. 凸多边形面积_C++计算任意多边形的面积

    任意多边形的面积计算_拾忆楓灵的博客-CSDN博客​blog.csdn.net 计算任意多边形的面积 - tenos - 博客园​www.cnblogs.com 完美解决计算3D空间任意多边形面积_S ...

  2. 计算任意多边形的面积

    转载自 对于凸多边形,很容易计算,如下图,以多边形的某一点为顶点,将其划分成几个三角形,计算这些三角形的面积,然后加起来即可.已知三角形顶点坐标,三角形面积可以利用向量的叉乘来计算. 对于凹多边形,如 ...

  3. 计算任意多边形的面积(Android)

    需求 线段:算出地图上线段的实际长度 面积:算出地图上不规则多边形的实际面积 解决方案 1.线段的实际长度 直接使用高德的AMapUtils.calculateLineDistance(latLng, ...

  4. python计算任意多边形面积

    看了一些方法网上的资料,也自己倒腾了一些想法. 然后看到这个大神的博客(<计算任意多边形的面积>),我就服气了. 我把代码转换为python: # 计算任意多边形的面积,顶点按照顺时针或者 ...

  5. vue+d3.js计算任意多边形面积

    效果图 代码 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF ...

  6. Java计算任意多边形面积

    任意多边形的面积可由任意一点与多边形上依次两点连线构成的三角形矢量面积求和得出. 矢量面积=三角形两边矢量的叉乘.![在这里插入图片描述](https://img-blog.csdnimg.cn/ad ...

  7. 任意多边形的面积公式

    设Ω是m边形(如下图),顶点沿边界正向排列,坐标依次为 建立Ω的多边形区域向量图. 由图知坐标原点与多边形任意相邻的两个顶点构成一个三角形,而三角形的面积可由三个顶点构成的两个平面向量的外积求得. 任 ...

  8. C++实现——任意多边形的面积

    //求任意多边形的面积 /*语法:result = polygonarea(vector<Point>&polygon, int N); 参数: polygon:多变形顶点数组 N ...

  9. 【几何】计算任意多边形面积

      给定一系列有序的线段(比如按顺序给定每个线段的左端点坐标),求这些线段围成的多边形的面积,公式为:   任意一个点与顺序相邻两点组成的三角形面积之和   分为凸多边形和凹多边形分别证明: 一.凸多 ...

最新文章

  1. 2022-2028年中国分散式风电行业投资分析及前景预测报告
  2. java如何让控制台不输出报错_Java 控制台输入输出操作记录
  3. XMLHttpRequest Post参数
  4. python怎么安装pandas模块-python如何导入安装pandas模块并使用别名
  5. cv dnn识别动作规范 open_OpenCV开发笔记(七十三):红胖子8分钟带你使用opencv+dnn+yolov3识别物体...
  6. could not create connection to database server.] with root cause
  7. Quartz.net定时任务的使用及获取正在运行的JOB
  8. python如何只保留数字_如何查询刷卡消费有没有积分?只需用4个数字马上能查...
  9. wxPython--学习笔记
  10. python捕捉warning_python – 如何格式化logging.captureWarnings捕获的警告?
  11. UVa 208-Firetruck
  12. Chrome浏览器上传文件卡死
  13. HDU1492/The number of divisors(约数) about Humble Numbers
  14. 交朋友游戏C语言,幼儿园小班社会教案《我会交朋友》游戏活动
  15. NAGA-Ⅱ与QPSO算法求解下层为非合作博弈模型的双层规划组合优化模型(铁路开行方案)
  16. hashmap java 排序_Java HashMap 默认排序
  17. Instant及LocalDateTime等使用方法
  18. juniper防火墙操作命令
  19. 基于ROS2开发的点云体素化
  20. 2022年第二届中国高校大数据挑战赛A题探究

热门文章

  1. Optional 使用方法
  2. mysql 1261 load data_Mysql错误积累001-load data导入文件数据出现1290错误
  3. 户外骑行运动耳机哪个好,几款适合在骑行佩戴的耳机推荐
  4. API:BUMO Websocket
  5. 23种设计模式-完结!
  6. python大学公众号_推荐几个专业的技术公众号
  7. 新零售时代线上线下的变革
  8. 写论文三大助手:看外文文献、下载文档、插入文献
  9. ubuntu 配置strongswan client
  10. 匠人精神打磨六年 “中国制造” Hubble自然走向AI-Native数据库