/// <summary> /// datum tranform method /// </summary> /// <param name="source"></param> /// <param name="dest"></param> /// <param name="xy"></param> /// <param name="z"></param> /// <param name="startIndex"></param> /// <param name="numPoints"></param> public void Transform(ProjectionInfo source, ProjectionInfo dest, double[] xy, double[] z, int startIndex, int numPoints) { if (_aiDts.Length == 0) { return; // "empty" datum transform } bool bCoordsAreGeocentric = false; /* -------------------------------------------------------------------- */ /* Create a temporary Z value if one is not provided. */ /* -------------------------------------------------------------------- */ if (z == null) { z = new double[xy.Length / 2]; } foreach (IDatumTransformStage idts in _aiDts) { if (idts.Method == TransformMethod.GridShift) { if (bCoordsAreGeocentric) { var gc = new GeocentricGeodetic(idts.FromSpheroid); gc.GeocentricToGeodetic(xy, z, startIndex, numPoints); bCoordsAreGeocentric = false; } var astrGrids = new string[1]; astrGrids[0] = "@" + idts.GridShiftTable; GridShift.Apply(astrGrids, idts.ApplyTableInverse, xy, startIndex, numPoints); } else { if (!bCoordsAreGeocentric) { var gc = new GeocentricGeodetic(idts.FromSpheroid); gc.GeodeticToGeocentric(xy, z, startIndex, numPoints); bCoordsAreGeocentric = true; } ApplyParameterizedTransform(idts, xy, z, startIndex, numPoints); } } /* -------------------------------------------------------------------- */ /* Convert back to geodetic coordinates, if needed. */ /* -------------------------------------------------------------------- */ if (bCoordsAreGeocentric) { var gc = new GeocentricGeodetic(_aiDts[_aiDts.Length - 1].ToSpheroid); gc.GeocentricToGeodetic(xy, z, startIndex, numPoints); } }
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); } }