0
votes

I am using the ArcGIS .NET SDK with WPF, and my code is based on this project.

I am trying to load polygons from a database to display on the Map. I also want to be able to edit these polygons and update them on the database. I got everything working fine, as I was saving my polygons with the SpatialReferences.WebMercator property.

But now I have a database where the polygons are saved as Wgs84 (lat & lon). Now I can load these polygons onto the map, but I am not able to edit them, as the Map is WebMercator and the polygons are Wgs84. As soon as I try to edit I get an exception:

The input spatial reference does not match the owning spatial reference...

I need to convert my polygons as soon as I load them from the database (Wgs84 to WebMercator), and convert them back right before I save to the database (WebMercator to Wgs84).

So I was able to do the first conversion, I load the Wgs84 polygon from the database and convert each point to WebMercator. I can display these polygons and I can also edit them.

But I am struggling to do the second conversion when trying to save a polygon. I did find a formula that can convert these WebMercator points back to Wgs84 to save on the database, but in addition to the lat and lon it also needs a zone. So the way I get the points:

String geomStr = MyMapView.SketchEditor.Geometry.ToJson();

From there I can get all the lat & lon pairs to convert, but I need the zone of each point. Is there any way to retrieve the zone from the Graphic or Geometry object? Or what about figuring out the zone from just knowing the lat or lon point? This is all I need before I can try the conversion formula for Wgs84 to WebMercator.

This tool has the functionality I need. But it is not 100% accurate when converting from EPSG:3857 to EPSG:4326.

2

2 Answers

0
votes

I do not know how ArcGIS actually stores or handles data that has WebMercator as spatial reference.

The "official" specification is given by EPSG:3857.

See also https://epsg.io/3857 and https://spatialreference.org/ref/sr-org/epsg3857-wgs84-web-mercator-auxiliary-sphere/

The map projection is explained here: https://en.wikipedia.org/wiki/Web_Mercator_projection

If you want to do the calculation yourself, use methods like the ones shown below, where Location is a class that holds WGS 84 latitude and longitude values in degrees, and Point is System.Windows.Point and holds X and Y values in meters, measured from the coordinate origin at Latitude=0 and Longitude=0.

public class Location
{
    public double Latitude { get; set; }  // degrees from -90 to 90
    public double Longitude { get; set; } // degrees from -180 to 180
}

public const double Wgs84EquatorialRadius = 6378137d;
public const double Wgs84MetersPerDegree = Wgs84EquatorialRadius * Math.PI / 180d;

public override Point LocationToPoint(Location location)
{
    return new Point(
        Wgs84MetersPerDegree * location.Longitude,
        Wgs84MetersPerDegree * LatitudeToY(location.Latitude));
}

public override Location PointToLocation(Point point)
{
    return new Location(
        YToLatitude(point.Y / Wgs84MetersPerDegree),
        point.X / Wgs84MetersPerDegree);
}

public static double LatitudeToY(double latitude)
{
    if (latitude <= -90d)
    {
        return double.NegativeInfinity;
    }

    if (latitude >= 90d)
    {
        return double.PositiveInfinity;
    }

    return Math.Log(Math.Tan((latitude + 90d) * Math.PI / 360d)) * 180d / Math.PI;
}

public static double YToLatitude(double y)
{
    return 90d - Math.Atan(Math.Exp(-y * Math.PI / 180d)) * 360d / Math.PI;
}
0
votes

This should do the trick:

 var geometry = GeometryEngine.Project(MyMapView.SketchEditor.Geometry, SpatialReferences.Wgs84);