GeographicLib  1.36
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, abbrev = true;
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 == "-l")
73  abbrev = false;
74  else if (arg == "-a")
75  abbrev = true;
76  else if (arg == "-p") {
77  if (++m == argc) return usage(1, true);
78  try {
79  prec = Utility::num<int>(std::string(argv[m]));
80  }
81  catch (const std::exception&) {
82  std::cerr << "Precision " << argv[m] << " is not a number\n";
83  return 1;
84  }
85  } else if (arg == "-z") {
86  if (++m == argc) return usage(1, true);
87  std::string zonestr(argv[m]);
88  try {
89  UTMUPS::DecodeZone(zonestr, zone, northp);
90  sethemisphere = true;
91  }
92  catch (const std::exception&) {
93  std::istringstream str(zonestr);
94  char c;
95  if (!(str >> zone) || (str >> c)) {
96  std::cerr << "Zone " << zonestr
97  << " is not a number or zone+hemisphere\n";
98  return 1;
99  }
100  if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) {
101  std::cerr << "Zone " << zone << " not in [0, 60]\n";
102  return 1;
103  }
104  sethemisphere = false;
105  }
106  } else if (arg == "-s") {
107  zone = UTMUPS::STANDARD;
108  sethemisphere = false;
109  } else if (arg == "-t") {
110  zone = UTMUPS::UTM;
111  sethemisphere = false;
112  } else if (arg == "--input-string") {
113  if (++m == argc) return usage(1, true);
114  istring = argv[m];
115  } else if (arg == "--input-file") {
116  if (++m == argc) return usage(1, true);
117  ifile = argv[m];
118  } else if (arg == "--output-file") {
119  if (++m == argc) return usage(1, true);
120  ofile = argv[m];
121  } else if (arg == "--line-separator") {
122  if (++m == argc) return usage(1, true);
123  if (std::string(argv[m]).size() != 1) {
124  std::cerr << "Line separator must be a single character\n";
125  return 1;
126  }
127  lsep = argv[m][0];
128  } else if (arg == "--comment-delimiter") {
129  if (++m == argc) return usage(1, true);
130  cdelim = argv[m];
131  } else if (arg == "--version") {
132  std::cout
133  << argv[0] << ": GeographicLib version "
134  << GEOGRAPHICLIB_VERSION_STRING << "\n";
135  return 0;
136  } else
137  return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
138  }
139 
140  if (!ifile.empty() && !istring.empty()) {
141  std::cerr << "Cannot specify --input-string and --input-file together\n";
142  return 1;
143  }
144  if (ifile == "-") ifile.clear();
145  std::ifstream infile;
146  std::istringstream instring;
147  if (!ifile.empty()) {
148  infile.open(ifile.c_str());
149  if (!infile.is_open()) {
150  std::cerr << "Cannot open " << ifile << " for reading\n";
151  return 1;
152  }
153  } else if (!istring.empty()) {
154  std::string::size_type m = 0;
155  while (true) {
156  m = istring.find(lsep, m);
157  if (m == std::string::npos)
158  break;
159  istring[m] = '\n';
160  }
161  instring.str(istring);
162  }
163  std::istream* input = !ifile.empty() ? &infile :
164  (!istring.empty() ? &instring : &std::cin);
165 
166  std::ofstream outfile;
167  if (ofile == "-") ofile.clear();
168  if (!ofile.empty()) {
169  outfile.open(ofile.c_str());
170  if (!outfile.is_open()) {
171  std::cerr << "Cannot open " << ofile << " for writing\n";
172  return 1;
173  }
174  }
175  std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
176 
177  GeoCoords p;
178  std::string s;
179  std::string os;
180  int retval = 0;
181 
182  while (std::getline(*input, s)) {
183  std::string eol("\n");
184  try {
185  if (!cdelim.empty()) {
186  std::string::size_type m = s.find(cdelim);
187  if (m != std::string::npos) {
188  eol = " " + s.substr(m) + "\n";
189  s = s.substr(0, m);
190  }
191  }
192  p.Reset(s, centerp, swaplatlong);
193  p.SetAltZone(zone);
194  switch (outputmode) {
195  case GEOGRAPHIC:
196  os = p.GeoRepresentation(prec, swaplatlong);
197  break;
198  case DMS:
199  os = p.DMSRepresentation(prec, swaplatlong, dmssep);
200  break;
201  case UTMUPS:
202  os = (sethemisphere
203  ? p.AltUTMUPSRepresentation(northp, prec, abbrev)
204  : p.AltUTMUPSRepresentation(prec, abbrev));
205  break;
206  case MGRS:
207  os = p.AltMGRSRepresentation(prec);
208  break;
209  case CONVERGENCE:
210  {
211  real
212  gamma = p.AltConvergence(),
213  k = p.AltScale();
214  int prec1 = std::max(-5, std::min( Math::extradigits + 8, prec ));
215  os = Utility::str<real>(gamma, prec1 + 5) + " "
216  + Utility::str<real>(k, prec1 + 7);
217  }
218  }
219  }
220  catch (const std::exception& e) {
221  // Write error message to cout so output lines match input lines
222  os = std::string("ERROR: ") + e.what();
223  retval = 1;
224  }
225  *output << os << eol;
226  }
227  return retval;
228  }
229  catch (const std::exception& e) {
230  std::cerr << "Caught exception: " << e.what() << "\n";
231  return 1;
232  }
233  catch (...) {
234  std::cerr << "Caught unknown exception\n";
235  return 1;
236  }
237 }