how to draw a path one place to another place in google map sdk iOS? - objective-c

i need to find path in google map view one place to another place. how to draw a direction map using google map sdk iOS.
can any of give source code. and then explain how to achieve this.
Below i attached image also, i need to achieve this in iPhone app using Google Map SDK iOS.
Thanks,

-(void)showRoute:(id)routeDict {
NSString *pointStr = [[[[routeDict objectForKey:#"routes"] objectAtIndex:0] objectForKey:#"overview_polyline"] objectForKey:#"points"];
float max_long = 0.0;
float min_long = 0.0;
float max_lat = 0.0;
float min_lat = 0.0;
NSMutableArray *routeArr = [self decodePolyLine:pointStr];
CLLocationCoordinate2D commuterLotCoords[[routeArr count]];
CLLocation *loc;
if ([routeArr count]) {
loc = [routeArr objectAtIndex:0];
max_long = loc.coordinate.longitude;
min_long = loc.coordinate.longitude;
max_lat = loc.coordinate.latitude;
min_lat = loc.coordinate.latitude;
}
for (int i=0; i<[routeArr count]; i++) {
CLLocation *loc = [routeArr objectAtIndex:i];
commuterLotCoords[i] = loc.coordinate;
if (loc.coordinate.latitude > max_lat) {
max_lat = loc.coordinate.latitude;
}
if (loc.coordinate.latitude < min_lat) {
min_lat = loc.coordinate.latitude;
}
if (loc.coordinate.longitude > max_long) {
max_long = loc.coordinate.longitude;
}
if (loc.coordinate.longitude < min_long) {
min_long = loc.coordinate.longitude;
}
}
MKPolyline *overflowRoutePolygon = [MKPolyline polylineWithCoordinates:commuterLotCoords count:[routeArr count]];
[mapView addOverlay:overflowRoutePolygon];
//NSLog(#"%f %f %f %f",min_lat,max_lat,min_long,max_long);
if ( max_lat == 0.0 || min_lat == 0.0 || max_long == 0.0 || min_long == 0.0 ) {
} else {
//calculate center of map
float center_long = (max_long + min_long) / 2;
float center_lat = (max_lat + min_lat) / 2;
//calculate deltas
float deltaLat = max_lat - min_lat + .00032;
float deltaLong = max_long - min_long + .00032;
//NSLog(#"%f %f %f %f",center_lat,center_long,deltaLat,deltaLong);
//create new region and set map
CLLocationCoordinate2D cordinate;
cordinate.latitude = center_lat;
cordinate.longitude = center_long;
MKCoordinateSpan span = MKCoordinateSpanMake(deltaLat, deltaLong);
MKCoordinateRegion region = {cordinate, span};
[mapView setRegion:region];
}
}
-(void)showRoute
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
float sourceLat = 0.00;
float sourceLong = 0.00;
float destinationLat = 0.00;
float destinationLong = 0.00;
id record = [routeArray objectAtIndex:selectedIndex];
sourceLat = [[[[record objectForKey:#"To"] objectForKey:#"Latitude"] objectForKey:#"text"] floatValue];
sourceLong = [[[[record objectForKey:#"To"] objectForKey:#"Longitude"] objectForKey:#"text"] floatValue];
destinationLat = [[[[record objectForKey:#"From"] objectForKey:#"Latitude"] objectForKey:#"text"] floatValue];
destinationLong = [[[[record objectForKey:#"From"] objectForKey:#"Longitude"] objectForKey:#"text"] floatValue];
if ( sourceLat == 0.00 || sourceLong == 0.00 || destinationLat == 0.00 || destinationLong == 0.00 ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Direction Error"
message: #"One of your destination is not valid."
delegate: self
cancelButtonTitle: #"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
return;
}
NSString *urlStr = [NSString stringWithFormat: #"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false",
sourceLat, sourceLong,
destinationLat,destinationLong];
NSLog(#"urlStr : %#",urlStr);
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:urlStr]];
//NSLog(#"direction response : %#",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
JSONDecoder *jsonKitDecoder = [JSONDecoder decoder];
NSMutableDictionary *routeDic = [[jsonKitDecoder objectWithData:data] copy];
if ( ![[[routeDic objectForKey:#"status"] uppercaseString] isEqualToString:#"OK"] ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Direction Error"
message: #"Not able to find direction from your default location."
delegate: self
cancelButtonTitle: #"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
[pool release];
return;
}
[self performSelectorOnMainThread:#selector(showRoute:) withObject:routeDic waitUntilDone:YES];
[pool release];
return;
}
-(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] 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 *latitute = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitute = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitute floatValue] longitude:[longitute floatValue]] autorelease];
[array addObject:loc];
}
[encoded release];
return array;
}
pragma mark MKMapKitDelegate
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
HAnnotation *ann = (HAnnotation *)annotation;
static NSString *AnnotationViewID = #"annotationViewID";
HAnnotationView *annotationView = (HAnnotationView *)[map dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
if (annotationView == nil)
{
annotationView = [[[HAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID type:ann.type] autorelease];
}
annotationView.type = ann.type;
annotationView.annotation = annotation;
[annotationView setNeedsDisplay];
return annotationView;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *aV;
for (aV in views) {
MKAnnotationView* annotationView = aV;
annotationView.canShowCallout = NO;
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id < MKOverlay >)overlay
{
if( [overlay isKindOfClass:[MKPolyline class]] ) {
MKPolylineView *view = [[MKPolylineView alloc] initWithOverlay:overlay];
view.lineWidth=2;
view.strokeColor=[UIColor blueColor];
view.fillColor=[[UIColor blueColor] colorWithAlphaComponent:0.5];
return [view autorelease];
} else {
MKPolygonView *view = [[MKPolygonView alloc] initWithOverlay:overlay];
view.lineWidth=2;
view.strokeColor=[UIColor yellowColor];
view.fillColor=[[UIColor yellowColor] colorWithAlphaComponent:0.3];
return [view autorelease];
}
return nil;
}
Try this code i have used this code in my project it is working fine.
First of all pass source and destination latitude and longitude in the google api you will get all the points between that place and after parsing using poly line method you will draw line.simply use this methods make changes according to your variable and data .

i hope this will help you. This is from google api. Draw polyline and give paths lat long in it .
https://developers.google.com/maps/documentation/ios/shapes#customize_a_polyline

Related

How can I display Latitude & Longitude in 19.0176° N, 72.8562° E format in Objective c

I am using the following code to get the current location,I have added the Corelocation framework
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSInteger degrees = newLocation.coordinate.latitude;
double decimal = fabs(newLocation.coordinate.latitude - degrees);
int minutes = decimal * 60;
double seconds = decimal * 3600 - minutes * 60;
NSString *lattitudeStr = [NSString stringWithFormat:#"%d° %d' %1.4f\"",
degrees, minutes, seconds];
_latitudeLabel.text = lattitudeStr;
degrees = newLocation.coordinate.longitude;
decimal = fabs(newLocation.coordinate.longitude - degrees);
minutes = decimal * 60;
seconds = decimal * 3600 - minutes * 60;
NSString *longitudeStr = [NSString stringWithFormat:#"%d° %d' %1.4f\"",
degrees, minutes, seconds];
_longitudeLabel.text = longitudeStr;
}
// Stop Location Manager
[locationManager stopUpdatingLocation];
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^
(NSArray *placemarks, NSError *error)
{
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
_addressLabel.text = [NSString stringWithFormat:#"%#\n%# %#\n%#\n%#",
placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
}
I am getting the values for,Latitude:19° 1’ 3.4129” and Longitude:72° 51’ 22.1918” So I need this coordinate display in 19.0176° N,72.8562° E format in Objective c. How to get the exact latitude and longitude. where i am doing the mistake or do i need to add any other method or function or framework or sample code.
You already have these values, see the comment this is what you want
if (currentLocation != nil) {
NSInteger degrees = newLocation.coordinate.latitude; //<--- this is what you want
NSString *lattitudeStr = [NSString stringWithFormat:#"%f° N",
degrees];
_latitudeLabel.text = lattitudeStr;
degrees = newLocation.coordinate.longitude; //<--- this is what you want
NSString *longitudeStr = [NSString stringWithFormat:#"%f° E",
degrees];
_longitudeLabel.text = longitudeStr;
}
NSString *lat = [self convertCoordinateFromDegreeMinuteSecond:#"19° 1’ 3.4129”" position:#"N"];
NSString *lon = [self convertCoordinateFromDegreeMinuteSecond:#"72° 51’ 22.1918”" position:#"E"];
- ( NSString * )convertCoordinateFromDegreeMinuteSecond:( NSString * )string position:( NSString * )position; {
NSCharacterSet *notAllowedChars = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
NSArray *arrayLat = [string componentsSeparatedByString:#" "];
if ( arrayLat.count == 3 ) {
NSString *degree = [[arrayLat[ 0 ] componentsSeparatedByCharactersInSet:notAllowedChars] componentsJoinedByString:#""];
NSString *minute = [[arrayLat[ 1 ] componentsSeparatedByCharactersInSet:notAllowedChars] componentsJoinedByString:#""];
NSString *second = [[arrayLat[ 2 ] componentsSeparatedByCharactersInSet:notAllowedChars] componentsJoinedByString:#""];
int sign = degree.doubleValue < 0 ? -1 : 1;
double coordinate = ( degree.doubleValue + ( sign * ( minute.doubleValue / 60. ) ) + ( sign * ( second.doubleValue / 3600. ) ) );
NSString *str = [NSString stringWithFormat:#"%f° %#", coordinate, position];
return str;
} else {
return #"NaN";
}
}

MapKit/CoreLocation iOS7 why can't I save annotation data (coordinates) to array?

Alright, I've looked high and low for an answer to this. Why can I query the mapview.annotations array for coordinate data but I cant save the same annotation data at generation into an array that is query-able in the same fashion.
This is my code:
- (void)retrieveData {
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"http://PRIVATE.com/api/cprapi.php?function=request&uid=PRIVATE"]];
NSLog(#"%#",url);
NSData * data = [NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
workzoneArray = [[NSMutableArray alloc]init];
for (int i = 0; i < json.count; i++) {
//Create workzone objects
NSString * sT = [[json objectAtIndex:i]objectForKey:#"startTime"];
NSString * eT = [[json objectAtIndex:i]objectForKey:#"endTime"];
NSString * sLat = [[json objectAtIndex:i]objectForKey:#"startLat"];
NSString * sLon = [[json objectAtIndex:i]objectForKey:#"startLon"];
NSString * eLat = [[json objectAtIndex:i]objectForKey:#"endLat"];
NSString * eLon = [[json objectAtIndex:i]objectForKey:#"endLon"];
NSString * A = [[json objectAtIndex:i]objectForKey:#"active"];
NSString * DUID = [[json objectAtIndex:i]objectForKey:#"deviceUID"];
LTB * workzone = [[LTB alloc] initWithStartTime:sT andEndTime:eT andStartLat:sLat andStartLon:sLon andEndLat:eLat andEndLon:eLon andActive:A andDeviceUID:DUID];
[workzoneArray addObject:workzone];
NSLog(#"workzoneArray: %#", workzoneArray);
}
for (int i = 0; i < workzoneArray.count; i++) {
LTB * workzone = [workzoneArray objectAtIndex:i];
CLLocationCoordinate2D thiscoordinate;
CLLocationCoordinate2D thatcoordinate;
float sLat = [workzone.startLat floatValue];
float sLon = [workzone.startLon floatValue];
NSLog(#"Start: %# %#",workzone.startLat,workzone.startLon);
float eLat = [workzone.endLat floatValue];
float eLon = [workzone.endLon floatValue];
NSLog(#"End: %# %#",workzone.endLat,workzone.endLon);
thiscoordinate.latitude = sLat;
thiscoordinate.longitude = sLon;
thatcoordinate.latitude = eLat;
thatcoordinate.longitude = eLon;
myAnnotation *annotation1 = [[myAnnotation alloc] initWithCoordinate:thiscoordinate title:#"Limit"];
[self.mapView addAnnotation:annotation1];
[AnnotationArray addObject:annotation1];
myAnnotation * annotation2 = [[myAnnotation alloc] initWithCoordinate:thatcoordinate title:#"Limit"];
[self.mapView addAnnotation:annotation2];
[AnnotationArray addObject:annotation2];
NSLog(#"%#", AnnotationArray);
NSLog(#"%#", [AnnotationArray objectAtIndex:0]);
NSLog(#"%#", [AnnotationArray objectAtIndex:1]);
}
}
and the code that handles comparisons between my points where I am attempting to pull data from my array.
-(void) mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"checking distances...");
myAnnotation * annotation = [AnnotationArray objectAtIndex:0];
CLLocation *loc = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];
NSLog(#"%f - %f", annotation.coordinate.latitude, annotation.coordinate.longitude);
annotation = [AnnotationArray objectAtIndex:1];
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];
NSLog(#"%f - %f", annotation.coordinate.latitude, annotation.coordinate.longitude);
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocationDistance dist = [loc1 distanceFromLocation:loc2];
float distance = dist;
NSLog(#"%f", distance);
if (distance < 50) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Limit Alert"
message:#"50 Meters to Limit"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
}
If I objectAtIndex the self.mapView.annotations I get the correct lat and lon, so I'm guessing it's an invalid type conversion as it goes into the array am I right in thinking that?
Is there a better way I could do that? I only am looking at using the array as the mapView.annotations is unreliable based on network speed to which annotated view is at which index with out alot more code.
The goal is to compare loc1 and loc2 get the distance between them. compare current location's distance to loc1 add the current location's distance to loc2 and if within a margin of error check that it is less or the same. But I cant do this until I figure out a reliable way of knowing which mapView.annotation is which.
Maybe I'm blind. Thanks!
ANSWER:
Looked through my code again, decided to use my earlier array which I fed my JSON into and then extract data from there as that will allow it to be extended further down the road. Here's the code I wound up with and it seems to work ok.
NSLog(#"checking distances...");
LTB * workzone = [workzoneArray objectAtIndex:0];
CLLocationCoordinate2D startCoord;
CLLocationCoordinate2D endCoord;
double sLat = [workzone.startLat doubleValue];
double sLon = [workzone.startLon doubleValue];
startCoord.latitude = sLat;
startCoord.longitude = sLon;
double eLat = [workzone.endLat doubleValue];
double eLon = [workzone.endLon doubleValue];
endCoord.latitude =eLat;
endCoord.longitude = eLon;
CLLocation *loc = [[CLLocation alloc] initWithLatitude:startCoord.latitude longitude:startCoord.longitude];
NSLog(#"%f - %f", startCoord.latitude, startCoord.longitude);
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:endCoord.latitude longitude:endCoord.longitude];
NSLog(#"%f - %f",endCoord.latitude, endCoord.longitude);
CLLocation *myloc = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocationDistance area = [loc distanceFromLocation:loc1];
NSLog(#"area: %f",area);
CLLocationDistance distToA = [myloc distanceFromLocation:loc];
NSLog(#"distToA %f",distToA);
CLLocationDistance distToB = [myloc distanceFromLocation:loc1];
NSLog(#"distToB %f",distToB);
double outOfBounds = ((distToA+distToB) - area);
NSLog(#"%f", outOfBounds);
if (outOfBounds < (area + 50)) {
if (workzoneAlert == TRUE) {
workzoneAlert = false;
}
if (distToA < 10) {
if (workzoneAlertA == false) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Limit Alert"
message:#"10 Meters to Limit A"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
//set variable so it only shows once
self.workzoneAlertA = true;
}
else {
}
}
else if (distToB <10) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Limit Alert"
message:#"10 Meters to Limit B"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
}
}
else {
if (workzoneAlert == FALSE){
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Limit Alert"
message:#"Exceeded WorkZone"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
workzoneAlert = TRUE;
}
}
}

How to rapidly create an NSMutableArray with CFDataRef image pixel data in Xcode for iOS

My question is simple, I have the following code, it creates an array of Hues got from a function that returns the UIColor of an image (this is not important, just context). So, I need to create this array as fast as possible, this test runs with only a 5x5 pixels image and it takes about 3sec, I want to be able to run a 50x50 pixels image (at least) in about 2 secods (tops), any ideas?
- (void)createArrayOfHues: (UIImage *)imageScaned{
if (imageScaned != nil) {
NSLog(#"Creating Array...");
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
img.contentMode = UIViewContentModeScaleToFill;
img.image = imageScaned;
img.contentMode = UIViewContentModeRedraw;
img.hidden = YES;
int i = 0;
CGFloat hue = 0;
CGFloat sat = 0;
CGFloat brit = 0;
CGFloat alph = 0;
CGFloat hue2 = 0;
CGFloat sat2 = 0;
CGFloat brit2 = 0;
CGFloat alph2 = 0;
[_colorsArray removeAllObjects];
[_satForHue removeAllObjects];
[_britForHue removeAllObjects];
[_alphForHue removeAllObjects];
_colorsArray = [[NSMutableArray alloc] initWithCapacity:(25)];
_satForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
_britForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
_alphForHue = [[NSMutableArray alloc] initWithCapacity:(25)];
while (i<25) {
for (int y=1; y <= 5; y++){
for (int x = 1; x <= 2.5; x++){
if (x != (5-x)){
UIColor *color = [self colorMatch:imageScaned :x :y];
UIColor *color2 = [self colorMatch:imageScaned :(5-x) :y];
if([color getHue:&hue saturation:&sat brightness:&brit alpha:&alph] && [color2 getHue:&hue2 saturation:&sat2 brightness:&brit2 alpha:&alph2]){
NSNumber *hueId = [NSNumber numberWithFloat:(float)hue];
NSNumber *satId = [NSNumber numberWithFloat:(float)sat];
NSNumber *britId = [NSNumber numberWithFloat:(float)brit];
NSNumber *alphId = [NSNumber numberWithFloat:(float)alph];
NSNumber *hueId2 = [NSNumber numberWithFloat:(float)hue2];
NSNumber *satId2 = [NSNumber numberWithFloat:(float)sat2];
NSNumber *britId2 = [NSNumber numberWithFloat:(float)brit2];
NSNumber *alphId2 = [NSNumber numberWithFloat:(float)alph2];
[_colorsArray insertObject:hueId atIndex:i];
[_satForHue insertObject:satId atIndex:i];
[_britForHue insertObject:britId atIndex:i];
[_alphForHue insertObject:alphId atIndex:i];
[_colorsArray insertObject:hueId2 atIndex:(i+1)];
[_satForHue insertObject:satId2 atIndex:(i+1)];
[_britForHue insertObject:britId2 atIndex:(i+1)];
[_alphForHue insertObject:alphId2 atIndex:(i+1)];
}
NSLog(#"color inserted at %i with x: %i and y: %i" , i , x, y);
i++;
}else {
UIColor *color = [self colorMatch:imageScaned :x :y];
if([color getHue:&hue saturation:&sat brightness:&brit alpha:&alph]){
NSNumber *hueId = [NSNumber numberWithFloat:(float)hue];
NSNumber *satId = [NSNumber numberWithFloat:(float)sat];
NSNumber *britId = [NSNumber numberWithFloat:(float)brit];
NSNumber *alphId = [NSNumber numberWithFloat:(float)alph];
[_colorsArray insertObject:hueId atIndex:i];
[_satForHue insertObject:satId atIndex:i];
[_britForHue insertObject:britId atIndex:i];
[_alphForHue insertObject:alphId atIndex:i];
}
}
}
}
}
NSLog(#"Returns the array");
}else{
NSLog(#"Returns nothing");
}
}
The code for colorMatch:
- (UIColor *) colorMatch: (UIImage *)image :(int) x :(int) y {
isBlackColored = NO;
if (image == nil){
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL customColor = [defaults boolForKey:#"custom_color"];
if (customColor){
float red = [defaults floatForKey:#"custom_color_slider_red"];
float green = [defaults floatForKey:#"custom_color_slider_green"];
float blue = [defaults floatForKey:#"custom_color_slider_blue"];
return [UIColor colorWithRed:red green:green blue:blue alpha:1];
}else
isDefaultS = YES;
}
else{
CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
const UInt8* data = CFDataGetBytePtr(pixelData);
int pixelInfo = ((image.size.width * y) + x ) * 4;
UInt8 red = data[pixelInfo];
UInt8 green = data[(pixelInfo + 1)];
UInt8 blue = data[pixelInfo + 2];
UInt8 alpha = data[pixelInfo + 3];
CFRelease(pixelData);
float redC = red/255.0f;
float greenC = green/255.0f;
float blueC = blue/255.0f;
UIColor* color = [UIColor colorWithRed:redC green:greenC blue:blueC alpha:alpha/255.0f];
return color;
}
return nil;
}
I think your main performance bottleneck is not the initialization of NSMutableArray instances, but the way you index your image:
UIColor *color = [self colorMatch:imageScaned :x :y];
I guess this method converts the UIImage to a CGImageRef, copies its data, indexes it, then destroys/releases these temporary objects, or something like this - for every single pixel...
You should refactor this code to get hold of the image buffer only once, and then work with it like a regular C pointer/array. If that doesn't solve your performance problem, you should do some profiling.

Drawing an Bar graph on cocoa using core plot

I'm new to mac app development. I'm drawing a bar graph using core plot frame work.
What actually i want to is, when i select a month i want to draw graph for last 6 months.when i select '12/2012' I'm able to draw the graph correctly for last 6 months. But when i select '02/2013' the graph is showing only January and February and not the previous months.
- (int)maxVal:(NSMutableArray *)arr {
NSDictionary *dict = [arr objectAtIndex:0];
NSString* dictValue = [dict objectForKey:#"X_VAL"];
int mxm = [dictValue intValue];
for (int i=0; i<[arr count]; i++) {
if ([[[arr objectAtIndex:i] objectForKey:#"X_VAL"] intValue] > mxm) {
mxm = [[[arr objectAtIndex:i] objectForKey:#"X_VAL"] intValue];
}
}
return mxm;
}
- (int)minVal:(NSMutableArray *)arr {
int mn = [[[arr objectAtIndex:0] objectForKey:#"X_VAL"] intValue];
for (int i=0; i<[arr count]; i++) {
if ([[[arr objectAtIndex:i] objectForKey:#"X_VAL"] intValue] < mn) {
mn = [[[arr objectAtIndex:i] objectForKey:#"X_VAL"] intValue];
}
}
return mn;
}
- (void)drawGraph {
if ([graphMutableArray count] > 0) {
NSRect viewRect = [aGraphView bounds];
double xAxisStart = 0, yAxisStart = 0, xAxisLength = [graphMutableArray count], yAxisLength = [[graphMutableArray valueForKeyPath:#"#max.Y_VAL"] doubleValue], tenthPartOfYAxis = (yAxisLength + (yAxisLength / 10));
NSLog(#"Y Axis Length = %f", yAxisLength);
for (int k = 0; k < xAxisLength; k++) {
NSDictionary *dict1 = [graphMutableArray objectAtIndex:k];
NSDictionary *dict2 = [dict1 objectForKey:#"X_VAL"];
NSDictionary *dict3 = [dict1 valueForKey:#"Y_VAL"];
NSLog(#"dict 2 = %# and dict 3 = %#", dict2, dict3);
}
graph = [[CPTXYGraph alloc] initWithFrame:viewRect];
[graph applyTheme:[CPTTheme themeNamed:kCPTSlateTheme]];//kCPTDarkGradientTheme]];//kCPTStocksTheme]];
aGraphView.hostedGraph = graph;
graph.plotAreaFrame.masksToBorder = NO;
graph.paddingLeft = 90.0;
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 70.0;
// Add plot space for horizontal bar charts
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(xAxisStart)
length:CPTDecimalFromDouble(xAxisLength + 1)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(yAxisStart)
length:CPTDecimalFromDouble(tenthPartOfYAxis)];
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
NSString *cptDecimalstr = [NSString stringWithFormat:#"%f", xAxisLength /[x.axisLabels count]];
x.majorIntervalLength = CPTDecimalFromString(cptDecimalstr);
x.minorTicksPerInterval = 1;
x.majorTickLineStyle = nil;
x.minorTickLineStyle = nil;
x.axisLineStyle = nil;
x.titleLocation = CPTDecimalFromFloat(1.0f);
x.titleOffset = 55.0f;
// Define some custom labels for the data elements
x.labelRotation = M_PI/4;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
NSLog(#"Max = %d and Min = %d", [self maxVal:graphMutableArray], [self minVal:graphMutableArray]);
NSMutableArray *tempCustomTickLocations = [NSMutableArray arrayWithObjects:[NSNumber numberWithFloat:0.5],[NSNumber numberWithFloat:1.7],[NSNumber numberWithFloat:3.0],[NSNumber numberWithFloat:4.1],[NSNumber numberWithFloat:5.3],[NSNumber numberWithFloat:6.5],[NSNumber numberWithFloat:6.9],[NSNumber numberWithFloat:7.1],[NSNumber numberWithFloat:7.5],[NSNumber numberWithFloat:8.1],[NSNumber numberWithFloat:8.5],[NSNumber numberWithFloat:8.9],nil];
NSMutableArray *tempMonthsArr = [NSMutableArray arrayWithObjects:#"",#"January", #"February", #"March", #"April", #"May", #"June", #"July", #"August", #"September", #"October", #"November", #"December", nil];
NSMutableArray *tempMonthsMutArr
= [[[NSMutableArray alloc] initWithCapacity:[graphMutableArray count]] autorelease], *tempMutCustomTickLocations
= [[[NSMutableArray alloc] initWithCapacity:[graphMutableArray count]] autorelease];
int k = 0;
for (int l = [self minVal:graphMutableArray]; l <=[self maxVal:graphMutableArray]; l++) {
NSString *tempMonth = [tempMonthsArr objectAtIndex:l];
[tempMonthsMutArr addObject:tempMonth];
[tempMutCustomTickLocations addObject:[tempCustomTickLocations objectAtIndex:k]];
k = k + 1;
NSLog(#"tempMutCustomTickLocations= %#",tempMutCustomTickLocations);
}
if ([self minVal:graphMutableArray] == [self maxVal:graphMutableArray]) {
NSString *tempMonth = [tempMonthsArr objectAtIndex:[self minVal:graphMutableArray]];
[tempMonthsMutArr addObject:tempMonth];
[tempMutCustomTickLocations addObject:[tempCustomTickLocations objectAtIndex:0]];
}
NSMutableArray *customTickLocations = [NSMutableArray arrayWithArray:tempMutCustomTickLocations];
NSArray *xAxisLabels = [NSArray arrayWithArray:tempMonthsMutArr];
NSUInteger labelLocation = 0;
NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:[graphMutableArray count]];
for (NSNumber *tickLocation in customTickLocations) {
//NSLog(#"tickLocation==%d",tickLocation.intValue);
CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText: [xAxisLabels objectAtIndex:labelLocation++] textStyle:x.labelTextStyle];
newLabel.tickLocation = [tickLocation decimalValue];//[tickLocation decimalValue];
newLabel.offset = x.labelOffset + x.majorTickLength;
// NSLog(#"[tickLocation floatValue] = %f", [tickLocation floatValue]);
newLabel.offset = x.labelOffset + x.majorTickLength;
//NSLog(#"x.labelOffset = %f, x.majorTickLength = %f and newLabel.offset = %f", x.labelOffset, x.majorTickLength, newLabel.offset);
newLabel.rotation = M_PI/4;
//NSLog(#"-=-=-=--=-=-=- %f",x.labelOffset);
//NSLog(#"%f", x.majorTickLength );
[customLabels addObject:newLabel];
//NSLog(#"%#",customLabels);
[newLabel release];
}
x.axisLabels = [NSSet setWithArray:customLabels];
NSLog(#"%#",x.axisLabels);
CPTXYAxis *y = axisSet.yAxis;
y.axisLineStyle = nil;
y.majorTickLineStyle = nil;
y.minorTickLineStyle = nil;
NSString *cptDecimalStr = [NSString stringWithFormat:#"%f", yAxisLength / 10];
y.majorIntervalLength = CPTDecimalFromString(cptDecimalStr);
//y.constantCoordinateValue = CPTDecimalFromString(#"0");
// y.title = #"Y Axis";
y.titleOffset = 45.0f;
y.titleLocation = CPTDecimalFromFloat(150.0f);
//CPTPieChart
CPTBarPlot *plot = [[CPTBarPlot alloc] initWithFrame:CGRectZero];
plot.plotRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0)
length:CPTDecimalFromDouble(xAxisLength)];
plot.barOffset = [[NSDecimalNumber decimalNumberWithString:#"0.50"]
decimalValue]; //CPTDecimalFromDouble(0.50f);
plot.fill = [CPTFill fillWithColor:[CPTColor lightGrayColor]];
plot.dataSource = self;
[graph addPlot:plot ];//toPlotSpace:plotSpace];
}
else {
aGraphView.hostedGraph = nil;
[[NSAlert alertWithMessageText:#"No Data Found" defaultButton:#"Ok" alternateButton:nil otherButton:nil informativeTextWithFormat:#""] runModal];
}
}
Can Anyone Help me to solve the problem!!!
You need to update the xRange of the plot space. This will move the axis labels to the correct position and draw data points in the new range. You'll also need to add the new data points to the plot.

unable to show anything on x-axis and y-axis labels in core-plot

I'm using core plot in an application and from past one week I am trying to show labels on x-axis and y-axis. But haven't succeed yet. I'm posting my code here with screen shot. If someone knows any solution to fix the problem let me know urgently.
Code -
-(void)viewDidLoad {
[super viewDidLoad];
// Initialize all graph dependent data.
//self.dataForPlot = [[NSMutableArray alloc] initWithCapacity:0];
minYValues = [[NSMutableArray alloc] initWithCapacity:0];
maxYValues = [[NSMutableArray alloc] initWithCapacity:0];
[self createGraph];
[self customizeGraph];
}
- (void) createGraph{
// Create graph
graph = [[CPXYGraph alloc] initWithFrame:CGRectZero];
CPGraphHostingView *hostingView = (CPGraphHostingView *)self.view;
hostingView.collapsesLayers = YES;
hostingView.hostedGraph = graph;
hostingView.frame = self.view.frame;
//Create a blue plot area
CPScatterPlot *boundLinePlot = [[[CPScatterPlot alloc] init] autorelease];
boundLinePlot.dataLineStyle.miterLimit = 1.0f;
boundLinePlot.dataLineStyle.lineWidth = 1.0f;
UIColor* color = [UIColor orangeColor];
boundLinePlot.dataLineStyle.lineColor = [CPColor colorWithCGColor:[color CGColor]];
boundLinePlot.dataSource = self;
[graph addPlot:boundLinePlot];
}
- (void) customizeGraph{
if(graph)
{
graph.paddingLeft = 20.0;
graph.paddingTop = 20.0;
graph.paddingRight = 20.0;
graph.paddingBottom = 20.0;
CPScatterPlot *goalWeightPlot = [[[CPScatterPlot alloc] init] autorelease];
goalWeightPlot.identifier = kGoalWeightPlot;
//boundLinePlot.dataLineStyle.miterLimit = 5.0f;
goalWeightPlot.dataLineStyle.lineWidth = 1.0f;
goalWeightPlot.dataLineStyle.lineColor = [CPColor redColor];
goalWeightPlot.dataLineStyle.dashPattern = [NSArray arrayWithObjects:[NSNumber numberWithFloat:5.0],[NSNumber numberWithFloat:2.0],nil];
goalWeightPlot.dataSource = self;
[graph addPlot:goalWeightPlot];
// Create a blue plot area
CPScatterPlot *boundLinePlot = [[[CPScatterPlot alloc] init] autorelease];
boundLinePlot.identifier = kActualWeightPlot;
//boundLinePlot.dataLineStyle.miterLimit = 5.0f;
boundLinePlot.dataLineStyle.lineWidth = 1.0f;
boundLinePlot.dataLineStyle.lineColor = [CPColor orangeColor];
boundLinePlot.dataSource = self;
// Add plot symbols
CPLineStyle *symbolLineStyle = [CPLineStyle lineStyle];
symbolLineStyle.lineColor = [CPColor orangeColor];
CPPlotSymbol *plotSymbol = [CPPlotSymbol ellipsePlotSymbol];
plotSymbol.fill = [CPFill fillWithColor:[CPColor orangeColor]];
plotSymbol.lineStyle = symbolLineStyle;
plotSymbol.size = CGSizeMake(5.0, 5.0);
boundLinePlot.plotSymbol = plotSymbol;
[graph addPlot:boundLinePlot];
}
}
- (void) resetData{
dataForPlot = nil;
}
- (void) setGraphData:(NSArray*)graphData andRefrenceValue:(float)goalValue{
self.refereceValue = goalValue;
[self setGraphData:graphData];
}
- (void) setGraphData:(NSArray*)graphData{
//Check if we have any single weight entry in the array
if(graphData && [graphData count] > 0) {
[self prepareGraphData:graphData];
[self setRangeForGraph];
[graph reloadData];
}
}
- (NSArray *)sortedWeightEntriesByWeightDate:(NSArray *)unsortedArray {
NSMutableArray *tempArray = [NSMutableArray array];
for(int i=0;i<[unsortedArray count];i++) {
NSDateFormatter *df = [[NSDateFormatter alloc]init];
WeightEntry *entry = [unsortedArray objectAtIndex:i];
[df setDateFormat:#"yyyy-MM-dd"];
NSDate *date = [df dateFromString:entry.weightDate];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
if(date) {
[dict setObject:entry forKey:#"entity"];
[dict setObject:date forKey:#"date"];
[tempArray addObject:dict];
}
[df release];
}
NSInteger counter = [tempArray count];
NSDate *compareDate;
NSInteger index;
for(int i = 0 ; i < counter; i++) {
index = i;
compareDate = [[tempArray objectAtIndex:i] valueForKey:#"date"];
NSDate *compareDateSecond;
for(int j = i+1 ; j < counter; j++)
{
compareDateSecond=[[tempArray objectAtIndex:j] valueForKey:#"date"];
NSComparisonResult result = [compareDate compare:compareDateSecond];
if(result == NSOrderedDescending)
{
compareDate = compareDateSecond;
index=j;
}
}
if(i!=index)
[tempArray exchangeObjectAtIndex:i withObjectAtIndex:index];
}
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:0];
NSInteger counterIndex = [tempArray count];
for(int i = 0; i < counterIndex ; i++) {
[sortedArray addObject:[[tempArray objectAtIndex:i] valueForKey:#"entity"]];
}
return [NSArray arrayWithArray:sortedArray];
}
- (void) prepareGraphData:(NSArray*)data{
data = [self sortedWeightEntriesByWeightDate:data];
NSNumber* minYValue = nil;
NSNumber* maxYValue = nil;
NSMutableArray *contentArray = [NSMutableArray arrayWithCapacity:[data count]];
NSUInteger i;
for ( i = 0; i < [data count]; i++ ) {
WeightEntry* weightEntry = [data objectAtIndex:i];
if(i == 0){
maxYValue = [NSNumber numberWithFloat:weightEntry.weight];
minYValue = [NSNumber numberWithFloat:weightEntry.weight];
}
//id x = [NSNumber numberWithFloat:weightEntry.weight];
//id y = [NSNumber numberWithFloat:1.2*rand()/(float)RAND_MAX + 1.2];
id x = [NSNumber numberWithFloat:i];
id y = [NSNumber numberWithFloat:weightEntry.weight];
if([y floatValue] > [maxYValue floatValue])
maxYValue = y;
if([y floatValue] < [minYValue floatValue])
minYValue = y;
//[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, #"x", y, #"y",[NSNumber numberWithFloat:goalWeight],#"goalY",nil]];
[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, #"x", y, #"y",nil]];
}
self.dataForPlot = [NSArray arrayWithArray:contentArray];
[minYValues addObject:minYValue];
[maxYValues addObject:maxYValue];
lblHighValue.text = [NSString stringWithFormat:#"High = %0.2f", [maxYValue floatValue]];
lblLowValue.text = [NSString stringWithFormat:#"Low = %0.2f", [minYValue floatValue]];
lblRefrenceValue.text = [NSString stringWithFormat:#"Goal = %0.2f", self.refereceValue];
}
// Update the Plot Space Range to cover all graphs
- (void) setRangeForGraph{
NSNumber* minimumYValue;
NSNumber* maxmumYValue;
if([minYValues count] > 0 && [maxYValues count] > 0){
minimumYValue = [minYValues objectAtIndex:0];
maxmumYValue = [maxYValues objectAtIndex:0];
// Calculate minimum y value among all graphs.
for (int i = 0 ; i < [minYValues count] ; i++) {
if([[minYValues objectAtIndex:i] floatValue] < [minimumYValue floatValue])
minimumYValue = [minYValues objectAtIndex:i];
}
// Calculate maximum y value among all graphs.
for (int i = 0 ; i < [maxYValues count] ; i++) {
if([[maxYValues objectAtIndex:i] floatValue] > [maxmumYValue floatValue])
maxmumYValue = [maxYValues objectAtIndex:i];
}
NSDecimalNumber *high = [NSDecimalNumber decimalNumberWithDecimal:[maxmumYValue decimalValue]];
high = [high decimalNumberByAdding:[NSDecimalNumber decimalNumberWithString:#"30"]];
// Modify the y range for plot space to cover all values.
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0) length:[high decimalValue]];
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0) length:CPDecimalFromInt([self.dataForPlot count])];
CPPlotAreaFrame *area = (CPPlotAreaFrame *)graph.plotAreaFrame;
area.paddingLeft = 20;
area.paddingBottom = 10;
CPXYAxisSet *axisSet = (CPXYAxisSet*)graph.axisSet;
//axis.paddingLeft = 20.0;
axisSet.xAxis.paddingBottom = 50.0;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromInteger([self.dataForPlot count]);
CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength = CPDecimalFromFloat([high floatValue]);
axisSet.xAxis.orthogonalCoordinateDecimal = CPDecimalFromFloat([minimumYValue floatValue]);
//axisSet.xAxis.labelOffset = 0.0;
CPLineStyle *lineStyle = [CPLineStyle lineStyle];
lineStyle.lineColor = [CPColor colorWithCGColor:((UIColor*)kProtienColor).CGColor];
lineStyle.lineWidth = 1.0f;
// style the graph with white text and lines
CPTextStyle *whiteText = [CPTextStyle textStyle];
whiteText.color = [CPColor redColor];
//CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromString(#"1");
x.axisLineStyle = lineStyle;
//x.majorGridLineStyle=lineStyle;
//x.minorTicksPerInterval = 0;
//x.minorTickLineStyle = lineStyle;
x.title = #"Weight";
x.titleOffset = 3.0f;
x.titleLocation = CPDecimalFromFloat(3.0f);
x.titleTextStyle = whiteText;
x.labelTextStyle = whiteText;
//y.majorIntervalLength = CPDecimalFromString(#"150");
//y.minorTicksPerInterval = 10;
y.axisLineStyle = lineStyle;
y.title = #"Date";
y.titleTextStyle = whiteText;
y.titleOffset = 0;
y.minorTickLineStyle = lineStyle;
//y.titleLocation = CPDecimalFromFloat(graph.frame.origin.y+10);
//y.majorGridLineStyle=lineStyle;
//y.labelTextStyle=whiteText;
}
}
- (NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot {
int nofOfRecords = 0;
#try {
nofOfRecords = [self.dataForPlot count];
}
#catch (NSException * e) {
NSLog(#"Exception while calculating graph index : %#", [e description]);
}
#finally {
//NSLog(#"Number of Records : %d For Graph Index : %d", nofOfRecords, graphIndex);
return nofOfRecords;
}
}
- (NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSNumber *num = 0;
//int plotIndex = [(NSString *)plot.identifier intValue];
if([self.dataForPlot count] > 0){
if(![((NSString*)[plot identifier]) isEqualToString:kGoalWeightPlot]){
num = [[dataForPlot objectAtIndex:index] valueForKey:(fieldEnum == CPScatterPlotFieldX ? #"x" : #"y")];
}else {
if(fieldEnum == CPScatterPlotFieldX)
num = [[dataForPlot objectAtIndex:index] valueForKey:#"x"];
else {
num = [NSNumber numberWithFloat:self.refereceValue];
}
}
}
return num;
}
Screenshot -
I want to show custom labels on x-axis and default labels on y-axis.
EDIT:
I've tried adding sample class of barChart+XIB from CPTest-iPhoneApp. The bar chart appears but axis label's don't. Here is the screenshot form CPTest-iPhone app and mine.
CPXYAxis *yy = axisSet.yAxis;
yy.axisLineStyle.lineColor=[CPColor whiteColor];
yy.majorTickLineStyle = nil;
yy.minorTickLineStyle = nil;
yy.title = #"Y Axis";
yy.titleLocation = CPDecimalFromFloat(100.0f);
yy.titleOffset = 245.0f;
// Define some custom labels for the data elements
yy.labelingPolicy = CPAxisLabelingPolicyNone;
NSArray *customTickLocations1 = [NSArray arrayWithObjects:[NSDecimalNumber numberWithInt:0], [NSDecimalNumber numberWithInt:10],[NSDecimalNumber numberWithInt:20], [NSDecimalNumber numberWithInt:30], nil];
NSArray *yAxisLabels = [NSArray arrayWithObjects:#"a",#"b", #"c",nil];
NSUInteger labelLocation1 = 0;
NSMutableArray *customLabels1 = [NSMutableArray arrayWithCapacity:[yAxisLabels count]];
for (NSNumber *tickLocation1 in customTickLocations1)
{
CPAxisLabel *newLabel1 = [[CPAxisLabel alloc]
initWithText: [yAxisLabels objectAtIndex:labelLocation1++]
textStyle:yy.labelTextStyle];
newLabel1.tickLocation = [tickLocation1 decimalValue];
newLabel1.offset = yy.labelOffset + yy.majorTickLength;
[customLabels1 addObject:newLabel1];
[newLabel1 release];
}
yy.axisLabels = [NSSet setWithArray:customLabels1];
I have resolved my problem. All I have to do is start adding core-plot from beginning. I removed core-plot from my project again add voila! it's working