What is Mapkit:
MapKit allows you to display maps, navigate through maps, add annotations for specific locations, add overlays on existing maps, in this tutorial you will learn how to draw a polygon on map with free hand.
Creating the Project:
First, create a new Xcode project using the Single View Template. Then type FreeHandDrawMap as the project name as shown below.
Design the Interface:
Click on ViewController.xib to bring up Interface Builder. Drag a toolbar to the bottom of the screen, Map View to the middle of the screen and two bar buttons on the bar from Object library. Then rename the toolbar buttons to Draw Map, ”Save Map” and “View Map”.
Frameworks required:
Before you can run your code, add these two frameworks to the project.
- CoreLocation
- MapKit
let’s run the app and see how it looks like.
Control-drag from the Map View down to your header file.A popup will appear. Set the connection type to Outlet, the name to mapView. Do the same things for the buttons, but when the pop-up menu goes on, select the Connection as “Action
” then name them As drawMap, saveMap, viewMap.
Go to ViewController.m, and add MKMapViewDelegate as shown below
Add the following instance variables in @interface section as shown below
@interfaceViewController ()
{
UIImageView *drawImage;
CGPoint location;
NSDate *lastClick;
BOOL mouseSwiped;
CGPoint lastPoint;
CGPoint currentPoint;
NSMutableArray *latLang;
MKPolygon *polygon;
}
@end
In ViewController.m add this code in viewDidLoad as Shown Below.
– (void)viewDidLoad
{
[superviewDidLoad];
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeSatellite;
latLang = [[NSMutableArrayalloc]init];//Array that holds latitudes and longitudes
[mapViewsetDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
We are going to Implement this functionality in three steps:
Step1:
First, add an UIImageView on mapview programatically.This is used as drawing area.
Step2:
While drawing collect the points and convert it into CLLocation objects and save it to an array.
step3:
Once the drawing is done imageview is removed and the polygon is drawn based on CLLocation objects.
Step 1
Add the folowing code in ViewController.m
– (IBAction)drawMap:(id)sender{
mapView.userInteractionEnabled = NO;
NSUserDefaults *defaults = [NSUserDefaultsstandardUserDefaults];
drawImage.image = [defaults objectForKey:@”drawImageKey”];
drawImage = [[UIImageViewalloc] initWithImage:nil];
drawImage.frame = CGRectMake(0, 0, self.mapView.frame.size.width, self.mapView.frame.size.height);
[self.mapViewaddSubview:drawImage];
drawImage.backgroundColor = [UIColorclearColor];
}
Step 2
These two methods are used to collect the points based on user drawing
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch tapCount] == 2) {
drawImage.image = nil;
}
location = [touch locationInView:mapView];
lastClick = [NSDatedate];
lastPoint = [touch locationInView:mapView];
lastPoint.y -= 0;
mouseSwiped = YES;
[supertouchesBegan: touches withEvent: event];
}
– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(CGSizeMake(self.mapView.frame.size.width, self.mapView.frame.size.height));
[drawImage.imagedrawInRect:CGRectMake(0, 0, self.mapView.frame.size.width, self.mapView.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 1, 0, 1);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
[drawImagesetFrame:CGRectMake(0, 0, self.mapView.frame.size.width, self.mapView.frame.size.height)];
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//converting points to latitude and longitude
if (mouseSwiped) {
NSLog(@”CurrentPoint:%@”,NSStringFromCGPoint(currentPoint));
CLLocationCoordinate2D centerOfMapCoord = [mapViewconvertPoint:currentPointtoCoordinateFromView:mapView]; //Step 2
CLLocation *towerLocation = [[CLLocationalloc] initWithLatitude:centerOfMapCoord.latitudelongitude:centerOfMapCoord.longitude];
[latLangaddObject:towerLocation];
}
lastPoint = currentPoint;
}
Step 3
– (IBAction)saveMap:(id)sender {
[drawImageremoveFromSuperview];
}
Draw polygon with collected points
– (IBAction)viewMap:(id)sender {
CLLocationCoordinate2D *coords =
malloc(sizeof(CLLocationCoordinate2D) * [latLangcount]);
for(int idx = 0; idx < [latLangcount]; idx++) {
CLLocation* locationCL = [latLangobjectAtIndex:idx];
coords[idx] = CLLocationCoordinate2DMake(locationCL.coordinate.latitude,locationCL.coordinate.longitude);
}
polygon = [MKPolygonpolygonWithCoordinates:coords count:[latLangcount]];
free(coords);
[mapViewaddOverlay:polygon];
}
– (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
MKPolygonView *polygonView = [[MKPolygonViewalloc] initWithPolygon:overlay];
polygonView.lineWidth = 5;
polygonView.strokeColor = [UIColorredColor];
polygonView.fillColor = [UIColorcolorWithRed:0green:191blue:255alpha:0.5];
mapView.userInteractionEnabled = YES;
return polygonView;
}
Now every thing was ready, run your code click on draw map. Draw the polygon with hand or stylus .save it and click on view map to view what you have drawed.
Finally It should look like this!!!
Let us know your comments/suggestions.