GeographicLib  1.35
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-2012) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * http://geographiclib.sourceforge.net/
8  *
9  * Compile and link with
10  * g++ -g -O3 -I../include -I../man -o GeoConvert \
11  * GeoConvert.cpp \
12  * ../src/DMS.cpp \
13  * ../src/GeoCoords.cpp \
14  * ../src/MGRS.cpp \
15  * ../src/PolarStereographic.cpp \
16  * ../src/TransverseMercator.cpp \
17  * ../src/UTMUPS.cpp
18  *
19  * See the <a href="GeoConvert.1.html">man page</a> for usage
20  * information.
21  **********************************************************************/
22 
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26 #include <sstream>
27 #include <fstream>
29 #include <GeographicLib/DMS.hpp>
31 
32 #if defined(_MSC_VER)
33 // Squelch warnings about constant conditional expressions
34 # pragma warning (disable: 4127)
35 #endif
36 
37 #include "GeoConvert.usage"
38 
39 int main(int argc, char* argv[]) {
40  try {
41  using namespace GeographicLib;
42  typedef Math::real real;
43  enum { GEOGRAPHIC, DMS, UTMUPS, MGRS, CONVERGENCE };
44  int outputmode = GEOGRAPHIC;
45  int prec = 0;
46  int zone = UTMUPS::MATCH;
47  bool centerp = true, swaplatlong = false;
48  std::string istring, ifile, ofile, cdelim;
49  char lsep = ';', dmssep = char(0);
50  bool sethemisphere = false, northp = false;
51 
52  for (int m = 1; m < argc; ++m) {
53  std::string arg(argv[m]);
54  if (arg == "-g")
55  outputmode = GEOGRAPHIC;
56  else if (arg == "-d") {
57  outputmode = DMS;
58  dmssep = '\0';
59  } else if (arg == "-:") {
60  outputmode = DMS;
61  dmssep = ':';
62  } else if (arg == "-u")
63  outputmode = UTMUPS;
64  else if (arg == "-m")
65  outputmode = MGRS;
66  else if (arg == "-c")
67  outputmode = CONVERGENCE;
68  else if (arg == "-n")
69  centerp = false;
70  else if (arg == "-w")
71  swaplatlong = true;
72  else if (arg == "-p") {
73  if (++m == argc) return usage(1, true);
74  try {
75  prec = Utility::num<int>(std::string(argv[m]));
76  }
77  catch (const std::exception&) {
78  std::cerr << "Precision " << argv[m] << " is not a number\n";
79  return 1;
80  }
81  } else if (arg == "-z") {
82  if (++m == argc) return usage(1, true);
83  std::string zonestr(argv[m]);
84  try {
85  UTMUPS::DecodeZone(zonestr, zone, northp);
86  sethemisphere = true;
87  }
88  catch (const std::exception&) {
89  std::istringstream str(zonestr);
90  char c;
91  if (!(str >> zone) || (str >> c)) {
92  std::cerr << "Zone " << zonestr
93  << " is not a number or zone+hemisphere\n";
94  return 1;
95  }
96  if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) {
97  std::cerr << "Zone " << zone << " not in [0, 60]\n";
98  return 1;
99  }
100  sethemisphere = false;
101  }
102  } else if (arg == "-s") {
103  zone = UTMUPS::STANDARD;
104  sethemisphere = false;
105  } else if (arg == "-t") {
106  zone = UTMUPS::UTM;
107  sethemisphere = false;
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
129  << argv[0] << ": GeographicLib version "
130  << GEOGRAPHICLIB_VERSION_STRING << "\n";
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;
175  std::string os;
176  int retval = 0;
177 
178  while (std::getline(*input, s)) {
179  std::string 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, swaplatlong);
189  p.SetAltZone(zone);
190  switch (outputmode) {
191  case GEOGRAPHIC:
192  os = p.GeoRepresentation(prec, swaplatlong);
193  break;
194  case DMS:
195  os = p.DMSRepresentation(prec, swaplatlong, dmssep);
196  break;
197  case UTMUPS:
198  os = (sethemisphere
199  ? p.AltUTMUPSRepresentation(northp, prec)
200  : p.AltUTMUPSRepresentation(prec));
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::extradigits + 8, prec ));
211  os = Utility::str<real>(gamma, prec1 + 5) + " "
212  + Utility::str<real>(k, prec1 + 7);
213  }
214  }
215  }
216  catch (const std::exception& e) {
217  // Write error message to cout so output lines match input lines
218  os = std::string("ERROR: ") + e.what();
219  retval = 1;
220  }
221  *output << os << eol;
222  }
223  return retval;
224  }
225  catch (const std::exception& e) {
226  std::cerr << "Caught exception: " << e.what() << "\n";
227  return 1;
228  }
229  catch (...) {
230  std::cerr << "Caught unknown exception\n";
231  return 1;
232  }
233 }