00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <iostream>
00027 #include <string>
00028 #include <sstream>
00029 #include <fstream>
00030 #include <GeographicLib/PolygonArea.hpp>
00031 #include <GeographicLib/DMS.hpp>
00032 #include <GeographicLib/Utility.hpp>
00033 #include <GeographicLib/GeoCoords.hpp>
00034 #include <GeographicLib/Ellipsoid.hpp>
00035
00036 #if defined(_MSC_VER)
00037
00038 # pragma warning (disable: 4127)
00039 #endif
00040
00041 #include "Planimeter.usage"
00042
00043 int main(int argc, char* argv[]) {
00044 try {
00045 using namespace GeographicLib;
00046 typedef Math::real real;
00047 Utility::set_digits();
00048 real
00049 a = Constants::WGS84_a(),
00050 f = Constants::WGS84_f();
00051 bool reverse = false, sign = true, polyline = false,
00052 exact = false, authalic = false;
00053 int prec = 6;
00054 std::string istring, ifile, ofile, cdelim;
00055 char lsep = ';';
00056
00057 for (int m = 1; m < argc; ++m) {
00058 std::string arg(argv[m]);
00059 if (arg == "-r")
00060 reverse = !reverse;
00061 else if (arg == "-s")
00062 sign = !sign;
00063 else if (arg == "-l")
00064 polyline = !polyline;
00065 else if (arg == "-e") {
00066 if (m + 2 >= argc) return usage(1, true);
00067 try {
00068 a = Utility::num<real>(std::string(argv[m + 1]));
00069 f = Utility::fract<real>(std::string(argv[m + 2]));
00070 }
00071 catch (const std::exception& e) {
00072 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
00073 return 1;
00074 }
00075 m += 2;
00076 } else if (arg == "-p") {
00077 if (++m == argc) return usage(1, true);
00078 try {
00079 prec = Utility::num<int>(std::string(argv[m]));
00080 }
00081 catch (const std::exception&) {
00082 std::cerr << "Precision " << argv[m] << " is not a number\n";
00083 return 1;
00084 }
00085 } else if (arg == "-E") {
00086 exact = true;
00087 authalic = false;
00088 } else if (arg == "-Q") {
00089 exact = false;
00090 authalic = true;
00091 } else if (arg == "--input-string") {
00092 if (++m == argc) return usage(1, true);
00093 istring = argv[m];
00094 } else if (arg == "--input-file") {
00095 if (++m == argc) return usage(1, true);
00096 ifile = argv[m];
00097 } else if (arg == "--output-file") {
00098 if (++m == argc) return usage(1, true);
00099 ofile = argv[m];
00100 } else if (arg == "--line-separator") {
00101 if (++m == argc) return usage(1, true);
00102 if (std::string(argv[m]).size() != 1) {
00103 std::cerr << "Line separator must be a single character\n";
00104 return 1;
00105 }
00106 lsep = argv[m][0];
00107 } else if (arg == "--comment-delimiter") {
00108 if (++m == argc) return usage(1, true);
00109 cdelim = argv[m];
00110 } else if (arg == "--version") {
00111 std::cout
00112 << argv[0] << ": GeographicLib version "
00113 << GEOGRAPHICLIB_VERSION_STRING << "\n";
00114 return 0;
00115 } else
00116 return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
00117 }
00118
00119 if (!ifile.empty() && !istring.empty()) {
00120 std::cerr << "Cannot specify --input-string and --input-file together\n";
00121 return 1;
00122 }
00123 if (ifile == "-") ifile.clear();
00124 std::ifstream infile;
00125 std::istringstream instring;
00126 if (!ifile.empty()) {
00127 infile.open(ifile.c_str());
00128 if (!infile.is_open()) {
00129 std::cerr << "Cannot open " << ifile << " for reading\n";
00130 return 1;
00131 }
00132 } else if (!istring.empty()) {
00133 std::string::size_type m = 0;
00134 while (true) {
00135 m = istring.find(lsep, m);
00136 if (m == std::string::npos)
00137 break;
00138 istring[m] = '\n';
00139 }
00140 instring.str(istring);
00141 }
00142 std::istream* input = !ifile.empty() ? &infile :
00143 (!istring.empty() ? &instring : &std::cin);
00144
00145 std::ofstream outfile;
00146 if (ofile == "-") ofile.clear();
00147 if (!ofile.empty()) {
00148 outfile.open(ofile.c_str());
00149 if (!outfile.is_open()) {
00150 std::cerr << "Cannot open " << ofile << " for writing\n";
00151 return 1;
00152 }
00153 }
00154 std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
00155
00156 const Ellipsoid ellip(a, f);
00157 if (authalic) {
00158 using std::sqrt;
00159 a = sqrt(ellip.Area() / (4 * Math::pi()));
00160 f = 0;
00161 }
00162 const Geodesic geod(a, f);
00163 const GeodesicExact geode(a, f);
00164 PolygonArea poly(geod, polyline);
00165 PolygonAreaExact polye(geode, polyline);
00166 GeoCoords p;
00167
00168
00169
00170 prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
00171 std::string s;
00172 real perimeter, area;
00173 unsigned num;
00174 std::string eol("\n");
00175 while (std::getline(*input, s)) {
00176 if (!cdelim.empty()) {
00177 std::string::size_type m = s.find(cdelim);
00178 if (m != std::string::npos) {
00179 eol = " " + s.substr(m) + "\n";
00180 s = s.substr(0, m);
00181 }
00182 }
00183 bool endpoly = s.empty();
00184 if (!endpoly) {
00185 try {
00186 p.Reset(s);
00187 if (Math::isnan(p.Latitude()) || Math::isnan(p.Longitude()))
00188 endpoly = true;
00189 }
00190 catch (const GeographicErr&) {
00191 endpoly = true;
00192 }
00193 }
00194 if (endpoly) {
00195 num = exact ? polye.Compute(reverse, sign, perimeter, area) :
00196 poly.Compute(reverse, sign, perimeter, area);
00197 if (num > 0) {
00198 *output << num << " " << Utility::str(perimeter, prec);
00199 if (!polyline) {
00200 *output << " " << Utility::str(area, std::max(0, prec - 5));
00201 }
00202 *output << eol;
00203 }
00204 exact ? polye.Clear() : poly.Clear();
00205 eol = "\n";
00206 } else {
00207 exact ? polye.AddPoint(p.Latitude(), p.Longitude()) :
00208 poly.AddPoint(authalic ? ellip.AuthalicLatitude(p.Latitude()) :
00209 p.Latitude(),
00210 p.Longitude());
00211 }
00212 }
00213 num = exact ? polye.Compute(reverse, sign, perimeter, area):
00214 poly.Compute(reverse, sign, perimeter, area);
00215 if (num > 0) {
00216 *output << num << " " << Utility::str(perimeter, prec);
00217 if (!polyline) {
00218 *output << " " << Utility::str(area, std::max(0, prec - 5));
00219 }
00220 *output << eol;
00221 }
00222 exact ? polye.Clear() : poly.Clear();
00223 eol = "\n";
00224 return 0;
00225 }
00226 catch (const std::exception& e) {
00227 std::cerr << "Caught exception: " << e.what() << "\n";
00228 return 1;
00229 }
00230 catch (...) {
00231 std::cerr << "Caught unknown exception\n";
00232 return 1;
00233 }
00234 }