GeographicLib  1.35
Planimeter.cpp
Go to the documentation of this file.
1 /**
2  * \file Planimeter.cpp
3  * \brief Command line utility for measuring the area of geodesic polygons
4  *
5  * Copyright (c) Charles Karney (2010-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 Planimeter \
11  * Planimeter.cpp \
12  * ../src/DMS.cpp \
13  * ../src/GeoCoords.cpp \
14  * ../src/Geodesic.cpp \
15  * ../src/GeodesicLine.cpp \
16  * ../src/MGRS.cpp \
17  * ../src/PolarStereographic.cpp \
18  * ../src/PolygonArea.cpp \
19  * ../src/TransverseMercator.cpp \
20  * ../src/UTMUPS.cpp
21  *
22  * See the <a href="Planimeter.1.html">man page</a> for usage
23  * information.
24  **********************************************************************/
25 
26 #include <iostream>
27 #include <string>
28 #include <sstream>
29 #include <fstream>
31 #include <GeographicLib/DMS.hpp>
34 
35 #if defined(_MSC_VER)
36 // Squelch warnings about constant conditional expressions
37 # pragma warning (disable: 4127)
38 #endif
39 
40 #include "Planimeter.usage"
41 
42 int main(int argc, char* argv[]) {
43  try {
44  using namespace GeographicLib;
45  typedef Math::real real;
46  real
47  a = Constants::WGS84_a<real>(),
48  f = Constants::WGS84_f<real>();
49  bool reverse = false, sign = true, polyline = false;
50  std::string istring, ifile, ofile, cdelim;
51  char lsep = ';';
52 
53  for (int m = 1; m < argc; ++m) {
54  std::string arg(argv[m]);
55  if (arg == "-r")
56  reverse = !reverse;
57  else if (arg == "-s")
58  sign = !sign;
59  else if (arg == "-l")
60  polyline = !polyline;
61  else if (arg == "-e") {
62  if (m + 2 >= argc) return usage(1, true);
63  try {
64  a = Utility::num<real>(std::string(argv[m + 1]));
65  f = Utility::fract<real>(std::string(argv[m + 2]));
66  }
67  catch (const std::exception& e) {
68  std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
69  return 1;
70  }
71  m += 2;
72  } else if (arg == "--input-string") {
73  if (++m == argc) return usage(1, true);
74  istring = argv[m];
75  } else if (arg == "--input-file") {
76  if (++m == argc) return usage(1, true);
77  ifile = argv[m];
78  } else if (arg == "--output-file") {
79  if (++m == argc) return usage(1, true);
80  ofile = argv[m];
81  } else if (arg == "--line-separator") {
82  if (++m == argc) return usage(1, true);
83  if (std::string(argv[m]).size() != 1) {
84  std::cerr << "Line separator must be a single character\n";
85  return 1;
86  }
87  lsep = argv[m][0];
88  } else if (arg == "--comment-delimiter") {
89  if (++m == argc) return usage(1, true);
90  cdelim = argv[m];
91  } else if (arg == "--version") {
92  std::cout
93  << argv[0] << ": GeographicLib version "
94  << GEOGRAPHICLIB_VERSION_STRING << "\n";
95  return 0;
96  } else
97  return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
98  }
99 
100  if (!ifile.empty() && !istring.empty()) {
101  std::cerr << "Cannot specify --input-string and --input-file together\n";
102  return 1;
103  }
104  if (ifile == "-") ifile.clear();
105  std::ifstream infile;
106  std::istringstream instring;
107  if (!ifile.empty()) {
108  infile.open(ifile.c_str());
109  if (!infile.is_open()) {
110  std::cerr << "Cannot open " << ifile << " for reading\n";
111  return 1;
112  }
113  } else if (!istring.empty()) {
114  std::string::size_type m = 0;
115  while (true) {
116  m = istring.find(lsep, m);
117  if (m == std::string::npos)
118  break;
119  istring[m] = '\n';
120  }
121  instring.str(istring);
122  }
123  std::istream* input = !ifile.empty() ? &infile :
124  (!istring.empty() ? &instring : &std::cin);
125 
126  std::ofstream outfile;
127  if (ofile == "-") ofile.clear();
128  if (!ofile.empty()) {
129  outfile.open(ofile.c_str());
130  if (!outfile.is_open()) {
131  std::cerr << "Cannot open " << ofile << " for writing\n";
132  return 1;
133  }
134  }
135  std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
136 
137  const Geodesic geod(a, f);
138  PolygonArea poly(geod, polyline);
139  GeoCoords p;
140 
141  std::string s;
142  real perimeter, area;
143  unsigned num;
144  std::string eol("\n");
145  while (std::getline(*input, s)) {
146  if (!cdelim.empty()) {
147  std::string::size_type m = s.find(cdelim);
148  if (m != std::string::npos) {
149  eol = " " + s.substr(m) + "\n";
150  s = s.substr(0, m);
151  }
152  }
153  bool endpoly = s.empty();
154  if (!endpoly) {
155  try {
156  p.Reset(s);
157  if (Math::isnan(p.Latitude()) || Math::isnan(p.Longitude()))
158  endpoly = true;
159  }
160  catch (const GeographicErr&) {
161  endpoly = true;
162  }
163  }
164  if (endpoly) {
165  num = poly.Compute(reverse, sign, perimeter, area);
166  if (num > 0) {
167  *output << num << " "
168  << Utility::str<real>(perimeter, 8 + Math::extradigits+1);
169  if (!polyline)
170  *output << " " << Utility::str<real>(area, 3 + Math::extradigits+1);
171  *output << eol;
172  }
173  poly.Clear();
174  eol = "\n";
175  } else
176  poly.AddPoint(p.Latitude(), p.Longitude());
177  }
178  num = poly.Compute(reverse, sign, perimeter, area);
179  if (num > 0) {
180  *output << num << " "
181  << Utility::str<real>(perimeter, 8 + Math::extradigits+1);
182  if (!polyline)
183  *output << " " << Utility::str<real>(area, 3 + Math::extradigits+1);
184  *output << eol;
185  }
186  poly.Clear();
187  eol = "\n";
188  return 0;
189  }
190  catch (const std::exception& e) {
191  std::cerr << "Caught exception: " << e.what() << "\n";
192  return 1;
193  }
194  catch (...) {
195  std::cerr << "Caught unknown exception\n";
196  return 1;
197  }
198 }
GeographicLib::Math::real real
Definition: GeodSolve.cpp:40
Header for GeographicLib::Utility class.
static bool isnan(T x)
Definition: Math.hpp:486
int main(int argc, char *argv[])
Definition: Planimeter.cpp:42
Conversion between geographic coordinates.
Definition: GeoCoords.hpp:49
static const int extradigits
Definition: Math.hpp:113
Header for GeographicLib::GeoCoords class.
Header for GeographicLib::PolygonArea class.
Exception handling for GeographicLib.
Definition: Constants.hpp:320
unsigned Compute(bool reverse, bool sign, real &perimeter, real &area) const
Definition: PolygonArea.cpp:49
Geodesic calculations
Definition: Geodesic.hpp:169
void AddPoint(real lat, real lon)
Definition: PolygonArea.cpp:16
Header for GeographicLib::DMS class.