3

We have an API which converts MS SQL geography type to well-known text, and sends it to the front end, which then sends WKT to OpenLayer maps, which renders canvas (borders, regions etc).

I am looking a way to reduce payload to the client and convert polygons, multypoligons, and maps in general to png on the backend side.

What I tried is to convert canvas to base64, and save it as PNG. That works well, but I need a full backend solution.

I tried to play around with SharpMap, but it's quite old, it's causing me dependency issues, and I did not manage to get it working.

I found a test SHP file and tried to render it to PictureBox in windows forms for a test, and all I got was an empty white box.

SharpMap.Map myMap = new SharpMap.Map(new Size(600, 300));
myMap.BackColor = Color.White;
var shapeFileProvider = new SharpMap.Data.Providers.ShapeFile(@"C:\Users\test\Downloads\FRA_adm\FRA_adm1.shp", true);

SharpMap.Layers.VectorLayer myLayer = new SharpMap.Layers.VectorLayer("World Countries");
myMap.Layers.Add(myLayer);
myMap.ZoomToExtents();
myLayer.DataSource = shapeFileProvider;
pictureBox1.Image = myMap.GetMap();

Any ideas on how to tackle this issue?

EDIT: I even tried geoserver, but it looks like it does not support Spatial Geography, but only geometry.

I need to find a way to convert borders, regions, countries to images in c# backend.

Edit 2: U am using SHP file for testing, but what I really want is to render it from Sql Server Geography type.

Robert
  • 3,353
  • 4
  • 32
  • 50
  • @OndrejSvejdar it's not only library related. Maybe someone will know why my SharpMap code is not working – Robert Jun 14 '17 at 09:16

1 Answers1

6

SharpMap is still maintained, but the nuget packages are not. And the packages (dated 2014) are not compatible with all the dependencies (GeoAPI, ProjNet, etc.) current nuget versions. What I suggest is:

  1. don't use SharpMap nuget, build your own SharpMap assemblies from github (most of the assemblies compile w/o any issue, especially the main one, SharpMap)
  2. reference that assembly (and only that one)
  3. reference the latest versions of the dependency assemblies manually one by one when you need it.

Here is your WinForms code adapted with the latest SharpMap, GeoAPI and ProjNet:

public partial class Form1 : Form
{
    public Form1()
    {
        // just add a PictureBox on the Winform.
        InitializeComponent();
        DrawMap();
    }

    private void DrawMap()
    {
        Session.Instance.SetCoordinateSystemServices(
            new CoordinateSystemServices(
                    new CoordinateSystemFactory(),
                    new CoordinateTransformationFactory(),
                    SpatialReference.GetAllReferenceSystems()));

        var map = new Map(pictureBox1.Size);
        map.BackColor = Color.White;
        var file = new ShapeFile(@"D:\Downloads\FRA_adm\FRA_adm1.shp", true);
        var layer = new VectorLayer("France", file);
        map.Layers.Add(layer);
        map.ZoomToExtents();
        pictureBox1.Image = map.GetMap();
    }
}

This will display this:

enter image description here

As you see, the map looks funny, if you happen to know France contours :-). If you want the correct projection, you need to add this code to the layer:

layer.CoordinateTransformation = Wgs84ToGoogle;

...

// Wgs84 to Google Mercator Coordinate Transformation
// this code comes from SharpMap\Examples\WinFormSamples\LayerTools.cs
private ICoordinateTransformation _wgs84ToGoogle;
public ICoordinateTransformation Wgs84ToGoogle
{
    get
    {
        if (_wgs84ToGoogle == null)
        {
            var csFac = new CoordinateSystemFactory();
            var ctFac = new CoordinateTransformationFactory();

            var wgs84 = csFac.CreateGeographicCoordinateSystem(
              "WGS 84", AngularUnit.Degrees, HorizontalDatum.WGS84, PrimeMeridian.Greenwich,
              new AxisInfo("north", AxisOrientationEnum.North), new AxisInfo("east", AxisOrientationEnum.East));

            var parameters = new List<ProjectionParameter>();
            parameters.Add(new ProjectionParameter("semi_major", 6378137.0));
            parameters.Add(new ProjectionParameter("semi_minor", 6378137.0));
            parameters.Add(new ProjectionParameter("latitude_of_origin", 0.0));
            parameters.Add(new ProjectionParameter("central_meridian", 0.0));
            parameters.Add(new ProjectionParameter("scale_factor", 1.0));
            parameters.Add(new ProjectionParameter("false_easting", 0.0));
            parameters.Add(new ProjectionParameter("false_northing", 0.0));

            var projection = csFac.CreateProjection("Google Mercator", "mercator_1sp", parameters);
            var epsg900913 = csFac.CreateProjectedCoordinateSystem(
              "Google Mercator", wgs84, projection, LinearUnit.Metre, new AxisInfo("East", AxisOrientationEnum.East),
              new AxisInfo("North", AxisOrientationEnum.North));

            ((CoordinateSystem)epsg900913).DefaultEnvelope = new[] { -20037508.342789, -20037508.342789, 20037508.342789, 20037508.342789 };

            _wgs84ToGoogle = ctFac.CreateFromCoordinateSystems(wgs84, epsg900913);
        }
        return _wgs84ToGoogle;
    }
}

And you now will get this:

enter image description here

SharpMap may be a bit bloated, but it still provides valuable code and the samples work. Since the documentation is hard to find, if you use it, you may have to dig in the source.

Also, you want to know that GDI+, which SharpMap uses, is not officially supported by Microsoft on server side. It doesn't mean it doesn't work, you'll have to try by yourself in your own context.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Wow, thanks! while testing code, I found an error. You pointed that i should reference ProjNet package, while i got to compile with Proj.Net package. One dot, gave me quite a headache :) Could you elaborate why map was "funny" on the first go, and why i had to add Wgs84ToGoogle ? It works fine until I add it. Then i get picturebox with red cross over it – Robert Jun 14 '17 at 11:33
  • I don't have the Proj.Net only ProjNet... I've put my test project main files here: https://gist.github.com/smourier/3d7739c0c719ee0c81fccbd2131fe62c funny means the image is obviously distorted. – Simon Mourier Jun 14 '17 at 14:54
  • Your code works fine and helped me to find 90% of my solution. Do you know how can i transform my coordinates from 4326 projection to 3857 Meridian? I tried supplied code, but it's not working when i use CoordinateTransformation. – Robert Jun 19 '17 at 07:14