GeographicLib: GeodSolve.cpp Source File (original) (raw)

31 bool longfirst) {

33 std::string

34 latstr = dms ? DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) :

35 DMS::Encode(lat, prec + 5, DMS::NUMBER),

36 lonstr = dms ? DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :

37 DMS::Encode(lon, prec + 5, DMS::NUMBER);

38 return

39 (longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);

40}

44 return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :

45 DMS::Encode(azi, prec + 5, DMS::NUMBER);

46}

49 bool full, bool arcmode, int prec, bool dms) {

51 std::string s;

52 if (full || !arcmode)

53 s += Utility::str(s12, prec);

54 if (full)

55 s += " ";

56 if (full || arcmode)

57 s += DMS::Encode(a12, prec + 5, dms ? DMS::NONE : DMS::NUMBER);

58 return s;

59}

61real ReadDistance(const std::string& s, bool arcmode, bool fraction = false) {

63 return fraction ? Utility::fract(s) :

64 (arcmode ? DMS::DecodeAngle(s) : Utility::val(s));

65}

67int main(int argc, const char* const argv[]) {

68 try {

70 enum { NONE = 0, LINE, DIRECT, INVERSE };

71 Utility::set_digits();

72 bool inverse = false, arcmode = false,

73 dms = false, full = false, exact = false, unroll = false,

74 longfirst = false, azi2back = false, fraction = false,

75 arcmodeline = false;

77 a = Constants::WGS84_a(),

78 f = Constants::WGS84_f();

79 real lat1, lon1, azi1, lat2, lon2, azi2, s12, m12, a12, M12, M21, S12,

80 mult = 1;

81 int linecalc = NONE, prec = 3;

82 std::string istring, ifile, ofile, cdelim;

83 char lsep = ';', dmssep = char(0);

84

85 for (int m = 1; m < argc; ++m) {

86 std::string arg(argv[m]);

87 if (arg == "-i") {

88 inverse = true;

89 linecalc = NONE;

90 } else if (arg == "-a")

91 arcmode = !arcmode;

92 else if (arg == "-F")

93 fraction = true;

94 else if (arg == "-L") {

95 inverse = false;

96 linecalc = LINE;

97 if (m + 3 >= argc) return usage(1, true);

98 try {

99 DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),

100 lat1, lon1, longfirst);

101 azi1 = DMS::DecodeAzimuth(std::string(argv[m + 3]));

102 }

103 catch (const std::exception& e) {

104 std::cerr << "Error decoding arguments of -L: " << e.what() << "\n";

105 return 1;

106 }

107 m += 3;

108 } else if (arg == "-D") {

109 inverse = false;

110 linecalc = DIRECT;

111 if (m + 4 >= argc) return usage(1, true);

112 try {

113 DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),

114 lat1, lon1, longfirst);

115 azi1 = DMS::DecodeAzimuth(std::string(argv[m + 3]));

116 s12 = ReadDistance(std::string(argv[m + 4]), arcmode);

117 arcmodeline = arcmode;

118 }

119 catch (const std::exception& e) {

120 std::cerr << "Error decoding arguments of -D: " << e.what() << "\n";

121 return 1;

122 }

123 m += 4;

124 } else if (arg == "-I") {

125 inverse = false;

126 linecalc = INVERSE;

127 if (m + 4 >= argc) return usage(1, true);

128 try {

129 DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),

130 lat1, lon1, longfirst);

131 DMS::DecodeLatLon(std::string(argv[m + 3]), std::string(argv[m + 4]),

132 lat2, lon2, longfirst);

133 }

134 catch (const std::exception& e) {

135 std::cerr << "Error decoding arguments of -I: " << e.what() << "\n";

136 return 1;

137 }

138 m += 4;

139 } else if (arg == "-e") {

140 if (m + 2 >= argc) return usage(1, true);

141 try {

142 a = Utility::val(std::string(argv[m + 1]));

143 f = Utility::fract(std::string(argv[m + 2]));

144 }

145 catch (const std::exception& e) {

146 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";

147 return 1;

148 }

149 m += 2;

150 } else if (arg == "-u")

151 unroll = true;

