MCPcopy Create free account
hub / github.com/OSGeo/PROJ / complex_iterative_inverse_impl

Function complex_iterative_inverse_impl

src/transformations/horner.cpp:440–490  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

438}
439
440static PJ_UV complex_iterative_inverse_impl(PJ *P, const HORNER *transformation,
441 PJ_UV position) {
442
443 double n, e;
444 // in this case fwd_origin and any existing flipping needs to be added in
445 // the end
446 e = position.u;
447 n = position.v;
448
449 if (coords_out_of_range(P, transformation, n, e)) {
450 return generate_error_coords();
451 }
452
453 {
454 // complex real part corresponds to Northing, imag part to Easting
455 const double tol = transformation->inverse_tolerance;
456 const std::complex<double> dZ(n - transformation->fwd_c[0],
457 e - transformation->fwd_c[1]);
458 std::complex<double> w0(0.0, 0.0);
459 int loops = 32; // usually converges really fast (1-2 loops)
460 bool converged = false;
461 while (loops-- > 0 && !converged) {
462 // sum coefficient pointers from back to front until the first
463 // complex pair (fwd_c0+i*fwd_c1)
464 const double *c = transformation->fwd_c;
465 PJ_UV en = {w0.imag(), w0.real()};
466 en = complex_horner_eval(transformation->order, c, en, 1);
467 std::complex<double> det(en.v, en.u);
468 std::complex<double> w1 = dZ / det;
469 converged = (fabs(w1.real() - w0.real()) < tol) &&
470 (fabs(w1.imag() - w0.imag()) < tol);
471 w0 = w1;
472 }
473 // if loops have been exhausted and we have not converged yet,
474 // we are never going to converge
475 if (!converged) {
476 proj_errno_set(P, PROJ_ERR_COORD_TRANSFM);
477 position = generate_error_coords();
478 } else {
479 double E = w0.imag();
480 double N = w0.real();
481 if (transformation->uneg)
482 E = -E;
483 if (transformation->vneg)
484 N = -N;
485 position.u = E + transformation->fwd_origin->u;
486 position.v = N + transformation->fwd_origin->v;
487 }
488 return position;
489 }
490}
491
492static void complex_horner_forward_4d(PJ_COORD &point, PJ *P) {
493 const HORNER *transformation = reinterpret_cast<const HORNER *>(P->opaque);

Callers 1

Calls 4

coords_out_of_rangeFunction · 0.85
generate_error_coordsFunction · 0.85
complex_horner_evalFunction · 0.85
proj_errno_setFunction · 0.85

Tested by

no test coverage detected