多边型无序点排序(地图绘制多边形)

2019-11-26 11:08:02

参考地址 多边型无序点排序(地图绘制多边形)

从这些点里随便选一个(比如最左边最下面哪一个)
然后以这个点为原点按极角排序(极角相同按距离排序)

 

前言

任务需求要做一个区域高亮的功能,用到地图,想到了高德地图的多边形API,但是多边形顶点的顺序是要有序的,需求是无序,在API查找无果的情况下,只能手动实现点集合排序。

排序步骤

  1. 计算所有坐标的中心点(将x坐标相加处以数量,将y坐标相加处以数量)

  2. 计算所有点与中点的夹角(水平夹角或者垂直夹角)

  3. 按夹角大小排序

代码实现

  • 收集3个以上的坐标点放入到集合中private ArrayList<LatLng> list;

  • 计算中心点坐标

double plusX = 0, plusY = 0;for (LatLng latLng : list) {plusX += latLng.latitude;plusY += latLng.longitude;}center = new LatLng(plusX / list.size(), plusY / list.size());
  • 通过工具方法获得2个点坐标对应的在垂直方向上的角度

/**     * @param lat_a 纬度1     * @param lng_a 经度1     * @param lat_b 纬度2     * @param lng_b 经度2     * @return     */private double getAngle1(double lat_a, double lng_a, double lat_b, double lng_b) {double y = Math.sin(lng_b - lng_a) * Math.cos(lat_b);double x = Math.cos(lat_a) * Math.sin(lat_b) - Math.sin(lat_a) * Math.cos(lat_b) * Math.cos(lng_b - lng_a);double brng = Math.atan2(y, x);brng = Math.toDegrees(brng);if (brng < 0)brng = brng + 360;return brng;}
  • 将坐标数组转换为HashMap<Integer, ArrayList<Object>> 映射为下标->(角度,坐标)

HashMap<Integer, ArrayList<Object>> mapAll = new HashMap<>();for (int i = 0; i < list.size(); i++) {//第一个放经纬度 第二个放角度ArrayList<Object> objList = new ArrayList<>();objList.add(list.get(i));objList.add(getAngle1(center.latitude, center.longitude,list.get(i).latitude, list.get(i).longitude));mapAll.put(i, objList);}
  • 采用冒泡排序法对角度进行排序

ArrayList<Object> temp = new ArrayList<>();int size = mapAll.size();for (int i = 0; i < size - 1; i++) {for (int j = 0; j < size - 1 - i; j++) {if (Double.parseDouble(mapAll.get(j).get(1).toString()) >Double.parseDouble(mapAll.get(j + 1).get(1).toString()))  //交换两数位置{temp = mapAll.get(j);mapAll.put(j, mapAll.get(j + 1));mapAll.put(j + 1, temp);}}}
  • 生成新的顺时针的坐标点集合

list.clear();for (Integer integer : mapAll.keySet()) {if (mapAll.get(integer).get(0) instanceof LatLng) {list.add((LatLng) mapAll.get(integer).get(0));}}

高德功能,将多点形成的多边形显示在一个屏幕上

for (int i = 0; i < list.size(); i++) {boundsBuilder.include(list.get(i));//把所有点都include进去(LatLng类型)}aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 100));//第二个参数为四周间隔


  • 2021-01-13 13:36:29

    shortid nodejs短id生成器

    短ID在实际运用中很广泛, 其中比较典型的运用就是短地址。 市面上肯定有不少开源的生成短ID库, 基于node.js的估计也不少。 鉴于本人已然是node.js的脑残粉(本职java开发), 很多业余项目从前端到后端都基于javascript开发, 加上npm和bower的包管理以及grunt的打包工具, 在项目开发过程中体验特别酸爽。 由于当时项目前后端都会用到短ID, 但没找到合适的库同时支持npm和bower的(可能孤陋寡闻). 因此自己乐此不疲地又造了个轮子js-shortid(夷,为什么会说又呢?!). 下面主要介绍它的实现方案, 自认为比较优雅简洁。

  • 2021-01-13 17:23:21

    CREATE TABLE 表名 AS SELECT 语句 快速复制表但是锁表

    注意Table2的主键约束,如果Table2有主键而且不为空,则 field1, field2…中必须包括主键 在执行语句的时候,MySQL是逐行加锁的(扫描一个锁一个),直至锁住所有符合条件的数据,执行完毕才释放锁。所以当业务在进行的时候,切忌使用这种方法。 在RR隔离级别下,还会加行锁和间隙锁

  • 2021-01-13 17:27:04

    Navicat配置mysql数据库用户权限

    用数据库的时候就会遇到有多个用户,分配用户权限的情况,有些用户只读,有些用户可以读写,有些用户只能操作一个或者多个数据库,如何给mysql的用户设置权限,我这里描述一下如何用navicat图形操作分配用户权限

  • 2021-01-14 06:15:04

    通过glide获取图片显示后的真正宽高

    有时候需要获取网络图片的宽高来设置图片显示的大小,很多人会直接利用Glide的加载监听去拿图片的宽高,但是这样拿到的不是图片真正的宽高,而是图片显示在ImageView后的宽高。如下:

  • 2021-01-14 09:38:57

    Chrome插件详细教程

    严格来讲,我们正在说的东西应该叫Chrome扩展(Chrome Extension),真正意义上的Chrome插件是更底层的浏览器功能扩展,可能需要对浏览器源码有一定掌握才有能力去开发。鉴于Chrome插件的叫法已经习惯,本文也全部采用这种叫法,但读者需深知本文所描述的Chrome插件实际上指的是Chrome扩展。

  • 2021-01-14 17:07:51

    chrome.contextMenus.create不出现菜单

    主要原因是,我每次刷新玩,都复制一下右键,然而并没有出现菜单,一度颓废啊,因为demo,还有其他人的文章都是这样的。 哎,后来发现是这样的,我缺少了contexts选项。其实我是成功了,我现在只要不选择文字,直接点右键,菜单已经出现了哦。