Load coordinates from text-file into NSMutableArray - objective-c

Im generating a plain txt file from Physics editor. It contains all the vertices for my polygon. Because I want my polygon to be textured, im running it through a triangulation method located at: https://github.com/asinesio/cocos2d-PRKit/
And I need my data to come from an NSMutableArray to doso for it to work.
Physics editor can export .plist and .txt files, but for simplicity sake, I just want to get the vertices from the .txt file and turn them into CGPoints and then add them into a NSMutableArray
The txt file looks like this:
(53.4011993408203, -44.4011993408203)
, (74.4011993408203,
-38.4011993408203) , (-0.598802387714386,
0.598802387714386) , (-0.598802387714386,
-39.4011993408203) , ...
I think the method would be to:
Load the data from its source.
Scan the data excluding parenthesis and alphbetical characters.
Take all the data upto the comma and add it into the CGPoint (x(1),y(0)).
Then scan all the data upto the next comma and insert it into the CGPoint (x(1),y(1)).
Then add this CGPoint to a NSMutableArray.
Continue scanning the document until all coordinates have been added.
This method could then be used with different text-files to create simplicity. Etc:
Level1ground.txt, Level2ground.txt.. It would be fantastic if I could get it running.
Could someone please help me with this?
Much Appreciated,
Oliver.

