GeographicLib 2.5
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>
20
21#include "GeoConvert.usage"
22
23int main(int argc, const char* const argv[]) {
24 try {
25 using namespace GeographicLib;
26 typedef Math::real real;
27 Utility::set_digits();
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::DMS class.
int main(int argc, const char *const argv[])
Header for GeographicLib::GeoCoords class.
GeographicLib::Math::real real
Definition GeodSolve.cpp:28
Header for GeographicLib::MGRS class.
Header for GeographicLib::Utility class.
Convert between degrees and the DMS representation.
Definition DMS.hpp:28
Conversion between geographic coordinates.
Definition GeoCoords.hpp:49
std::string DMSRepresentation(int prec=0, bool longfirst=false, char dmssep=char(0)) const
Definition GeoCoords.cpp:68
void Reset(const std::string &s, bool centerp=true, bool longfirst=false)
Definition GeoCoords.cpp:19
std::string AltMGRSRepresentation(int prec=0) const
Definition GeoCoords.cpp:85
std::string GeoRepresentation(int prec=0, bool longfirst=false) const
Definition GeoCoords.cpp:61
void SetAltZone(int zone=UTMUPS::STANDARD) const
Math::real AltConvergence() const
std::string AltUTMUPSRepresentation(int prec=0, bool abbrev=true) const
Math::real AltScale() const
Convert between UTM/UPS and MGRS.
Definition MGRS.hpp:68
Convert between geographic coordinates and UTM/UPS.
Definition UTMUPS.hpp:75
Namespace for GeographicLib.