22 , _a(_geod.EquatorialRadius())
23 , _f(_geod.Flattening())
24 , _R(sqrt(_geod.EllipsoidArea() / (4 *
Math::pi())))
26 , _eps(3 * numeric_limits<real>::epsilon())
27 , _tol(_d * pow(numeric_limits<real>::epsilon(), 3/real(4)))
28 , _delta(_d * pow(numeric_limits<real>::epsilon(), 1/real(5)))
36 _t1 = _t4 = _a * (1 - _f) *
Math::pi();
37 _t2 = 2 * distpolar(90);
38 _geod.
Inverse(0, 0, 90, 0, _t5); _t5 *= 2;
50 if (! (_d1 < _d3 && _d2 < _d3 && _d2 < 2 * _t1) )
66 XPoint p = ClosestInt(lineX, lineY, XPoint(p0));
76 int& segmode,
int* c)
const {
85 XPoint p = SegmentInt(lineX, lineY, segmode);
100 XPoint p = NextInt(lineX, lineY);
105 std::vector<Intersect::Point>
114 std::vector<Intersect::Point>
124 std::vector<Intersect::Point>
128 return AllInternal(lineX, lineY, maxdist, p0, c,
false);
131 std::vector<Intersect::Point>
135 return AllInternal(lineX, lineY, maxdist, p0, c,
true);
140 const Intersect::XPoint& p)
const {
143 real latX, lonX, aziX, latY, lonY, aziY;
144 lineX.
Position(p.x , latX, lonX, aziX);
145 lineY.
Position(p.y, latY, lonY, aziY);
146 real z, aziXa, aziYa;
147 _geod.
Inverse(latX, lonX, latY, lonY, z, aziXa, aziYa);
148 real sinz = sin(z/_R), cosz = cos(z/_R);
153 real s = copysign(
real(1), XY + (dXY + dY - dX));
164 if (z <= _eps * _R) {
167 if (fabs(sinX - sinY) <= _eps && fabs(cosX - cosY) <= _eps)
169 else if (fabs(sinX + sinY) <= _eps && fabs(cosX + cosY) <= _eps)
173 }
else if (fabs(sinX) <= _eps && fabs(sinY) <= _eps) {
174 c = cosX * cosY > 0 ? 1 : -1;
176 sX = cosX * z/2; sY = -cosY * z/2;
184 sX = _R * atan2(sinY * sinz, sinY * cosX * cosz - cosY * sinX);
185 sY = _R * atan2(sinX * sinz, -sinX * cosY * cosz + cosX * sinY);
188 return XPoint(sX, sY, c);
192 Intersect::Basic(
const GeodesicLine& lineX,
const GeodesicLine& lineY,
193 const Intersect::XPoint& p0)
const {
198 XPoint dq = Spherical(lineX, lineY, q);
200 if (q.c || !(dq.Dist() > _tol))
break;
206 Intersect::ClosestInt(
const GeodesicLine& lineX,
const GeodesicLine& lineY,
207 const Intersect::XPoint& p0)
const {
209 const int ix[num] = { 0, 1, -1, 0, 0 };
210 const int iy[num] = { 0, 0, 0, 1, -1 };
211 bool skip[num] = { 0, 0, 0, 0, 0 };
213 for (
int n = 0; n < num; ++n) {
214 if (skip[n])
continue;
215 XPoint qx = Basic(lineX, lineY, p0 + XPoint(ix[n] * _d1, iy[n] * _d1));
216 qx = fixcoincident(p0, qx);
217 if (_comp.eq(q, qx))
continue;
218 if (qx.Dist(p0) < _t1) { q = qx; ++_cnt2;
break; }
219 if (n == 0 || qx.Dist(p0) < q.Dist(p0)) { q = qx; ++_cnt2; }
220 for (
int m = n + 1; m < num; ++m)
222 qx.Dist(p0 + XPoint(ix[m]*_d1, iy[m]*_d1)) < 2*_t1 - _d1 - _delta;
228 Intersect::NextInt(
const GeodesicLine& lineX,
const GeodesicLine& lineY)
231 const int ix[num] = { -1, -1, 1, 1, -2, 0, 2, 0 };
232 const int iy[num] = { -1, 1, -1, 1, 0, 2, 0, -2 };
233 bool skip[num] = { 0, 0, 0, 0, 0, 0, 0, 0 };
236 for (
int n = 0; n < num; ++n) {
237 if (skip[n])
continue;
238 XPoint qx = Basic(lineX, lineY, XPoint(ix[n] * _d2, iy[n] * _d2));
239 qx = fixcoincident(z, qx);
240 bool zerop = _comp.eq(z, qx);
241 if (qx.c == 0 && zerop)
continue;
243 for (
int sgn = -1; sgn <= 1; sgn+=2) {
244 real s = ConjugateDist(lineX, sgn * _d,
false);
245 XPoint qa(s, qx.c*s, qx.c);
246 if (qa.Dist() < q.Dist()) { q = qa; ++_cnt2; }
249 if (qx.Dist() < q.Dist()) { q = qx; ++_cnt2; }
251 for (
int sgn = -1; sgn <= 1; ++sgn) {
254 if ((qx.c == 0 && sgn != 0) || (zerop && sgn == 0))
continue;
255 XPoint qy = qx.c ? qx +
Point(sgn * _d2, qx.c * sgn *_d2) : qx;
256 for (
int m = n + 1; m < num; ++m)
258 qy.Dist(XPoint(ix[m]*_d2, iy[m]*_d2)) < 2*_t1 - _d2 - _delta;
265 Intersect::SegmentInt(
const GeodesicLine& lineX,
const GeodesicLine& lineY,
266 int& segmode)
const {
270 const bool conjectureproved =
false;
271 real sx = lineX.Distance(), sy = lineY.Distance();
273 XPoint p0 = XPoint(sx/2, sy/2), q = ClosestInt(lineX, lineY, p0);
274 q = fixsegment(sx, sy, q);
275 segmode = segmentmode(sx, sy, q);
277 if (!conjectureproved && segmode != 0 && p0.Dist() >= p0.Dist(q)) {
281 for (
int ix = 0; ix < 2 && segmodex != 0; ++ix) {
282 for (
int iy = 0; iy < 2 && segmodex != 0; ++iy) {
283 XPoint t(ix * sx, iy * sy);
285 if (q.Dist(t) >= 2 * _t1) {
287 qx = Basic(lineX, lineY, t);
290 qx = fixcoincident(t, qx);
293 segmodex = segmentmode(sx, sy, qx);
297 if (segmodex == 0) { ++_cnt4; segmode = 0; q = qx; }
302 std::vector<Intersect::XPoint>
303 Intersect::AllInt0(
const GeodesicLine& lineX,
304 const GeodesicLine& lineY,
306 real maxdistx = maxdist + _delta;
307 const int m = int(ceil(maxdistx / _d3)),
308 m2 = m*m + (m - 1) % 2,
310 real d3 = maxdistx/m;
311 vector<XPoint> start(m2);
312 vector<bool> skip(m2,
false);
315 for (
int i = -n; i <= n; i += 2)
316 for (
int j = -n; j <= n; j += 2) {
317 if (!(i == 0 && j == 0))
318 start[h++] = p0 + XPoint( d3 * (i + j) / 2, d3 * (i - j) / 2);
321 set<XPoint, SetComp> r(_comp);
322 set<XPoint, SetComp> c(_comp);
323 vector<XPoint> added;
324 for (
int k = 0; k < m2; ++k) {
325 if (skip[k])
continue;
326 XPoint q = Basic(lineX, lineY, start[k]);
327 if (r.find(q) != r.end()
329 || (c0 != 0 && c.find(fixcoincident(p0, q)) != c.end()))
337 q = fixcoincident(p0, q);
341 for (
auto qp = r.begin(); qp != r.end(); ) {
342 if (_comp.eq(fixcoincident(p0, *qp, c0), q)) {
350 real t, m12, M12, M21;
351 lineX.GenPosition(
false, s0,
354 t, t, t, t, m12, M12, M21, t);
356 for (
int sgn = -1; sgn <= 1; sgn += 2) {
359 sa = ConjugateDist(lineX, s0 + sa + sgn*_d,
false, m12, M12, M21)
361 qc = q + XPoint(sa, c0*sa);
364 }
while (qc.Dist(p0) <= maxdistx);
369 for (
auto qp = added.cbegin(); qp != added.cend(); ++qp) {
370 for (
int l = k + 1; l < m2; ++l)
371 skip[l] = skip[l] || qp->Dist(start[l]) < 2*_t1 - d3 - _delta;
375 for (
auto qp = r.begin(); qp != r.end(); ) {
376 if (!(qp->Dist(p0) <= maxdist))
381 vector<XPoint> v(r.size());
383 for (
auto p = r.cbegin(); p != r.cend(); ++p)
385 sort(v.begin(), v.end(), RankPoint(p0));
389 std::vector<Intersect::Point>
390 Intersect::AllInternal(
const GeodesicLine& lineX,
const GeodesicLine& lineY,
392 std::vector<int>& c,
bool cp)
const {
394 v = AllInt0(lineX, lineY, fmax(
real(0), maxdist), XPoint(p0));
395 int i = int(v.size());
398 for (
int j = 0; j < i; ++j) {
400 if (cp) c[j] = v[j].c;
407 GeodesicLine line = _geod.
Line(lat1, 0, 0,
411 real s = ConjugateDist(line, (1 + _f/2) * _a *
Math::pi() / 2,
true);
415 *lat2, t, t, t, t, t, t, t);
422 if (lata) *lata = 64;
423 if (latb) *latb = 90-64;
427 lat0 = 63, s0 = distpolar(lat0),
428 lat1 = 65, s1 = distpolar(lat1),
429 lat2 = 64, s2 = distpolar(lat2),
430 latx = lat2, sx = s2;
432 for (
int i = 0; i < 10; ++i) {
433 real den = (lat1-lat0)*s2 + (lat0-lat2)*s1 + (lat2-lat1)*s0;
434 if (!(den < 0 || den > 0))
break;
435 real latn = ((lat1-lat0)*(lat1+lat0)*s2 + (lat0-lat2)*(lat0+lat2)*s1 +
436 (lat2-lat1)*(lat2+lat1)*s0) / (2*den);
437 lat0 = lat1; s0 = s1;
438 lat1 = lat2; s1 = s2;
439 lat2 = latn; s2 = distpolar(lat2);
440 if (_f < 0 ? (s2 < sx) : (s2 > sx)) {
445 if (lata) *lata = latx;
446 if (latb) distpolar(latx, latb);
459 for (
int i = 0; i < 100; ++i) {
460 real t, m13, M13, M31;
461 line.GenPosition(
false, s,
464 t, t, t, t, m13, M13, M31, t);
467 m23 = m13 * M12 - m12 * M13,
469 M23 = M13 * M21 + (m12 == 0 ? 0 : (1 - M12 * M21) * m13/m12),
470 M32 = M31 * M12 + (m13 == 0 ? 0 : (1 - M13 * M31) * m12/m13);
471 real ds = semi ? m23 * M23 / (1 - M23*M32) : -m23 / M32;
473 if (!(fabs(ds) > _tol))
break;
482 real s = ConjugateDist(line, _d,
false);
484 XPoint p = Basic(line, line, XPoint(s/2, -3*s/2));
487 *ds = p.Dist() - 2*s;
502 azi0 = 46, ds0, s0 = conjdist(azi0, &ds0, &sa, &sb),
503 azi1 = 44, ds1, s1 = conjdist(azi1, &ds1, &sa, &sb),
504 azix = azi1, dsx = fabs(ds1), sx = s1, sax = sa, sbx = sb;
507 for (
int i = 0; i < 10 && ds1 != ds0; ++i) {
508 real azin = (azi0*ds1-azi1*ds0)/(ds1-ds0);
509 azi0 = azi1; s0 = s1; ds0 = ds1;
510 azi1 = azin; s1 = conjdist(azi1, &ds1, &sa, &sb);
511 if (fabs(ds1) < dsx) {
512 azix = azi1, sx = s1, dsx = fabs(ds1);
517 if (azi) *azi = azix;
524 Intersect::fixcoincident(
const Intersect::XPoint& p0,
525 const Intersect::XPoint& p) {
526 return fixcoincident(p0, p, p.c);
530 Intersect::fixcoincident(
const Intersect::XPoint& p0,
531 const Intersect::XPoint& p,
int c) {
532 if (c == 0)
return p;
540 real s = ((p0.x + c * p0.y) - (p.x + c * p.y))/2;
541 return p + XPoint(s, c*s);
546 const Intersect::XPoint& p) {
547 if (p.c == 0)
return p;
558 pya = p.y - p.c * p.x, sa = -p.x,
559 pyb = p.y - p.c * (p.x-sx), sb = sx - p.x,
560 pxc = p.x - p.c * p.y, sc = p.c * -p.y,
561 pxd = p.x - p.c * (p.y-sy), sd = p.c * (sy - p.y);
563 ga = 0 <= pya && pya <= sy,
564 gb = 0 <= pyb && pyb <= sy,
565 gc = 0 <= pxc && pxc <= sx,
566 gd = 0 <= pxd && pxd <= sx;
569 if (ga && gb) s = (sa + sb) / 2;
570 else if (gc && gd) s = (sc + sd) / 2;
571 else if (ga && gc) s = (sa + sc) / 2;
572 else if (ga && gd) s = (sa + sd) / 2;
573 else if (gb && gc) s = (sb + sc) / 2;
574 else if (gb && gd) s = (sb + sd) / 2;
580 if (fabs((p.x - p.y) + sy) < fabs((p.x - p.y) - sx))
581 s = (sy - (p.x + p.y))/2;
583 s = (sx - (p.x + p.y))/2;
587 if (fabs(p.x + p.y) < fabs((p.x + p.y) - (sx + sy)))
588 s = (0 - (p.x - p.y))/2;
590 s = ((sx - sy) - (p.x - p.y))/2;
593 return p + XPoint(s, p.c*s);
GeographicLib::Math::real real
Header for GeographicLib::Intersect class.
#define GEOGRAPHICLIB_PANIC
Math::real Position(real s12, real &lat2, real &lon2, real &azi2, real &m12, real &M12, real &M21, real &S12) const
GeodesicLine InverseLine(real lat1, real lon1, real lat2, real lon2, unsigned caps=ALL) const
GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps=ALL) const
Math::real Inverse(real lat1, real lon1, real lat2, real lon2, real &s12, real &azi1, real &azi2, real &m12, real &M12, real &M21, real &S12) const
Exception handling for GeographicLib.
Point Segment(Math::real latX1, Math::real lonX1, Math::real latX2, Math::real lonX2, Math::real latY1, Math::real lonY1, Math::real latY2, Math::real lonY2, int &segmode, int *c=nullptr) const
static const unsigned LineCaps
Point Closest(Math::real latX, Math::real lonX, Math::real aziX, Math::real latY, Math::real lonY, Math::real aziY, const Point &p0=Point(0, 0), int *c=nullptr) const
std::pair< Math::real, Math::real > Point
std::vector< Point > All(Math::real latX, Math::real lonX, Math::real aziX, Math::real latY, Math::real lonY, Math::real aziY, Math::real maxdist, std::vector< int > &c, const Point &p0=Point(0, 0)) const
Point Next(Math::real latX, Math::real lonX, Math::real aziX, Math::real aziY, int *c=nullptr) const
Intersect(const Geodesic &geod)
Mathematical functions needed by GeographicLib.
static void sincosde(T x, T t, T &sinx, T &cosx)
static T AngDiff(T x, T y, T &e)
Namespace for GeographicLib.
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)