private static void DatumTransform(ProjectionInfo source, ProjectionInfo dest, double[] xy, double[] z, int startIndex, int numPoints) { Spheroid wgs84 = new Spheroid(Proj4Ellipsoid.WGS_1984); Datum sDatum = source.GeographicInfo.Datum; Datum dDatum = dest.GeographicInfo.Datum; /* -------------------------------------------------------------------- */ /* We cannot do any meaningful datum transformation if either */ /* the source or destination are of an unknown datum type */ /* (ie. only a +ellps declaration, no +datum). This is new */ /* behavior for PROJ 4.6.0. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.Unknown || dDatum.DatumType == DatumType.Unknown) return; /* -------------------------------------------------------------------- */ /* Short cut if the datums are identical. */ /* -------------------------------------------------------------------- */ if (sDatum.Matches(dDatum)) return; // proj4 actually allows some tollerance here if (sDatum.DatumType == dDatum.DatumType) { if (sDatum.Spheroid.EquatorialRadius == dDatum.Spheroid.EquatorialRadius) { if (Math.Abs(sDatum.Spheroid.EccentricitySquared() - dDatum.Spheroid.EccentricitySquared()) < 0.000000000050) { // The tolerence is to allow GRS80 and WGS84 to escape without being transformed at all. return; } } } double srcA = sDatum.Spheroid.EquatorialRadius; double srcEs = sDatum.Spheroid.EccentricitySquared(); double dstA = dDatum.Spheroid.EquatorialRadius; double dstEs = dDatum.Spheroid.EccentricitySquared(); /* -------------------------------------------------------------------- */ /* Create a temporary Z value if one is not provided. */ /* -------------------------------------------------------------------- */ if (z == null) { z = new double[xy.Length / 2]; } /* -------------------------------------------------------------------- */ /* If this datum requires grid shifts, then apply it to geodetic */ /* coordinates. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.GridShift) { // pj_apply_gridshift(pj_param(srcdefn->params,"snadgrids").s, 0, // point_count, point_offset, x, y, z ); GridShift.Apply(source.GeographicInfo.Datum.NadGrids, false, xy, startIndex, numPoints); srcA = wgs84.EquatorialRadius; srcEs = wgs84.EccentricitySquared(); } if (dDatum.DatumType == DatumType.GridShift) { dstA = wgs84.EquatorialRadius; dstEs = wgs84.EccentricitySquared(); } /* ==================================================================== */ /* Do we need to go through geocentric coordinates? */ /* ==================================================================== */ if (srcEs != dstEs || srcA != dstA || sDatum.DatumType == DatumType.Param3 || sDatum.DatumType == DatumType.Param7 || dDatum.DatumType == DatumType.Param3 || dDatum.DatumType == DatumType.Param7) { /* -------------------------------------------------------------------- */ /* Convert to geocentric coordinates. */ /* -------------------------------------------------------------------- */ GeocentricGeodetic gc = new GeocentricGeodetic(sDatum.Spheroid); gc.GeodeticToGeocentric(xy, z, startIndex, numPoints); /* -------------------------------------------------------------------- */ /* Convert between datums. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.Param3 || sDatum.DatumType == DatumType.Param7) { PjGeocentricToWgs84(source, xy, z, startIndex, numPoints); } if (dDatum.DatumType == DatumType.Param3 || dDatum.DatumType == DatumType.Param7) { PjGeocentricFromWgs84(dest, xy, z, startIndex, numPoints); } /* -------------------------------------------------------------------- */ /* Convert back to geodetic coordinates. */ /* -------------------------------------------------------------------- */ gc = new GeocentricGeodetic(dDatum.Spheroid); gc.GeocentricToGeodetic(xy, z, startIndex, numPoints); } /* -------------------------------------------------------------------- */ /* Apply grid shift to destination if required. */ /* -------------------------------------------------------------------- */ if (dDatum.DatumType == DatumType.GridShift) { // pj_apply_gridshift(pj_param(dstdefn->params,"snadgrids").s, 1, // point_count, point_offset, x, y, z ); GridShift.Apply(dest.GeographicInfo.Datum.NadGrids, true, xy, startIndex, numPoints); } }
/// <summary> /// Creates a new instance of GeocentricGeodetic /// </summary> public GeocentricGeodetic(Spheroid gi) { _a = gi.EquatorialRadius; _b = gi.PolarRadius; _a2 = _a * _a; _b2 = _b * _b; _e2 = (_a2 - _b2) / _a2; //_ep2 = (_a2 - _b2)/_b2; }
/// <summary> /// DatumTranformStage constructor for a gridshift transform /// </summary> public DatumTransformStage(string strFrom, string strTo, Spheroid sphFrom, Spheroid sphTo, string strTableName, bool bApplyTableInv) { From = strFrom; To = strTo; FromSph = sphFrom; ToSph = sphTo; Tm = TransformMethod.GridShift; TableName = strTableName; ApplyTableInv = bApplyTableInv; }
/// <summary> /// DatumTranformStage constructor for a geocentric transform /// </summary> public DatumTransformStage(string strFrom, string strTo, Spheroid sphFrom, Spheroid sphTo, double dx, double dy, double dz) { From = strFrom; To = strTo; FromSph = sphFrom; ToSph = sphTo; Dx = dx; Dy = dy; Dz = dz; Tm = TransformMethod.Param3; }
/// <summary> /// DatumTranformStage constructor for a 7-parameter transform /// </summary> public DatumTransformStage(string strFrom, string strTo, Spheroid sphFrom, Spheroid sphTo, double dx, double dy, double dz, double rx, double ry, double rz, double ds) { From = strFrom; To = strTo; FromSph = sphFrom; ToSph = sphTo; Tm = TransformMethod.Param7; Dx = dx; Dy = dy; Dz = dz; Rx = rx; Ry = ry; Rz = rz; Ds = ds; }
/// <summary> /// DatumTransfromStage copy constructor /// </summary> /// <param name="dts"></param> public DatumTransformStage(DatumTransformStage dts) { From = dts.From; To = dts.To; FromSph = dts.FromSph; ToSph = dts.ToSph; Tm = dts.Tm; Dx = dts.Dx; Dy = dts.Dy; Dz = dts.Dz; Rx = dts.Rx; Ry = dts.Ry; Rz = dts.Rz; Ds = dts.Ds; TableName = dts.TableName; ApplyTableInv = dts.ApplyTableInv; }
/// <summary> /// Returns a representaion of this object as a Proj4 string. /// </summary> /// <returns></returns> public string ToProj4String() { // if you have a datum name you don't need to say anything about the Spheroid string str = Proj4DatumName; if (str == null) { switch (DatumType) { case DatumType.Unknown: case DatumType.WGS84: break; case DatumType.Param3: Debug.Assert(_toWgs84.Length >= 3); str = String.Format(CultureInfo.InvariantCulture, " +towgs84={0},{1},{2}", _toWgs84[0], _toWgs84[1], _toWgs84[2]); break; case DatumType.Param7: Debug.Assert(_toWgs84.Length >= 7); str = String.Format(CultureInfo.InvariantCulture, " +towgs84={0},{1},{2},{3},{4},{5},{6}", _toWgs84[0], _toWgs84[1], _toWgs84[2], _toWgs84[3] / SEC_TO_RAD, _toWgs84[4] / SEC_TO_RAD, _toWgs84[5] / SEC_TO_RAD, (_toWgs84[6] - 1) * 1000000.0); break; case DatumType.GridShift: str = String.Format(" +nadgrids={0}", String.Join(",", NadGrids)); break; default: throw new ArgumentOutOfRangeException("DatumType"); } return(str + Spheroid.ToProj4String()); } else { return(String.Format(" +datum={0}", Proj4DatumName)); } }
/// <summary> /// Creates an esri well known text string for the datum part of the string /// </summary> /// <returns>The datum portion of the esri well known text</returns> public string ToEsriString() { return(@"DATUM[""" + _name + @"""," + Spheroid.ToEsriString() + "]"); }
private static bool IsInvalidSpheroid(Spheroid spheroid) { return spheroid.InverseFlattening == 0; }
/// <summary> /// Creates a new instance of Datum /// </summary> public Datum() { _spheroid = new Spheroid(); DatumType = DatumType.Unknown; }
/// <summary> /// Expresses the entire projection as the Esri well known text format that can be found in .prj files /// </summary> /// <returns> /// The generated string /// </returns> public string ToEsriString() { Spheroid tempSpheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { tempSpheroid = GeographicInfo.Datum.Spheroid; GeographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); } // if (_auxiliarySphereType != AuxiliarySphereType.NotSpecified) // { // tempSpheroid = _geographicInfo.Datum.Spheroid; // _geographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); // } string result = string.Empty; if (!IsLatLon) { result += String.Format(@"PROJCS[""{0}"",", Name); } result += GeographicInfo.ToEsriString(); if (IsLatLon) { return(result); } result += ", "; if (Transform != null) { // Since we can have semi-colon delimited names for aliases, we have to output just one in the WKT. Issue #297 var name = Transform.Name.Contains(";") ? Transform.Name.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[0] : Transform.Name; result += String.Format(@"PROJECTION[""{0}""],", name); } if (FalseEasting != null) { string alias = FalseEastingAlias ?? "False_Easting"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(FalseEasting / Unit.Meters, CultureInfo.InvariantCulture) + "],"; } if (FalseNorthing != null) { string alias = FalseNorthingAlias ?? "False_Northing"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(FalseNorthing / Unit.Meters, CultureInfo.InvariantCulture) + "],"; } if (CentralMeridian != null && CentralMeridianValid()) { result += @"PARAMETER[""Central_Meridian""," + Convert.ToString(CentralMeridian, CultureInfo.InvariantCulture) + "],"; } if (StandardParallel1 != null) { result += @"PARAMETER[""Standard_Parallel_1""," + Convert.ToString(StandardParallel1, CultureInfo.InvariantCulture) + "],"; } if (StandardParallel2 != null) { result += @"PARAMETER[""Standard_Parallel_2""," + Convert.ToString(StandardParallel2, CultureInfo.InvariantCulture) + "],"; } if (_scaleFactor != null) { result += @"PARAMETER[""Scale_Factor""," + Convert.ToString(_scaleFactor, CultureInfo.InvariantCulture) + "],"; } if (alpha != null) { result += @"PARAMETER[""Azimuth""," + Convert.ToString(alpha, CultureInfo.InvariantCulture) + "],"; } if (LongitudeOfCenter != null) { string alias = LongitudeOfCenterAlias ?? "Longitude_Of_Center"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(LongitudeOfCenter, CultureInfo.InvariantCulture) + "],"; } if (_longitudeOf1st != null) { result += @"PARAMETER[""Longitude_Of_1st""," + Convert.ToString(_longitudeOf1st, CultureInfo.InvariantCulture) + "],"; } if (_longitudeOf2nd != null) { result += @"PARAMETER[""Longitude_Of_2nd""," + Convert.ToString(_longitudeOf2nd, CultureInfo.InvariantCulture) + "],"; } if (LatitudeOfOrigin != null) { string alias = LatitudeOfOriginAlias ?? "Latitude_Of_Origin"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(LatitudeOfOrigin, CultureInfo.InvariantCulture) + "],"; } // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { result += @"PARAMETER[""Auxiliary_Sphere_Type""," + ((int)AuxiliarySphereType) + ".0],"; } result += Unit.ToEsriString() + "]"; // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { GeographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); GeographicInfo.Datum.Spheroid = tempSpheroid; } return(result); }
public static Spheroid Create(ISpheroidInfo spheroidInfo) { if(spheroidInfo == null) throw new ArgumentNullException("spheroidInfo"); Contract.Ensures(Contract.Result<Spheroid>() != null); var aMeters = spheroidInfo.A; var bMeters = spheroidInfo.B; if (spheroidInfo.AxisUnit != null) { var conversion = SimpleUnitConversionGenerator.FindConversion(spheroidInfo.AxisUnit, Proj4LinearUnit.Meter); if (conversion != null && !(conversion is UnitUnityConversion)) { aMeters = conversion.TransformValue(aMeters); bMeters = conversion.TransformValue(bMeters); } } Spheroid result; if (aMeters == bMeters) { var knownMatch = AllKnownSpheroids .Where(k => k.PolarRadius == aMeters) .OrderByDescending(k => SpheroidNameNormalizedComparer.Default.Equals(k.Name, spheroidInfo.Name)) .FirstOrDefault(); if (knownMatch != null) return knownMatch; result = new Spheroid(Proj4Ellipsoid.Custom); result.PolarRadius = aMeters; } else{ var knownMatch = AllKnownSpheroids .Where(k => k.EquatorialRadius == aMeters && (k.InverseFlattening == spheroidInfo.InvF || k.PolarRadius == bMeters)) .OrderByDescending(k => SpheroidNameNormalizedComparer.Default.Equals(k.Name, spheroidInfo.Name)) .FirstOrDefault(); if (knownMatch != null) return knownMatch; result = new Spheroid(Proj4Ellipsoid.Custom); result.EquatorialRadius = aMeters; // NOTE: do not directly set the InverseFlattening as it is stored as PolarRadius result.PolarRadius = bMeters; } result.Name = spheroidInfo.Name; return result; }
private static bool IsFalseWgs84(Spheroid spheroid) { if (spheroid.KnownEllipsoid != Proj4Ellipsoid.WGS_1984) return false; return spheroid.EquatorialRadius != 6378137.0 || spheroid.InverseFlattening != 298.257223563; }
public Proj4SpheroidWrapper(Spheroid spheroid) : base(spheroid.Name ?? "Unknown", new AuthorityTag("PROJ4", spheroid.Code)) { Contract.Requires(spheroid != null); Core = spheroid; }
public void GeocentricAfterDatumTest() { double[] xy = new double[2]; xy[0] = 4257349.7546790326000000; xy[1] = 401477.6657818287500000; double[] z = new double[1]; z[0] = 4716473.1891765557000000; Spheroid s = new Spheroid(Proj4Ellipsoid.WGS_1984); GeocentricGeodetic gc = new GeocentricGeodetic(s); gc.GeocentricToGeodetic(xy, z, 0, 1); }
/// <summary> /// Expresses the entire projection as the Esri well known text format that can be found in .prj files /// </summary> /// <returns> /// The generated string /// </returns> public string ToEsriString() { Spheroid tempSpheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { tempSpheroid = GeographicInfo.Datum.Spheroid; GeographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); } // if (_auxiliarySphereType != AuxiliarySphereType.NotSpecified) // { // tempSpheroid = _geographicInfo.Datum.Spheroid; // _geographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); // } string result = string.Empty; if (!IsLatLon) { result += String.Format(@"PROJCS[""{0}"",", Name); } result += GeographicInfo.ToEsriString(); if (IsLatLon) { return result; } result += ", "; if (Transform != null) { // Since we can have semi-colon delimited names for aliases, we have to output just one in the WKT. Issue #297 var name = Transform.Name.Contains(";") ? Transform.Name.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[0] : Transform.Name; result += String.Format(@"PROJECTION[""{0}""],", name); } if (FalseEasting != null) { string alias = FalseEastingAlias ?? "False_Easting"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(FalseEasting / Unit.Meters, CultureInfo.InvariantCulture) + "],"; } if (FalseNorthing != null) { string alias = FalseNorthingAlias ?? "False_Northing"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(FalseNorthing / Unit.Meters, CultureInfo.InvariantCulture) + "],"; } if (CentralMeridian != null && CentralMeridianValid()) { result += @"PARAMETER[""Central_Meridian""," + Convert.ToString(CentralMeridian, CultureInfo.InvariantCulture) + "],"; } if (StandardParallel1 != null) { result += @"PARAMETER[""Standard_Parallel_1""," + Convert.ToString(StandardParallel1, CultureInfo.InvariantCulture) + "],"; } if (StandardParallel2 != null) { result += @"PARAMETER[""Standard_Parallel_2""," + Convert.ToString(StandardParallel2, CultureInfo.InvariantCulture) + "],"; } if (_scaleFactor != null) { result += @"PARAMETER[""Scale_Factor""," + Convert.ToString(_scaleFactor, CultureInfo.InvariantCulture) + "],"; } if (alpha != null) { result += @"PARAMETER[""Azimuth""," + Convert.ToString(alpha, CultureInfo.InvariantCulture) + "],"; } if (LongitudeOfCenter != null) { string alias = LongitudeOfCenterAlias ?? "Longitude_Of_Center"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(LongitudeOfCenter, CultureInfo.InvariantCulture) + "],"; } if (_longitudeOf1st != null) { result += @"PARAMETER[""Longitude_Of_1st""," + Convert.ToString(_longitudeOf1st, CultureInfo.InvariantCulture) + "],"; } if (_longitudeOf2nd != null) { result += @"PARAMETER[""Longitude_Of_2nd""," + Convert.ToString(_longitudeOf2nd, CultureInfo.InvariantCulture) + "],"; } if (LatitudeOfOrigin != null) { string alias = LatitudeOfOriginAlias ?? "Latitude_Of_Origin"; result += @"PARAMETER[""" + alias + @"""," + Convert.ToString(LatitudeOfOrigin, CultureInfo.InvariantCulture) + "],"; } // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { result += @"PARAMETER[""Auxiliary_Sphere_Type""," + ((int)AuxiliarySphereType) + ".0],"; } result += Unit.ToEsriString() + "]"; // changed by JK to fix the web mercator auxiliary sphere Esri string if (Name == "WGS_1984_Web_Mercator_Auxiliary_Sphere") { GeographicInfo.Datum.Spheroid = new Spheroid(Proj4Ellipsoid.WGS_1984); GeographicInfo.Datum.Spheroid = tempSpheroid; } return result; }
private static void DatumTransform(ProjectionInfo source, ProjectionInfo dest, double[] xy, double[] z, int startIndex, int numPoints) { Spheroid wgs84 = new Spheroid(Proj4Ellipsoid.WGS_1984); Datum sDatum = source.GeographicInfo.Datum; Datum dDatum = dest.GeographicInfo.Datum; /* -------------------------------------------------------------------- */ /* We cannot do any meaningful datum transformation if either */ /* the source or destination are of an unknown datum type */ /* (ie. only a +ellps declaration, no +datum). This is new */ /* behavior for PROJ 4.6.0. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.Unknown || dDatum.DatumType == DatumType.Unknown) { return; } /* -------------------------------------------------------------------- */ /* Short cut if the datums are identical. */ /* -------------------------------------------------------------------- */ if (sDatum.Matches(dDatum)) { return; } // proj4 actually allows some tollerance here if (sDatum.DatumType == dDatum.DatumType) { if (sDatum.Spheroid.EquatorialRadius == dDatum.Spheroid.EquatorialRadius) { if (Math.Abs(sDatum.Spheroid.EccentricitySquared() - dDatum.Spheroid.EccentricitySquared()) < 0.000000000050) { // The tolerence is to allow GRS80 and WGS84 to escape without being transformed at all. return; } } } double srcA = sDatum.Spheroid.EquatorialRadius; double srcEs = sDatum.Spheroid.EccentricitySquared(); double dstA = dDatum.Spheroid.EquatorialRadius; double dstEs = dDatum.Spheroid.EccentricitySquared(); /* -------------------------------------------------------------------- */ /* Create a temporary Z value if one is not provided. */ /* -------------------------------------------------------------------- */ if (z == null) { z = new double[xy.Length / 2]; } /* -------------------------------------------------------------------- */ /* If this datum requires grid shifts, then apply it to geodetic */ /* coordinates. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.GridShift) { // pj_apply_gridshift(pj_param(srcdefn->params,"snadgrids").s, 0, // point_count, point_offset, x, y, z ); GridShift.Apply(source.GeographicInfo.Datum.NadGrids, false, xy, startIndex, numPoints); srcA = wgs84.EquatorialRadius; srcEs = wgs84.EccentricitySquared(); } if (dDatum.DatumType == DatumType.GridShift) { dstA = wgs84.EquatorialRadius; dstEs = wgs84.EccentricitySquared(); } /* ==================================================================== */ /* Do we need to go through geocentric coordinates? */ /* ==================================================================== */ if (srcEs != dstEs || srcA != dstA || sDatum.DatumType == DatumType.Param3 || sDatum.DatumType == DatumType.Param7 || dDatum.DatumType == DatumType.Param3 || dDatum.DatumType == DatumType.Param7) { /* -------------------------------------------------------------------- */ /* Convert to geocentric coordinates. */ /* -------------------------------------------------------------------- */ GeocentricGeodetic gc = new GeocentricGeodetic(sDatum.Spheroid); gc.GeodeticToGeocentric(xy, z, startIndex, numPoints); /* -------------------------------------------------------------------- */ /* Convert between datums. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumType.Param3 || sDatum.DatumType == DatumType.Param7) { PjGeocentricToWgs84(source, xy, z, startIndex, numPoints); } if (dDatum.DatumType == DatumType.Param3 || dDatum.DatumType == DatumType.Param7) { PjGeocentricFromWgs84(dest, xy, z, startIndex, numPoints); } /* -------------------------------------------------------------------- */ /* Convert back to geodetic coordinates. */ /* -------------------------------------------------------------------- */ gc = new GeocentricGeodetic(dDatum.Spheroid); gc.GeocentricToGeodetic(xy, z, startIndex, numPoints); } /* -------------------------------------------------------------------- */ /* Apply grid shift to destination if required. */ /* -------------------------------------------------------------------- */ if (dDatum.DatumType == DatumType.GridShift) { // pj_apply_gridshift(pj_param(dstdefn->params,"snadgrids").s, 1, // point_count, point_offset, x, y, z ); GridShift.Apply(dest.GeographicInfo.Datum.NadGrids, true, xy, startIndex, numPoints); } }