GeographicLib: IntersectTool.cpp Source File (original) (raw)
26int main(int argc, const char* const argv[]) {
27 try {
28 enum { CLOSE = 0, OFFSET, NEXT, SEGMENT };
33 maxdist = -1;
34 bool exact = false, check = false, longfirst = false;
35 int prec = 3, mode = CLOSE;
36 std::string istring, ifile, ofile, cdelim;
37 char lsep = ';';
38
39 for (int m = 1; m < argc; ++m) {
40 std::string arg(argv[m]);
41 if (arg == "-e") {
42 if (m + 2 >= argc) return usage(1, true);
43 try {
44 a = Utility::val(std::string(argv[m + 1]));
45 f = Utility::fract(std::string(argv[m + 2]));
46 }
47 catch (const std::exception& e) {
48 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
49 return 1;
50 }
51 m += 2;
52 } else if (arg == "-E")
53 exact = true;
54 else if (arg == "-p") {
55 if (++m == argc) return usage(1, true);
56 try {
57 prec = Utility::val(std::string(argv[m]));
58 }
59 catch (const std::exception&) {
60 std::cerr << "Precision " << argv[m] << " is not a number\n";
61 return 1;
62 }
63 } else if (arg == "-R") {
64 if (++m == argc) return usage(1, true);
65 try {
66 maxdist = Utility::val(std::string(argv[m]));
67 }
68 catch (const std::exception&) {
69 std::cerr << "Maxdist " << argv[m] << " is not a number\n";
70 return 1;
71 }
72 if (!(maxdist >= 0)) {
73 std::cerr << "Maxdist must be nonnegative\n";
74 return 1;
75 }
76 } else if (arg == "-c")
77 mode = CLOSE;
78 else if (arg == "-o")
79 mode = OFFSET;
80 else if (arg == "-n")
81 mode = NEXT;
82 else if (arg == "-i")
83 mode = SEGMENT;
84 else if (arg == "-C")
85 check = true;
86 else if (arg == "-w")
87 longfirst = true;
88 else if (arg == "--input-string") {
89 if (++m == argc) return usage(1, true);
90 istring = argv[m];
91 } else if (arg == "--input-file") {
92 if (++m == argc) return usage(1, true);
93 ifile = argv[m];
94 } else if (arg == "--output-file") {
95 if (++m == argc) return usage(1, true);
96 ofile = argv[m];
97 } else if (arg == "--line-separator") {
98 if (++m == argc) return usage(1, true);
99 if (std::string(argv[m]).size() != 1) {
100 std::cerr << "Line separator must be a single character\n";
101 return 1;
102 }
103 lsep = argv[m][0];
104 } else if (arg == "--comment-delimiter") {
105 if (++m == argc) return usage(1, true);
106 cdelim = argv[m];
107 } else if (arg == "--version") {
108 std::cout << argv[0] << ": GeographicLib version "
109 << GEOGRAPHICLIB_VERSION_STRING << "\n";
110 return 0;
111 } else
112 return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
113 }
114
115 if (!ifile.empty() && !istring.empty()) {
116 std::cerr << "Cannot specify --input-string and --input-file together\n";
117 return 1;
118 }
119 if (ifile == "-") ifile.clear();
120 std::ifstream infile;
121 std::istringstream instring;
122 if (!ifile.empty()) {
123 infile.open(ifile.c_str());
124 if (!infile.is_open()) {
125 std::cerr << "Cannot open " << ifile << " for reading\n";
126 return 1;
127 }
128 } else if (!istring.empty()) {
129 std:🧵:size_type m = 0;
130 while (true) {
131 m = istring.find(lsep, m);
132 if (m == std:🧵:npos)
133 break;
134 istring[m] = '\n';
135 }
136 instring.str(istring);
137 }
138 std::istream* input = !ifile.empty() ? &infile :
139 (!istring.empty() ? &instring : &std::cin);
140
141 std::ofstream outfile;
142 if (ofile == "-") ofile.clear();
143 if (!ofile.empty()) {
144 outfile.open(ofile.c_str());
145 if (!outfile.is_open()) {
146 std::cerr << "Cannot open " << ofile << " for writing\n";
147 return 1;
148 }
149 }
150 std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
151
154 real latX1, lonX1, aziX, latY1, lonY1, aziY, latX2, lonX2, latY2, lonY2,
155 x0 = 0, y0 = 0, x, y;
156 std::string inp[8], s, sc, eol;
157 std::istringstream str;
158 int retval = 0,
159 ninp = mode == CLOSE ? 6 : (mode == NEXT ? 4 :
160 8);
163 while (std::getline(*input, s)) {
164 try {
165 eol = "\n";
166 if (!cdelim.empty()) {
167 std:🧵:size_type m = s.find(cdelim);
168 if (m != std:🧵:npos) {
169 eol = " " + s.substr(m) + "\n";
170 s = s.substr(0, m);
171 }
172 }
173 str.clear(); str.str(s);
174 for (int i = 0; i < ninp; ++i) {
175 if (!(str >> inp[i]))
177 }
178 if (str >> sc)
180 if (mode == CLOSE || mode == OFFSET) {
185 if (mode == OFFSET) {
186 x0 = Utility::val(inp[6]);
187 y0 = Utility::val(inp[7]);
188 } else
189 x0 = y0 = 0;
190 lineX = geod.Line(latX1, lonX1, aziX, caps);
191 lineY = geod.Line(latY1, lonY1, aziY, caps);
192 } else if (mode == NEXT) {
196 lineX = geod.Line(latX1, lonX1, aziX, caps);
197 lineY = geod.Line(latX1, lonX1, aziY, caps);
198 } else {
203 lineX = geod.InverseLine(latX1, lonX1, latX2, lonX2,
205 lineY = geod.InverseLine(latY1, lonY1, latY2, lonY2,
209 }
210 std::pair<real, real> p0(x0, y0);
211 if (maxdist < 0) {
212 int segmode = 0, c;
213 auto p = mode == CLOSE || mode == OFFSET ?
214 intersect.Closest(lineX, lineY, p0, &c) :
215 mode == NEXT ? intersect.Next(lineX, lineY, &c) :
216 intersect.Segment(lineX, lineY, segmode, &c);
217 x = p.first; y = p.second;
220 if (mode == SEGMENT)
221 *output << " " << segmode;
222 *output << eol;
223 if (check) {
224 lineX.Position(x, latX2, lonX2);
225 lineY.Position(y, latY2, lonY2);
227 geod.Inverse(latX2, lonX2, latY2, lonY2, sXY);
228 std::cerr << Utility::str(longfirst ? lonX2 : latX2, prec+5) << " "
229 << Utility::str(longfirst ? latX2 : lonX2, prec+5) << " "
230 << Utility::str(longfirst ? lonY2 : latY2, prec+5) << " "
231 << Utility::str(longfirst ? latY2 : lonY2, prec+5) << " "
233 }
234 } else {
235 std::vector c;
236 auto v = intersect.All(lineX, lineY, maxdist, c, p0);
237 unsigned n = unsigned(v.size());
238 for (unsigned i = 0; i < n; ++i) {
239 x = v[i].first; y = v[i].second;
241 << " " << c[i] << " "
243 << eol;
244 if (check) {
245 lineX.Position(x, latX2, lonX2);
246 lineY.Position(y, latY2, lonY2);
248 geod.Inverse(latX2, lonX2, latY2, lonY2, sXY);
249 std::cerr << Utility::str(longfirst ? lonX2 : latX2, prec+5) << " "
250 << Utility::str(longfirst ? latX2 : lonX2, prec+5) << " "
251 << Utility::str(longfirst ? lonY2 : latY2, prec+5) << " "
252 << Utility::str(longfirst ? latY2 : lonY2, prec+5) << " "
254 }
255 }
256 *output << "nan nan 0 nan" << eol;
257 if (check)
258 std::cerr << "nan nan nan nan nan" << eol;
259 }
260 }
261 catch (const std::exception& e) {
262
263 *output << "ERROR: " << e.what() << "\n";
264 retval = 1;
265 }
266 }
267 return retval;
268 }
269 catch (const std::exception& e) {
270 std::cerr << "Caught exception: " << e.what() << "\n";
271 return 1;
272 }
273 catch (...) {
274 std::cerr << "Caught unknown exception\n";
275 return 1;
276 }
277}