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

2018-10-19  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读