GeographicLib  2.6
GeoConvert.cpp
Go to the documentation of this file.
1 /**
2  * \file GeoConvert.cpp
3  * \brief Command line utility for geographic coordinate conversions
4  *
5  * Copyright (c) Charles Karney (2008-2017) <karney@alum.mit.edu> and licensed
6  * under the MIT/X11 License. For more information, see
7  * https://geographiclib.sourceforge.io/
8  *
9  * See the <a href="GeoConvert.1.html">man page</a> for usage information.
10  **********************************************************************/
11 
12 #include <iostream>
13 #include <string>
14 #include <sstream>
15 #include <fstream>
17 #include <GeographicLib/DMS.hpp>
19 #include <GeographicLib/MGRS.hpp>
20 
21 #include "GeoConvert.usage"
22 
23 int main(int argc, const char* const argv[]) {
24  try {
25  using namespace GeographicLib;
26  typedef Math::real real;
28  enum { GEOGRAPHIC, DMS, UTMUPS, MGRS, CONVERGENCE };
29  int outputmode = GEOGRAPHIC;
30  int prec = 0;
31  int zone = UTMUPS::MATCH;
32  bool centerp = true, longfirst = false;
33  std::string istring, ifile, ofile, cdelim;
34  char lsep = ';', dmssep = char(0);
35  bool sethemisphere = false, northp = false, abbrev = true, latch = false;
36 
37  for (int m = 1; m < argc; ++m) {
38  std::string arg(argv[m]);
39  if (arg == "-g")
40  outputmode = GEOGRAPHIC;
41  else if (arg == "-d") {
42  outputmode = DMS;
43  dmssep = '\0';
44  } else if (arg == "-:") {
45  outputmode = DMS;
46  dmssep = ':';
47  } else if (arg == "-u")
48  outputmode = UTMUPS;
49  else if (arg == "-m")
50  outputmode = MGRS;
51  else if (arg == "-c")
52  outputmode = CONVERGENCE;
53  else if (arg == "-n")
54  centerp = false;
55  else if (arg == "-z") {
56  if (++m == argc) return usage(1, true);
57  std::string zonestr(argv[m]);
58  try {
59  UTMUPS::DecodeZone(zonestr, zone, northp);
60  sethemisphere = true;
61  }
62  catch (const std::exception&) {
63  std::istringstream str(zonestr);
64  char c;
65  if (!(str >> zone) || (str >> c)) {
66  std::cerr << "Zone " << zonestr
67  << " is not a number or zone+hemisphere\n";
68  return 1;
69  }
70  if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) {
71  std::cerr << "Zone " << zone << " not in [0, 60]\n";
72  return 1;
73  }
74  sethemisphere = false;
75  }
76  latch = false;
77  } else if (arg == "-s") {
78  zone = UTMUPS::STANDARD;
79  sethemisphere = false;
80  latch = false;
81  } else if (arg == "-S") {
82  zone = UTMUPS::STANDARD;
83  sethemisphere = false;
84  latch = true;
85  } else if (arg == "-t") {
86  zone = UTMUPS::UTM;
87  sethemisphere = false;
88  latch = false;
89  } else if (arg == "-T") {
90  zone = UTMUPS::UTM;
91  sethemisphere = false;
92  latch = true;
93  } else if (arg == "-w")
94  longfirst = !longfirst;
95  else if (arg == "-p") {
96  if (++m == argc) return usage(1, true);
97  try {
98  prec = Utility::val<int>(std::string(argv[m]));
99  }
100  catch (const std::exception&) {
101  std::cerr << "Precision " << argv[m] << " is not a number\n";
102  return 1;
103  }
104  } else if (arg == "-l")
105  abbrev = false;
106  else if (arg == "-a")
107  abbrev = true;
108  else if (arg == "--input-string") {
109  if (++m == argc) return usage(1, true);
110  istring = argv[m];
111  } else if (arg == "--input-file") {
112  if (++m == argc) return usage(1, true);
113  ifile = argv[m];
114  } else if (arg == "--output-file") {
115  if (++m == argc) return usage(1, true);
116  ofile = argv[m];
117  } else if (arg == "--line-separator") {
118  if (++m == argc) return usage(1, true);
119  if (std::string(argv[m]).size() != 1) {
120  std::cerr << "Line separator must be a single character\n";
121  return 1;
122  }
123  lsep = argv[m][0];
124  } else if (arg == "--comment-delimiter") {
125  if (++m == argc) return usage(1, true);
126  cdelim = argv[m];
127  } else if (arg == "--version") {
128  std::cout << argv[0] << ": GeographicLib version "
129  << GEOGRAPHICLIB_VERSION_STRING << "\n";
130  MGRS::Check();
131  return 0;
132  } else
133  return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
134  }
135 
136  if (!ifile.empty() && !istring.empty()) {
137  std::cerr << "Cannot specify --input-string and --input-file together\n";
138  return 1;
139  }
140  if (ifile == "-") ifile.clear();
141  std::ifstream infile;
142  std::istringstream instring;
143  if (!ifile.empty()) {
144  infile.open(ifile.c_str());
145  if (!infile.is_open()) {
146  std::cerr << "Cannot open " << ifile << " for reading\n";
147  return 1;
148  }
149  } else if (!istring.empty()) {
150  std::string::size_type m = 0;
151  while (true) {
152  m = istring.find(lsep, m);
153  if (m == std::string::npos)
154  break;
155  istring[m] = '\n';
156  }
157  instring.str(istring);
158  }
159  std::istream* input = !ifile.empty() ? &infile :
160  (!istring.empty() ? &instring : &std::cin);
161 
162  std::ofstream outfile;
163  if (ofile == "-") ofile.clear();
164  if (!ofile.empty()) {
165  outfile.open(ofile.c_str());
166  if (!outfile.is_open()) {
167  std::cerr << "Cannot open " << ofile << " for writing\n";
168  return 1;
169  }
170  }
171  std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
172 
173  GeoCoords p;
174  std::string s, eol;
175  std::string os;
176  int retval = 0;
177 
178  while (std::getline(*input, s)) {
179  eol = "\n";
180  try {
181  if (!cdelim.empty()) {
182  std::string::size_type m = s.find(cdelim);
183  if (m != std::string::npos) {
184  eol = " " + s.substr(m) + "\n";
185  s = s.substr(0, m);
186  }
187  }
188  p.Reset(s, centerp, longfirst);
189  p.SetAltZone(zone);
190  switch (outputmode) {
191  case GEOGRAPHIC:
192  os = p.GeoRepresentation(prec, longfirst);
193  break;
194  case DMS:
195  os = p.DMSRepresentation(prec, longfirst, dmssep);
196  break;
197  case UTMUPS:
198  os = (sethemisphere
199  ? p.AltUTMUPSRepresentation(northp, prec, abbrev)
200  : p.AltUTMUPSRepresentation(prec, abbrev));
201  break;
202  case MGRS:
203  os = p.AltMGRSRepresentation(prec);
204  break;
205  case CONVERGENCE:
206  {
207  real
208  gamma = p.AltConvergence(),
209  k = p.AltScale();
210  int prec1 = std::max(-5, std::min(Math::extra_digits() + 8, prec));
211  os = Utility::str(gamma, prec1 + 5) + " "
212  + Utility::str(k, prec1 + 7);
213  }
214  }
215  if (latch &&
216  zone < UTMUPS::MINZONE && p.AltZone() >= UTMUPS::MINZONE) {
217  zone = p.AltZone();
218  northp = p.Northp();
219  sethemisphere = true;
220  latch = false;
221  }
222  }
223  catch (const std::exception& e) {
224  // Write error message to cout so output lines match input lines
225  os = std::string("ERROR: ") + e.what();
226  retval = 1;
227  }
228  *output << os << eol;
229  }
230  return retval;
231  }
232  catch (const std::exception& e) {
233  std::cerr << "Caught exception: " << e.what() << "\n";
234  return 1;
235  }
236  catch (...) {
237  std::cerr << "Caught unknown exception\n";
238  return 1;
239  }
240 }
Header for GeographicLib::Utility class.
Math::real AltScale() const
Definition: GeoCoords.hpp:373
Conversion between geographic coordinates.
Definition: GeoCoords.hpp:49
Header for GeographicLib::GeoCoords class.
Header for GeographicLib::MGRS class.
static int extra_digits()
Definition: Math.cpp:49
int usage(int retval, bool)
Definition: Geod3ODE.cpp:41
Convert between geographic coordinates and UTM/UPS.
Definition: UTMUPS.hpp:75
Convert between degrees and the DMS representation.
Definition: DMS.hpp:34
static void Check()
Definition: MGRS.cpp:449
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
static void DecodeZone(const std::string &zonestr, int &zone, bool &northp)
Definition: UTMUPS.cpp:205
static std::string str(T x, int p=-1)
Definition: Utility.hpp:161
std::string AltMGRSRepresentation(int prec=0) const
Definition: GeoCoords.cpp:84
std::string AltUTMUPSRepresentation(int prec=0, bool abbrev=true) const
Definition: GeoCoords.cpp:133
GeographicLib::Math::real real
Definition: Geod3Solve.cpp:25
static int set_digits(int ndigits=0)
Definition: Utility.cpp:184
std::string GeoRepresentation(int prec=0, bool longfirst=false) const
Definition: GeoCoords.cpp:61
std::string DMSRepresentation(int prec=0, bool longfirst=false, char dmssep=char(0)) const
Definition: GeoCoords.cpp:67
int main(int argc, const char *const argv[])
Definition: GeoConvert.cpp:23
void SetAltZone(int zone=UTMUPS::STANDARD) const
Definition: GeoCoords.hpp:335
Math::real AltConvergence() const
Definition: GeoCoords.hpp:368
void Reset(const std::string &s, bool centerp=true, bool longfirst=false)
Definition: GeoCoords.cpp:19
Convert between UTM/UPS and MGRS.
Definition: MGRS.hpp:68
Header for GeographicLib::DMS class.