iOS 功能类GIS小铺程序员

给你的地图点灯

2017-06-10  本文已影响1215人  ccSundayChina

曾经坐在飞机上俯瞰整个北京城,在万米高空上可以看到北京的全貌,即使是凌晨一两点,北京依然灯火通明,俨然是一座不眠之城。四通八达的交通线仿佛是这座城市的血脉,里面流淌着的,是生活在这里的人们的梦想。

然而,今天要讲的不是北京,也不是梦想。今天要讲的是我们该如何在地图上点起一盏灯,就像夜幕下的北京城一样。

为了方便理解,我们先看一下最终的实现效果。


最终效果.png

没错,就是要在夜幕下,放几盏灯,告诉别人这块区域目前有人正在里面工作。

在讲解如何实现这种效果前,先分享一下之前的那种存在问题的思路

之前的做法是:

然而这样做会产生一个无法避免的问题,那就是无论我们怎么设置高亮区域的背景色与透明度,都不够好看:透明度低的时候,就看不到下面的地图,透明度高的时候,虽然能看到下面的地图,但是却雾蒙蒙的,仿佛那片高亮区域,被雾霾笼罩了。。

被雾霾笼罩的效果图.png

那么问题来了,如何让大晚上还在工作的人们,少呼吸点雾霾呢。

思路其实很简单,只需要换个角度来思考就可以了,那就是我们不再分别绘制高亮区域和底部的全屏阴影区域,而是只需要绘制一个阴影区域就可以了,这样剩下的没有绘制的区域自然就是没有雾霾的。
对,再说一遍,只需要绘制一个阴影区域就可以。
先来一张图:

绘制过程分解.png

屏幕的四个点分别是S1、S2、S3、S4,两个高亮区域分别是区域A区域B,区域A的四个点分别是A1、A2、A3、A4,区域B的四个点分别是B1、B2、B3、B4。我们要绘制的就是除去区域A,区域B后,把剩下的那部分当做一个PolygonView来绘制。(注意:这里所说的点是指经纬度点,而不是point点)

So ,如何得到阴影区域的Polygon

总结一下规律,我们需要从屏幕四个角的任意一个点开始,假设是S1点,然后依次添加区域A、区域B、区域C等区域的点,区域点添加完一圈后,一定要把区域的第一个点再添加一遍,然后再去添加另一个区域的点,添加完后,依然要再加一遍该区域的第一个点,如果当前区域是最后一个区域了,那么添加完后,需要让它原路返回,也就是说除了最后一个区域的起点是填加两遍其他区域的起点都是添加三遍,添加完后,再添加一遍屏幕的S1点,最后就是按照顺时针或者逆时针添加屏幕的剩余三个点,添加完三个点后,必须再添加S1点,构成闭合(此时点被添加三遍)。

这样我们就只需要绘制这么一个整合后的阴影区域就可以了。由此就实现了我们的去雾霾目的。

过程有点绕,可能不太好理解,那怎么办,多看几遍然后自己试一试就可以了。demo还是之前的给你的地图模块动手术的demo。代码比较多,但是却很简单,所以文章里就不写代码了,本文介绍的关键在于这种思路,使用的时候,只需要借鉴思路,并且这种思路是通用的,移动端与web端都适用。

为了方便大伙,下面给出对数据的程序处理。

    /*从self.locationArray中获取数据进行展示,
      里面存储的是一个个模型数组,模型是TestPolygonModel,有lng与lat属性
    */
   
    /*1、获取需要malloc的内存区域,由以下几个部分组成:
     •  6个屏幕点
     •  self.locationArray.count*2 - 1 计算多边形起点被多加的次数,
        后面的减一是因为最后一个数组的第一个点只需要多加一遍,其他的都是多加两遍,
        注意这里计算的是起点被多加的次数,而不是起点被添加的总次数。
     •  self.locationArray子数组中元素的个数和,self.locationArray存放的是经纬度模型数组。
     */
    NSInteger mallocCount = 0;//需要分配的内存大小,也就是经纬度数组中总共的点数,也就是上面提到的三部分之和
    NSInteger itemCount = 0;  //也就是self.locationArray子数组中经纬度模型的个数和
    NSInteger itemIndex = 0;  //coors下表
    for (int i = 0; i<self.locationArray.count; i++) {
        itemCount = itemCount + [self.locationArray[i] count];
    }
    mallocCount = 6 + self.locationArray.count * 2 - 1 + itemCount;
    /*2、正序计算,无论是不是最后一个数组,先依次将该数组的点加进去,加完后再加一遍该数组中的第一个点。*/
    CLLocationCoordinate2D * coors = (CLLocationCoordinate2D *)malloc(mallocCount * sizeof(CLLocationCoordinate2D));
    /*添加屏幕左下角的S1点*/
    coors[0].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[0].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    /*正序添加每一个数组中的所有元素*/
    for (int i = 0; i < self.locationArray.count; i++) {
        NSArray *polygonArray = self.locationArray[i];
        for (int j = 0; j<polygonArray.count; j++) {
            TestPolygonModel *polygonModel = self.locationArray[i][j];                      //获取model
            itemIndex++;
            coors[itemIndex].longitude = [polygonModel.lng floatValue];
            coors[itemIndex].latitude = [polygonModel.lat floatValue];
        }
        //添加完每一组的元素后,需要再添加一遍该组的第一个点,
        itemIndex ++;
        TestPolygonModel *startPolygon = polygonArray[0];
        coors[itemIndex].latitude = [startPolygon.lat floatValue];
        coors[itemIndex].longitude = [startPolygon.lng floatValue];
    }
    
    /*3、倒叙添加每一组的第一个元素,但是最后一个组不需要添加,因为最后一个组总共只需要加两遍,所以过滤掉最后一组*/
    for (NSInteger i = self.locationArray.count - 1; i>0; i--) {
        itemIndex ++;
        TestPolygonModel *startPolygon = self.locationArray[i-1][0];                      //获取model
        coors[itemIndex].latitude = [startPolygon.lat floatValue];
        coors[itemIndex].longitude = [startPolygon.lng floatValue];
    }
    
    /*4、添加屏幕的边界点*/
    /*再次添加屏幕的起点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕右下角的S2点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude+self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕右上角的S3点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude+self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude+self.mapView.region.span.latitudeDelta*1.5;
    /*添加屏幕左上角的S4点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude+self.mapView.region.span.latitudeDelta*1.5;
    /*再次添加屏幕左下角的S1点*/
    itemIndex ++;
    coors[itemIndex].longitude = self.mapView.region.center.longitude-self.mapView.region.span.longitudeDelta*1.5;
    coors[itemIndex].latitude = self.mapView.region.center.latitude-self.mapView.region.span.latitudeDelta*1.5;
    if (mallocCount == itemIndex+1) {
        BMKPolygon *polygonModel0 = [BMKPolygon polygonWithCoordinates:coors count:mallocCount];
        [self.mapView addOverlay:polygonModel0];
    }else{
        [SVProgressHUD showErrorWithStatus:@"计算错误"];
    }

好吧,作者比较懒,三篇文章,只留下了一个demo

上一篇 下一篇

猜你喜欢

热点阅读