GeographicLib
1.21
|
00001 /** 00002 * \file Planimeter.cpp 00003 * \brief Command line utility for measuring the area of geodesic polygons 00004 * 00005 * Copyright (c) Charles Karney (2010-2012) <charles@karney.com> and licensed 00006 * under the MIT/X11 License. For more information, see 00007 * http://geographiclib.sourceforge.net/ 00008 * 00009 * Compile and link with 00010 * g++ -g -O3 -I../include -I../man -o Planimeter \ 00011 * Planimeter.cpp \ 00012 * ../src/DMS.cpp \ 00013 * ../src/GeoCoords.cpp \ 00014 * ../src/Geodesic.cpp \ 00015 * ../src/GeodesicLine.cpp \ 00016 * ../src/MGRS.cpp \ 00017 * ../src/PolarStereographic.cpp \ 00018 * ../src/PolygonArea.cpp \ 00019 * ../src/TransverseMercator.cpp \ 00020 * ../src/UTMUPS.cpp 00021 * 00022 * See the <a href="Planimeter.1.html">man page</a> for usage 00023 * information. 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 00035 #include "Planimeter.usage" 00036 00037 int main(int argc, char* argv[]) { 00038 try { 00039 using namespace GeographicLib; 00040 typedef Math::real real; 00041 real 00042 a = Constants::WGS84_a<real>(), 00043 f = Constants::WGS84_f<real>(); 00044 bool reverse = false, sign = true, polyline = false; 00045 std::string istring, ifile, ofile, cdelim; 00046 char lsep = ';'; 00047 00048 for (int m = 1; m < argc; ++m) { 00049 std::string arg(argv[m]); 00050 if (arg == "-r") 00051 reverse = !reverse; 00052 else if (arg == "-s") 00053 sign = !sign; 00054 else if (arg == "-l") 00055 polyline = !polyline; 00056 else if (arg == "-e") { 00057 if (m + 2 >= argc) return usage(1, true); 00058 try { 00059 a = Utility::num<real>(std::string(argv[m + 1])); 00060 f = Utility::fract<real>(std::string(argv[m + 2])); 00061 } 00062 catch (const std::exception& e) { 00063 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n"; 00064 return 1; 00065 } 00066 m += 2; 00067 } else if (arg == "--input-string") { 00068 if (++m == argc) return usage(1, true); 00069 istring = argv[m]; 00070 } else if (arg == "--input-file") { 00071 if (++m == argc) return usage(1, true); 00072 ifile = argv[m]; 00073 } else if (arg == "--output-file") { 00074 if (++m == argc) return usage(1, true); 00075 ofile = argv[m]; 00076 } else if (arg == "--line-separator") { 00077 if (++m == argc) return usage(1, true); 00078 if (std::string(argv[m]).size() != 1) { 00079 std::cerr << "Line separator must be a single character\n"; 00080 return 1; 00081 } 00082 lsep = argv[m][0]; 00083 } else if (arg == "--comment-delimiter") { 00084 if (++m == argc) return usage(1, true); 00085 cdelim = argv[m]; 00086 } else if (arg == "--version") { 00087 std::cout 00088 << argv[0] 00089 << ": $Id: dbb8a9a0d79f172256044e72f65ebc667801eeac $\n" 00090 << "GeographicLib version " << GEOGRAPHICLIB_VERSION_STRING << "\n"; 00091 return 0; 00092 } else 00093 return usage(!(arg == "-h" || arg == "--help"), arg != "--help"); 00094 } 00095 00096 if (!ifile.empty() && !istring.empty()) { 00097 std::cerr << "Cannot specify --input-string and --input-file together\n"; 00098 return 1; 00099 } 00100 if (ifile == "-") ifile.clear(); 00101 std::ifstream infile; 00102 std::istringstream instring; 00103 if (!ifile.empty()) { 00104 infile.open(ifile.c_str()); 00105 if (!infile.is_open()) { 00106 std::cerr << "Cannot open " << ifile << " for reading\n"; 00107 return 1; 00108 } 00109 } else if (!istring.empty()) { 00110 std::string::size_type m = 0; 00111 while (true) { 00112 m = istring.find(lsep, m); 00113 if (m == std::string::npos) 00114 break; 00115 istring[m] = '\n'; 00116 } 00117 instring.str(istring); 00118 } 00119 std::istream* input = !ifile.empty() ? &infile : 00120 (!istring.empty() ? &instring : &std::cin); 00121 00122 std::ofstream outfile; 00123 if (ofile == "-") ofile.clear(); 00124 if (!ofile.empty()) { 00125 outfile.open(ofile.c_str()); 00126 if (!outfile.is_open()) { 00127 std::cerr << "Cannot open " << ofile << " for writing\n"; 00128 return 1; 00129 } 00130 } 00131 std::ostream* output = !ofile.empty() ? &outfile : &std::cout; 00132 00133 const Geodesic geod(a, f); 00134 PolygonArea poly(geod, polyline); 00135 GeoCoords p; 00136 00137 std::string s; 00138 real perimeter, area; 00139 unsigned num; 00140 std::string eol("\n"); 00141 while (std::getline(*input, s)) { 00142 if (!cdelim.empty()) { 00143 std::string::size_type m = s.find(cdelim); 00144 if (m != std::string::npos) { 00145 eol = " " + s.substr(m) + "\n"; 00146 s = s.substr(0, m); 00147 } 00148 } 00149 bool endpoly = s.empty(); 00150 if (!endpoly) { 00151 try { 00152 p.Reset(s); 00153 if (Math::isnan(p.Latitude()) || Math::isnan(p.Longitude())) 00154 endpoly = true; 00155 } 00156 catch (const GeographicErr&) { 00157 endpoly = true; 00158 } 00159 } 00160 if (endpoly) { 00161 num = poly.Compute(reverse, sign, perimeter, area); 00162 if (num > 0) { 00163 *output << num << " " 00164 << Utility::str<real>(perimeter, 8); 00165 if (!polyline) 00166 *output << " " << Utility::str<real>(area, 3); 00167 *output << eol; 00168 } 00169 poly.Clear(); 00170 eol = "\n"; 00171 } else 00172 poly.AddPoint(p.Latitude(), p.Longitude()); 00173 } 00174 num = poly.Compute(reverse, sign, perimeter, area); 00175 if (num > 0) { 00176 *output << num << " " 00177 << Utility::str<real>(perimeter, 8); 00178 if (!polyline) 00179 *output << " " << Utility::str<real>(area, 3); 00180 *output << eol; 00181 } 00182 poly.Clear(); 00183 eol = "\n"; 00184 return 0; 00185 } 00186 catch (const std::exception& e) { 00187 std::cerr << "Caught exception: " << e.what() << "\n"; 00188 return 1; 00189 } 00190 catch (...) { 00191 std::cerr << "Caught unknown exception\n"; 00192 return 1; 00193 } 00194 }