C++ code formatting. Replaced long to string and string to long functions with standard imlementations.

Signed-off-by: S. Kozyr <s.trump@gmail.com>
This commit is contained in:
Sergiy Kozyr 2023-05-29 09:58:34 +03:00
parent 5c48c4a5bc
commit 7929db8466
Signed by: strump
GPG key ID: C622E5563CAC205D
6 changed files with 491 additions and 555 deletions

View file

@ -678,14 +678,14 @@ UNIT_TEST(to_string_dac)
TEST_EQUAL(strings::to_string_dac(1.0 + 1.0E-14, 15), "1.00000000000001", ());
}
UNIT_TEST(to_string_prec)
UNIT_TEST(to_string_width)
{
TEST_EQUAL(strings::to_string_prec(123, 5), "00123", ());
TEST_EQUAL(strings::to_string_prec(99, 3), "099", ());
TEST_EQUAL(strings::to_string_prec(0, 4), "0000", ());
TEST_EQUAL(strings::to_string_prec(-10, 4), "-0010", ());
TEST_EQUAL(strings::to_string_prec(545, 1), "545", ());
TEST_EQUAL(strings::to_string_prec(1073741824, 0), "1073741824", ());
TEST_EQUAL(strings::to_string_width(123, 5), "00123", ());
TEST_EQUAL(strings::to_string_width(99, 3), "099", ());
TEST_EQUAL(strings::to_string_width(0, 4), "0000", ());
TEST_EQUAL(strings::to_string_width(-10, 4), "-0010", ());
TEST_EQUAL(strings::to_string_width(545, 1), "545", ());
TEST_EQUAL(strings::to_string_width(1073741824, 0), "1073741824", ());
}

View file

@ -408,30 +408,12 @@ std::string to_string_dac(double d, int dac)
return ss.str();
}
std::string to_string_prec(long l, int prec)
std::string to_string_width(long l, int width)
{
long absL = abs(l);
int digs = 0;
while (absL > 0L)
{
absL /= 10;
++digs;
}
if (digs == 0)
digs = 1;
std::ostringstream ss;
if (l<0)
ss << '-';
while(prec > digs)
{
ss << '0';
--prec;
}
ss << abs(l);
ss << '-';
ss << std::setfill('0') << std::setw(width) << abs(l);
return ss.str();
}

View file

@ -566,8 +566,8 @@ inline std::string to_string(uint64_t i) { return std::to_string(i); }
std::string to_string_dac(double d, int dac);
//@}
// Get string with fixed count of digits. Extra '0' are added at the begining to fit size.
std::string to_string_prec(long l, int prec);
// Get string with fixed width. Extra '0' are added at the begining to fit size.
std::string to_string_width(long l, int width);
template <typename IterT1, typename IterT2>
bool StartsWith(IterT1 beg, IterT1 end, IterT2 begPrefix, IterT2 endPrefix)

View file

