Reg locationmanager: didUpdateLocation - objective-c

Hi !!
I am new to Objective-C.
I am developing a tracker application, in which I have to store all the gps coordinates and then analyse them to track the path in which the vehicle was. I am using two arrays for storing the latitude and longitude points. When trying to use the Latitude points for calculations later, its giving me an error saying "Out of bound exception at index 1", but the size of the array is being shown to me as 4. Here is the code snippet of my ViewController.h, please take a look and let me know how I do this.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[trackingMapView addPoint:newLocation];
float time = -[startDate timeIntervalSinceNow];
displayLabel.text = [NSString stringWithFormat:#"Speed: %.02f mph", distance * 2.2369 / time];
// if there was a previous location
if (oldLocation != nil)
{
// add distance from the old location tp the total distance
distance += [newLocation getDistanceFrom:oldLocation];
}
// create a region centered around the new point
MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005);
// create a new MKCoordinateRegion centered around the new location
MKCoordinateRegion region = MKCoordinateRegionMake(newLocation.coordinate, span);
//New Added Code
CLLocationSpeed speed = newLocation.speed ;
speed = speed * 2.2369 ;
/* if (speed > 10.000)
{
NSString *message = #"Slow Down !!" ;
UIAlertView *alertforspeed = [[UIAlertView alloc] initWithTitle:#"Speed Monitor" message: message delegate:self cancelButtonTitle:#"Return" otherButtonTitles:nil];
[alertforspeed show];
[alertforspeed release];
}*/
//NEW CODE 2
//----------------------------------------------
arraywithlat= [[NSMutableArray alloc]init];
arraywithlong= [[NSMutableArray alloc]init];
NSNumber *lati = [NSNumber numberWithFloat:newLocation.coordinate.latitude];
NSNumber *longi = [NSNumber numberWithFloat:newLocation.coordinate.longitude];
[arraywithlat addObject:lati];
[arraywithlong addObject:longi];
//[locations addObject:newLocation];
NSLog(#"Array with lat : %#" , arraywithlat);
NSLog(#"Array with long: %#", arraywithlong);
//-----------------------------------------------
int i;
float r1 = 0.0, r2, result ;
NSLog(#"IN LANE TRACKING, BEFORE IFF");
int exsize = sizeof(arraywithlat);
NSLog(#"SIze of array before the loop: %d", exsize);
if (sizeof(arraywithlat) >= 4) {
NSLog(#"CROSSED THE IFFFFF");
NSLog(#"SIXE OF ARRAYWITHLAT: %lu" , sizeof(arraywithlat));
for (i = 0; i <= sizeof(arraywithlat); i++) {
NSNumber *tla1 = [arraywithlat objectAtIndex:i];
float temp1 = [tla1 floatValue];
NSLog(#"temp111111111: %f",temp1);
NSNumber *tla2 = [arraywithlat objectAtIndex:i+1] ;
float temp2 = [tla2 floatValue];
float r1 = temp1 - temp2 ;
// float r1 = [NSNumber numberWithFloat:tla2] - [NSNumber numberWithFloat:tla1];
//float r1 = [tla2 floatValue] - [tla1 floatValue];
r1 = r1 * r1 ;
//float tla = arraywithlat objectAtIndex: i+1) - (arraywithlat objectAtIndex: i);
//float tlo = [arraywithlong obj]
// float tr1 = powf(((arraywithlat objectAtIndex:(i+1))-([arraywithlat objectatIndex:(i)])), <#float#>)
}
}
NSLog(#"r1 after cal: %f",r1);
// reposition the map t show the new point
[mapView setRegion:region animated:YES];
}

I think your problem is here:
for (i = 0; i <= sizeof(arraywithlat); i++) {
NSNumber *tla1 = [arraywithlat objectAtIndex:i];
float temp1 = [tla1 floatValue];
NSLog(#"temp111111111: %f",temp1);
NSNumber *tla2 = [arraywithlat objectAtIndex:i+1] ;
float temp2 = [tla2 floatValue];
float r1 = temp1 - temp2 ;
// float r1 = [NSNumber numberWithFloat:tla2] - [NSNumber numberWithFloat:tla1];
//float r1 = [tla2 floatValue] - [tla1 floatValue];
r1 = r1 * r1 ;
//float tla = arraywithlat objectAtIndex: i+1) - (arraywithlat objectAtIndex: i);
//float tlo = [arraywithlong obj]
// float tr1 = powf(((arraywithlat objectAtIndex:(i+1))-([arraywithlat objectatIndex:(i)])), <#float#>)
}
first indexes in array starts from 0 to n-1, so i <= sizeof(arraywithlat) here wrong, i < sizeof(arraywithlat) should be.
And NSNumber *tla2 = [arraywithlat objectAtIndex:i+1] is wrong. change it, coz when i will be equal to n-1 then you get exception out of bound. And can you explain what does this loop, may be we help you to rewrite it
Also note that - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation method of delegate is deprecated. Use locationManager:didUpdateLocations: instead.

Related

Can not differentiate between data for plots, CorePlot

I am trying to plot 2 lines on 1 graph using CorePlot. Right now I am plotting the same data twice, I am not sure how to choose the other data source.
Any help would be appreciated.
Code:
graph view code .m:
CPTScatterPlot *limitplot = [[CPTScatterPlot alloc] init];
limitplot.dataSource = self;
limitplot.identifier = #"limplot";
limitplot.dataLineStyle = lineStylelimit;
limitplot.plotSymbol = plotSymbollimit;
[self.graph addPlot:limitplot];
CPTScatterPlot *calplot = [[CPTScatterPlot alloc] init];
calplot.dataSource = self;
calplot.identifier = #"plot";
calplot.dataLineStyle = lineStylecalc;
calplot.plotSymbol = plotSymbolcalc;
[self.graph addPlot:calplot];
}
// Delegate method that returns the number of points on the plot
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [plot.identifier isEqual:#"limplot"] )
{
return [self.graphData count];
}
else if ( [plot.identifier isEqual:#"plot"] )
{
return [self.graphData count];
}
return 0;
}
// Delegate method that returns a single X or Y value for a given plot.
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
if ( [plot.identifier isEqual:#"limplot"] )
{
NSValue *value = [self.graphData objectAtIndex:index];
CGPoint point = [value CGPointValue];
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithFloat:point.x];
}
else // Y-Axis
{
return [NSNumber numberWithFloat:point.y];
}
} else if ( [plot.identifier isEqual:#"plot"] )
{
NSValue *value = [self.graphData objectAtIndex:index];
CGPoint point = [value CGPointValue];
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithFloat:point.x];
}
else // Y-Axis
{
return [NSNumber numberWithFloat:point.y];
}
}
return [NSNumber numberWithFloat:0];
}
Data .m:
NSMutableArray *limitdata = [NSMutableArray array];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5477, 5400)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5292, 5400)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5053, 6425)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5029, 7154)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5138, 8300)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5503, 8300)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5570, 7100)]];
[limitdata addObject:[NSValue valueWithCGPoint:CGPointMake(5477, 5400)]];
self.lewis = [[TUTSimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:limitdata];
[self.lewis initialisePlot];
double cofullMass = [coTOMass doubleValue];
double cofullStation = [coTOstation doubleValue];
double coeeMass = [coEEmass doubleValue];
double coeeStation = [coEEstation doubleValue];
double cossMass = [coSSmass doubleValue];
double cossStation = [coSSstation doubleValue];
double codryMass = [coZmass doubleValue];
double codryStation = [coZstation doubleValue];
NSMutableArray *caldata = [NSMutableArray array];
[caldata addObject:[NSValue valueWithCGPoint:CGPointMake(cofullStation, cofullMass)]];
[caldata addObject:[NSValue valueWithCGPoint:CGPointMake(coeeStation, coeeMass)]];
[caldata addObject:[NSValue valueWithCGPoint:CGPointMake(cossStation, cossMass)]];
[caldata addObject:[NSValue valueWithCGPoint:CGPointMake(codryStation, codryMass)]];
self.lewis = [[TUTSimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:caldata];
[self.lewis initialisePlot];
You've got everything correct including testing the plot identifier and the fieldEnum. Once you determine which plot is asking for data, use that to choose the right data array instead of getting the count and data points from self.graphData for both plots.

BLE (iBeacons) Trilateration

I'm a student at the University of Furtwangen in Germany.
I am in my final term and I am writing my thesis now. I'm very interested in iBeacons and the technology behind them. My current project is to compare the beacon technology with other technologies like GPS, Wireless-location, GSM, and NFC. For my thesis, I will create different use-cases and compare the results.
Over the last few days I've tried to determine my position in a room. I use the relative distance (accuracy) from three beacons and gave every beacon a fixed position in my room.
I get three circles and calculate 6 intersections.
When a radian (accuracy) is too low I increase this value artificially. Then I look which of the 6 points (intersections) are the nearest. (The three nearest points)
With those points I get an triangle, and with this I calculate the middle point.
My problem is that the result is not really the best.
I found a better solution here:
https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points
but I have am having trouble implementing this in Objective C.
But I understand the solution. How can I import or get this in Objective C.
I found some libs (C, C++) but I'm not really sure which of these libs is the best.
The best solution for me will be a Objectice C math library which can calculate with these points (x1,x2,x3, -- ,y1,y2,y3, --- ,r1,r2,r3).
Graphic of my calculation now
I was struggling with the same problem, then I found this solution, written in python. I tried porting the code into objective-c and using the same case for testing and the result is accurate. I modified the code so it can accept 2-dimension vector as well.
The test case was :
P1 = (3,0) r1 = 6.4031
P2 = (9,0) r2 = 4.1231
P3 = (4,8) r3 = 5.6568
I ran this data through the code :
//P1,P2,P3 is the point and 2-dimension vector
NSMutableArray *P1 = [[NSMutableArray alloc] initWithCapacity:0];
[P1 addObject:[NSNumber numberWithDouble:3]];
[P1 addObject:[NSNumber numberWithDouble:0]];
NSMutableArray *P2 = [[NSMutableArray alloc] initWithCapacity:0];
[P2 addObject:[NSNumber numberWithDouble:9]];
[P2 addObject:[NSNumber numberWithDouble:0]];
NSMutableArray *P3 = [[NSMutableArray alloc] initWithCapacity:0];
[P3 addObject:[NSNumber numberWithDouble:4]];
[P3 addObject:[NSNumber numberWithDouble:8]];
//this is the distance between all the points and the unknown point
double DistA = 6.4031;
double DistB = 4.1231;
double DistC = 5.6568;
// ex = (P2 - P1)/(numpy.linalg.norm(P2 - P1))
NSMutableArray *ex = [[NSMutableArray alloc] initWithCapacity:0];
double temp = 0;
for (int i = 0; i < [P1 count]; i++) {
double t1 = [[P2 objectAtIndex:i] doubleValue];
double t2 = [[P1 objectAtIndex:i] doubleValue];
double t = t1 - t2;
temp += (t*t);
}
for (int i = 0; i < [P1 count]; i++) {
double t1 = [[P2 objectAtIndex:i] doubleValue];
double t2 = [[P1 objectAtIndex:i] doubleValue];
double exx = (t1 - t2)/sqrt(temp);
[ex addObject:[NSNumber numberWithDouble:exx]];
}
// i = dot(ex, P3 - P1)
NSMutableArray *p3p1 = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < [P3 count]; i++) {
double t1 = [[P3 objectAtIndex:i] doubleValue];
double t2 = [[P1 objectAtIndex:i] doubleValue];
double t3 = t1 - t2;
[p3p1 addObject:[NSNumber numberWithDouble:t3]];
}
double ival = 0;
for (int i = 0; i < [ex count]; i++) {
double t1 = [[ex objectAtIndex:i] doubleValue];
double t2 = [[p3p1 objectAtIndex:i] doubleValue];
ival += (t1*t2);
}
// ey = (P3 - P1 - i*ex)/(numpy.linalg.norm(P3 - P1 - i*ex))
NSMutableArray *ey = [[NSMutableArray alloc] initWithCapacity:0];
double p3p1i = 0;
for (int i = 0; i < [P3 count]; i++) {
double t1 = [[P3 objectAtIndex:i] doubleValue];
double t2 = [[P1 objectAtIndex:i] doubleValue];
double t3 = [[ex objectAtIndex:i] doubleValue] * ival;
double t = t1 - t2 -t3;
p3p1i += (t*t);
}
for (int i = 0; i < [P3 count]; i++) {
double t1 = [[P3 objectAtIndex:i] doubleValue];
double t2 = [[P1 objectAtIndex:i] doubleValue];
double t3 = [[ex objectAtIndex:i] doubleValue] * ival;
double eyy = (t1 - t2 - t3)/sqrt(p3p1i);
[ey addObject:[NSNumber numberWithDouble:eyy]];
}
// ez = numpy.cross(ex,ey)
// if 2-dimensional vector then ez = 0
NSMutableArray *ez = [[NSMutableArray alloc] initWithCapacity:0];
double ezx;
double ezy;
double ezz;
if ([P1 count] !=3){
ezx = 0;
ezy = 0;
ezz = 0;
}else{
ezx = ([[ex objectAtIndex:1] doubleValue]*[[ey objectAtIndex:2]doubleValue]) - ([[ex objectAtIndex:2]doubleValue]*[[ey objectAtIndex:1]doubleValue]);
ezy = ([[ex objectAtIndex:2] doubleValue]*[[ey objectAtIndex:0]doubleValue]) - ([[ex objectAtIndex:0]doubleValue]*[[ey objectAtIndex:2]doubleValue]);
ezz = ([[ex objectAtIndex:0] doubleValue]*[[ey objectAtIndex:1]doubleValue]) - ([[ex objectAtIndex:1]doubleValue]*[[ey objectAtIndex:0]doubleValue]);
}
[ez addObject:[NSNumber numberWithDouble:ezx]];
[ez addObject:[NSNumber numberWithDouble:ezy]];
[ez addObject:[NSNumber numberWithDouble:ezz]];
// d = numpy.linalg.norm(P2 - P1)
double d = sqrt(temp);
// j = dot(ey, P3 - P1)
double jval = 0;
for (int i = 0; i < [ey count]; i++) {
double t1 = [[ey objectAtIndex:i] doubleValue];
double t2 = [[p3p1 objectAtIndex:i] doubleValue];
jval += (t1*t2);
}
// x = (pow(DistA,2) - pow(DistB,2) + pow(d,2))/(2*d)
double xval = (pow(DistA,2) - pow(DistB,2) + pow(d,2))/(2*d);
// y = ((pow(DistA,2) - pow(DistC,2) + pow(i,2) + pow(j,2))/(2*j)) - ((i/j)*x)
double yval = ((pow(DistA,2) - pow(DistC,2) + pow(ival,2) + pow(jval,2))/(2*jval)) - ((ival/jval)*xval);
// z = sqrt(pow(DistA,2) - pow(x,2) - pow(y,2))
// if 2-dimensional vector then z = 0
double zval;
if ([P1 count] !=3){
zval = 0;
}else{
zval = sqrt(pow(DistA,2) - pow(xval,2) - pow(yval,2));
}
// triPt = P1 + x*ex + y*ey + z*ez
NSMutableArray *triPt = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < [P1 count]; i++) {
double t1 = [[P1 objectAtIndex:i] doubleValue];
double t2 = [[ex objectAtIndex:i] doubleValue] * xval;
double t3 = [[ey objectAtIndex:i] doubleValue] * yval;
double t4 = [[ez objectAtIndex:i] doubleValue] * zval;
double triptx = t1+t2+t3+t4;
[triPt addObject:[NSNumber numberWithDouble:triptx]];
}
NSLog(#"ex %#",ex);
NSLog(#"i %f",ival);
NSLog(#"ey %#",ey);
NSLog(#"d %f",d);
NSLog(#"j %f",jval);
NSLog(#"x %f",xval);
NSLog(#"y %f",yval);
NSLog(#"y %f",yval);
NSLog(#"final result %#",triPt);
I've tested by drawing on cartesian diagram using the test case data above, and got the result that the unknown point is located at (8,4), then testing using the code above and got the result (7.999978,4.000021710625001).
Then I did a second test using data :
P1 = (2,0) r1 = 5.831
P2 = (8,0) r2 = 5.831
P3 = (8,10) r3 = 5.831
The manual result is (5,5), and the result using the code is (5,5).
So, I believe the code is correct.

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.

Aligning CCMenu to a grid

Does anybody know the best practice approach to getting an array of CCMenuItems to align to a grid? This is a cocos2d question
For example :
int levelCount = 10;
CCMenu *menuArray = [CCMenu menuWithItems:nil];
for (int x = 1; x<=levelCount; x++) {
CCLOG(#"Creating level icon for Level %i", x);
[menuArray addChild:[CCMenuItemImage itemFromNormalImage:#"Button2n.png"
selectedImage:#"Button2s.png"
target:self
selector:#selector(onPlay:)]];
}
[menuArray alignToGridWouldbeGreat????!!!!];
[self addChild:menuArray];
I can align vertically, horizontally, in columns or rows however cannot wrap a column or row configuration.
Thanks in advance!
You just have to call one of the overloaded alignItemsInColumns or alignItemsInRows methods. For example if you have 15 menu items and you want 3 rows of 5 columns, do this:
CCMenu* menu = [CCMenu menuWithItems:...];
NSNumber* itemsPerRow = [NSNumber numberWithInt:5];
[menu alignItemsInColumns:itemsPerRow, itemsPerRow, itemsPerRow, nil];
The only down side is that there doesn't seem to be a way to set padding when aligning to a grid.
Ok, while not as flexible as I would like, I've got a decent enough solution for my purposes. Anyone else can feel free to use this code if they too find it useful.
//////// Put images (or whatever) for all levels in an array /////////
int levelCount = 15;
NSMutableArray* menuArray = [NSMutableArray arrayWithCapacity:levelCount];
for (int x = 1; x<=levelCount; x++) {
CCLOG(#"Creating level icon for Level %i", x);
CCMenuItemImage* item = [CCMenuItemImage itemFromNormalImage:#"Button2n.png"
selectedImage:#"Button2s.png"
target:self
selector:#selector(onPlay:)];
[menuArray addObject:item];
}
//////// arrange in a grid with specific number of columns /////////
CGSize screenSize = [CCDirector sharedDirector].winSize;
int columns = 5;
int spaceBetweenColumns = columns + 1;
int spacing = screenSize.width / spaceBetweenColumns;
CCLOG(#"screenWidth (%f) / columnsWithEdges (%i) = spacing = %i, ", screenSize.width, spaceBetweenColumns, spacing);
CGPoint currentDrawPoint = CGPointMake(0, screenSize.height - spacing); // start at the top
for (CCMenuItem *item in menuArray) {
currentDrawPoint.x = currentDrawPoint.x + spacing;
if (currentDrawPoint.x > (columns * spacing)) {
// start a new line as we have reached the end of the previous one
currentDrawPoint.x = spacing;
currentDrawPoint.y = currentDrawPoint.y - spacing;
}
item.position = currentDrawPoint;
[self addChild:item];
}
Here is my solution, i hope it helps.
First define this struct somewhere:
typedef struct
{
int cols;
}RowInfo;
Then:
-(void)layoutMenu:(CCMenu *)menu rowInfo:(RowInfo[])inf rows:(int)rows padding:(CGPoint)padding
{
CCMenuItem *dummy = (CCMenuItem *)[menu.children objectAtIndex:0];
int itemIndex = 0;
float w = dummy.contentSize.width;
float h = dummy.contentSize.height;
CGSize screenSize = [[CCDirector sharedDirector]winSize];
CCArray *items = [menu children];
float startX;
for (int i = rows - 1; i >=0; i--)
{
int colsNow = info[i].cols;
startX = (screenSize.width - (colsNow * w + padding.x * (colsNow - 1)))/2;
float y = i * (padding.y + h);
for (int j = 0; j < colsNow; j++)
{
CCMenuItem *item = (CCMenuItem *)[items objectAtIndex:itemIndex];
item.anchorPoint = ccp(0,0);
item.position = ccp(startX, y);
startX += padding.x + w;
itemIndex++;
}
}
}
The call goes like this(a custom keyboard):
//create custom keyboard
NSArray *captions = [NSArray arrayWithObjects:
#"Q", #"W", #"E", #"R", #"T", #"Y", #"U", #"I", #"O", #"P",
#"A", #"S", #"D", #"F", #"G",#"H", #"J", #"K", #"L",
#"Z", #"X", #"C", #"V", #"B", #"N", #"M", nil];
CCMenu *menu = [CCMenu menuWithItems:nil];
[self addChild:menu];
for (NSString *caption in captions)
{
CCLabelTTF *label = [CCLabelTTF labelWithString:caption fontName:#"Courier" fontSize:25];
CCMenuItemLabel *item = [CCMenuItemLabel itemWithLabel:label target:self selector:#selector(callDelegate:)];
[menu addChild:item];
}
RowInfo info[3] = {{7}, {9}, {10}}; //inverse order
[self layoutMenu:menu withRowInfo:info rows:3 padding:ccp(15, 15)];
May be you can try this....
[menuArray alignItemsVerticallyWithPadding:20.0];
or
[first_menu alignItemsHorizontallyWithPadding:20.0];
To the best of my knowledge Anish's answer is your best course of action. It would be the same as aligning to a grid and it is what I personally use. Just set your menu position and alignment padding and you should have what you are looking for.

[OBJ-C][iOS] Getting floating point from NSArray - Problem

I’ve recently stuck at a problem. Here is the thing, I’m trying to get a float object from NSArray that holds it, and all I can get is (null). Obviously not the thing that I want to receive. Look at the snippet of code:
h = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithFloat:1.0],[NSNumber numberWithFloat:1.0],[NSNumber numberWithFloat:1.0], nil];
x = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithFloat:1.0],[NSNumber numberWithFloat:2.0], nil];
y = [[NSMutableArray alloc] init];
int step = 15; // That is just a random value, will depend on size of h and x.
for (int i = 0; i < step; ++i) {
NSLog(#"step = %i", i);
NSMutableArray *xTemp = [[NSMutableArray alloc] initWithArray:x];
NSMutableArray *hTemp = [[NSMutableArray alloc] initWithArray:h];
for (int j = 0; j < 3; ++j) {
float xToMul = [[xTemp objectAtIndex:j] floatValue];
float hToMul = [[hTemp objectAtIndex:(j+i)] floatValue];
NSLog(#"xToMul = %#", xToMul);
NSLog(#"hToMul = %#", hToMul);
}
NSLog(#"\n");
}
And the resul is:
xToMul = (null)
hToMul = (null)
and all I need those values is to do some easy math.
Thanks.
M.R.
Here's your problem:
float xToMul = [[xTemp objectAtIndex:j] floatValue]; float hToMul = [[hTemp objectAtIndex:(j+i)] floatValue];
NSLog(#"xToMul = %#", xToMul); NSLog(#"hToMul = %#", hToMul);
%# is for objects that support -description. float is not an object at all. This code sends the float a -description message, which it can't respond to.
There's two ways to solve this.
The first is to make xToMul and hToMul objects instead of floats and keep the format string.
id xToMul = [xTemp objectAtIndex:j];
id hToMul = [hTemp objectAtIndex:(j+i)];
NSLog(#"xToMul = %#", xToMul);
NSLog(#"hToMul = %#", hToMul);
The second is to keep them as floats but fix the format string:
float xToMul = [[xTemp objectAtIndex:j] floatValue];
float hToMul = [[hTemp objectAtIndex:(j+i)] floatValue];
NSLog(#"xToMul = %f", xToMul);
NSLog(#"hToMul = %f", hToMul);
If you're planning to do math with the floats, you probably want to pick this option.
Another interesting point is this loop:
for (int j = 0; j < 3; ++j) {
This will step through j with three values: 0, 1 and 2. That corresponds to the first, second and third item in NSArray. You have two items in x and three in h. I'm guessing this is just a simplification of your original code, but in both cases it's one short. j of 2+1 will access the 4th item in h, and j of 2 will access the 3rd item in x.