// // textConverter.m // Compass Screen // // Created by Jeremy on 7/4/08. // Copyright 2008 Stone Software. All rights reserved. // #import "textConverter.h" #import "Calculations.h" @implementation textConverter - (id)initWithString:(NSString*)str { self = [super init]; if (self != nil) { if (str != nil) [str retain]; else str = [[NSString alloc] init]; stringToParse = str; } return self; } - (id) init { self = [super init]; if (self != nil) { stringToParse = [self initWithString:nil]; } return self; } - (void) dealloc { if (stringToParse != nil) [stringToParse release]; [super dealloc]; } // returns if conversion was successful. passes back the degrees parsed from the val string. - (BOOL) hourMinuteDecimalToDegrees:(double*) degrees { double deg = 0; char temp[512]; char tempX[512]; char* ptr = temp; if (NO == [stringToParse getCString:temp maxLength:512 encoding:NSMacOSRomanStringEncoding]) { return NO; } // move to the numbers while (!isdigit(ptr[0])) { ptr++; } // get the primary non-decimal portion. int x = 0; do { tempX[x] = ptr[0]; ptr++; x++; } while (*ptr != kDividerCharacter && *ptr != 0); tempX[x] = 0; // null terminate ptr++; // now skip the delimiter. deg = atof(tempX); // combine deg with the float version of the remainder of the string. *degrees = deg + (atof(ptr) / 60); // degree + decimal minute degrees / 60 // convert deg to positive or negative depending on the string passed. if (NO == [Calculations directionIsPositiveDegree:stringToParse]) *degrees *= -1; return YES; } - (BOOL) decimalFromString:(double*) val { BOOL retVal = NO; char tempArray[512]; char buffer[512]; char prevChar = 0; int spaceCounter = -1; // cheat currently as I'm not cool enough to parse strings the obj-C way with NSScanner... seems busted? Probably jsut me. // verify that we can get a valid c string. if (NO == [stringToParse getCString:buffer maxLength:512 encoding:NSASCIIStringEncoding]) { // Maybe later add a dialog or something here to explain to the user why it doesn't like the input. For now ignore this. return retVal; } // remove all non-essential characters from the string, mushing things together. int len = 0; tempArray[0] = 0; // start with a blank cstring. for(unsigned int x = 0; x < strlen(buffer); x++) { buffer[x] = toupper(buffer[x]); // make sure it's uppercase. if (strchr(".-1234567890NESW ", buffer[x]) == nil) // if we don't find this character in our list of "good" characters, convert it to a space. { buffer[x] = ' '; } if (strchr(".-1234567890NESW ", buffer[x]) != nil) // if we find this character in our list of "good" characters, let it through. { if (buffer[x] == ' ' && prevChar == buffer[x]) continue; // skip multiple spaces in a row // after the initial NSEW, once we hit a digit, start counting the remaining spaces as dividers between segments. if (isdigit(buffer[x])) spaceCounter++; // if it's a space and we're counting spaces and we didn't just have a space. if (spaceCounter > -1 && buffer[x] == ' ' && prevChar != buffer[x]) buffer[x] = kDividerCharacter; if (buffer[x] != ' ' || (buffer[x] == ' ' && spaceCounter > -1)) { // append the string strncat(tempArray, &buffer[x], 1); prevChar = buffer[x]; len++; } } } // ensure this str is null terminated. tempArray[len] = 0; if (strlen(tempArray)) { if ([self isDegMin:tempArray]) { double theVal; // parse the deg min sec format here // How do you convert to Degrees, from Degrees:Minutes:Seconds? // The latitude and longitude are input in degrees, so you might need to convert to degrees from // degrees:minutes:seconds. There are 60 seconds in 1 minute and 60 minutes in 1 degree. So, for example: // // 65:45:36 south latitude converts to // // -(65 degrees + (45 minutes * (1 degree/60 minutes)) + (36 seconds * (1 minute/60 seconds) * (1 degree/60 minutes))) = -65.76 degrees latitude textConverter* converts = [[[textConverter alloc] initWithString:[NSString stringWithCString:tempArray encoding:NSMacOSRomanStringEncoding]] autorelease]; if (YES == [converts hourMinuteDecimalToDegrees:&theVal]) *val = theVal; else *val = 0.0; } // Assume decimal if its not [NESW] HH MM.MMM format for now. else //if ([self isDecimal:tempArray]) { // parse the decimal format here. if (tempArray[0] == 'N' || tempArray[0] == 'E') // north and east are positive. { int length = strlen(tempArray); memmove(&tempArray[0], &tempArray[1], strlen(&tempArray[1])); // skip the 'N' or 'E' tempArray[length - 1] = 0; // we are now 1 off since we skipped a char, so reduce our total length by one. } else if (tempArray[0] == 'S' || tempArray[0] == 'W') // south and west are negative. { tempArray[0] = '-'; } *val = atof(tempArray); } retVal = YES; } return retVal; } // - (BOOL) isDegMin:(char*)inStr { BOOL retVal = NO; if (strstr(inStr, "N") || strstr(inStr, "E") || strstr(inStr, "S") || strstr(inStr, "W")) { retVal = YES; } // check to see if the stringToParse has degree minute seconds return retVal; } - (BOOL) isDecimal:(char*)inStr { BOOL retVal = YES; // check to see if this is a decimal string return retVal; } @end