/// <summary> /// /// </summary> /// <param name="points"></param> /// <param name="source"></param> /// <param name="dest"></param> /// <param name="startIndex"></param> /// <param name="numPoints"></param> public static void ReprojectPoints(double[][] points, ProjectionInfo source, ProjectionInfo dest, int startIndex, int numPoints) { double toMeter = source.Unit.Meters; // Geocentric coordinates are centered at the core of the earth. Z is up toward the north pole. // The X axis goes from the center of the earth through greenwich. // The Y axis passes through 90E. // This section converts from geocentric coordinates to geodetic ones if necessary. if (source.IsGeocentric) { if (points[0].Length < 3) { throw new ProjectionException(45); } for (int i = startIndex; i < numPoints; i++) { if (toMeter != 1) { points[i][0] *= toMeter; points[i][1] *= toMeter; } } GeocentricGeodetic g = new GeocentricGeodetic(source.GeographicInfo.Datum.Spheroid); g.GeocentricToGeodetic(points, startIndex, numPoints); } // Transform source points to lat/long if they are not already if (!source.IsLatLon) { ConvertToLatLon(source, points, startIndex, numPoints); } double fromGreenwich = source.GeographicInfo.Meridian.Longitude * source.GeographicInfo.Unit.Radians; if (fromGreenwich != 0) { for (int i = startIndex; i < numPoints; i++) { if (points[i][0] != double.PositiveInfinity) { points[i][0] += fromGreenwich; } } } // TO DO: DATUM TRASNFORM IF NEEDED // Adjust to new prime meridian if there is one in the destination cs fromGreenwich = dest.GeographicInfo.Meridian.Longitude * dest.GeographicInfo.Unit.Radians; if (fromGreenwich != 0) { for (int i = startIndex; i < numPoints; i++) { if (points[i][0] != double.PositiveInfinity) { points[i][0] -= fromGreenwich; } } } if (dest.IsGeocentric) { if (points[0].Length < 3) { throw new ProjectionException(45); } GeocentricGeodetic g = new GeocentricGeodetic(dest.GeographicInfo.Datum.Spheroid); g.GeodeticToGeocentric(points, startIndex, numPoints); double frmMeter = 1 / dest.Unit.Meters; if (frmMeter != 1) { for (int i = startIndex; i < numPoints; i++) { if (points[i][0] != double.PositiveInfinity) { points[i][0] *= frmMeter; points[i][1] *= frmMeter; } } } } else { if (!dest.IsLatLon) { ConvertToProjected(dest, points, startIndex, numPoints); } } }
private static void DatumTransform(ProjectionInfo source, ProjectionInfo dest, double[][] points, int startIndex, int numPoints) { Spheroid wgs84 = new Spheroid(Proj4Ellipsoids.WGS_1984); Datum sDatum = source.GeographicInfo.Datum; Datum dDatum = dest.GeographicInfo.Datum; double[][] zPoints = new double[points.Length][]; bool zIsTemp = false; /* -------------------------------------------------------------------- */ /* 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 == DatumTypes.Unknown || dDatum.DatumType == DatumTypes.Unknown) { return; } /* -------------------------------------------------------------------- */ /* Short cut if the datums are identical. */ /* -------------------------------------------------------------------- */ if (sDatum.Matches(dDatum)) { 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 (points[0].Length > 2) { zPoints = points; } else { for (int i = startIndex; i < numPoints; i++) { zPoints[i] = new[] { points[i][0], points[i][1], 0 }; } zIsTemp = true; } /* -------------------------------------------------------------------- */ /* If this datum requires grid shifts, then apply it to geodetic */ /* coordinates. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumTypes.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, points, startIndex, numPoints); srcA = wgs84.EquatorialRadius; srcEs = wgs84.EccentricitySquared(); } if (dDatum.DatumType == DatumTypes.GridShift) { dstA = wgs84.EquatorialRadius; dstEs = wgs84.EccentricitySquared(); } /* ==================================================================== */ /* Do we need to go through geocentric coordinates? */ /* ==================================================================== */ if (srcEs != dstEs || srcA != dstA || sDatum.DatumType == DatumTypes.Param3 || sDatum.DatumType == DatumTypes.Param7 || dDatum.DatumType == DatumTypes.Param3 || dDatum.DatumType == DatumTypes.Param7) { /* -------------------------------------------------------------------- */ /* Convert to geocentric coordinates. */ /* -------------------------------------------------------------------- */ GeocentricGeodetic gc = new GeocentricGeodetic(sDatum.Spheroid); gc.GeodeticToGeocentric(zPoints, startIndex, numPoints); /* -------------------------------------------------------------------- */ /* Convert between datums. */ /* -------------------------------------------------------------------- */ if (sDatum.DatumType == DatumTypes.Param3 || sDatum.DatumType == DatumTypes.Param7) { // pj_geocentric_to_wgs84( srcdefn, point_count, point_offset,x,y,z); } if (dDatum.DatumType == DatumTypes.Param3 || dDatum.DatumType == DatumTypes.Param7) { // pj_geocentric_from_wgs84( dstdefn, point_count,point_offset,x,y,z); } /* -------------------------------------------------------------------- */ /* Convert back to geodetic coordinates. */ /* -------------------------------------------------------------------- */ gc = new GeocentricGeodetic(dDatum.Spheroid); gc.GeodeticToGeocentric(zPoints, startIndex, numPoints); } /* -------------------------------------------------------------------- */ /* Apply grid shift to destination if required. */ /* -------------------------------------------------------------------- */ if (dDatum.DatumType == DatumTypes.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, points, startIndex, numPoints); } if (zIsTemp) { for (int i = startIndex; i < numPoints; i++) { points[i][0] = zPoints[i][0]; points[i][1] = zPoints[i][1]; } } }