I am developing an application in which I need to draw a route between two points using lat/long.
I have used google API to get polylines and drawing it after decoding it.
Problems:
Route is not in the middle of the road (Attached image_1)
While zooming in/out route doesn't draw completely (Attached image_2)
Below is the code:
if(!routeView)
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.mapView.frame.origin.y, mapView.frame.size.width, self.mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
[self.lat1 resignFirstResponder];
[self.long1 resignFirstResponder];
[self.lat2 resignFirstResponder];
[self.long2 resignFirstResponder];
NSString* saddr = [NSString stringWithFormat:#"%#,%#",self.lat1.text,self.long1.text];
NSString* daddr = [NSString stringWithFormat:#"%#,%#",self.lat2.text,self.long2.text];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.apple.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSData *responseData = [apiResponse dataUsingEncoding:NSUTF8StringEncoding];
NSError* error1;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&error1];
NSLog(#"Error: %#\n%#",[error1 localizedDescription],[error1 localizedFailureReason]);
if([[json objectForKey:#"status"] isEqualToString:#"OK"])
{
NSArray *routes1 = [json objectForKey:#"routes"];
NSDictionary *route = [routes1 lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
routes = [self decodePolyLine:overviewPolyline];
//NSLog(#"%#",[routes objectAtIndex:0]);
[self updateRouteView];
[self centerMap];
}
}
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
One possible reason that your route is misaligned is that your route is coming rom Google (http://maps.apple.com/maps redirects to http://maps.google.com/maps) and you are drawing it on Apple's maps. Their data is slightly different.
The partially drawn route I can't solve, but I would suggest you add an MKPolyline rather than a static image overlay. They invented that line drawing tool for a good reason.
Related
I have three nsmutable array in ios. I have to print data as below example using printer , How should i do it?
example:--
0.5 1 10
1 10 11
2 5 22
3 4 6
For example these are arrays :
NSArray *arr = [NSArray arrayWithObjects:#"1",#"2",#"3",#"4",#"5",#"6", nil];
NSArray *arr1 = [NSArray arrayWithObjects:#"17",#"27",#"37",#"47",#"57",#"67", nil];
NSArray *arr2 = [NSArray arrayWithObjects:#"171",#"271",#"371",#"471",#"571",#"671", nil];
Now get all data in NSString
NSMutableString *str = [NSMutableString string];
for (int i=0; i<[arr count]; i++)
{
str = [str stringByAppendingFormat:[NSString stringWithFormat:#"%# %# %#\n",[arr objectAtIndex:i],[arr1 objectAtIndex:i],[arr2 objectAtIndex:i]]];
}
NSLog(#"%#",str);
Use toPdfData method to get NSData to print.
NSData *data = [self toPdfData:str];
Add these method:
- (NSData *) toPdfData :(NSMutableString *)str
{
//calculate size
CGSize stringSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:CGSizeMake(320 , 999) lineBreakMode:UILineBreakModeWordWrap];
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, CGRectMake(0, 0, stringSize.width, stringSize.height), nil);
UIGraphicsBeginPDFPage();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[str drawInRect:CGRectMake(0, 0, stringSize.width, stringSize.height) withFont:[UIFont systemFontOfSize:15]];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
return pdfData;
}
EDIT : Now you have PDF Data and PDF file also store in NSDocument Directory so print using UIPrintInteractionController
You can use the UIPrintInteractionController for doing this.
Please check the below code:
NSMutableString *stringToPrint = [[NSMutableString alloc] initWithString:#""];
for(int i = 0;i<[array count];i++)
{
[stringToPrint appendFormat:#"%#",[array objectAtIndex:i]];
if(i%2 == 0)
{
[stringToPrint appendFormat:#"\n"];
}
else
{
[stringToPrint appendFormat:#"\t"];
}
}
UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = #"Midhun";
pic.printInfo = printInfo;
UISimpleTextPrintFormatter *textFormatter = [[UISimpleTextPrintFormatter alloc]
initWithText:stringToPrint];
textFormatter.startPage = 0;
textFormatter.contentInsets = UIEdgeInsetsMake(72.0, 72.0, 72.0, 72.0); // 1 inch margins
textFormatter.maximumContentWidth = 6 * 72.0;
pic.printFormatter = textFormatter;
pic.showsPageRange = YES;
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) =
^(UIPrintInteractionController *printController, BOOL completed, NSError *error)
{
if (!completed && error)
{
NSLog(#"Printing could not complete because of error: %#", error);
}
};
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
[pic presentFromBarButtonItem:sender animated:YES completionHandler:completionHandler];
}
else
{
[pic presentAnimated:YES completionHandler:completionHandler];
}
Please read Printing and Drawing in iOS for more details.
Use following code to traverse and print.
for (int i=0; i<[array count]; i++) {
NSLog(#"%#",[array objectAtIndex:i]);
}
I have customized pins in my mapview with custom callout.
While drawing path on map, the route is coming over callout & pins. Image Attached.
I have used google API to get polylines and drawing it after decoding it.
Here is the code:
if(!routeView)
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.mapView.frame.origin.y, mapView.frame.size.width, self.mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
[self.lat1 resignFirstResponder];
[self.long1 resignFirstResponder];
[self.lat2 resignFirstResponder];
[self.long2 resignFirstResponder];
NSString* saddr = [NSString stringWithFormat:#"%#,%#",self.lat1.text,self.long1.text];
NSString* daddr = [NSString stringWithFormat:#"%#,%#",self.lat2.text,self.long2.text];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.apple.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSData *responseData = [apiResponse dataUsingEncoding:NSUTF8StringEncoding];
NSError* error1;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&error1];
NSLog(#"Error: %#\n%#",[error1 localizedDescription],[error1 localizedFailureReason]);
if([[json objectForKey:#"status"] isEqualToString:#"OK"])
{
NSArray *routes1 = [json objectForKey:#"routes"];
NSDictionary *route = [routes1 lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
routes = [self decodePolyLine:overviewPolyline];
//NSLog(#"%#",[routes objectAtIndex:0]);
[self updateRouteView];
[self centerMap];
}
}
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
I think your problem is that you add your routeView after adding your pin, so the routeview is the first subview. What happens if you try to add the routeView first, in your viewDidLoad method for example ?
Thanks for the responses. I have figure this out using MKPolylines. Refer code below
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyLine];
I want to draw route on mapview using latitude and longitude. how is it possible to draw?
Here is my code. but it is not working. i have added location in points Mutable array. and after that called drawRoute function to draw route between that location.
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D location;
location.latitude = (double) 23.00000;
location.longitude = (double) 73.00000;
CLLocationCoordinate2D location2;
location2.latitude = (double) 73.00000;
location2.longitude = (double) 23.00000;
CLLocation *locationPoint1 = [[CLLocation alloc]initWithLatitude:location.latitude longitude:location.longitude];
CLLocation *locationPoint2 = [[CLLocation alloc]initWithLatitude:location2.latitude longitude:location2.longitude];
[self.points addObject:locationPoint1];
[self.points addObject:locationPoint2];
[self performSelector:#selector(drowRoute)];
}
-(void)drowRoute{
CGContextRef context = UIGraphicsGetCurrentContext();
// CGContextSetStrokeColorWithColor(context, [[UIColor blueColor]CGColor]);
CGContextSetLineWidth(context, 2.0);
for(int idx = 0; idx < self.points.count; idx++)
{
CLLocation* location = [self.points objectAtIndex:idx];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:self.view];
if(idx == 0)
{
// move to the first point
CGContextMoveToPoint(context, point.x, point.y);
}
else
{
CGContextAddLineToPoint(context, point.x, point.y);
}
}
CGContextStrokePath(context);
}
I use it using Goggle Map Services. You just have to pass longitude and latitude as a parameter to URL and rest is taken care by Google maps.
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
NSString *url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f",c_lat,c_long,lat,lat];
//saddr= we pass source address long, lat.
//daddr= we pass destination address long, lat.
//--------use this if you have current long,lat and destination's address or street name etc...
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=%f,%f&daddr=%#",
currentLocation.latitude, currentLocation.longitude,
[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
//------------------------------------------------------------------------------
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:url]]; // this line will open Google map on Maps application on device and in Safari in Simulator.
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
curntloc = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
NSLog(#"in func--> %f %f",curntloc.coordinate.latitude, curntloc.coordinate.longitude);
}
Use following code:
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(void) centerMap {
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90;
CLLocationDegrees maxLon = -180;
CLLocationDegrees minLat = 90;
CLLocationDegrees minLon = 180;
for(int idx = 0; idx < routes.count; idx++)
{
CLLocation* currentLocation = [routes objectAtIndex:idx];
if(currentLocation.coordinate.latitude > maxLat)
maxLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.latitude < minLat)
minLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.longitude > maxLon)
maxLon = currentLocation.coordinate.longitude;
if(currentLocation.coordinate.longitude < minLon)
minLon = currentLocation.coordinate.longitude;
}
region.center.latitude = (maxLat + minLat) / 2;
region.center.longitude = (maxLon + minLon) / 2;
region.span.latitudeDelta = maxLat - minLat;
region.span.longitudeDelta = maxLon - minLon;
[mapView setRegion:region animated:YES];
}
-(void) calculate_distance{
float target = [location1 distanceFromLocation:location2]/1000;
text2=[NSString stringWithFormat:#"%fkm",target];
routes = [[self calculateRoutesFrom:location1.coordinate to:location2.coordinate] retain];
if([routes count]!=0){
[self updateRouteView];
[self centerMap];
UIAlertView* alert1=[[UIAlertView alloc]initWithTitle:#"MESSAGE" message:text2 delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert1 show];
[alert1 release];
}
else{
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:#"MESSAGE" message:#"We could not draw direction between your desired locations" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
location1=0;
location2=0;
}
-(void) updateRouteView {
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
Here is an example source code for drawing route on the map using lat,long coordinates.
http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html
This is how i learnt to do the very task.
Besides, to draw lines, in this post you will find classes for annotation. Check out the source code in the post, it will be more then sufficient to help you i hope.
By using the classes in the second link i have post, you will just have to provide the coordinates (lat,long) and the classes will do the rest :)
I use the code given below to draw a route between two locations:
- (void)fetchPolylineWithOrigin:(CLLocation *)origin destination:(CLLocation *)destination {
NSString *originString = [NSString stringWithFormat:#"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
NSString *destinationString = [NSString stringWithFormat:#"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];
NSString *directionsAPI = #"https://maps.googleapis.com/maps/api/directions/json?";
NSString *directionsUrlString = [NSString stringWithFormat:#"%#&origin=%#&destination=%#&mode=driving", directionsAPI, originString, destinationString];
NSURL *directionsUrl = [NSURL URLWithString:directionsUrlString];
NSURLSessionDataTask *fetchDirectionsTask = [[NSURLSession sharedSession] dataTaskWithURL:directionsUrl completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error) {
//Error in fetching poline
return;
}
NSArray *routesArray = [json objectForKey:#"routes"];
if ([routesArray count] > 0) {
NSDictionary *routeDict = [routesArray objectAtIndex:0];
NSDictionary *routeOverviewPolyline = [routeDict objectForKey:#"overview_polyline"];
NSString *points = [routeOverviewPolyline objectForKey:#"points"];
GMSPath *path = [GMSPath pathFromEncodedPath:points];
[self drawPath:path];
}
}];
[fetchDirectionsTask resume];
}
- (void)drawPath:(GMSPath *)newPath {
GMSPolyline *polyline = [GMSPolyline polylineWithPath:newPath];
polyline.strokeColor =PathColor;
polyline.strokeWidth = 2.5;
polyline.geodesic = YES;
NSArray *styles = #[[GMSStrokeStyle solidColor:PathColor],
[GMSStrokeStyle solidColor:PathColor]];
NSArray *lengths = #[#100000, #50000];
polyline.spans = GMSStyleSpans(polyline.path, styles, lengths, kGMSLengthRhumb);
polyline.map = _mapView;
}
I want to draw lines over google maps, the lines may be straight or curve, but i want to draw lines such that they connect two points, that may be at any geographical locations.
Thanks.
GuruPrasad R Gujjar.
Here is the example code, please try with this.
EDIT:Also you have to download "RegexKitLite" header file and class file.
// This method will calculate the routes and return an array with point
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index = 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) = 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
// This method will draw the route with array of points.
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i &ls; routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [map convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
//[self.view addSubview:routeView];
CGContextRelease(context);
//29-07-10
CGContextRef context2 = CGBitmapContextCreate(nil,
routeView2.frame.size.width,
routeView2.frame.size.height,
8,
4 * routeView2.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context2, lineColor2.CGColor);
CGContextSetRGBFillColor(context2, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context2, 3.0);
for(int i = 0; i &ls; routes2.count; i++) {
CLLocation* location2 = [routes2 objectAtIndex:i];
CGPoint point2 = [map convertCoordinate:location2.coordinate toPointToView:routeView2];
if(i == 0) {
CGContextMoveToPoint(context2, point2.x, routeView2.frame.size.height - point2.y);
} else {
CGContextAddLineToPoint(context2, point2.x, routeView2.frame.size.height - point2.y);
}
}
CGContextStrokePath(context2);
CGImageRef image2 = CGBitmapContextCreateImage(context2);
UIImage* img2 = [UIImage imageWithCGImage:image2];
routeView2.image = img2;
//[self.view addSubview:routeView];
CGContextRelease(context2);
}
I think it will help you to complete your task.
Refer this Link1 and Link2. It might be helpful for you.
You'll need to use JavaScript and the Google Maps API - Key is free if I remember right.
Everything else here:
http://code.google.com/apis/maps/documentation/javascript/v2/overlays.html#Drawing_Polylines
i want to draw line between two points in my view how it possible.?
Edit:ya thax.i have got solution. Line draw perfectly.I want to draw multiple line with different points.I am using for loop and every rotaion i pass the start and end points.but only last point is drawn.how to solve this problem?
You need to use a few CoreGraphics functions:
// get the current context
CGContextRef context = UIGraphicsGetCurrentContext();
// set the stroke color and width
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
// move to your first point
CGContextMoveToPoint(context, 10.0, 10.0);
// add a line to your second point
CGContextAddLineToPoint(context, 50.0, 10.0);
// tell the context to draw the stroked line
CGContextStrokePath(context);
This example would draw a horizontal white line with a thickness of 2. Apple has some great sample code and tutorials including the QuartzDemo tutorial: http://developer.apple.com/iPhone/library/samplecode/QuartzDemo/index.html.
The QuartzDemo application has great examples of how to use CoreGraphics, including lines and bezier curves. download here
Take a look at QuartzLineDrawing.m in the sample code. You'll be able to find some great examples there :-)
Since this is 09' answers and whatnot I figure I update the link and code here for anyone looking in 11'.
The link for the Quartz Demo is: http://developer.apple.com/library/ios/#samplecode/QuartzDemo/Introduction/Intro.html
and the code I use to draw multiple lines is:
//Drawing lines
// Set the color that we want to use to draw the line
[ [ UIColor brownColor] set];
//Get the current graphics context (pen)
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Set the width for the line
CGContextSetLineWidth(currentContext,
5.0f);
// Start the line at this point
CGContextMoveToPoint(currentContext,
20.0f,
20.0f);
// And end it at this point
CGContextAddLineToPoint(currentContext,
100.0f,
100.0f);
// Extend the line to another point
CGContextAddLineToPoint(currentContext,
300.0f,
100.0f);
//Use the context's current color to draw the line
CGContextStrokePath(currentContext);
I recommend reading Graphics and Animation on iOS: A Beginner's Guide to Core Graphics and Core Animation by Vandad Nahavandipoor. It's mostly on graphics than animation though. I recommend checking out his videos on animation if your interested. http://www.youtube.com/watch?v=ybMFPB-Gbsw&feature=player_embedded They're called Animations in iOS using Block Objects Part I and II. Supposedly there are supposed to be more videos at some point. But the videos go with the book.
That's it.
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation)
{
let CurrentLogitude = String(format: "%.8f", newLocation.coordinate.longitude)
//print(CurrentLogitude)
let CurrentLatitude = String(format: "%.8f", newLocation.coordinate.latitude)
// print(CurrentLatitude)
//[self.locationManager stopUpdatingLocation];
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
}
func locationManager(manager: CLLocationManager,
didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
var shouldIAllow = false
var locationStatus :String
switch status
{
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true)
{
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
let pin = MKAnnotationView(annotation: annotation, reuseIdentifier: "locationpin")
pin.image = UIImage(named: "locationpin.png")
let notationView: UIView = UIView()
notationView.frame = CGRectMake(0, 0, 400, 300)
notationView.backgroundColor = UIColor.grayColor()
pin.leftCalloutAccessoryView = notationView
pin.canShowCallout = true
return pin
}
#pragma mark - Mapview Delegate Method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier: #"id"];
if (!pin && ![annotation isKindOfClass:[MKUserLocation class]])
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
pin.pinTintColor=[UIColor blueColor];
pin.canShowCallout = true;
}
else
{
if (pin == nil)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
}
else
{
pin.annotation = annotation;
}
pin.pinTintColor=[UIColor grayColor];
UIView *notationView=[[UIView alloc]init];
notationView.frame=CGRectMake(0, 0, 320, 300);
notationView.backgroundColor = [UIColor grayColor];
UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(5, 5, 300, 25);
lbl.text=#"Current Location";
lbl.textColor=[UIColor whiteColor];
[notationView addSubview:lbl];
UIImageView *img=[[UIImageView alloc]init];
img.frame=CGRectMake(0, 0, 50,50);
img.image=[UIImage imageNamed:#"ios.png"];
// pin.leftCalloutAccessoryView = notationView;
// pin.rightCalloutAccessoryView = img;
//pin.detailCalloutAccessoryView=customView;
pin.animatesDrop = true;
pin.canShowCallout = true;
}
return pin;
}
-(IBAction)btnRoutePathClicked:(id)sender
{
[self.mapView removeAnnotation:point];
[self.mapView removeOverlay:polyline];
[self.mapView reloadInputViews];
MKCoordinateSpan span = MKCoordinateSpanMake(1.0, 1.0);
MKCoordinateRegion region = MKCoordinateRegionMake(currentLocation.coordinate, span);
[self.mapView setRegion:region];
[self.mapView setCenterCoordinate:currentLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true",[NSString stringWithFormat:#"%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude],[NSString stringWithFormat:#"22.45,72.4545"]];
//http://maps.googleapis.com/maps/api/directions/json?origin=51.194400,4.475816&destination=50.941278,6.958281&sensor=true
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *routes = [result objectForKey:#"routes"];
if ([routes count]==0)
{
NSLog(#"Routs:=>%#",routes);
}
else
{
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
double latitudes = [[end_location objectForKey:#"lat"] doubleValue];
double longitudes = [[end_location objectForKey:#"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitudes, longitudes);
point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:#"end_address"];
[self.mapView addAnnotation:point];
NSDictionary *route = [routes lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
NSMutableArray *_path = [self decodePolyLine:overviewPolyline];
NSInteger numberOfSteps = _path.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [_path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyline = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyline];
}
}
}];
}
-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr
{
NSMutableString *encoded = [[NSMutableString alloc] initWithCapacity:[encodedStr length]];
[encoded appendString:encodedStr];
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len)
{
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do
{
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do
{
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitudes = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitudes = [[NSNumber alloc] initWithFloat:lng * 1e-5];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitudes floatValue] longitude:[longitudes floatValue]];
[array addObject:location];
}
return array;
}
- (MKPolylineRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay{
MKPolylineRenderer *polylineView = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 4.0;
polylineView.alpha = 0.5;
return polylineView;
}