美文网首页
IOS 地图画曲线,并动态计算缩放级别

IOS 地图画曲线,并动态计算缩放级别

作者: 透支未来 | 来源:发表于2018-10-19 12:21 被阅读214次

    效果图


    D6F43000-961E-456F-803C-F025F4E7690F.png
    
    #import "UCGridVC.h"
    #import "UCGriddAnnotation.h"
    #import "ZTBezierPathHelper.h"//画曲线
    #import "SYMapHelper.h"
    
    @interface UCGridVC ()<MKMapViewDelegate>
    
    @property(nonatomic,strong)MKMapView *mapView;//地图
    @end
    
    @implementation UCGridVC
    
    - (void)dealloc
    {
        _mapView = nil;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self createUI];
        [self addAnnotations];
        // Do any additional setup after loading the view.
    }
    
    #pragma mark UI
    - (void)createUI
    {
        [self.view addSubview:self.mapView];
    }
    
    #pragma mark 地图
    //地图
    - (MKMapView *)mapView
    {
        if (_mapView == nil) {
            _mapView = [[MKMapView alloc] initWithFrame:self.view.frame];
            _mapView.delegate=self;//设置代理
            _mapView.mapType=MKMapTypeStandard;//设置地图类型
            _mapView.showsBuildings=NO;
            _mapView.showsUserLocation=NO;//在地图上显示用户当前位置
            _mapView.showsCompass = NO;//指南针隐藏
        }
        return _mapView;
    }
    
    #pragma mark 添加网点大头针
    //添加大头针
    - (void)addAnnotations
    {
        
        //清除大头针和线
        [self.mapView removeAnnotations:self.mapView.annotations];
        [self.mapView removeOverlays:self.mapView.overlays];
        
        //设置中心点
    //    MKCoordinateRegion region;
    //    region.span = MKCoordinateSpanMake(0.5, 0.5);
    //    region.center = CLLocationCoordinate2DMake(31.165456, 121.401279);
    //    [self.mapView setRegion:region animated:YES];
        
        
        NSMutableArray *coor = [NSMutableArray array];
        [coor addObject:@{@"lat":@(31.163982907147894),@"lng":@(121.30678802929651)}];
        [coor addObject:@{@"lat":@(32.163982907147894),@"lng":@(121.30678802929651)}];
        [coor addObject:@{@"lat":@(33.163982907147894),@"lng":@(121.30678802929651)}];
        [coor addObject:@{@"lat":@(34.163982907147894),@"lng":@(121.30678802929651)}];
        [coor addObject:@{@"lat":@(35.163982907147894),@"lng":@(121.30678802929651)}];
        [coor addObject:@{@"lat":@(36.163982907147894),@"lng":@(121.30678802929651)}];
        
        
        
        CLLocationCoordinate2D coordinates[(6)];
        coordinates[0] = CLLocationCoordinate2DMake(31.163982907147894, 121.30678802929651);
        coordinates[1] = CLLocationCoordinate2DMake(32.163982907147894, 121.30678802929651);
        coordinates[2] = CLLocationCoordinate2DMake(33.163982907147894, 121.30678802929651);
        coordinates[3] = CLLocationCoordinate2DMake(34.163982907147894, 121.30678802929651);
        coordinates[4] = CLLocationCoordinate2DMake(35.163982907147894, 121.30678802929651);
        coordinates[5] = CLLocationCoordinate2DMake(36.163982907147894, 121.30678802929651);
        
        
        
        MKCoordinateRegion region=[SYMapHelper calculate:coordinates count:5 latitudeDeltaAdd:0.1f longitudeDeltaAdd:0.1f];
        
        NSLog(@"%f %f  %f  %f",region.center.latitude,region.center.longitude,region.span.latitudeDelta,region.span.longitudeDelta);
        
        if (region.span.latitudeDelta < 0.035) {
            region.span.latitudeDelta = 0.035;
        }
        if (region.span.longitudeDelta < 0.04) {
            region.span.longitudeDelta = 0.04;
        }
        region = [_mapView regionThatFits:region];
        NSLog(@"%f %f  %f  %f",region.center.latitude,region.center.longitude,region.span.latitudeDelta,region.span.longitudeDelta);
        
        if (isnan(region.span.latitudeDelta) || isnan(region.span.longitudeDelta)) {
            
            //如果在这里操作,就会崩溃,抛出异常
        }else{
            //        [self.mapView setRegion:region animated:NO];
            [self.mapView setRegion:region];
        }
        
        
        
        
        
        CLLocationDistance kilometers = 0.0;
        for (int i = 0; i < coor.count; i++) {
            NSDictionary *dic = coor[I];
            double lat = [dic[@"lat"] doubleValue];
            double lng = [dic[@"lng"] doubleValue];
            
            CLLocation *orig=[[CLLocation alloc] initWithLatitude:31.165456 longitude:121.401279];
            CLLocation* dist=[[CLLocation alloc] initWithLatitude:lat longitude:lng];
            
            if (kilometers != 0) {
                if (kilometers > [orig distanceFromLocation:dist]) {
                    kilometers=[orig distanceFromLocation:dist];
                }
            }else{
                 kilometers=[orig distanceFromLocation:dist];
            }
            NSLog(@"距离: = %f",kilometers);
            
            
            [self drawCurveLat:lat lng:lng];
        }
        
        
        //构造圆
        MKCircle *circle = [MKCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(31.165456, 121.401279) radius:kilometers];
        circle.title = @"A";
        //在地图上添加圆
        [_mapView addOverlay: circle];
        
     
        
        
    }
    
    //画线和点
    - (void)drawCurveLat:(double)lat lng:(double)lng
    {
        //大头针
        CLLocationCoordinate2D location1= CLLocationCoordinate2DMake(lat,lng);
        UCGriddAnnotation *annotation1= [[UCGriddAnnotation alloc] init];//配套大仓
        annotation1.coordinate = location1;
        [self.mapView addAnnotation:annotation1];
        
        //画曲线
        CLLocationCoordinate2D startLocation = CLLocationCoordinate2DMake(31.165456, 121.401279);
        CLLocationCoordinate2D endLocation= CLLocationCoordinate2DMake(lat, lng);
        NSMutableArray *bezierPaths=[ZTBezierPathHelper bezierPath:startLocation targetPoint:endLocation clockwise:YES];
        
        CLLocationCoordinate2D pointsToUse[bezierPaths.count];
        for (int i = 0; i < bezierPaths.count; i++) {
            pointsToUse[i] = ((CLLocation *)[bezierPaths objectAtIndex:i]).coordinate;
        }
        
        MKPolyline *polyline = [MKPolyline polylineWithCoordinates:pointsToUse count:bezierPaths.count];
        [self.mapView addOverlay:polyline];
    }
    
    
    
    //这样就在地图上面增加了一个圆形覆盖。但是就这样的画我们是看不到的。需要实现代理方法,去设置背景色,线宽什么的。
    - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
    {
        if ([overlay isKindOfClass:[MKCircle class]])
        {
            MKCircleRenderer *circleRenderer = [[MKCircleRenderer alloc] initWithCircle:overlay];
            circleRenderer.lineWidth    = 1.0f;
            circleRenderer.strokeColor  =[UIColor colorWithHex:(0x04A504)];
            return circleRenderer;
        }else if ([overlay isKindOfClass:MKPolyline.class]) {
            MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
            lineView.strokeColor = [UIColor greenColor];
            lineView.lineWidth=1.0f;
            return lineView;
        }
        return nil;
    }
    
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
        static NSString *key1=@"current";
        MKAnnotationView *annotationView= (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:key1];
        //如果缓存池中不存在则新建
        if (annotationView == nil) {
            annotationView=[[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:key1];
        }
        annotationView.image=[UIImage imageNamed:@"bigGlodOneIcon"];//设置大头针视图的图片
        return annotationView;
    }
    // 选中大头针
    - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
    {
        NSLog(@"选中大头针");
    }
    
    // 取消选中大头针
    -(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view{
        //    self.hintView.hidden=YES;
        NSLog(@"取消选中大头针");
    }
    
    //自定义大头针不能使用系统的MKPinAnnotationView来添加从天儿降的效果,只能自己添加动画
    #pragma mark MKMapViewDelegate
    - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
    {
        
    }
    
    

    //计算曲线的点.h文件

    
    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>
    
    @interface ZTBezierPathHelper : NSObject
    
    
    +(NSMutableArray *)bezierPath:(CLLocationCoordinate2D)p1 targetPoint:(CLLocationCoordinate2D)p2 clockwise:(BOOL)isClockWise;
    
    
    @end
    

    //计算曲线的点.m文件

    
    #import "ZTBezierPathHelper.h"
    
    //angle of the auxiliaty point between start point and end point
    #define ANGEL_OF_AUXILIARY_POINT 30
    
    @implementation ZTBezierPathHelper
    
    
    
    /**
     * p1 -> 起始点 CLLocationCoordinate2D
     *
     * p2 -> 结束点 CLLocationCoordinate2D
     *
     * isClockWise -> 是否顺时针方向 YES NO
     */
    +(NSMutableArray *)bezierPath:(CLLocationCoordinate2D)p1 targetPoint:(CLLocationCoordinate2D)p2 clockwise:(BOOL)isClockWise{
        
        
        //get the auxiliary point
        CLLocationCoordinate2D auxiliaryPoint = [self fetchThirdPointByLocations:p1 withEndLocation:p2 withAngle:ANGEL_OF_AUXILIARY_POINT clockwise:isClockWise];
        
        float bezier1x;
        float bezier1y;
        float bezier2x;
        float bezier2y;
        
        NSMutableArray *targetPoints=[NSMutableArray arrayWithCapacity:3];
        
        float bezier_x,bezier_y;
        
        float t = 0;
        //t between 0.01 and 1
        while ( [targetPoints count]<=100 ) {
            
            //get the start point of a Bezier curve
            bezier1x = p1.longitude + ( auxiliaryPoint.longitude - p1.longitude ) * t;
            bezier1y = p1.latitude + ( auxiliaryPoint.latitude - p1.latitude ) * t;
            
            //get the end point of a Bezier curve
            bezier2x = auxiliaryPoint.longitude + ( p2.longitude - auxiliaryPoint.longitude ) * t;
            bezier2y = auxiliaryPoint.latitude + ( p2.latitude - auxiliaryPoint.latitude ) * t;
            
            //get the point of quadratic Bezier curve
            bezier_x = bezier1x + ( bezier2x - bezier1x ) * t;
            bezier_y  = bezier1y + ( bezier2y - bezier1y ) * t;
            
            CLLocation *bezierPoint=[[CLLocation alloc] initWithLatitude:bezier_y longitude:bezier_x];
            [targetPoints addObject:bezierPoint];
            
            t += 0.01f;
            
        }
        
        return targetPoints;
    }
    
    
    +(CLLocationCoordinate2D)fetchThirdPointByLocations:(CLLocationCoordinate2D)startLoc withEndLocation:(CLLocationCoordinate2D)endLoc withAngle:(float)angle  clockwise:(BOOL)isClockWise{
        
        CLLocationCoordinate2D target;
        
        //angle between the two points
        double btpAngle=0.0;
    
        btpAngle=atan2(fabs(startLoc.latitude-endLoc.latitude) , fabs(startLoc.longitude-endLoc.longitude))*180/M_PI;
        
        
        //center point
        CLLocationCoordinate2D center=CLLocationCoordinate2DMake((startLoc.latitude+endLoc.latitude)/2.0, (startLoc.longitude+endLoc.longitude)/2.0);
        
        //distance between the two points
        double distance=sqrtf((startLoc.latitude-endLoc.latitude)*(startLoc.latitude-endLoc.latitude)+(startLoc.longitude-endLoc.longitude)*(startLoc.longitude-endLoc.longitude));
        
        
        //distance taget point between and center point
        double adis=(distance/2.0)*tan(angle*M_PI/180);
        
        
        //target distance  longt and lat
        double longt=adis*cosf((90-btpAngle)*M_PI/180);
        
        double lat=adis*sinf((90-btpAngle)*M_PI/180);
        
        
        if (startLoc.longitude>endLoc.longitude) {
            isClockWise=!isClockWise;
        }
        
        //to get the right side of target
        if (isClockWise) {
            
            target.latitude=center.latitude+lat;
            target.longitude=center.longitude+longt;
        }else{
            
            target.latitude=center.latitude-lat;
            target.longitude=center.longitude-longt;
        }
        
        //avoid the target out of the map
        if (target.latitude>90) {
            target.latitude=90.0f;
        }else if (target.latitude<-90){
            target.latitude=-90.0f;
        }
        
        if (target.longitude>180) {
            target.longitude=target.longitude-360.0;
        }else if (target.longitude<-180){
            target.longitude=360.0f+target.longitude;
        }
        
        return target;
        
    }
    
    
    @end
    
    

    动态计算缩放级别和中心点.h文件

    
    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>
    #import <MAMapKit/MAMapKit.h>
    
    @interface SYMapHelper : NSObject
    
    +(MKCoordinateRegion )calculate:(CLLocationCoordinate2D [])coordinates count:(NSInteger)count latitudeDeltaAdd:(double)latitudeDeltaAdd longitudeDeltaAdd:(double)longitudeDeltaAdd;
    
    @end
    
    

    动态计算缩放级别和中心点.m文件

    
    #import "SYMapHelper.h"
    
    @implementation SYMapHelper
    
    +(MKCoordinateRegion )calculate:(CLLocationCoordinate2D [])coordinates count:(NSInteger)count latitudeDeltaAdd:(double)latitudeDeltaAdd longitudeDeltaAdd:(double)longitudeDeltaAdd{
        
        CLLocationDegrees minLat = 0.0;
        CLLocationDegrees maxLat=0.0;
        CLLocationDegrees minLon=0.0;
        CLLocationDegrees maxLon=0.0;
        
        for (int i=0; i<count; i++) {
            CLLocationCoordinate2D coordinate=coordinates[I];
            if (i==0) {
                minLat =coordinate.latitude;
                maxLat = coordinate.latitude;
                minLon = coordinate.longitude;
                maxLon = coordinate.longitude;
            }else{
                //对比筛选出最小纬度,最大纬度;最小经度,最大经度
                minLat = MIN(minLat, coordinate.latitude);
                maxLat = MAX(maxLat, coordinate.latitude);
                minLon = MIN(minLon, coordinate.longitude);
                maxLon = MAX(maxLon, coordinate.longitude);
            }
        }
            CLLocationCoordinate2D centCoor;
            centCoor.latitude = (CLLocationDegrees)((maxLat+minLat) * 0.5f);
            centCoor.longitude = (CLLocationDegrees)((maxLon+minLon) * 0.5f);
            MKCoordinateSpan span;
        
        span.latitudeDelta  = (maxLat - minLat) * 2;
        span.longitudeDelta = (maxLon - minLon) * 2;
    //        span.latitudeDelta = maxLat - minLat+latitudeDeltaAdd;// 边缘坐标 不被边界覆盖
    //        span.longitudeDelta = maxLon - minLon+longitudeDeltaAdd;
            //得出数据的坐标区域
            MKCoordinateRegion center_region = MKCoordinateRegionMake(centCoor, span);
        
        return center_region ;
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:IOS 地图画曲线,并动态计算缩放级别

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