Lat-lon parsing: allow lon,lat order, and detect order
Flightplan/route-manager defaults to lon,lat order. Allow the parser to detect the correct order when NSEW suffixes are provided and consistent.
This commit is contained in:
parent
609ac93c10
commit
d7a413d5e7
@ -1179,7 +1179,21 @@ bool parseStringAsLatLonValue(const std::string& s, double& degrees)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseStringAsGeod(const std::string& s, SGGeod* result)
|
namespace {
|
||||||
|
bool isLatString(const std::string &s)
|
||||||
|
{
|
||||||
|
const char lastChar = ::toupper(s.back());
|
||||||
|
return (lastChar == 'N') || (lastChar == 'S');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLonString(const std::string &s)
|
||||||
|
{
|
||||||
|
const char lastChar = ::toupper(s.back());
|
||||||
|
return (lastChar == 'E') || (lastChar == 'W');
|
||||||
|
}
|
||||||
|
} // of anonymous namespace
|
||||||
|
|
||||||
|
bool parseStringAsGeod(const std::string& s, SGGeod* result, bool assumeLonLatOrder)
|
||||||
{
|
{
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
return false;
|
return false;
|
||||||
@ -1189,16 +1203,27 @@ bool parseStringAsGeod(const std::string& s, SGGeod* result)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double lat, lon;
|
auto termA = simplify(s.substr(0, commaPos)),
|
||||||
if (!parseStringAsLatLonValue(s.substr(0, commaPos), lat) ||
|
termB = simplify(s.substr(commaPos+1));
|
||||||
!parseStringAsLatLonValue(s.substr(commaPos+1), lon))
|
double valueA, valueB;
|
||||||
{
|
if (!parseStringAsLatLonValue(termA, valueA) || !parseStringAsLatLonValue(termB, valueB)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
*result = SGGeod::fromDeg(lon, lat);
|
// explicit ordering
|
||||||
|
if (isLatString(termA) && isLonString(termB)) {
|
||||||
|
*result = SGGeod::fromDeg(valueB, valueA);
|
||||||
|
} else if (isLonString(termA) && isLatString(termB)) {
|
||||||
|
*result = SGGeod::fromDeg(valueA, valueB);
|
||||||
|
} else {
|
||||||
|
// implicit ordering
|
||||||
|
// SGGeod wants longitude, latitude
|
||||||
|
*result = assumeLonLatOrder ? SGGeod::fromDeg(valueA, valueB)
|
||||||
|
: SGGeod::fromDeg(valueB, valueA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,8 +367,19 @@ namespace simgear {
|
|||||||
*
|
*
|
||||||
* Supported formats:
|
* Supported formats:
|
||||||
* <signed decimal degrees latitude>,<signed decimal degress longitude>
|
* <signed decimal degrees latitude>,<signed decimal degress longitude>
|
||||||
|
* <unsigned decimal degrees>[NS],<unsigned decimal degrees>[EW]
|
||||||
|
* <degrees>*<decimal minutes>'[NS],<degrees>*<decimal minutes>'[EW]
|
||||||
|
*
|
||||||
|
* Latitude and longitude are parsed seperately so the formats for each
|
||||||
|
* do not need to agree. Latitude is assumed to precede longitude
|
||||||
|
* unless assumeLonLatOrder = true
|
||||||
|
*
|
||||||
|
* When NSEW characters are used, the order can be swapped and will be
|
||||||
|
* fixed correctly (longitude then latitude).
|
||||||
*/
|
*/
|
||||||
bool parseStringAsGeod(const std::string& string, SGGeod* result = nullptr);
|
bool parseStringAsGeod(const std::string& string,
|
||||||
|
SGGeod* result = nullptr,
|
||||||
|
bool assumeLonLatOrder = false);
|
||||||
|
|
||||||
// enum values here correspond to existing lon-lat format codes inside
|
// enum values here correspond to existing lon-lat format codes inside
|
||||||
// FlightGear (property: /sim/lon-lat-format )
|
// FlightGear (property: /sim/lon-lat-format )
|
||||||
|
@ -654,6 +654,28 @@ void test_parseGeod()
|
|||||||
|
|
||||||
SG_VERIFY(strutils::parseStringAsGeod("") == false);
|
SG_VERIFY(strutils::parseStringAsGeod("") == false);
|
||||||
SG_VERIFY(strutils::parseStringAsGeod("aaaaaaaa") == false);
|
SG_VERIFY(strutils::parseStringAsGeod("aaaaaaaa") == false);
|
||||||
|
|
||||||
|
// ordering tests
|
||||||
|
|
||||||
|
// normal default order, but explicitly pass as lon,lat
|
||||||
|
// (should work)
|
||||||
|
SG_VERIFY(strutils::parseStringAsGeod("3.12345678w, 56.12345678s", &a));
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLongitudeDeg(), -3.12345678);
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -56.12345678);
|
||||||
|
|
||||||
|
|
||||||
|
// different default order
|
||||||
|
// also some embedded whitespace for fun
|
||||||
|
SG_VERIFY(strutils::parseStringAsGeod(" -12 34.56,\n-45 27.89 ", &a, true));
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLongitudeDeg(), -12.576);
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -45.464833333);
|
||||||
|
|
||||||
|
|
||||||
|
// differnet default order, but still set explicitly so should
|
||||||
|
// use the lat,lon order
|
||||||
|
SG_VERIFY(strutils::parseStringAsGeod("\t40 30'50\"S, 12 34'56\"W ", &a, true));
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLongitudeDeg(), -12.58222222);
|
||||||
|
SG_CHECK_EQUAL_EP(a.getLatitudeDeg(), -40.5138888);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_formatGeod()
|
void test_formatGeod()
|
||||||
|
Loading…
Reference in New Issue
Block a user