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

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));//第二个参数为四周间隔


  • 2019-06-04 16:40:30

    为了美观当网页图片不存在时不显示叉叉图片

    当在页面显示的时候,万一图片被移动了位置或者丢失的话,将会在页面显示一个带X的图片,很是影响用户的体验。即使使用alt属性给出了”图片XX”的提示信息,也起不了多大作用。

  • 2019-06-04 17:38:44

    PHP时间转换今天昨天前天几天前

    实际情况应该是,昨天任何时间都算一天前,前天任意时间都算2天前,所以自己琢磨了一番,去动态更新时间与今天23:59:59相差的时间秒数与86400(24 x 3600)相除后,向下取整,这样就得到了相差的天数,比如昨天00:00~昨天23:59:59的任何时间与今天的23:59:59,都相差 86400~(86400 x 2) 天,也就是2天。

  • 2019-06-04 17:44:14

    【VUE】图片预览放大缩小插件

    在看项目时,突然看到预览图片的弹窗,感觉好僵硬,不能放大,不能切换,于是便在网上找下关于图片预览的插件,有找到三个插件,具体的优劣势的看自己的使用吧,我目前只是在电脑查看效果,分别是viewerjs插件、基于photoswipe的vue-photo-preview插件以及vue-picture-preview插件 作者:北极星丶超帅的 链接:https://www.jianshu.com/p/e3350aa1b0d0 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 2019-06-04 21:32:05

    Android 全局Dialog的简单实现

    这里所说的全局Dialog是指无论当前应用是处于哪一个页面上,都能够及时弹出Dialog来提示用户一些信息,用户体验不会很好,一般应用于优先级非常高的通知。

  • 2019-06-06 16:14:50

    intent-filter的action,category,data匹配规则

    我们知道有两种方式来启动Activity,显示调用和隐式调用。当使用隐式调用时,又会涉及到IntentFilter的匹配规则。我确信大多数开发者很少关注隐式调用,因为平时开发中用到大多数是显示调用。例如:用Intent直接打开一个Activity,或者用Intent通过包名等其他信息打开另外一个应用等。而隐式调用则使用的比较少,当然也不是完全不使用。例如:当我们需要打开浏览器访问某个链接时,手机上可能存在多个浏览器,我们也无法拿到某一个浏览器的包名,那么一般情况下我们会写如下代码:

  • 2019-06-06 17:57:57

    input【type="checkbox"】标签与字体对齐

    今天分享一个比较实用的技巧,在实际项目中我们会经常遇到表单的input标签多选和单选的问题,但是往往由于标签自身的样式和我们项目的风格很不搭调,就不能实现了,今天就来告诉大家怎么去实现吧。

  • 2019-06-10 11:54:52

    html.div禁用点击事件

    今天做项目中偶然误把元素加上了pointer-events属性,结果导致后来在js中给该元素加点击事件不能用,检查了半天才发现是这个属性的问题。之前没有好好研究,于是决定仔细研究一下。