52int main(
int argc,
const char*
const argv[]) {
59 using vec3 = Ellipsoid3::vec3;
60 using coord = Cartesian3::coord;
61 enum { GEODETIC, PARAMETRIC, GEOCENTRIC, ELLIPSOIDAL };
62 coord mode = coord::ELLIPSOIDAL;
63 bool threed =
false, direction =
false, reverse =
false, dms =
false,
64 longfirst =
false, randompts =
false;
69 e2 = -1, k2 = 0, kp2 = 0;
70 int prec = 3, nrand = 0;
71 unsigned long long seed = 0;
72 std::string istring, ifile, ofile, cdelim;
73 char lsep =
';', dmssep = char(0);
75 for (
int m = 1; m < argc; ++m) {
76 std::string arg(argv[m]);
78 mode = coord::ELLIPSOIDAL;
80 mode = coord::GEODETIC;
82 mode = coord::PARAMETRIC;
84 mode = coord::GEOCENTRIC;
85 else if (arg ==
"-GX")
86 mode = coord::GEODETIC_X;
87 else if (arg ==
"-PX")
88 mode = coord::PARAMETRIC_X;
89 else if (arg ==
"-CX")
90 mode = coord::GEOCENTRIC_X;
91 else if (arg ==
"-R") {
92 if (++m == argc)
return usage(1,
true);
96 catch (
const std::exception&) {
97 std::cerr <<
"Number of randoms " << argv[m] <<
" is not a number\n";
101 }
else if (arg ==
"-3")
103 else if (arg ==
"-D")
105 else if (arg ==
"-r")
107 else if (arg ==
"--seed") {
108 if (++m == argc)
return usage(1,
true);
112 catch (
const std::exception&) {
113 std::cerr <<
"Precision " << argv[m] <<
" is not a number\n";
116 }
else if (arg ==
"-t") {
117 if (m + 3 >= argc)
return usage(1,
true);
123 catch (
const std::exception& e) {
124 std::cerr <<
"Error decoding arguments of -t: " << e.what() <<
"\n";
129 }
else if (arg ==
"-e") {
132 if (m + 4 >= argc)
return usage(1,
true);
139 catch (
const std::exception& e) {
140 std::cerr <<
"Error decoding arguments of -e: " << e.what() <<
"\n";
145 }
else if (arg ==
"-d") {
148 }
else if (arg ==
"-:") {
151 }
else if (arg ==
"-w")
152 longfirst = !longfirst;
153 else if (arg ==
"-p") {
154 if (++m == argc)
return usage(1,
true);
158 catch (
const std::exception&) {
159 std::cerr <<
"Precision " << argv[m] <<
" is not a number\n";
162 }
else if (arg ==
"--input-string") {
163 if (++m == argc)
return usage(1,
true);
165 }
else if (arg ==
"--input-file") {
166 if (++m == argc)
return usage(1,
true);
168 }
else if (arg ==
"--output-file") {
169 if (++m == argc)
return usage(1,
true);
171 }
else if (arg ==
"--line-separator") {
172 if (++m == argc)
return usage(1,
true);
173 if (std::string(argv[m]).size() != 1) {
174 std::cerr <<
"Line separator must be a single character\n";
178 }
else if (arg ==
"--comment-delimiter") {
179 if (++m == argc)
return usage(1,
true);
181 }
else if (arg ==
"--version") {
182 std::cout << argv[0] <<
": GeographicLib version "
183 << GEOGRAPHICLIB_VERSION_STRING <<
"\n";
186 return usage(!(arg ==
"-h" || arg ==
"--help"), arg !=
"--help");
189 Cartesian3 tc(e2 >= 0 ? Ellipsoid3(b, e2, k2, kp2) : Ellipsoid3(a, b, c));
193 std::cerr <<
"Cannot specify -3 for random points\n";
196 if (!ifile.empty() || !istring.empty()) {
198 <<
"Cannot specify --input-{string,file} with random points\n";
201 if (direction && threed) {
202 std::cerr <<
"Cannot specify both -3 and -D\n";
207 if (!ifile.empty() && !istring.empty()) {
208 std::cerr <<
"Cannot specify --input-string and --input-file together\n";
211 if (ifile ==
"-") ifile.clear();
212 std::ifstream infile;
213 std::istringstream instring;
214 if (!ifile.empty()) {
215 infile.open(ifile.c_str());
216 if (!infile.is_open()) {
217 std::cerr <<
"Cannot open " << ifile <<
" for reading\n";
220 }
else if (!istring.empty()) {
221 std::string::size_type m = 0;
223 m = istring.find(lsep, m);
224 if (m == std::string::npos)
228 instring.str(istring);
230 std::istream* input = !ifile.empty() ? &infile :
231 (!istring.empty() ? &instring : &std::cin);
233 std::ofstream outfile;
234 if (ofile ==
"-") ofile.clear();
235 if (!ofile.empty()) {
236 outfile.open(ofile.c_str());
237 if (!outfile.is_open()) {
238 std::cerr <<
"Cannot open " << ofile <<
" for writing\n";
242 std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
247 using std::round, std::log10, std::ceil, std::signbit;
248 int disprec = std::max(0, prec +
int(round(log10(6400000/b)))),
249 angprec = prec + 5, vecprec = prec + 7;
252 unsigned long long s1 = 0x4361727433436f6eULL, s2 = seed;
254 s1 = std::random_device()();
255 s2 = std::random_device()();
257 std::seed_seq seq{s1, s2};
259 for (
int i = 0; i < nrand; ++i) {
262 tc.cart2rand(g, r, v);
276 tc.cart2toany(r, v, mode, bet, omg, alp);
278 angprec, dms, dmssep, longfirst);
286 std::string s, eol, sbet, somg, salp, sh, sx, sy, sz, svx, svy, svz, strc;
287 std::istringstream str;
289 vec3 r = {0,0,0}, v = {0,0,0};
292 while (std::getline(*input, s)) {
295 if (!cdelim.empty()) {
296 std::string::size_type m = s.find(cdelim);
297 if (m != std::string::npos) {
298 eol =
" " + s.substr(m) +
"\n";
303 str.clear(); str.str(s);
305 if (!(str >> sx >> sy >> sz))
311 if (!(str >> svx >> svy >> svz))
318 if (!(str >> sbet >> somg))
321 if (mode != coord::ELLIPSOIDAL && (bet.
n() != 0 || signbit(bet.
c())))
322 throw GeographicErr(
"Latitude outside range [-90,90]: " + s);
327 }
else if (direction) {
338 tc.carttoany(r, mode, bet, omg, h);
340 tc.cart2toany(r, v, mode, bet, omg, alp);
342 tc.cart2toany(r, mode, bet, omg);
345 tc.anytocart(mode, bet, omg, h, r);
347 tc.anytocart2(mode, bet, omg, alp, r, v);
349 tc.anytocart2(mode, bet, omg, r);
354 angprec, dms, dmssep, longfirst);
371 catch (
const std::exception& e) {
373 *output <<
"ERROR: " << e.what() <<
"\n";
379 catch (
const std::exception& e) {
380 std::cerr <<
"Caught exception: " << e.what() <<
"\n";
384 std::cerr <<
"Caught unknown exception\n";