This solution assumes that you have loded the file already into a string.
You can make use of pathForResource:ofType:inDirectory: of NSBundle class to load a file.
NSArray * rawPoints = [#"(53.4011993408203, -44.4011993408203) , (74.4011993408203, -38.4011993408203) , (-0.598802387714386, 0.598802387714386) , (-0.598802387714386, -39.4011993408203)" componentsSeparatedByString:#" , "];
for (NSString * rawPoint in rawPoints) {
NSString *tmp = [rawPoint stringByReplacingOccurrencesOfString:#"(" withString:#""];
tmp = [tmp stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSArray * coordinates = [tmp componentsSeparatedByString:#", "];
CGPoint point;
for (NSString * coordinate in coordinates) {
point = CGPointMake([[coordinates objectAtIndex:0] floatValue],
[[coordinates objectAtIndex:1] floatValue]);
}
NSLog(#"x:%f, y:%f", point.x, point.y);
}

In this case, you probably want to use an NSScanner instance. See -scanUpToCharactersInSet: and -scanFloat.

Related

How can I handle this in cocoa? Retrieve an entry from a plist file?

I have this small excel file given by a brazilian government authority, it contains records for each city in Brazil, a ZIP Code range for each city and its "city code" .
I need to retrieve for a given city its "city code".
I imagine the best way would be to parse a given zip code for the city and return its "city code", based on the first two columns that display the zip code range.
I am confident that using AppleScript I can compile a plist file for the given Excel file. But can someone point me for a few lines of objectiveC code to retrieve the given entry from a plist file once I parse the ZIP code?
Please see excel file at http://www.idanfe.com/dl/codes.xls.zip
Thanks.
I have uploaded a sample plist file to http://www.idanfe.com/dl/cityCodes.plist
Further explanation:
I will parse a ZIP CODE value like: 01123010 which is in the range of 01001000 and 05895490, so my routines should return me City Code = 3550308 and City Name = São Paulo.
I have no idea how to achieve this, I might have built the sample plist wrong.
I am confident I can build a plist file using AppleScript, reading from the Excel sheet.
But retrieving the City code for a given ZIP CODE range is a puzzle.
+++ EDIT: +++
I think I have solved it, but it looks kind of clumsy, as almost everything I write.
This AppleScript reads the Excel sheet and writes the plist file : http://www.idanfe.com/dl/creating.scpt.zip
Here you find the 1 MB plist file: http://www.idanfe.com/dl/cityCodes.plist.zip
This is the code I wrote to get the City Code I need:
NSString *zipCodeString;
zipCodeString = #"99990000";
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"cityCodes" ofType:#"plist"];
NSDictionary *cityCodes_dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSArray *allKeys = [cityCodes_dictionary allKeys];
int i = 0;
for (i = 0 ; i <= [allKeys count]; i++) {
NSString *someKey = [allKeys objectAtIndex:i];
NSRange range08 = NSMakeRange (0, 8);
NSRange range88 = NSMakeRange (8, 8);
NSString *startZipCode = [someKey substringWithRange:range08];
NSString *finalZipCode = [someKey substringWithRange:range88];
int startZipCodeInt = [startZipCode intValue];
int finalZipCodeInt = [finalZipCode intValue];
if(startZipCodeInt <= [zipCodeString intValue] && finalZipCodeInt >= [zipCodeString intValue]){
NSLog(#"we found a winner");
NSString *cityCode = [NSString stringWithFormat: #"%#",[[cityCodes_dictionary objectForKey:someKey]objectForKey:#"City Code"]];
[cityCodeIBGEField setStringValue:cityCode];
NSLog(#"cityCode = %#",cityCode);
break;
} else {
// NSLog(#"no winners");
}
}
Basically I append the start zipCode and finalZip Code into one string of 16 digits, so I create one single record in the plist file.
Then when searching for the City Code I break the long key (2 zip codes) in 2 (back to normal zipCode) and search to see which record fits the given zipCode I need a cityCode for.
Some how it doesn't look the best for me, but for my own surprise the code is very fast, although in a loop.
I would appreciate comments...
Thanks,
I would use indexOfObjectPassingTest: to do this kind of search. Something like this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"cityCodes" ofType:#"plist"];
self.cityCodes_dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
[self findCityWithZip:#"01123010"];
}
-(void)findCityWithZip:(NSString *) searchZip {
NSUInteger indx = [self.cityCodes_dictionary.allKeys indexOfObjectPassingTest:^BOOL(NSString *zip, NSUInteger idx, BOOL *stop) {
NSString *startZipCode = [zip substringWithRange:NSMakeRange(0, 8)];
NSString *finalZipCode = [zip substringWithRange:NSMakeRange(8, 8)];
return (searchZip.integerValue < finalZipCode.integerValue && searchZip.integerValue > startZipCode.integerValue);
}];
NSLog(#"%#",[self.cityCodes_dictionary valueForKey:[self.cityCodes_dictionary.allKeys objectAtIndex:indx]]);
}
Reading the plist shouldn't be a problem at all if it is structured as a dictionary:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: #"cities.plist"];
//NSString *zipStr = [dict valueForKey: #"CityNme"]; //this was an example
That's the easy part. The harder part is parsing and structuring the plist file from an xls file.
Or did I misunderstand your question?
PS: to get a quick look at the dictionary's plist structure, create a mock dictionary and NSLog it's description to see how it's supposed to be (or writeToFile to see the file contents or of course refer to the docs)
edit
You load the supplied plist file in a dictionary using the above code. Then you retrieve another dictionary from within it using
NSDictionary *city = [dict valueForKey : #"yourZipCodeHere"];
From that dictionary you get the cityCode like this
NSString *cityCode = [city valueOrKey: #"City Code"];
As for your range problem, I'm not sure I understand it completely. But you can get an array of all the zip codes using
NSArray *zipArray = [dict allKeys];
And then you can simply iterate over that to get the correct zip code.
PS: I don't know much apple script and would be interested in how you converted the xls to plist using it.

Not showing smily ( Emoji ) in in UITextView in iOS?

I have stored all uni-codes(emoji characters) in plist supported by iphone. When i write directly as
- (IBAction)sendButtonSelected:(id)sender {
NSMutableArray *emoticonsArray = [[NSMutableArray alloc]initWithObjects:#"\ue415",nil];
NSString *imageNameToPass = [NSString stringWithFormat:#"%#",[emoticonsArray objectAtIndex:0]];
NSLog(#"imageNameToPass1...%#",imageNameToPass);
messageTextView.text =imageNameToPass;
}
it show emoji in textview but as soon as i fetch from plist
NSString *plistPath1 = [[NSBundle mainBundle] pathForResource:#"unicodes" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath1];
activeArray= [dictionary objectForKey:categoryString];
NSLog(#"activeArray...%#",activeArray);
emoticonsArrayForHomeEmoji = [[NSMutableArray alloc]initWithCapacity:[activeArray count]];
for(int i=0; i<[activeArray count]; i++)
{
id objects = (id)[activeArray objectAtIndex:i];
[emoticonsArrayForHomeEmoji insertObject:objects atIndex:i];
}
NSString *imageNameToPass = [NSString stringWithFormat:#"%#",[emoticonsArrayForHomeEmoji
objectAtIndex:0]];
NSLog(#"imageNameToPass1...%#",imageNameToPass);
messageTextView.text =imageNameToPass;
then it shows unicode as text \ue415 in text view instead of emoji.
What i am doing wrong?. Please help me out!
Wel said by #AliSoftware, the Plist data will be read as-it is, so you can add the emojis to your plist by following this steps:
1) Go to your top bar, and click on Edit.
2) Now select Special Characters
3) Now drag and drop emoji to plist.
For more details I am adding snap shots. take a look at it.
The \uxxxx notation is only interpreted by the compiler (as the source code is usually in ASCII or MacRoman or whatever but not often UTF8)
Plist files uses the characters directly, and are encoded in UTF8.
So you should insert the emoji character itself into the plist directly, instead of using the \uxxxx notation, as the Plist data will be read as-is.
Lion and Mountain Lion Keyboard palettes contains emoji characters directly, so that should not be difficult to insert the characters when editing the PLIST anyway.

getting NSArray length/count - Objective C

Well I've looked at similar problems over the site but haven't reached a solution thus far so I must be doing something wrong.
Essentially, I am importing a text file, then splitting each line into an element of an array. Since the text file will be updated etc.. I won't every know the exact amount of lines in the file and therefore how many elements in the array. I know in Java you can do .length() etc.. and supposedly in Objective C you can use 'count' but i'm having no luck returning the length of my array... suggestions?
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"allshows"
ofType:#"txt"];
NSString *fileString = [NSString stringWithContentsOfFile:filePath];
NSArray *lines = [fileString componentsSeparatedByString:#"\n"];
NSUInteger *elements = [lines count];
NSLog(#"Number of Shows : ", elements);
and what is being output is NOTHING. as in "Number of Shows : " - blank, like it didn't even count at all.
Thank you for any help!
You're missing the format string placeholder. It should be:
NSLog(#"Number of shows: %lu", elements);
You need to use a format specifier to print an integer (%d):
NSLog(#"Number of Shows : %d", elements);
Looking at your other post, it seems like you are a Java developer. In Java's System.out, you just append the variables. In Objective-C, I suggest you look at "print format specifiers". Objective-C uses the same format.

Using CGPoints in an NSArray

I have been trying to create an array stating the location of a UIImageView in an app I've been working on. What I am trying to do is by using an array I can store the location of my "player" image by using its x,y and z coordinates. The script I am trying to accomplish would look like
NSArray *location[3];
-(IBAction)startup;{
[location addObject: player.center.x];
[location addObject: player.center.y];
[location addObject: playerheight];
}
So I will be able to access this array to move my "player" on the screen in "3-dimensions", but I don't know how to convert the CGpoint values to NSValues so they can be used in the array, is there a simple way to do this inside of the array?
To convert floating point values to objects, use NSNumber. NSValue has wrappers for geometric types like CGPoint. Either would work for you.
[NSValue valueWithCGPoint:player.center];
[NSNumber numberWithFloat:player.center.x];
[NSNumber numberWithFloat:player.center.y];
To addition for the first answer.
When you'll need to read CGPoint back from your array, you can use something like that:
CGPoint point = [(NSValue *)[pointsArray objectAtIndex:i] CGPointValue];
Also note that there's no addObject method for NSArray (you can't add objects to an NSArray after its been created); you want NSMutableArray.
Instead of:
NSArray *location[3];
you probably want something more like:
NSMutableArray *location = [NSMutableArray arrayWithCapacity:3];
Does it have to be an NSArray? Why not use an array of structs?
typedef struct {
CGPoint location;
CGFloat height;
} PlayerLocation;
PlayerLocation players[3];
players[0].location = player.center;
players[0].height = playerheight;
Or depending on your design it may make more sense to declare an objective-C class that contains the x,y,z coordinates as ivars and store those objects into an NSArray.
#interface PlayerLocation : NSObject {
CGPoint location;
CGFloat height;
}
#end

Comparing Touch Coordinates

Is it possible to compare touch coordinates made by the users on the UIView to the one store in a plist or txt format? The argument looks like this;
if (user touch coordinate == touch coordinate stored in plist or text)
then
(do something)
else
(do something)
If possible in what format should i write the coordinates in the list and how to associate it inside the program?
thanks in advance and sorry if you find my question a bit noobie.
Not sure if there's a one-liner solution.
On a UITouch instance, the locationInView: method returns a CGPoint struct (x and y coordinates, both of type float). So you can store the x and y coordinates in your plist, then compare them with your current touch's x and y coordinates.
EDIT:
Also, when comparing the coordinates, you probably want to use the distance between the two points to determine when you have a "hit".
EDIT:
Below is sample code for loading and writing to a property list, where the values are based on a NSDictionary:
- (NSMutableDictionary *)loadDictionaryFromPList: (NSString *)plistName
{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
NSDictionary *immutableDictionary = [NSDictionary dictionaryWithContentsOfFile: plistPath];
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary: immutableDictionary];
return mutableDictionary;
}
- (void)saveDictionary: (NSDictionary *)mySettings toPList: (NSString *)plistName
{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
[mySettings writeToFile: plistPath atomically: YES];
}
The method to calculate the distance between the two locations of the UITouches:
-(CGFloat) distanceBetween: (CGPoint) point1 and: (CGPoint)point2
{
CGFloat dx = point2.x - point1.x;
CGFloat dy = point2.y - point1.y;
return sqrt(dx*dx + dy*dy );
}
And finally, the code that uses the values in the property list to determine if the user hit the previous location:
CGPoint currentTouchLocation = [currentTouch locationInView:self];
// Lookup last Touch location from plist, and handle case when current Touch matches it:
NSMutableDictionary *mySettings = [self loadDictionaryFromPList: #"MySettings"];
NSNumber *lastXCoordinate = [mySettings objectForKey:#"lastXCoordinate"];
NSNumber *lastYCoordinate = [mySettings objectForKey:#"lastYCoordinate"];
if (lastXCoordinate && lastYCoordinate)
{
CGPoint lastTouchLocation = CGPointMake([lastXCoordinate floatValue], [lastYCoordinate floatValue]);
CGFloat distanceBetweenTouches = [self distanceBetween: currentTouchLocation and: lastTouchLocation];
if (distanceBetweenTouches < 25) // 25 is just an example
{
// Handle case where current touch is close enough to "hit" previous one
NSLog(#"You got a hit!");
}
}
// Save current touch location to property list:
[mySettings setValue: [NSNumber numberWithFloat: currentTouchLocation.x] forKey: #"lastXCoordinate"];
[mySettings setValue: [NSNumber numberWithFloat: currentTouchLocation.y] forKey: #"lastYCoordinate"];
[self saveDictionary:mySettings toPList: #"MySettings"];
The functions you're probably looking for are NSStringFromCGPoint() and CGPointFromString().
But two touch coordinates will almost certainly never be the exact same. You should almost never be comparing CGFloats with ==, let alone ones you get from such an analog input as a finger touch. You need to compare whether they are "close enough." See this blog for a good example of how to measure the distance between two points. You want that result to be less than some value (epsilon, or "a small number") that is appropriate for your purposes.