152 else if (arg == "-d") {

153 dms = true;

154 dmssep = '\0';

155 } else if (arg == "-:") {

156 dms = true;

157 dmssep = ':';

158 } else if (arg == "-w")

159 longfirst = !longfirst;

160 else if (arg == "-b")

161 azi2back = true;

162 else if (arg == "-f")

163 full = true;

164 else if (arg == "-p") {

165 if (++m == argc) return usage(1, true);

166 try {

167 prec = Utility::val(std::string(argv[m]));

168 }

169 catch (const std::exception&) {

170 std::cerr << "Precision " << argv[m] << " is not a number\n";

171 return 1;

172 }

173 } else if (arg == "-E")

174 exact = true;

175 else if (arg == "--input-string") {

176 if (++m == argc) return usage(1, true);

177 istring = argv[m];

178 } else if (arg == "--input-file") {

179 if (++m == argc) return usage(1, true);

180 ifile = argv[m];

181 } else if (arg == "--output-file") {

182 if (++m == argc) return usage(1, true);

183 ofile = argv[m];

184 } else if (arg == "--line-separator") {

185 if (++m == argc) return usage(1, true);

186 if (std::string(argv[m]).size() != 1) {

187 std::cerr << "Line separator must be a single character\n";

188 return 1;

189 }

190 lsep = argv[m][0];

191 } else if (arg == "--comment-delimiter") {

192 if (++m == argc) return usage(1, true);

193 cdelim = argv[m];

194 } else if (arg == "--version") {

195 std::cout << argv[0] << ": GeographicLib version "

196 << GEOGRAPHICLIB_VERSION_STRING << "\n";

197 return 0;

198 } else

199 return usage(!(arg == "-h" || arg == "--help"), arg != "--help");

200 }

201

202 if (!ifile.empty() && !istring.empty()) {

203 std::cerr << "Cannot specify --input-string and --input-file together\n";

204 return 1;

205 }

206 if (ifile == "-") ifile.clear();

207 std::ifstream infile;

208 std::istringstream instring;

209 if (!ifile.empty()) {

210 infile.open(ifile.c_str());

211 if (!infile.is_open()) {

212 std::cerr << "Cannot open " << ifile << " for reading\n";

213 return 1;

214 }

215 } else if (!istring.empty()) {

216 std:🧵:size_type m = 0;

217 while (true) {

218 m = istring.find(lsep, m);

219 if (m == std:🧵:npos)

220 break;

221 istring[m] = '\n';

222 }

223 instring.str(istring);

224 }

225 std::istream* input = !ifile.empty() ? &infile :

226 (!istring.empty() ? &instring : &std::cin);

227

228 std::ofstream outfile;

229 if (ofile == "-") ofile.clear();

230 if (!ofile.empty()) {

231 outfile.open(ofile.c_str());

232 if (!outfile.is_open()) {

233 std::cerr << "Cannot open " << ofile << " for writing\n";

234 return 1;

235 }

236 }

237 std::ostream* output = !ofile.empty() ? &outfile : &std::cout;

238

239 unsigned outmask = Geodesic::LATITUDE | Geodesic::LONGITUDE |

240 Geodesic::AZIMUTH;

241 outmask |= inverse ? Geodesic::DISTANCE :

242 (arcmode ? Geodesic::NONE : Geodesic::DISTANCE_IN);

243

244 outmask |= unroll ? Geodesic::LONG_UNROLL : Geodesic::NONE;

245

246 outmask |= full ? (Geodesic::DISTANCE | Geodesic::REDUCEDLENGTH |

247 Geodesic::GEODESICSCALE | Geodesic::AREA) :

248 Geodesic::NONE;

249

250 const Geodesic geods(a, f, exact);

252 if (linecalc) {

253 if (linecalc == LINE) fraction = false;

254 ls = linecalc == DIRECT ?

255 geods.GenDirectLine(lat1, lon1, azi1, arcmodeline, s12, outmask) :

256 linecalc == INVERSE ?

257 geods.InverseLine(lat1, lon1, lat2, lon2, outmask) :

258

259 geods.Line(lat1, lon1, azi1, outmask);

260 mult = fraction ? ls.GenDistance(arcmode) : 1;

261 if (linecalc == INVERSE) azi1 = ls.Azimuth();

262 }

263

264

265

