public ConversionResults TryConvert(string str) { //some local variables int sign; //sign of the coordinate string[] DecimalBit, DdMmSs, DdMm; //arrays for splitting double Dd = 0, Mm = 0, Ss = 0, Mmm = 0, Sss = 0, Dec = 0; //parts of the coordinates char DecSeparator = char.Parse(GetDecimalSeparator()); //gets the current decimal separator Regex TempRegex; //regular expression object for 'on demand' patern matching ConversionResults results = new ConversionResults(); //Get the matched pattern string[] pattern; int ptrnnum = MatchPattern(str); if (ptrnnum != -1) { pattern = (string[])patterns[ptrnnum]; } else { pattern = new string[2]; pattern[0] = "Unknown"; pattern[1] = "No pattern matched"; } switch (pattern[0]) //pattern[0] holds patern name { default: //pattern not recognised results.PatternRecognised = false; results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments = "Coordinate pattern not recognised!"; break; case "Variation of DD.DDD": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetSign(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Remove all the unwanted stuff str = RemoveSign(str); str = RemoveWhiteSpace(str); //Since this is already a decimal degree no spliting is needed Dd = double.Parse(str); //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { results.ConversionComments = "Conversion successful."; Dec = sign * Dd; results.ConvertedCoord = Dec; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } break; case "Variation of DD(°|d)MM.MMM('|m)": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetSign(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Remove all the unwanted stuff str = RemoveSign(str); str = RemoveWhiteSpace(str); //do some further replacing //Replace degree symbol TempRegex = new Regex("(°|º|D|d)"); str = TempRegex.Replace(str, ":"); //remove minute symbol TempRegex = new Regex("(ʹ|'|M|m)"); str = TempRegex.Replace(str, ""); //Extract decimal part DecimalBit = str.Split(DecSeparator); //split degrees and minutes DdMm = DecimalBit[0].Split(':'); //extract values from the strings Dd = int.Parse(DdMm[0]); //Degrees if (DdMm.Length > 1)//Minutes { //check if the string is not empty if (DdMm[1] != "") { Mm = int.Parse(DdMm[1]); } } if (DecimalBit.Length > 1)//DecimalSeconds { //check if the string is not empty if (DecimalBit[1] != "") { Mmm = double.Parse(DecimalBit[1]) / Math.Pow(10, (DecimalBit[1].Length)); } } //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } if (Mm > 59) //minutes { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Minutes fall outside the range: MM > 59; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { Dec = sign * (Dd + (Mm + Mmm) / 60); //one more check to ensure a coord does not exceed 180 if (Dec > 180 | Dec < -180) { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Coordinate is either > 180 or < -180; "; } else { results.ConvertedCoord = Dec; results.ConversionComments = "Conversion successful."; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } } break; case "Variation of DD(°|d)MM(ʹ|m)SS.SSS(ʺ|s)": /* * Note: * This pattern allows the seconds to be specified with S, s or " or nothing at all * If the seconds are marked with "s" and there is no other indication of the hemisphere * the coordinate will be parsed as southern (negative). * * If the N / E / W / + indicator is found the coordinate will be parsed appropriately no matter * what is the second notation */ //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetSign(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Remove all the unwanted stuff str = RemoveSign(str); str = RemoveWhiteSpace(str); //remove second symbol (s is removed by the get sign method) //double apostrophe is not removed here as single apostrphe may mark minutes! //it's taken care of later after extracting the decimal part TempRegex = new Regex("(ʺ|\")"); str = TempRegex.Replace(str, ""); //do some further replacing //Replace degree symbol TempRegex = new Regex("(°|º|D|d|ʹ|'|M|m)"); str = TempRegex.Replace(str, ":"); //Extract decimal part DecimalBit = str.Split(DecSeparator); //remove : from the decimal part [1]! This is needed when a double apostrophe was used to mark seconds if (DecimalBit.Length > 1) { DecimalBit[1].Replace(":", ""); } //split degrees and minutes DdMmSs = DecimalBit[0].Split(':'); //extract values from the strings Dd = int.Parse(DdMmSs[0]); //Degrees if (DdMmSs.Length > 1)//Minutes { //check if the string is not empty if (DdMmSs[1] != "") { Mm = int.Parse(DdMmSs[1]); } } if (DdMmSs.Length > 2)//Seconds { //check if the string is not empty if (DdMmSs[2] != "") { Ss = int.Parse(DdMmSs[2]); } } if (DecimalBit.Length > 1)//DecimalSeconds { //check if the string is not empty if (DecimalBit[1] != "") { Sss = double.Parse(DecimalBit[1]) / Math.Pow(10, (DecimalBit[1].Length)); } } //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } if (Mm > 59) //minutes { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Minutes fall outside the range: MM > 59; "; } if (Ss > 59) //seconds { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Seconds fall outside the range: MM >= 60; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { results.ConversionComments = "Conversion successful."; Dec = sign * (Dd + Mm / 60 + (Ss + Sss) / 3600); //one more check to ensure a coord does not exceed 180 if (Dec > 180 | Dec < -180) { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Coordinate is either > 180 or < -180; "; } else { results.ConvertedCoord = Dec; results.ConversionComments = "Conversion successful."; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } } break; case "Variation of DD:MM:SS.SSS": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetSign(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Remove all the unwanted stuff str = RemoveSign(str); str = RemoveWhiteSpace(str); //Do some splitting DecimalBit = str.Split(DecSeparator); DdMmSs = DecimalBit[0].Split(':'); //extract values from the strings Dd = int.Parse(DdMmSs[0]); //Degrees if (DdMmSs.Length > 1)//Minutes { //check if the string is not empty if (DdMmSs[1] != "") { Mm = int.Parse(DdMmSs[1]); } } if (DdMmSs.Length > 2)//Seconds { //check if the string is not empty if (DdMmSs[2] != "") { Ss = int.Parse(DdMmSs[2]); } } if (DecimalBit.Length > 1)//DecimalSeconds { //check if the string is not empty if (DecimalBit[1] != "") { Sss = double.Parse(DecimalBit[1]) / Math.Pow(10, (DecimalBit[1].Length)); } } //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } if (Mm > 59) //minutes { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Minutes fall outside the range: MM > 59; "; } if (Ss > 59) //seconds { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Seconds fall outside the range: MM >= 60; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { results.ConversionComments = "Conversion successful."; Dec = sign * (Dd + Mm / 60 + (Ss + Sss) / 3600); //one more check to ensure a coord does not exceed 180 if (Dec > 180 | Dec < -180) { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Coordinate is either > 180 or < -180; "; } else { results.ConvertedCoord = Dec; results.ConversionComments = "Conversion successful."; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } } break; //-------------Customs patterns start here------------- case "Custom variation of DD.DDD": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetCustomSign(str); //Remove all the unwanted stuff //Note: This method also replaces the symbols with ":" //Note: In certain cases it may make the coord unparsable str = RemoveCustomPatternParts(str); str = RemoveWhiteSpace(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //remove the ":" here as it is not needed here for decimal degrees str = str.Replace(":", ""); try { //Since this is already a decimal degree no spliting is needed Dd = double.Parse(str); } catch { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments = "It looks like the supplied pattern has some ambiguous elements and the parser was unable to parse the coordinate." + "<br/>If the supplied symbols used for marking degrees, minutes or seconds contain hemisphere indicators, " + "the parser is likely to fail or yield rubbish results even though the pattern itself has been recognised." ; //exit method return results; } //Since this is already a decimal degree no spliting is needed Dd = double.Parse(str); //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { results.ConversionComments = "Conversion successful."; Dec = sign * Dd; results.ConvertedCoord = Dec; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } break; case "Custom variation of DD:MM.MMM": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetCustomSign(str); //Remove all the unwanted stuff //Note: This method also replaces the symbols with ":" //Note: In certain cases it may make the coord unparsable str = RemoveCustomPatternParts(str); str = RemoveWhiteSpace(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Extract decimal part DecimalBit = str.Split(DecSeparator); //split degrees and minutes DdMm = DecimalBit[0].Split(':'); try { //extract values from the strings Dd = int.Parse(DdMm[0]); //Degrees if (DdMm.Length > 1)//Minutes { //check if the string is not empty if (DdMm[1] != "") { Mm = int.Parse(DdMm[1]); } } if (DecimalBit.Length > 1)//DecimalSeconds { //check if the string is not empty if (DecimalBit[1] != "") { //replace the ":" if any (may be here as a result of custom symbol replacement DecimalBit[1] = DecimalBit[1].Replace(":", ""); Mmm = double.Parse(DecimalBit[1]) / Math.Pow(10, (DecimalBit[1].Length)); } } } catch { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments = "It looks like the supplied pattern has some ambiguous elements and the parser was unable to parse the coordinate." + "<br/>If the supplied symbols used for marking degrees, minutes or seconds contain hemisphere indicators, " + "the parser is likely to fail or yield rubbish results even though the pattern itself has been recognised." ; //exit method return results; } //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } if (Mm > 59) //minutes { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Minutes fall outside the range: MM > 59; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { Dec = sign * (Dd + (Mm + Mmm) / 60); //one more check to ensure a coord does not exceed 180 if (Dec > 180 | Dec < -180) { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Coordinate is either > 180 or < -180; "; } else { results.ConvertedCoord = Dec; results.ConversionComments = "Conversion successful."; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } } break; case "Custom variation of DD:MM:SS.SSS": //Pattern matched results.PatternRecognised = true; //Matching pattern succeeded so intialy the parsing is ok results.ConversionSuccessful = true; //pattern info results.PatternType = pattern[0]; results.PatternMatched = pattern[1]; //get sign sign = GetCustomSign(str); //Remove all the unwanted stuff //Note: This method also replaces the symbols with ":" //Note: In certain cases it may make the coord unparsable str = RemoveCustomPatternParts(str); str = RemoveWhiteSpace(str); //Replace comma or dot with a current decimal separator str = FixDecimalSeparator(str); //Extract decimal part DecimalBit = str.Split(DecSeparator); //split degrees and minutes DdMmSs = DecimalBit[0].Split(':'); try { //extract values from the strings Dd = int.Parse(DdMmSs[0]); //Degrees if (DdMmSs.Length > 1)//Minutes { //check if the string is not empty if (DdMmSs[1] != "") { Mm = int.Parse(DdMmSs[1]); } } if (DdMmSs.Length > 2)//Seconds { //check if the string is not empty if (DdMmSs[2] != "") { Ss = int.Parse(DdMmSs[2]); } } if (DecimalBit.Length > 1)//DecimalSeconds { //check if the string is not empty if (DecimalBit[1] != "") { Sss = double.Parse(DecimalBit[1]) / Math.Pow(10, (DecimalBit[1].Length)); } } } catch { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments = "It looks like the supplied pattern has some ambiguous elements and the parser was unable to parse the coordinate." + "<br/>If the supplied symbols used for marking degrees, minutes or seconds contain hemisphere indicators, " + "the parser is likely to fail or yield rubbish results even though the pattern itself has been recognised." ; //exit method return results; } //do some additional checking if the coords fall into the range if (Dd < -180 | Dd > 180)//degree may require another param specifying whether it's lat or lon... { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Degrees fall outside the range: DD < -180 | DD > 180; "; } if (Mm > 59) //minutes { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Minutes fall outside the range: MM > 59; "; } if (Ss > 59) //seconds { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Seconds fall outside the range: MM >= 60; "; } //Do the conversion if everything ok if (results.ConversionSuccessful) { results.ConversionComments = "Conversion successful."; Dec = sign * (Dd + Mm / 60 + (Ss + Sss) / 3600); //one more check to ensure a coord does not exceed 180 if (Dec > 180 | Dec < -180) { results.ConversionSuccessful = false; results.ConvertedCoord = 99999; //this is to mark an error... results.ConversionComments += "Coordinate is either > 180 or < -180; "; } else { results.ConvertedCoord = Dec; results.ConversionComments = "Conversion successful."; //Check whether the coordinate exceeds +/- 90 and mark it in comments if (Dec <= 90 & Dec >= -90) { results.CanBeLat = true; } } } break; } //do the self check here results = selfTest(results); //return conversion results return results; }
private ConversionResults selfTest(ConversionResults results) { ConversionResults newresults = results; if (results.ConversionSuccessful != false) { int sign = 1; if (Math.Sign(results.ConvertedCoord) < 0) { sign = -1; } double decimalDegrees = sign * results.ConvertedCoord; int fullDegrees; double decimalMinutes; int fullMinutes; double decimalSeconds; int fullSeconds; //Get full degrees fullDegrees = (int)Math.Floor(decimalDegrees); //get minutes decimalMinutes = (decimalDegrees - fullDegrees) * 60; fullMinutes = (int)Math.Floor(decimalMinutes); decimalSeconds = (decimalMinutes - fullMinutes) * 60; fullSeconds = (int)Math.Floor(decimalSeconds); //save the test results newresults.Dd = fullDegrees; newresults.Mm = fullMinutes; newresults.Mmm = decimalSeconds; newresults.Ss = fullSeconds; newresults.Sss = decimalSeconds; } return newresults; }