/// <summary> /// Initializes the transform using the parameters from the specified coordinate system information /// </summary> /// <param name="projInfo">A ProjectionInfo class contains all the standard and custom parameters needed to initialize this transform</param> protected override void OnInit(ProjectionInfo projInfo) { double t; if (projInfo.StandardParallel1 != null) { t = projInfo.StandardParallel1.Value.FromDegreesToRadians(); } else { t = projInfo.lat_ts.Value.FromDegreesToRadians(); } if ((K0 = Math.Cos(t)) < 0) { throw new ProjectionException(-24); } if (!IsElliptical) { return; } t = Math.Sin(t); K0 /= Math.Sqrt(1 - Es * t * t); E = Math.Sqrt(Es); _apa = Proj.Authset(Es); _qp = Proj.Qsfn(1, E, OneEs); }
/// <inheritdoc /> protected override void EllipticalForward(double[] lp, double[] xy, int startIndex, int numPoints) { for (int i = startIndex; i < startIndex + numPoints; i++) { int phi = i * 2 + PHI; int lam = i * 2 + LAMBDA; int x = i * 2 + X; int y = i * 2 + Y; xy[x] = K0 * lp[lam]; xy[y] = .5 * Proj.Qsfn(Math.Sin(lp[phi]), E, OneEs) / K0; } }
/// <summary> /// Initializes the transform using the parameters from the specified coordinate system information /// </summary> /// <param name="projInfo">A ProjectionInfo class contains all the standard and custom parameters needed to initialize this transform</param> protected override void OnInit(ProjectionInfo projInfo) { double t = Math.Abs(Phi0); if (Math.Abs(t - HALF_PI) < EPS10) { _mode = Phi0 < 0 ? Modes.SouthPole : Modes.NorthPole; } else if (Math.Abs(t) < EPS10) { _mode = Modes.Equitorial; } else { _mode = Modes.Oblique; } if (Es == 0) { IsElliptical = false; _mode = Modes.Oblique; _sinb1 = Math.Sin(Phi0); _cosb1 = Math.Cos(Phi0); return; } IsElliptical = true; _qp = Proj.Qsfn(1, Es, OneEs); // _mmf = .5/(1 - Es); _apa = Proj.Authset(Es); switch (_mode) { case Modes.NorthPole: case Modes.SouthPole: _dd = 1; break; case Modes.Equitorial: _dd = 1 / (_rq = Math.Sqrt(.5 * _qp)); _xmf = 1; _ymf = .5 * _qp; break; case Modes.Oblique: _rq = Math.Sqrt(.5 * _qp); double sinphi = Math.Sin(Phi0); _sinb1 = Proj.Qsfn(sinphi, E, OneEs); _cosb1 = Math.Sqrt(1 - _sinb1 * _sinb1); _dd = Math.Cos(Phi0) / (Math.Sqrt(1 - Es * sinphi * sinphi) * _rq * _cosb1); _ymf = _xmf = _rq / _dd; _xmf *= _dd; break; } }
/// <summary> /// Internal code handling the setup operations for the transform /// </summary> protected void Setup() { double sinphi; if (Math.Abs(_phi1 + _phi2) < EPS10) { throw new ProjectionException(-21); } _n = sinphi = Math.Sin(_phi1); double cosphi = Math.Cos(_phi1); bool secant = Math.Abs(_phi1 - _phi2) >= EPS10; if (IsElliptical) { double m1 = Proj.Msfn(sinphi, cosphi, Es); double ml1 = Proj.Qsfn(sinphi, E, OneEs); if (secant) { /* secant cone */ sinphi = Math.Sin(_phi2); cosphi = Math.Cos(_phi2); double m2 = Proj.Msfn(sinphi, cosphi, Es); double ml2 = Proj.Qsfn(sinphi, E, OneEs); _n = (m1 * m1 - m2 * m2) / (ml2 - ml1); } _ec = 1 - .5 * OneEs * Math.Log((1 - E) / (1 + E)) / E; _c = m1 * m1 + _n * ml1; _dd = 1 / _n; _rho0 = _dd * Math.Sqrt(_c - _n * Proj.Qsfn(Math.Sin(Phi0), E, OneEs)); } else { if (secant) { _n = .5 * (_n + Math.Sin(_phi2)); } _n2 = _n + _n; _c = cosphi * cosphi + _n2 * sinphi; _dd = 1 / _n; _rho0 = _dd * Math.Sqrt(_c - _n2 * Math.Sin(Phi0)); } }
/// <inheritdoc /> protected override void OnForward(double[] lp, double[] xy, int startIndex, int numPoints) { for (int i = startIndex; i < startIndex + numPoints; i++) { int phi = i * 2 + PHI; int lam = i * 2 + LAMBDA; int x = i * 2 + X; int y = i * 2 + Y; if ((_rho = _c - (IsElliptical ? _n * Proj.Qsfn(Math.Sin(lp[phi]), E, OneEs) : _n2 *Math.Sin(lp[phi]))) < 0) { xy[x] = double.NaN; xy[y] = double.NaN; continue; //throw new ProjectionException(20); } _rho = _dd * Math.Sqrt(_rho); xy[x] = _rho * Math.Sin(lp[lam] *= _n); xy[y] = _rho0 - _rho * Math.Cos(lp[lam]); } }
/// <inheritdoc /> protected override void EllipticalForward(double[] lp, double[] xy, int startIndex, int numPoints) { for (int i = startIndex; i < startIndex + numPoints; i++) { int phi = i * 2 + PHI; int lam = i * 2 + LAMBDA; int x = i * 2 + X; int y = i * 2 + Y; double sinb = 0, cosb = 0, b = 0; double coslam = Math.Cos(lp[lam]); double sinlam = Math.Sin(lp[lam]); double sinphi = Math.Sin(lp[phi]); double q = Proj.Qsfn(sinphi, E, OneEs); if (_mode == Modes.Oblique || _mode == Modes.Equitorial) { sinb = q / _qp; cosb = Math.Sqrt(1 - sinb * sinb); } switch (_mode) { case Modes.Oblique: b = 1 + _sinb1 * sinb + _cosb1 * cosb * coslam; break; case Modes.Equitorial: b = 1 + cosb * coslam; break; case Modes.NorthPole: b = HALF_PI + lp[phi]; q = _qp - q; break; case Modes.SouthPole: b = lp[phi] - HALF_PI; q = _qp + q; break; } if (Math.Abs(b) < EPS10) { xy[x] = double.NaN; xy[y] = double.NaN; continue; //throw new ProjectionException(20); } switch (_mode) { case Modes.Oblique: xy[y] = _ymf * (b = Math.Sqrt(2 / b)) * (_cosb1 * sinb - _sinb1 * cosb * coslam); xy[x] = _xmf * b * cosb * sinlam; break; case Modes.Equitorial: xy[y] = (b = Math.Sqrt(2 / (1 + cosb * coslam))) * sinb * _ymf; xy[x] = _xmf * b * cosb * sinlam; break; case Modes.NorthPole: case Modes.SouthPole: if (q >= 0) { xy[x] = (b = Math.Sqrt(q)) * sinlam; xy[y] = coslam * (_mode == Modes.SouthPole ? b : -b); } else { xy[x] = xy[y] = 0; } break; } } }