23int main(
int argc, 
const char* 
const argv[]) {
 
   27    Utility::set_digits();
 
   28    bool verbose = 
false, longfirst = 
false;
 
   30    std::string model = MagneticModel::DefaultMagneticName();
 
   31    std::string istring, ifile, ofile, cdelim;
 
   33    real time = 0, lat = 0, h = 0;
 
   34    bool timeset = 
false, circle = 
false, rate = 
false;
 
   35    real hguard = 500000, tguard = 50;
 
   36    int prec = 1, Nmax = -1, Mmax = -1;
 
   38    for (
int m = 1; m < argc; ++m) {
 
   39      std::string arg(argv[m]);
 
   41        if (++m == argc) 
return usage(1, 
true);
 
   43      } 
else if (arg == 
"-d") {
 
   44        if (++m == argc) 
return usage(1, 
true);
 
   46      } 
else if (arg == 
"-N") {
 
   47        if (++m == argc) 
return usage(1, 
true);
 
   49          Nmax = Utility::val<int>(std::string(argv[m]));
 
   51            std::cerr << 
"Maximum degree " << argv[m] << 
" is negative\n";
 
   55        catch (
const std::exception&) {
 
   56          std::cerr << 
"Precision " << argv[m] << 
" is not a number\n";
 
   59      } 
else if (arg == 
"-M") {
 
   60        if (++m == argc) 
return usage(1, 
true);
 
   62          Mmax = Utility::val<int>(std::string(argv[m]));
 
   64            std::cerr << 
"Maximum order " << argv[m] << 
" is negative\n";
 
   68        catch (
const std::exception&) {
 
   69          std::cerr << 
"Precision " << argv[m] << 
" is not a number\n";
 
   72      } 
else if (arg == 
"-t") {
 
   73        if (++m == argc) 
return usage(1, 
true);
 
   75          time = Utility::fractionalyear<real>(std::string(argv[m]));
 
   79        catch (
const std::exception& e) {
 
   80          std::cerr << 
"Error decoding argument of " << arg << 
": " 
   84      } 
else if (arg == 
"-c") {
 
   85        if (m + 3 >= argc) 
return usage(1, 
true);
 
   88          time = Utility::fractionalyear<real>(std::string(argv[++m]));
 
   90          lat = DMS::Decode(std::string(argv[++m]), ind);
 
   91          if (ind == DMS::LONGITUDE)
 
   93          if (!(fabs(lat) <= Math::qd))
 
   94            throw GeographicErr(
"Latitude not in [-" + std::to_string(Math::qd)
 
   95                                + 
"d, " + std::to_string(Math::qd) + 
"d]");
 
   96          h = Utility::val<real>(std::string(argv[++m]));
 
  100        catch (
const std::exception& e) {
 
  101          std::cerr << 
"Error decoding argument of " << arg << 
": " 
  105      } 
else if (arg == 
"-r")
 
  107      else if (arg == 
"-w")
 
  108        longfirst = !longfirst;
 
  109      else if (arg == 
"-p") {
 
  110        if (++m == argc) 
return usage(1, 
true);
 
  112          prec = Utility::val<int>(std::string(argv[m]));
 
  114        catch (
const std::exception&) {
 
  115          std::cerr << 
"Precision " << argv[m] << 
" is not a number\n";
 
  118      } 
else if (arg == 
"-T") {
 
  119        if (++m == argc) 
return usage(1, 
true);
 
  121          tguard = Utility::val<real>(std::string(argv[m]));
 
  123        catch (
const std::exception& e) {
 
  124          std::cerr << 
"Error decoding argument of " << arg << 
": " 
  128      } 
else if (arg == 
"-H") {
 
  129        if (++m == argc) 
return usage(1, 
true);
 
  131          hguard = Utility::val<real>(std::string(argv[m]));
 
  133        catch (
const std::exception& e) {
 
  134          std::cerr << 
"Error decoding argument of " << arg << 
": " 
  138      } 
else if (arg == 
"-v")
 
  140      else if (arg == 
"--input-string") {
 
  141        if (++m == argc) 
return usage(1, 
true);
 
  143      } 
else if (arg == 
"--input-file") {
 
  144        if (++m == argc) 
return usage(1, 
true);
 
  146      } 
else if (arg == 
"--output-file") {
 
  147        if (++m == argc) 
return usage(1, 
true);
 
  149      } 
else if (arg == 
"--line-separator") {
 
  150        if (++m == argc) 
return usage(1, 
true);
 
  151        if (std::string(argv[m]).size() != 1) {
 
  152          std::cerr << 
"Line separator must be a single character\n";
 
  156      } 
else if (arg == 
"--comment-delimiter") {
 
  157        if (++m == argc) 
return usage(1, 
true);
 
  159      } 
else if (arg == 
"--version") {
 
  160        std::cout << argv[0] << 
": GeographicLib version " 
  161                  << GEOGRAPHICLIB_VERSION_STRING << 
"\n";
 
  164        int retval = usage(!(arg == 
"-h" || arg == 
"--help"), arg != 
"--help");
 
  166          std::cout<< 
"\nDefault magnetic path = \"" 
  167                   << MagneticModel::DefaultMagneticPath()
 
  168                   << 
"\"\nDefault magnetic name = \"" 
  169                   << MagneticModel::DefaultMagneticName()
 
  175    if (!ifile.empty() && !istring.empty()) {
 
  176      std::cerr << 
"Cannot specify --input-string and --input-file together\n";
 
  179    if (ifile == 
"-") ifile.clear();
 
  180    std::ifstream infile;
 
  181    std::istringstream instring;
 
  182    if (!ifile.empty()) {
 
  183      infile.open(ifile.c_str());
 
  184      if (!infile.is_open()) {
 
  185        std::cerr << 
"Cannot open " << ifile << 
" for reading\n";
 
  188    } 
else if (!istring.empty()) {
 
  189      std::string::size_type m = 0;
 
  191        m = istring.find(lsep, m);
 
  192        if (m == std::string::npos)
 
  196      instring.str(istring);
 
  198    std::istream* input = !ifile.empty() ? &infile :
 
  199      (!istring.empty() ? &instring : &std::cin);
 
  201    std::ofstream outfile;
 
  202    if (ofile == 
"-") ofile.clear();
 
  203    if (!ofile.empty()) {
 
  204      outfile.open(ofile.c_str());
 
  205      if (!outfile.is_open()) {
 
  206        std::cerr << 
"Cannot open " << ofile << 
" for writing\n";
 
  210    std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
 
  213    tguard = fmax(
real(0), tguard);
 
  214    hguard = fmax(
real(0), hguard);
 
  215    prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
 
  219      const MagneticModel m(model, dir, Geocentric::WGS84(), Nmax, Mmax);
 
  220      if ((timeset || circle)
 
  221          && (!isfinite(time) ||
 
  225                            " too far outside allowed range [" +
 
  226                            Utility::str(m.
MinTime()) + 
"," +
 
  227                            Utility::str(m.
MaxTime()) + 
"]");
 
  233                            "km too far outside allowed range [" +
 
  234                            Utility::str(m.
MinHeight()/1000) + 
"km," +
 
  235                            Utility::str(m.
MaxHeight()/1000) + 
"km]");
 
  237        std::cerr << 
"Magnetic file: " << m.
MagneticFile()      << 
"\n" 
  240                  << 
"Date & Time: "   << m.
DateTime()          << 
"\n" 
  248      if ((timeset || circle) && (time < m.
MinTime() || time > m.
MaxTime()))
 
  249        std::cerr << 
"WARNING: Time " << time
 
  250                  << 
" outside allowed range [" 
  253        std::cerr << 
"WARNING: Height " << h/1000
 
  254                  << 
"km outside allowed range [" 
  259      std::string s, eol, stra, strb;
 
  260      std::istringstream str;
 
  261      while (std::getline(*input, s)) {
 
  264          if (!cdelim.empty()) {
 
  265            std::string::size_type n = s.find(cdelim);
 
  266            if (n != std::string::npos) {
 
  267              eol = 
" " + s.substr(n) + 
"\n";
 
  271          str.clear(); str.str(s);
 
  272          if (!(timeset || circle)) {
 
  275            time = Utility::fractionalyear<real>(stra);
 
  278                                  " too far outside allowed range [" +
 
  279                                  Utility::str(m.
MinTime()) + 
"," +
 
  283              std::cerr << 
"WARNING: Time " << time
 
  284                        << 
" outside allowed range [" 
  292            lon = DMS::Decode(strb, ind);
 
  293            if (ind == DMS::LATITUDE)
 
  296            if (!(str >> stra >> strb))
 
  298            DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
 
  303                                    "km too far outside allowed range [" +
 
  304                                    Utility::str(m.
MinHeight()/1000) + 
"km," +
 
  305                                    Utility::str(m.
MaxHeight()/1000) + 
"km]");
 
  307                std::cerr << 
"WARNING: Height " << h/1000
 
  308                          << 
"km outside allowed range [" 
  317          real bx, by, bz, bxt, byt, bzt;
 
  319            c(lon, bx, by, bz, bxt, byt, bzt);
 
  321            m(time, lat, lon, h, bx, by, bz, bxt, byt, bzt);
 
  322          real H, F, D, I, Ht, Ft, Dt, It;
 
  323          MagneticModel::FieldComponents(bx, by, bz, bxt, byt, bzt,
 
  324                                         H, F, D, I, Ht, Ft, Dt, It);
 
  326          *output << DMS::Encode(D, prec + 1, DMS::NUMBER) << 
" " 
  327                  << DMS::Encode(I, prec + 1, DMS::NUMBER) << 
" " 
  328                  << Utility::str(H, prec) << 
" " 
  329                  << Utility::str(by, prec) << 
" " 
  330                  << Utility::str(bx, prec) << 
" " 
  331                  << Utility::str(-bz, prec) << 
" " 
  332                  << Utility::str(F, prec) << eol;
 
  334            *output << DMS::Encode(Dt, prec + 1, DMS::NUMBER) << 
" " 
  335                    << DMS::Encode(It, prec + 1, DMS::NUMBER) << 
" " 
  336                    << Utility::str(Ht, prec) << 
" " 
  337                    << Utility::str(byt, prec) << 
" " 
  338                    << Utility::str(bxt, prec) << 
" " 
  339                    << Utility::str(-bzt, prec) << 
" " 
  340                    << Utility::str(Ft, prec) << eol;
 
  342        catch (
const std::exception& e) {
 
  343          *output << 
"ERROR: " << e.what() << 
"\n";
 
  348    catch (
const std::exception& e) {
 
  349      std::cerr << 
"Error reading " << model << 
": " << e.what() << 
"\n";
 
  354  catch (
const std::exception& e) {
 
  355    std::cerr << 
"Caught exception: " << e.what() << 
"\n";
 
  359    std::cerr << 
"Caught unknown exception\n";