美文网首页
聚合算法-基础理论篇

聚合算法-基础理论篇

作者: erki_stwee | 来源:发表于2018-05-19 00:19 被阅读161次

今天接到一个任务,平哥让我看一下聚合算法(第一反应是一脸懵逼,还好平哥是个老江湖看到我样子给我简单简绍了一下公司中使用聚合算法的地方O(∩_∩)O)这篇文章主要是从高德地图API来分析它的一些核心类和实现方法。在下一篇文章中我将结合实际需求对其进行修改。

为什么需要聚合算法

主要用于解决用户在地图上绘制大量标注时,出现相互压盖,底图加载的卡顿问题。

思路

服务端计算标注统计数据,在客户端加载绘制
所有数据必须是实时性的,这也就意味着每次变化都要从服务器返回数据,实现难度大而且会对服务端和客户端造成巨大压力。

一次性加载所有数据,在客户端实现算法在需要的时候计算重载
为了避免上述情况的出现。这里采用了点聚合的概念。

原理及实现

核心类库 包名

都混淆了看不到具体实现逻辑╮(╯▽╰)╭

以下是我自己对一些类的猜测(读者可以跳过)
maps/model/animation:放大和缩小是标注点的变化会用到
LatLng:j经纬度
Marker:生成标记点
Poi:当前位置

核心代码

AMap

//可视范围改变时回调的接口
 public final void setOnCameraChangeListener(AMap.OnCameraChangeListener var1) {
        try {
            this.a.setOnCameraChangeListener(var1);
        } catch (Throwable var3) {
            var3.printStackTrace();
        }
    }
//marker对象呗点击时回调的接口
 public final void setOnMarkerClickListener(AMap.OnMarkerClickListener var1) {
        try {
            this.a.setOnMarkerClickListener(var1);
        } catch (Throwable var3) {
            var3.printStackTrace();
        }
    }
//获取比例尺数据。当前缩放级别下,地图上1px对应的长度
  public float getScalePerPixel() {
        try {
            return this.a.getScalePerPixel();
        } catch (Throwable var2) {
            var2.printStackTrace();
            return 0.0F;
        }
    }
// 返回Projection对象。可以通过这个对象在屏幕坐标与经纬度之间转换。Projection对象返回的是当前可视区域的坐标,当可视区域变换时他不会自己更新
public final Projection getProjection() {
        try {
            if(this.c == null) {
                this.c = this.a.getAMapProjection();
            }

            return this.c;
        } catch (Throwable var2) {
            var2.printStackTrace();
            return null;
        }
    }

核心难点

1.初始化聚合和加入元素
批量初始化,适合一次加入大量数据

//添加测试数据
List<ClusterItem> items = new ArrayList<ClusterItem>();
 //随机10000个点
for (int i = 0; i < 10000; i++) {
      double lat = Math.random() + 39.474923;
      double lon = Math.random() + 116.027116;

      LatLng latLng = new LatLng(lat, lon, false);
      RegionItem regionItem = new RegionItem(latLng, "test" + i);
                    items.add(regionItem);
}
mClusterOverlay = new ClusterOverlay(mAMap, items,dp2px(getApplicationContext(), clusterRadius),getApplicationContext());
                

点击添加单个数据

 //点击可以动态添加点
mAMap.setOnMapClickListener(new AMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
          double lat = Math.random() + 39.474923;
          double lon = Math.random() + 116.027116;

          LatLng latLng1 = new LatLng(lat, lon, false);
          RegionItem regionItem = new RegionItem(latLng1,"test");
          mClusterOverlay.addClusterItem(regionItem);
          }
 });

2.设置渲染render和聚合点点击事件监听

@Override
mClusterOverlay.setClusterRenderer(MainActivity.this);
mClusterOverlay.setOnClusterClickListener(MainActivity.this);

3.自定义渲染

public Drawable getDrawAble(int clusterNum) {
        int radius = dp2px(getApplicationContext(), 80);
        if (clusterNum == 1) {
            Drawable bitmapDrawable = mBackDrawAbles.get(1);
            if (bitmapDrawable == null) {
                bitmapDrawable =
                        getApplication().getResources().getDrawable(
                                R.drawable.icon_openmap_mark);
                mBackDrawAbles.put(1, bitmapDrawable);
            }

            return bitmapDrawable;
        } else if (clusterNum < 5) {

            Drawable bitmapDrawable = mBackDrawAbles.get(2);
            if (bitmapDrawable == null) {
                bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                        Color.argb(159, 210, 154, 6)));
                mBackDrawAbles.put(2, bitmapDrawable);
            }

            return bitmapDrawable;
        } else if (clusterNum < 10) {
            Drawable bitmapDrawable = mBackDrawAbles.get(3);
            if (bitmapDrawable == null) {
                bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                        Color.argb(199, 217, 114, 0)));
                mBackDrawAbles.put(3, bitmapDrawable);
            }

            return bitmapDrawable;
        } else {
            Drawable bitmapDrawable = mBackDrawAbles.get(4);
            if (bitmapDrawable == null) {
                bitmapDrawable = new BitmapDrawable(null, drawCircle(radius,
                        Color.argb(235, 215, 66, 2)));
                mBackDrawAbles.put(4, bitmapDrawable);
            }

            return bitmapDrawable;
        }
    }

4.聚合点击事件

@Override
public void onClick(Marker marker, List<ClusterItem> clusterItems) {
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (ClusterItem clusterItem : clusterItems) {
            builder.include(clusterItem.getPosition());
        }
        LatLngBounds latLngBounds = builder.build();
        mAMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)
        );
    }

总结

第一次接触算法的东西。内心很激动,同时自己也无从下手。在跟老师沟通后他告诉我一些思路以及针对我的水平学习算法的方法。现在内功不足,我首要目标是能使用聚合算法来做一些简单修改来满足日常开发。
写完这篇理论文章后,感觉没必要写demo了(懒得飞起T——T)。但是自己两个月没写过业务方面的东西,再加上最近我要开始写业务。最后决定拿这个来练练手。最后附上一篇聚合算法的文章,希望对你有帮助。

聚合算法思路

相关文章

网友评论

      本文标题:聚合算法-基础理论篇

      本文链接:https://www.haomeiwen.com/subject/hwindftx.html