266 prec = std::min(10 + Math::extra_digits(), std::max(0, prec));

267 std::string s, eol, slat1, slon1, slat2, slon2, sazi1, ss12, strc;

268 std::istringstream str;

269 int retval = 0;

270 while (std::getline(*input, s)) {

271 try {

272 eol = "\n";

273 if (!cdelim.empty()) {

274 std:🧵:size_type m = s.find(cdelim);

275 if (m != std:🧵:npos) {

276 eol = " " + s.substr(m) + "\n";

277 s = s.substr(0, m);

278 }

279 }

280 str.clear(); str.str(s);

281 if (inverse) {

282 if (!(str >> slat1 >> slon1 >> slat2 >> slon2))

284 if (str >> strc)

285 throw GeographicErr("Extraneous input: " + strc);

286 DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);

287 DMS::DecodeLatLon(slat2, slon2, lat2, lon2, longfirst);

288 a12 = geods.GenInverse(lat1, lon1, lat2, lon2, outmask,

289 s12, azi1, azi2, m12, M12, M21, S12);

290 if (full) {

291 if (unroll) {

293 lon2 = lon1 + Math::AngDiff(lon1, lon2, e);

294 lon2 += e;

295 } else {

296 lon1 = Math::AngNormalize(lon1);

297 lon2 = Math::AngNormalize(lon2);

298 }

299 *output << LatLonString(lat1, lon1, prec, dms, dmssep, longfirst)

300 << " ";

301 }

302 *output << AzimuthString(azi1, prec, dms, dmssep) << " ";

303 if (full)

304 *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)

305 << " ";

306 if (azi2back) {

307 using std::copysign;

308

309

310 azi2 = copysign(azi2 + copysign(real(Math::hd), -azi2), -azi2);

311 }

312 *output << AzimuthString(azi2, prec, dms, dmssep) << " "

314 if (full)

315 *output << " " << Utility::str(m12, prec)

316 << " " << Utility::str(M12, prec+7)

317 << " " << Utility::str(M21, prec+7)

318 << " " << Utility::str(S12, std::max(prec-7, 0));

319 *output << eol;

320 } else {

321 if (linecalc) {

322 if (!(str >> ss12))

324 if (str >> strc)

325 throw GeographicErr("Extraneous input: " + strc);

326

327 s12 = ReadDistance(ss12, !fraction && arcmode, fraction) * mult;

328 a12 = ls.GenPosition(arcmode, s12, outmask,

329 lat2, lon2, azi2, s12, m12, M12, M21, S12);

330 } else {

331 if (!(str >> slat1 >> slon1 >> sazi1 >> ss12))

333 if (str >> strc)

334 throw GeographicErr("Extraneous input: " + strc);

335 DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);

336 azi1 = DMS::DecodeAzimuth(sazi1);

338 a12 = geods.GenDirect(lat1, lon1, azi1, arcmode, s12, outmask,

339 lat2, lon2, azi2, s12, m12, M12, M21, S12);

340 }

341 if (full)

342 *output

343 << LatLonString(lat1, unroll ? lon1 : Math::AngNormalize(lon1),

344 prec, dms, dmssep, longfirst)

345 << " " << AzimuthString(azi1, prec, dms, dmssep) << " ";

346 if (azi2back) {

347 using std::copysign;

348

349

350 azi2 = copysign(azi2 + copysign(real(Math::hd), -azi2), -azi2);

351 }

352 *output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)

353 << " " << AzimuthString(azi2, prec, dms, dmssep);

354 if (full)

355 *output << " "

357 << " " << Utility::str(m12, prec)

358 << " " << Utility::str(M12, prec+7)

359 << " " << Utility::str(M21, prec+7)

360 << " " << Utility::str(S12, std::max(prec-7, 0));

361 *output << eol;

362 }

363 }

364 catch (const std::exception& e) {

365

366 *output << "ERROR: " << e.what() << "\n";

367 retval = 1;

368 }

369 }

370 return retval;

371 }

372 catch (const std::exception& e) {

373 std::cerr << "Caught exception: " << e.what() << "\n";

374 return 1;

375 }

376 catch (...) {

377 std::cerr << "Caught unknown exception\n";

378 return 1;

379 }

380}