zoukankan      html  css  js  c++  java
  • 地图

    目录[-]

    之前工作在一家智能设备的公司,做过一个亲友定位监控系统,类似现在比较流行的360儿童手环。所以这里简单介绍定位与地图。

    1 定位服务

        iOS设备提供三种不同定位途径,蜂窝式移动电话基站定位;WiFi定位,通过查询一个WiFi路由器的地理位置信息,比较省电;GPS卫星定位,通过3~4颗卫星定位,最为准确,但是耗电量大。iOS系统如果能够接收GPS信息,那么设备优先采用GPS,其次是WiFi,最后是基站,开发人员不能选择哪种定位方式。

        定位服务使用CoreLocation框架,主要使用CLLocationMananger、CLLocationManangerDelegate和CLLocation三个类,CLLocationMananger是定位服务管理类,获取设备的位置信息,CLLocationManangerDelegate是代理协议,CLLocation封装了位置信息。

        这里要注意,CLLocationManangerDelegate 的locationManager:didUpdateToLocation:fromLocation:方法得到的坐标是火星坐标,这个原因你懂得,所以需要转换成真实的地理坐标。我使用的是一个第三方的CSqlite类,有一个转换坐标的数据库,你调用就可以转换为正确坐标了。

        得到经纬度后,要进行地理位置信息反编码,使用CLGeocoder类实现,将地理坐标转换为地理文字描述信息,这些文字描述信息被封装在CLPlacemark类中。

        当然给定地理信息的文字描述,也可以进行地理信息编码查询,转换为地理坐标,也是采用CLGeocoder类。

    判断一个坐标点是否在一个无规则的多边形内

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    //    在范围内返回1,不在返回0
    -(int)mutableBoundConrtolAction:(NSMutableArray *)arrSome:(CLLocationCoordinate2D )myCoordinate4{
        int n=arrSome.count;
        float vertx[n];
        float verty[n];
        for (int i=0; i<arrSome.count; i++) {
    //MyPoint类存储的是经度和纬度
            vertx[i]=((MyPoint *)(arrSome[i])).x;
            verty[i]=((MyPoint *)(arrSome[i])).y;
        }
        if (arrSome.count==0) {
             
            return 1;
        }
        BOOL i=pnpoly(arrSome.count, vertx, verty, myCoordinate4.latitude, myCoordinate4.longitude);
         
         
        if (i) {
            return 1;
        }else{
            return 0;
        }
         
         
        return 1;
    }
    //多边形由边界的坐标点所构成的数组组成,参数格式 该数组的count,  多边形边界点x坐标 的组成的数组,多边形边界点y坐标 的组成的数组,需要判断的点的x坐标,需要判断的点的y坐标
    BOOL pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) {
        int i, j;
        BOOL c=NO;
        for (i = 0, j = nvert-1; i < nvert; j = i++) {
             
            if ( ( (verty[i]>testy) != (verty[j]>testy) ) &&
                (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
                c = !c;
        }
        return c;
    }

    2 系统地图

        地图我目前用过系统、百度以及高德,开发人员使用都是差不多的,下面的代码涉及的类都是高德地图api提供的类。

        我之前做项目,使用高德地图,做到后期,项目会出现闪退,后来查出是地图区域内存的问题,然后重新布局了地图区域,使得每一个地图区域能够及时销毁,虽然闪退周期明显延长,但是还是存在,这里不知道是何原因,说来惭愧。

    设置地图区域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    -(void)SetMapRegion:(CLLocationCoordinate2D)myCoordinate
    {
        MACoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } };
        theRegion.center=myCoordinate;
        [self.m_map setScrollEnabled:YES];
        theRegion.span.longitudeDelta = 0.01f;
        theRegion.span.latitudeDelta = 0.01f;
        [self.m_map setRegion:theRegion animated:YES];
    }



    平移地图,上下左右

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    -(void)panMap:(NSString *)direction{
        CLLocationCoordinate2D changeCoordinate=self.m_map.centerCoordinate;
        CGPoint changePoint=[self.m_map convertCoordinate:changeCoordinate toPointToView:self.m_map];
         
        if ([direction isEqualToString:@"up"]) {
            changePoint.y=changePoint.y+50;
             
        }else if ([direction isEqualToString:@"down"]) {
            changePoint.y=changePoint.y-50;
        }else if ([direction isEqualToString:@"left"]) {
            changePoint.x=changePoint.x-50;
        }else if ([direction isEqualToString:@"right"]) {
            changePoint.x=changePoint.x+50;
        }
        changeCoordinate=[self.m_map convertPoint:changePoint toCoordinateFromView:self.m_map];
        [self.m_map setCenterCoordinate:changeCoordinate animated:YES];
    }



    判断某一个坐标点是否在当前地图区域内

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -(void)isAtCurrentRegion:(CLLocationCoordinate2D)coordiante{
         
        CGPoint point=[self.m_map convertCoordinate:coordiante toPointToView:self.view];
        if ((point.x<0)||(point.y<0)||(point.x>WScreen)||(point.y>HScreen)) {
    //        如果不在 设置该点为地图中心点
            [self SetMapRegion:coordiante];
        }
         
         
    }

    在地图上添加标注

        系统地图使用MapKit框架,核心是MKMapView类,显示地图只要添加MKMapView实例就可以了。如果要实现在地图上添加标注点,第以是触发添加动作,第二实现MKMapViewDelegate的mapView:viewForAnnotation:完成添加标注。

        高德地图实现的原理也是一样的,高德地图使用的是MAMapKit框架。对于annotation,一般会自定义一个继承NSobject并且实现了maannotation协议的类,然后使用mapview的addAnnotation:方法就可以。MKReverseGeocoder类可以实现coordinate的反编码,这里需要实现它的代理,把得到的地理文字描述信息赋给annotation。这里需要实现代理的mapView:viewForAnnotation:方法,一个标注其实就是一个MAAnnotationView,标注有点类似tableviewcell,这里也有重用机制。实现代理的mapView:annotationView:calloutAccessoryControlTapped:方法可以响应leftCalloutAccessoryView或者rightCalloutAccessoryView的点击事件,不过这个accessory view必须继承自UIControl。

    在地图上绘制线条和多边形

        MAPolyline类定义一个由多个点相连的多段线,点与点之间尾部想连但第一点与最后一个点不相连, 通常MAPolyline是MAPolylineView的model,它提供了两个方法polylineWithPoints:count:、polylineWithCoordinates:count:用来添加线条,然后再通过map view的addOverlay:方法把Polyline实例添加进去,最后实现mapviewdelegate的mapView:viewForOverlay:方法就可以了。注意如果一开始添加的不是coordinate,而是point,可以通过map view的convertPoint:toCoordinateFromView:方法进行转换。

        MAPolygon类定义的就是一个不规则的由多个点组成的闭合多边形,点与点之间按顺序尾部相连, 第一个点与最后一个点相连, 通常MAPolygon是MAPolygonView的model,首先需要添加坐标点的数组,可以使用polygonWithCoordinates:count:方法或者polygonWithPoints:count:方法,然后把这个polygon通过addOverlay:方法添加到map view上就可以了。然后可以在mapviewdelegate里面的mapView:viewForOverlay:方法里面给MAPolygonView的属性赋值,这样一个完整的多边形就出来了。

        不管是高德地图还是百度地图等第三方,都会有一个mapsearchkit,这是一个用于查询的框架,有兴趣的朋友可以多加研究。

  • 相关阅读:
    mybatis 错误 Invalid bound statement (not found)
    Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
    bug 记录 Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans
    解决:The Tomcat connector configured to listen on port 8182 failed to start. The port may already be in use or the connector may be misconfigured.
    jquery validate 验证插件 解决多个相同的Name 只验证第一个的方案
    phpStorm+xdebug调试(php7.3)
    小程序视频多个视频播放与暂停
    CSS实现单行、多行文本溢出显示省略号(…)
    Packet for query is too large (4,544,730 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.
    idea自动在文件头中添加作者和创建时间
  • 原文地址:https://www.cnblogs.com/fengmin/p/4949578.html
Copyright © 2011-2022 走看看