@ -12,10 +12,10 @@ using namespace std;
typedef struct UTMPoint_Value
{
double easting;
double northing;
int zone_number;
char zone_letter;
double easting;
double northing;
int zone_number;
char zone_letter;
} UTMPoint;
@ -69,229 +69,228 @@ const int SET_ORIGIN_ROW_LETTERS[] = { 'A', 'F', 'A', 'F', 'A', 'F' };
double degToRad(double deg)
{
return deg * DEGREES_TO_RADIANS;
return deg * DEGREES_TO_RADIANS;
}
double radToDeg(double rad)
{
return rad * RADIANS_TO_DEGREES;
return rad * RADIANS_TO_DEGREES;
}
// Convert lat,lon for WSG 84 ellipsoid to MGRS string.
string FormatMGRS(double lat, double lon, int precision)
{
if (precision > 5)
precision = 5;
else if (precision < 1)
precision = 1;
if (precision > 5)
precision = 5;
else if (precision < 1)
precision = 1;
if (lat <= -80 || lat > 84)
return "Latitude limit exceeded";
if (lon <= -180 || lon > 180)
return "Longitude limit exceeded";
if (lat <= -80 || lat > 84)
return "Latitude limit exceeded";
if (lon <= -180 || lon > 180)
return "Longitude limit exceeded";
UTMPoint mgrsp = latlon_to_utm(lat, lon);
UTMPoint mgrsp = latlon_to_utm(lat, lon);
// Need to add this to set the right letter for the latitude.
mgrsp.zone_letter = latitude_to_zone_letter(lat);
return utm_to_mgrs_str(mgrsp, precision);
// Need to add this to set the right letter for the latitude.
mgrsp.zone_letter = latitude_to_zone_letter(lat);
return utm_to_mgrs_str(mgrsp, precision);
}
// Convert lat,lon for WSG 84 ellipsoid to UTM string.
string FormatUTM(double lat, double lon)
{
if (lat <= -80 || lat > 84)
return "Latitude limit exceeded";
if (lon <= -180 || lon > 180)
return "Longitude limit exceeded";
if (lat <= -80 || lat > 84)
return "Latitude limit exceeded";
if (lon <= -180 || lon > 180)
return "Longitude limit exceeded";
UTMPoint utm = latlon_to_utm(lat, lon);
return utm_to_str(utm);
UTMPoint utm = latlon_to_utm(lat, lon);
return utm_to_str(utm);
}
// Main algorithm. Formulars sourcre: https://github.com/Turbo87/utm
UTMPoint latlon_to_utm(double lat, double lon)
{
double lat_rad = degToRad(lat);
double lat_sin = sin(lat_rad);
double lat_cos = cos(lat_rad);
double lat_rad = degToRad(lat);
double lat_sin = sin(lat_rad);
double lat_cos = cos(lat_rad);
double lat_tan = lat_sin / lat_cos;
double lat_tan2 = lat_tan * lat_tan;
double lat_tan4 = lat_tan2 * lat_tan2;
double lat_tan = lat_sin / lat_cos;
double lat_tan2 = lat_tan * lat_tan;
double lat_tan4 = lat_tan2 * lat_tan2;
int zone_number = latlon_to_zone_number(lat, lon);
char zone_letter = (lat >= 0.0) ? 'N' : 'S';
int zone_number = latlon_to_zone_number(lat, lon);
char zone_letter = (lat >= 0.0) ? 'N' : 'S';
double lon_rad = degToRad(lon);
double central_lon = zone_number_to_central_longitude(zone_number);
double central_lon_rad = degToRad(central_lon);
double lon_rad = degToRad(lon);
double central_lon = zone_number_to_central_longitude(zone_number);
double central_lon_rad = degToRad(central_lon);
double n = R / sqrt(1 - E * lat_sin * lat_sin);
double c = E_P2 * lat_cos * lat_cos;
double n = R / sqrt(1 - E * lat_sin * lat_sin);
double c = E_P2 * lat_cos * lat_cos;
double a = lat_cos * mod_angle(lon_rad - central_lon_rad);
double a2 = a * a;
double a3 = a2 * a;
double a4 = a3 * a;
double a5 = a4 * a;
double a6 = a5 * a;
double a = lat_cos * mod_angle(lon_rad - central_lon_rad);
double a2 = a * a;
double a3 = a2 * a;
double a4 = a3 * a;
double a5 = a4 * a;
double a6 = a5 * a;
double m = R * (M1 * lat_rad -
double m = R * (M1 * lat_rad -
M2 * sin(2 * lat_rad) +
M3 * sin(4 * lat_rad) -
M4 * sin(6 * lat_rad));
double easting = K0 * n * (a +
a3 / 6 * (1 - lat_tan2 + c) +
a5 / 120 * (5 - 18 * lat_tan2 + lat_tan4 + 72 * c - 58 * E_P2)) + 500000.0;
double easting = K0 * n * (a +
a3 / 6 * (1 - lat_tan2 + c) +
a5 / 120 * (5 - 18 * lat_tan2 + lat_tan4 + 72 * c - 58 * E_P2)) + 500000.0;
double northing = K0 * (m + n * lat_tan * (a2 / 2 +
a4 / 24 * (5 - lat_tan2 + 9 * c + 4 * c * c) +
a6 / 720 * (61 - 58 * lat_tan2 + lat_tan4 + 600 * c - 330 * E_P2)));
if (lat < 0.0)
northing += 10000000.0;
return {easting, northing, zone_number, zone_letter};
double northing = K0 * (m + n * lat_tan * (a2 / 2 +
a4 / 24 * (5 - lat_tan2 + 9 * c + 4 * c * c) +
a6 / 720 * (61 - 58 * lat_tan2 + lat_tan4 + 600 * c - 330 * E_P2)));
if (lat < 0.0)
northing += 10000000.0;
return {easting, northing, zone_number, zone_letter};
}
int latlon_to_zone_number(double lat, double lon)
{
if (56.0 <= lat && lat < 64.0 && 3.0 <= lon && lon < 12.0)
return 32;
if (56.0 <= lat && lat < 64.0 && 3.0 <= lon && lon < 12.0)
return 32;
if (72.0 <= lat && lat <= 84.0 and lon >= 0.0)
{
if (lon < 9.0)
return 31;
else if (lon < 21.0)
return 33;
else if (lon < 33.0)
return 35;
else if (lon < 42.0)
return 37;
}
if (72.0 <= lat && lat <= 84.0 and lon >= 0.0)
{
if (lon < 9.0)
return 31;
else if (lon < 21.0)
return 33;
else if (lon < 33.0)
return 35;
else if (lon < 42.0)
return 37;
}
return int((lon + 180.0) / 6.0) + 1;
return int((lon + 180.0) / 6.0) + 1;
}
char latitude_to_zone_letter(double lat)
{
if (-80.0 <= lat && lat <= 84.0)
return ZONE_LETTERS[int(lat + 80.0) >> 3];
else
return '?';
if (-80.0 <= lat && lat <= 84.0)
return ZONE_LETTERS[int(lat + 80.0) >> 3];
else
return '?';
}
int zone_number_to_central_longitude(int zone_number)
{
return (zone_number - 1) * 6 - 180 + 3;
return (zone_number - 1) * 6 - 180 + 3;
}
// Returns angle in radians to be between -PI and PI.
double mod_angle(double value)
{
if (value < -PI)
value += - 2 * PI * ((int)(value - PI) / (2 * PI));
else if (value > PI)
value -= 2 * PI * ((int)(value + PI) / (2 * PI));
return value;
if (value < -PI)
value += - 2 * PI * ((int)(value - PI) / (2 * PI));
else if (value > PI)
value -= 2 * PI * ((int)(value + PI) / (2 * PI));
return value;
}
// Generate UTM string from UTM point parameters.
string utm_to_str(UTMPoint point)
{
return to_string(point.zone_number) + string(1, point.zone_letter) + " " +\
to_string(int(round(point.easting))) + " " + \
to_string(int(round(point.northing)));
return to_string(point.zone_number) + string(1, point.zone_letter) + " " +\
to_string(int(round(point.easting))) + " " + \
to_string(int(round(point.northing)));
}
// Convert UTM point parameters to MGRS parameters. Additional 2 char code is deducted.
// Easting and northing parameters are reduced to 5 digits.
string utm_to_mgrs_str(UTMPoint point, int precision)
{
if (point.zone_letter == 'Z') {
return "Latitude limit exceeded";
} else {
string eastingStr = strings::to_string_prec(point.easting, precision+1);
string northingStr = strings::to_string_prec(point.northing, precision+1);
if (point.zone_letter == 'Z')
return "Latitude limit exceeded";
else
{
string eastingStr = strings::to_string_width(point.easting, precision+1);
string northingStr = strings::to_string_width(point.northing, precision+1);
if (northingStr.size() > 6)
northingStr = northingStr.substr(northingStr.size() - 6);
if (northingStr.size() > 6)
northingStr = northingStr.substr(northingStr.size() - 6);
return strings::to_string_prec((long) point.zone_number, 2) + point.zone_letter + " " + \
get_100k_id(point.easting, point.northing, point.zone_number) + " " + \
eastingStr.substr(1, precision) + " " + \
northingStr.substr(1, precision);
}
return strings::to_string_width((long) point.zone_number, 2) + point.zone_letter + " " + \
get_100k_id(point.easting, point.northing, point.zone_number) + " " + \
eastingStr.substr(1, precision) + " " + \
northingStr.substr(1, precision);
}
}
// Build 2 chars string with 100k square ID
string get_100k_id(double easting, double northing, int zone_number)
{
int set = zone_to_100k(zone_number);
int setColumn = ((int) easting / 100000);
int setRow = ((int) northing / 100000) % 20;
int set = zone_to_100k(zone_number);
int setColumn = ((int) easting / 100000);
int setRow = ((int) northing / 100000) % 20;
int colOrigin = SET_ORIGIN_COLUMN_LETTERS[set - 1];
int rowOrigin = SET_ORIGIN_ROW_LETTERS[set - 1];
int colOrigin = SET_ORIGIN_COLUMN_LETTERS[set - 1];
int rowOrigin = SET_ORIGIN_ROW_LETTERS[set - 1];
int colInt = colOrigin + setColumn - 1;
int rowInt = rowOrigin + setRow;
bool rollover = false;
int colInt = colOrigin + setColumn - 1;
int rowInt = rowOrigin + setRow;
bool rollover = false;
if (colInt > 'Z') {
colInt = colInt - 'Z' + 'A' - 1;
rollover = true;
}
if (colInt > 'Z')
{
colInt = colInt - 'Z' + 'A' - 1;
rollover = true;
}
if (colInt == 'I' || (colOrigin < 'I' && colInt > 'I') || ((colInt > 'I' || colOrigin < 'I') && rollover)) {
colInt++;
}
if (colInt == 'O' || (colOrigin < 'O' && colInt > 'O') || ((colInt > 'O' || colOrigin < 'O') && rollover)) {
colInt++;
if (colInt == 'I') {
colInt++;
}
}
if (colInt == 'I' || (colOrigin < 'I' && colInt > 'I') || ((colInt > 'I' || colOrigin < 'I') && rollover))
colInt++;
if (colInt == 'O' || (colOrigin < 'O' && colInt > 'O') || ((colInt > 'O' || colOrigin < 'O') && rollover))
{
colInt++;
if (colInt == 'I')
colInt++;
}
if (colInt > 'Z') {
colInt = colInt - 'Z' + 'A' - 1;
}
if (colInt > 'Z')
colInt = colInt - 'Z' + 'A' - 1;
if (rowInt > 'V') {
rowInt = rowInt - 'V' + 'A' - 1;
rollover = true;
} else {
rollover = false;
}
if (rowInt > 'V')
{
rowInt = rowInt - 'V' + 'A' - 1;
rollover = true;
}
else
rollover = false;
if (rowInt == 'I' || (rowOrigin < 'I' && rowInt > 'I') || ((rowInt > 'I' || rowOrigin < 'I') && rollover)) {
rowInt++;
}
if (rowInt == 'I' || (rowOrigin < 'I' && rowInt > 'I') || ((rowInt > 'I' || rowOrigin < 'I') && rollover)) {
rowInt++;
}
if (rowInt == 'O' || (rowOrigin < 'O' && rowInt > 'O') || ((rowInt > 'O' || rowOrigin < 'O') && rollover)) {
rowInt++;
if (rowInt == 'I') {
rowInt++;
}
}
if (rowInt == 'O' || (rowOrigin < 'O' && rowInt > 'O') || ((rowInt > 'O' || rowOrigin < 'O') && rollover))
{
rowInt++;
if (rowInt == 'I')
rowInt++;
}
if (rowInt > 'V') {
rowInt = rowInt - 'V' + 'A' - 1;
}
if (rowInt > 'V')
rowInt = rowInt - 'V' + 'A' - 1;
string twoLetter = {char(colInt), char(rowInt)};
string twoLetter = {char(colInt), char(rowInt)};
return twoLetter;
return twoLetter;
}
int zone_to_100k(int i) {
int set = i % NUM_100K_SETS;
if (set == 0)
set = NUM_100K_SETS;
return set;
int set = i % NUM_100K_SETS;
if (set == 0)
set = NUM_100K_SETS;
return set;
}
// Convert UTM parameters to lat,lon for WSG 84 ellipsoid.
@ -299,113 +298,113 @@ int zone_to_100k(int i) {
// Otherwise function returns 'false'.
bool UTMtoLatLon(double easting, double northing, int zone_number, char zone_letter, double &lat, double &lon)
{
if (zone_number < 1 || zone_number > 60)
return false;
if (zone_number < 1 || zone_number > 60)
return false;
if (easting < 100000.0 || easting >= 1000000.0)
return false;
if (easting < 100000.0 || easting >= 1000000.0)
return false;
if (northing < 0.0 || northing > 10000000.0)
return false;
if (northing < 0.0 || northing > 10000000.0)
return false;
if (zone_letter<'C' || zone_letter>'X' || zone_letter == 'I' || zone_letter == 'O')
return false;
if (zone_letter<'C' || zone_letter>'X' || zone_letter == 'I' || zone_letter == 'O')
return false;
bool northern = (zone_letter >= 'N');
double x = easting - 500000.0;
double y = northing;
bool northern = (zone_letter >= 'N');
double x = easting - 500000.0;
double y = northing;
if (!northern)
y -= 10000000.0;
if (!northern)
y -= 10000000.0;
double m = y / K0;
double mu = m / (R * M1);
double m = y / K0;
double mu = m / (R * M1);
double p_rad = (mu +
P2 * sin(2.0 * mu) +
P3 * sin(4.0 * mu) +
P4 * sin(6.0 * mu) +
P5 * sin(8.0 * mu));
double p_rad = (mu +
P2 * sin(2.0 * mu) +
P3 * sin(4.0 * mu) +
P4 * sin(6.0 * mu) +
P5 * sin(8.0 * mu));
double p_sin = sin(p_rad);
double p_sin2 = p_sin * p_sin;
double p_sin = sin(p_rad);
double p_sin2 = p_sin * p_sin;
double p_cos = cos(p_rad);
double p_cos = cos(p_rad);
double p_tan = p_sin / p_cos;
double p_tan2 = p_tan * p_tan;
double p_tan4 = p_tan2 * p_tan2;
double p_tan = p_sin / p_cos;
double p_tan2 = p_tan * p_tan;
double p_tan4 = p_tan2 * p_tan2;
double ep_sin = 1 - E * p_sin2;
double ep_sin_sqrt = sqrt(1 - E * p_sin2);
double ep_sin = 1 - E * p_sin2;
double ep_sin_sqrt = sqrt(1 - E * p_sin2);
double n = R / ep_sin_sqrt;
double r = (1 - E) / ep_sin;
double n = R / ep_sin_sqrt;
double r = (1 - E) / ep_sin;
double c = E_P2 * p_cos * p_cos;
double c2 = c * c;
double c = E_P2 * p_cos * p_cos;
double c2 = c * c;
double d = x / (n * K0);
double d2 = d * d;
double d3 = d2 * d;
double d4 = d3 * d;
double d5 = d4 * d;
double d6 = d5 * d;
double d = x / (n * K0);
double d2 = d * d;
double d3 = d2 * d;
double d4 = d3 * d;
double d5 = d4 * d;
double d6 = d5 * d;
double latitude = (p_rad - (p_tan / r) *
(d2 / 2.0 -
d4 / 24.0 * (5.0 + 3.0 * p_tan2 + 10.0 * c - 4.0 * c2 - 9.0 * E_P2)) +
d6 / 720.0 * (61.0 + 90.0 * p_tan2 + 298.0 * c + 45.0 * p_tan4 - 252.0 * E_P2 - 3.0 * c2));
double latitude = (p_rad - (p_tan / r) *
(d2 / 2.0 -
d4 / 24.0 * (5.0 + 3.0 * p_tan2 + 10.0 * c - 4.0 * c2 - 9.0 * E_P2)) +
d6 / 720.0 * (61.0 + 90.0 * p_tan2 + 298.0 * c + 45.0 * p_tan4 - 252.0 * E_P2 - 3.0 * c2));
double longitude = (d -
d3 / 6.0 * (1.0 + 2.0 * p_tan2 + c) +
d5 / 120.0 * (5.0 - 2.0 * c + 28.0 * p_tan2 - 3.0 * c2 + 8.0 * E_P2 + 24.0 * p_tan4)) / p_cos;
double longitude = (d -
d3 / 6.0 * (1.0 + 2.0 * p_tan2 + c) +
d5 / 120.0 * (5.0 - 2.0 * c + 28.0 * p_tan2 - 3.0 * c2 + 8.0 * E_P2 + 24.0 * p_tan4)) / p_cos;
longitude = mod_angle(longitude + degToRad(zone_number_to_central_longitude(zone_number)));
longitude = mod_angle(longitude + degToRad(zone_number_to_central_longitude(zone_number)));
lat = radToDeg(latitude);
lon = radToDeg(longitude);
lat = radToDeg(latitude);
lon = radToDeg(longitude);
return true;
return true;
}
// Convert MGRS parameters to UTM parameters and then use UTM to lat,lon conversion.
bool MGRStoLatLon(double easting, double northing, int zone_code, char zone_letter, char square_code[2], double &lat, double &lon)
{
// Convert easting and northing according to zone_code and square_code
if (zone_code < 1 || zone_code > 60)
return false;
// Convert easting and northing according to zone_code and square_code
if (zone_code < 1 || zone_code > 60)
return false;
if (zone_letter <= 'B' || zone_letter >= 'Y' || zone_letter == 'I' || zone_letter == 'O')
return false;
if (zone_letter <= 'B' || zone_letter >= 'Y' || zone_letter == 'I' || zone_letter == 'O')
return false;
int set = zone_to_100k(zone_code);
int set = zone_to_100k(zone_code);
char char1 = square_code[0];
char char2 = square_code[1];
char char1 = square_code[0];
char char2 = square_code[1];
if (char1 < 'A' || char2 < 'A' || char1 > 'Z' || char2 > 'Z' || char1 == 'I' || char2 == 'I' || char1 == 'O' || char2 == 'O')
return false;
if (char1 < 'A' || char2 < 'A' || char1 > 'Z' || char2 > 'Z' || char1 == 'I' || char2 == 'I' || char1 == 'O' || char2 == 'O')
return false;
float east100k = square_char_to_easting(char1, set);
if (east100k < 0)
return false;
float east100k = square_char_to_easting(char1, set);
if (east100k < 0)
return false;
float north100k = square_char_to_northing(char2, set);
if (north100k < 0)
return false;
float north100k = square_char_to_northing(char2, set);
if (north100k < 0)
return false;
double minNorthing = zone_to_min_northing(zone_letter);
if (minNorthing < 0)
return false;
double minNorthing = zone_to_min_northing(zone_letter);
if (minNorthing < 0)
return false;
while (north100k < minNorthing)
north100k += 2000000.0;
while (north100k < minNorthing)
north100k += 2000000.0;
easting += east100k;
northing += north100k;
easting += east100k;
northing += north100k;
return UTMtoLatLon(easting, northing, zone_code, zone_letter, lat, lon);
return UTMtoLatLon(easting, northing, zone_code, zone_letter, lat, lon);
}
/**
@ -414,28 +413,28 @@ bool MGRStoLatLon(double easting, double northing, int zone_code, char zone_lett
* should be added to the other, secondary easting value.
*/
double square_char_to_easting(char e, int set) {
int curCol = SET_ORIGIN_COLUMN_LETTERS[set - 1];
double eastingValue = 100000.0;
bool rewindMarker = false;
int curCol = SET_ORIGIN_COLUMN_LETTERS[set - 1];
double eastingValue = 100000.0;
bool rewindMarker = false;
while (curCol != e)
while (curCol != e)
{
curCol++;
if (curCol == 'I')
curCol++;
if (curCol == 'O')
curCol++;
if (curCol > 'Z')
{
curCol++;
if (curCol == 'I')
curCol++;
if (curCol == 'O')
curCol++;
if (curCol > 'Z')
{
if (rewindMarker)
return -1;
curCol = 'A';
rewindMarker = true;
}
eastingValue += 100000.0;
if (rewindMarker)
return -1;
curCol = 'A';
rewindMarker = true;
}
eastingValue += 100000.0;
}
return eastingValue;
return eastingValue;
}
/**
@ -449,39 +448,40 @@ double square_char_to_easting(char e, int set) {
* to be added for the zone letter of the MGRS coordinate.
*
* @param n
* second letter of the MGRS 100k zone
* second letter of the MGRS 100k zone
* @param set
* the MGRS table set number, which is dependent on the UTM zone
* number.
* the MGRS table set number, which is dependent on the UTM zone
* number.
*/
double square_char_to_northing(char n, int set) {
if (n > 'V')
return -1;
if (n > 'V')
return -1;
int curRow = SET_ORIGIN_ROW_LETTERS[set - 1];
double northingValue = 0.0;
bool rewindMarker = false;
int curRow = SET_ORIGIN_ROW_LETTERS[set - 1];
double northingValue = 0.0;
bool rewindMarker = false;
while (curRow != n)
while (curRow != n)
{
curRow++;
if (curRow == 'I')
curRow++;
if (curRow == 'O')
curRow++;
// fixing a bug making whole application hang in this loop
// when 'n' is a wrong character
if (curRow > 'V')
{
curRow++;
if (curRow == 'I')
curRow++;
if (curRow == 'O')
curRow++;
// fixing a bug making whole application hang in this loop
// when 'n' is a wrong character
if (curRow > 'V') {
if (rewindMarker) // making sure that this loop ends
return -1;
curRow = 'A';
rewindMarker = true;
}
northingValue += 100000.0;
if (rewindMarker) // making sure that this loop ends
return -1;
curRow = 'A';
rewindMarker = true;
}
northingValue += 100000.0;
}
return northingValue;
return northingValue;
}
/**
@ -493,74 +493,74 @@ double square_char_to_northing(char n, int set) {
*/
double zone_to_min_northing(char zoneLetter)
{
double northing;
switch (zoneLetter)
{
case 'C':
northing = 1100000.0;
break;
case 'D':
northing = 2000000.0;
break;
case 'E':
northing = 2800000.0;
break;
case 'F':
northing = 3700000.0;
break;
case 'G':
northing = 4600000.0;
break;
case 'H':
northing = 5500000.0;
break;
case 'J':
northing = 6400000.0;
break;
case 'K':
northing = 7300000.0;
break;
case 'L':
northing = 8200000.0;
break;
case 'M':
northing = 9100000.0;
break;
case 'N':
northing = 0.0;
break;
case 'P':
northing = 800000.0;
break;
case 'Q':
northing = 1700000.0;
break;
case 'R':
northing = 2600000.0;
break;
case 'S':
northing = 3500000.0;
break;
case 'T':
northing = 4400000.0;
break;
case 'U':
northing = 5300000.0;
break;
case 'V':
northing = 6200000.0;
break;
case 'W':
northing = 7000000.0;
break;
case 'X':
northing = 7900000.0;
break;
default:
northing = -1.0;
}
double northing;
switch (zoneLetter)
{
case 'C':
northing = 1100000.0;
break;
case 'D':
northing = 2000000.0;
break;
case 'E':
northing = 2800000.0;
break;
case 'F':
northing = 3700000.0;
break;
case 'G':
northing = 4600000.0;
break;
case 'H':
northing = 5500000.0;
break;
case 'J':
northing = 6400000.0;
break;
case 'K':
northing = 7300000.0;
break;
case 'L':
northing = 8200000.0;
break;
case 'M':
northing = 9100000.0;
break;
case 'N':
northing = 0.0;
break;
case 'P':
northing = 800000.0;
break;
case 'Q':
northing = 1700000.0;
break;
case 'R':
northing = 2600000.0;
break;
case 'S':
northing = 3500000.0;
break;
case 'T':
northing = 4400000.0;
break;
case 'U':
northing = 5300000.0;
break;
case 'V':
northing = 6200000.0;
break;
case 'W':
northing = 7000000.0;
break;
case 'X':
northing = 7900000.0;
break;
default:
northing = -1.0;
}
return northing;
return northing;
}

View file

@ -609,35 +609,24 @@ bool Processor::SearchCoordinates()
{
bool coords_found = false;
buffer_vector<ms::LatLon, 3> results;
double lat, lon;
if (MatchLatLonDegree(m_query, lat, lon))
{
double lat;
double lon;
if (MatchLatLonDegree(m_query, lat, lon))
{
coords_found = true;
results.emplace_back(lat, lon);
}
coords_found = true;
results.emplace_back(lat, lon);
}
if (MatchUTMCoords(m_query, lat, lon))
{
double lat;
double lon;
if (MatchUTMCoords(m_query, lat, lon))
{
coords_found = true;
results.emplace_back(lat, lon);
}
coords_found = true;
results.emplace_back(lat, lon);
}
if (MatchMGRSCoords(m_query, lat, lon))
{
double lat;
double lon;
if (MatchMGRSCoords(m_query, lat, lon))
{
coords_found = true;
results.emplace_back(lat, lon);
}
coords_found = true;
results.emplace_back(lat, lon);
}
istringstream iss(m_query);

View file

@ -7,128 +7,106 @@
#include <iterator>
#include <string>
#include <utility>
#include <iostream>
#include <math.h>
using namespace std;
#include "base/math.hpp"
#include "base/string_utils.hpp"
namespace search
{
bool IsSpace(char ch);
string::size_type FindNonSpace(string const & txt, string::size_type startPos);
string::size_type MatchZoneCode(string const & query, int &zone_code);
string::size_type MatchZoneLetter(string const & query, char &zone_letter, string::size_type startPos);
string::size_type MatchLong(string const & query, long &value, string::size_type startPos);
bool ParseFixDigitsNumber(string const & txt, int numDigits, string::size_type startPos, long & value);
std::string StripSpaces(string const & txt);
bool parseLong(string const & txt, long & value);
using namespace std;
string const kSpaceChars = " \t\r";
size_t MatchZoneCode(string const & query, int &zone_code);
size_t MatchZoneLetter(string const & query, char &zone_letter, size_t startPos);
size_t MatchLong(string const & query, long &value, size_t startPos);
// Parse UTM format "(\d\d)\s?(\W)\s+(\d+)\s+(\d+)" and converts it to lat,lon.
// Return true if parsed successfully or false otherwise.
// See utm_mgrs_coords_match_test.cpp for sample UTM strings
bool MatchUTMCoords(string const & query, double & lat, double & lon)
{
int zone_code;
char zone_letter;
long easting, northing;
int zone_code;
char zone_letter;
long easting, northing;
string::size_type pos = MatchZoneCode(query, zone_code);
if (pos == string::npos)
return false;
size_t pos = MatchZoneCode(query, zone_code);
if (pos == string::npos)
return false;
pos = MatchZoneLetter(query, zone_letter, pos);
if (pos == string::npos)
return false;
pos = MatchZoneLetter(query, zone_letter, pos);
if (pos == string::npos)
return false;
pos = MatchLong(query, easting, pos);
if (pos == string::npos)
return false;
pos = MatchLong(query, easting, pos);
if (pos == string::npos)
return false;
pos = MatchLong(query, northing, pos);
if (pos == string::npos)
return false;
pos = MatchLong(query, northing, pos);
if (pos == string::npos)
return false;
return utm_mgrs_utils::UTMtoLatLon((double)easting, (double)northing, zone_code, zone_letter, lat, lon);
return utm_mgrs_utils::UTMtoLatLon((double)easting, (double)northing, zone_code, zone_letter, lat, lon);
}
// Matches 2 digits zone code. Returns end position of matched chars or string::npos if no match.
string::size_type MatchZoneCode(string const & query, int &zone_code)
size_t MatchZoneCode(string const & query, int &zone_code)
{
auto pos = FindNonSpace(query, 0);
if (query.size()-pos < 2)
return string::npos;
auto pos = query.find_first_not_of(kSpaceChars);
if (query.size()-pos < 2)
return string::npos;
char dig1 = query[pos];
char dig2 = query[pos+1];
if (dig1 < '0' || dig1 > '9' || dig2 < '0' || dig2 > '9')
return string::npos;
char dig1 = query[pos];
char dig2 = query[pos+1];
if (dig1 < '0' || dig1 > '9' || dig2 < '0' || dig2 > '9')
return string::npos;
zone_code = (dig1 - '0') * 10 + (dig2 - '0');
return pos + 2;
zone_code = (dig1 - '0') * 10 + (dig2 - '0');
return pos + 2;
}
// Matches zone letter ignoring spaces. Returns end position of matched chars or string::npos if no match.
string::size_type MatchZoneLetter(string const & query, char &zone_letter, string::size_type startPos)
size_t MatchZoneLetter(string const & query, char &zone_letter, size_t startPos)
{
auto pos = FindNonSpace(query, startPos);
if (query.size() == pos)
return string::npos;
auto pos = query.find_first_not_of(kSpaceChars, startPos);
if (query.size() == pos)
return string::npos;
char l = query[pos];
if (l < 'A' || l > 'Z')
return string::npos;
char l = query[pos];
if (l < 'A' || l > 'Z')
return string::npos;
zone_letter = l;
return pos + 1;
zone_letter = l;
return pos + 1;
}
// Matches long number ignoring spaces. Returns end position of matched chars or string::npos if no match.
string::size_type MatchLong(string const & query, long &value, string::size_type startPos)
size_t MatchLong(string const & query, long &value, size_t startPos)
{
auto pos = FindNonSpace(query, startPos);
if (query.size() == pos)
return string::npos;
auto pos = query.find_first_not_of(kSpaceChars, startPos);
if (query.size() == pos)
return string::npos;
long n = 0;
while(pos < query.size())
long n = 0;
while(pos < query.size())
{
char ch = query[pos];
if (ch >= '0' && ch <= '9')
{
char ch = query[pos];
if (ch >= '0' && ch <= '9')
{
n = n*10 + (ch-'0');
pos ++;
}
else if (IsSpace(ch))
break;
else
return string::npos;
n = n*10 + (ch-'0');
pos ++;
}
else if (kSpaceChars.find(ch) != string::npos) // Found space char matching end of the number
break;
else
return string::npos;
}
value = n;
return pos;
}
// Return position of non-space char starting from startPos.
// Return txt.size() if no such character found.
string::size_type FindNonSpace(string const & txt, string::size_type startPos)
{
auto pos = startPos;
while(pos < txt.size())
{
if (IsSpace(txt[pos]))
pos++;
else
break;
}
return pos;
}
bool IsSpace(char ch)
{
return ch == ' ' || ch == '\t' || ch == '\r';
value = n;
return pos;
}
// Parse MGRS format "(\d\d\W)\s*(\W\W)\s*(\d+)\s*(\d+)" and converts it to lat,lon.
@ -136,116 +114,103 @@ bool IsSpace(char ch)
// See utm_mgrs_coords_match_test.cpp for sample MGRS strings
bool MatchMGRSCoords(std::string const & query, double & lat, double & lon)
{
long zone_code;
char zone_letter;
char square_code[2];
string eastingStr;
string northingStr;
long easting;
long northing;
long zone_code;
char zone_letter;
char square_code[2];
string eastingStr;
string northingStr;
int64_t easting;
int64_t northing;
strings::SimpleTokenizer it(query, " \t\r");
if (!it)
return false;
strings::SimpleTokenizer it(query, " \t\r");
if (!it)
return false;
auto token = std::string(*it);
// Parse 2 digit zone code and 1 char zone letter
if (token.size() >= 3)
{
char dig1 = token[0];
char dig2 = token[1];
if (dig1 < '0' || dig1 > '9' || dig2 < '0' || dig2 > '9')
return false;
auto token = std::string(*it);
// Parse 2 digit zone code and 1 char zone letter
if (token.size() >= 3)
{
char dig1 = token[0];
char dig2 = token[1];
if (dig1 < '0' || dig1 > '9' || dig2 < '0' || dig2 > '9')
return false;
zone_code = (dig1 - '0') * 10 + (dig2 - '0');
if (zone_code<1 || zone_code > 60)
return false;
zone_code = (dig1 - '0') * 10 + (dig2 - '0');
if (zone_code<1 || zone_code > 60)
return false;
zone_letter = token[2];
token = token.substr(3);
}
else
return false;
zone_letter = token[2];
token = token.substr(3);
}
else
return false;
// Read next token if needed.
if (token.size() == 0)
{
++it;
if (!it)
return false;
token = std::string(*it);
}
// Parse 2 chars zone code.
if (token.size() >= 2)
{
square_code[0] = token[0];
square_code[1] = token[1];
token = token.substr(2);
}
// Read next token if needed.
if (token.size() == 0)
{
++it;
if (!it)
return false;
token = std::string(*it);
}
// Parse easting and norhing.
eastingStr = token;
// Get next token if available.
// Read next token if needed.
if (token.size() == 0)
{
++it;
if (it)
northingStr = std::string(*it);
if (!it)
return false;
token = std::string(*it);
}
// Convert eastingStr & northingStr to numbers.
if (northingStr.empty())
{
// eastingStr contains both easting and northing. Let's split
if (eastingStr.size()%2 != 0)
return false;
// Parse 2 chars zone code.
if (token.size() >= 2)
{
square_code[0] = token[0];
square_code[1] = token[1];
token = token.substr(2);
}
int eastingSize = eastingStr.size()/2;
northingStr = eastingStr.substr(eastingSize);
eastingStr = eastingStr.substr(0, eastingSize);
}
// Read next token if needed.
if (token.size() == 0)
{
++it;
if (!it)
return false;
token = std::string(*it);
}
if (eastingStr.size() != northingStr.size() || eastingStr.size()>5 || northingStr.size()>5)
return false;
// Parse easting and norhing.
eastingStr = token;
if (!parseLong(eastingStr, easting))
return false;
if (eastingStr.size() < 5)
{
int decShift = 5 - eastingStr.size();
easting *= pow(10L, decShift);
}
// Get next token if available.
++it;
if (it)
northingStr = std::string(*it);
if (!parseLong(northingStr, northing))
return false;
if (northingStr.size() < 5)
{
int decShift = 5 - northingStr.size();
northing *= pow(10L, decShift);
}
// Convert eastingStr & northingStr to numbers.
if (northingStr.empty())
{
// eastingStr contains both easting and northing. Let's split
if (eastingStr.size()%2 != 0)
return false;
return utm_mgrs_utils::MGRStoLatLon((double)easting, (double)northing, zone_code, zone_letter, square_code, lat, lon);
}
int eastingSize = eastingStr.size()/2;
northingStr = eastingStr.substr(eastingSize);
eastingStr = eastingStr.substr(0, eastingSize);
}
bool parseLong(string const & txt, long & value)
{
long parsedValue = 0;
for (char ch : txt)
{
if (ch < '0' || ch > '9')
return false;
parsedValue = parsedValue * 10 + (ch - '0');
}
value = parsedValue;
return true;
if (eastingStr.size() != northingStr.size() || eastingStr.size()>5 || northingStr.size()>5)
return false;
if (!strings::to_int64(eastingStr, easting))
return false;
if (eastingStr.size() < 5)
{
int decShift = 5 - eastingStr.size();
easting *= base::PowUint(10L, decShift);
}
if (!strings::to_int64(northingStr, northing))
return false;
if (northingStr.size() < 5)
{
int decShift = 5 - northingStr.size();
northing *= base::PowUint(10L, decShift);
}
return utm_mgrs_utils::MGRStoLatLon((double)easting, (double)northing, zone_code, zone_letter, square_code, lat, lon);
}
}