internal static PolarGeoCoordinate Convert(PolarGeoCoordinate source, CoordinateSystems destination) { PolarGeoCoordinate retVal; if (source.CoordinateSystem == CoordinateSystems.OSGB36 && destination == CoordinateSystems.WGS84) { retVal = Convert( source, EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.Airy1830), HelmertTransform.GetTransform(HelmertTransform.HelmertTransformType.OSGB36toWGS84), EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.WGS84) ); } else if (source.CoordinateSystem == CoordinateSystems.WGS84 && destination == CoordinateSystems.OSGB36) { retVal = Convert( source, EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.WGS84), HelmertTransform.GetTransform(HelmertTransform.HelmertTransformType.WGS84toOSGB36), EllipseParameter.GetEllipseParameters(EllipseParameter.Ellipses.Airy1830) ); } else { throw new NotImplementedException("Requested source and destination are not currently supported"); } retVal.AlignSigFigs(source); return(retVal); }
private static PolarGeoCoordinate Convert( PolarGeoCoordinate originalCoord, EllipseParameter e1, HelmertTransform t, EllipseParameter e2) { // -- convert polar to cartesian coordinates (using ellipse 1) PolarGeoCoordinate p1 = PolarGeoCoordinate.ChangeUnits(originalCoord, AngleUnit.Radians); double sinPhi = Math.Sin(p1.Lat); double cosPhi = Math.Cos(p1.Lat); double sinLambda = Math.Sin(p1.Lon); double cosLambda = Math.Cos(p1.Lon); double H = p1.Height; double eSq = (Math.Pow(e1.SemimajorAxis, 2) - Math.Pow(e1.SemiMinorAxis, 2)) / Math.Pow(e1.SemimajorAxis, 2); double nu = e1.SemimajorAxis / Math.Sqrt(1 - eSq * sinPhi * sinPhi); double x1 = (nu + H) * cosPhi * cosLambda; double y1 = (nu + H) * cosPhi * sinLambda; double z1 = ((1 - eSq) * nu + H) * sinPhi; // -- apply helmert transform using appropriate params double tx = t.tx, ty = t.ty, tz = t.tz; double rx = t.rx / 3600 * Math.PI / 180; // normalise seconds to radians double ry = t.ry / 3600 * Math.PI / 180; double rz = t.rz / 3600 * Math.PI / 180; double s1 = t.s / 1e6 + 1; // normalise ppm to (s+1) // apply transform double x2 = tx + x1 * s1 - y1 * rz + z1 * ry; double y2 = ty + x1 * rz + y1 * s1 - z1 * rx; double z2 = tz - x1 * ry + y1 * rx + z1 * s1; // -- convert cartesian to polar coordinates (using ellipse 2) double a = e2.SemimajorAxis; double precision = 4 / e2.SemimajorAxis; // results accurate to around 4 metres eSq = (Math.Pow(e2.SemimajorAxis, 2) - Math.Pow(e2.SemiMinorAxis, 2)) / Math.Pow(e2.SemimajorAxis, 2); double p = Math.Sqrt(x2 * x2 + y2 * y2); double phi = Math.Atan2(z2, p * (1 - eSq)), phiP = 2 * Math.PI; while (Math.Abs(phi - phiP) > precision) { nu = a / Math.Sqrt(1 - eSq * Math.Sin(phi) * Math.Sin(phi)); phiP = phi; phi = Math.Atan2(z2 + eSq * nu * Math.Sin(phi), p); } double lambda = Math.Atan2(y2, x2); H = p / Math.Cos(phi) - nu; return(new PolarGeoCoordinate( RadToDeg(phi), RadToDeg(lambda), H, AngleUnit.Degrees, t.outputCoordinateSystem)); }
private static PolarGeoCoordinate Convert( PolarGeoCoordinate originalCoord, EllipseParameter e1, HelmertTransform t, EllipseParameter e2) { // -- convert polar to cartesian coordinates (using ellipse 1) PolarGeoCoordinate p1 = PolarGeoCoordinate.ChangeUnits(originalCoord, AngleUnit.Radians); double sinPhi = Math.Sin(p1.Lat); double cosPhi = Math.Cos(p1.Lat); double sinLambda = Math.Sin(p1.Lon); double cosLambda = Math.Cos(p1.Lon); double H = p1.Height; double eSq = (Math.Pow(e1.SemimajorAxis, 2) - Math.Pow(e1.SemiMinorAxis, 2)) / Math.Pow(e1.SemimajorAxis, 2); double nu = e1.SemimajorAxis / Math.Sqrt(1 - eSq * sinPhi * sinPhi); double x1 = (nu + H) * cosPhi * cosLambda; double y1 = (nu + H) * cosPhi * sinLambda; double z1 = ((1 - eSq) * nu + H) * sinPhi; // -- apply helmert transform using appropriate params double tx = t.tx, ty = t.ty, tz = t.tz; double rx = t.rx / 3600 * Math.PI / 180; // normalise seconds to radians double ry = t.ry / 3600 * Math.PI / 180; double rz = t.rz / 3600 * Math.PI / 180; double s1 = t.s / 1e6 + 1; // normalise ppm to (s+1) // apply transform double x2 = tx + x1 * s1 - y1 * rz + z1 * ry; double y2 = ty + x1 * rz + y1 * s1 - z1 * rx; double z2 = tz - x1 * ry + y1 * rx + z1 * s1; // -- convert cartesian to polar coordinates (using ellipse 2) double a = e2.SemimajorAxis; double precision = 4 / e2.SemimajorAxis; // results accurate to around 4 metres eSq = (Math.Pow(e2.SemimajorAxis, 2) - Math.Pow(e2.SemiMinorAxis, 2)) / Math.Pow(e2.SemimajorAxis, 2); double p = Math.Sqrt(x2 * x2 + y2 * y2); double phi = Math.Atan2(z2, p * (1 - eSq)), phiP = 2 * Math.PI; while (Math.Abs(phi - phiP) > precision) { nu = a / Math.Sqrt(1 - eSq * Math.Sin(phi) * Math.Sin(phi)); phiP = phi; phi = Math.Atan2(z2 + eSq * nu * Math.Sin(phi), p); } double lambda = Math.Atan2(y2, x2); H = p / Math.Cos(phi) - nu; return new PolarGeoCoordinate( RadToDeg(phi), RadToDeg(lambda), H, AngleUnit.Degrees, t.outputCoordinateSystem); }