Search code examples
c#.netgeolocationsharpmap

How to render image of a country on a globe using sharpmap


I have a list of region borders inside SQL database and i am using sharpmap to render thumbnail images for every country i need. It works really well.

But I would like to go one step further and add a small globe around it and position country on it's place in globe, but I do not know where to start.

Here's the code i'm using so far to render country thumbs. Any ideas?

var map = new Map(new Size(command.Width, command.Height));
map.BackColor = Color.Transparent;
var countryGeometry = GeometryFromWKT.Parse(command.CountryLevelWkt);
IProvider countryProvider = new GeometryFeatureProvider(countryGeometry);
var countryLayer = new VectorLayer("country", countryProvider);
var borderColor = System.Drawing.ColorTranslator.FromHtml(command.BorderColor);
countryLayer.Style.EnableOutline = true;
countryLayer.Style.Outline = new Pen(borderColor);
countryLayer.Style.Outline.Width = command.BorderWidth;
countryLayer.Style.Fill = Brushes.Transparent;

var transformationFactory = new CoordinateTransformationFactory();
countryLayer.CoordinateTransformation = transformationFactory.CreateFromCoordinateSystems(
            GeographicCoordinateSystem.WGS84,
            ProjectedCoordinateSystem.WebMercator);
map.Layers.Add(countryLayer);
var bottomLeft = new Coordinate(command.Extents.BottomLeft.Longitude, command.Extents.BottomLeft.Latitude);
var topRight = new Coordinate(command.Extents.TopRight.Longitude, command.Extents.TopRight.Latitude);


// transformations
var bottomLeftLongLat = countryLayer.CoordinateTransformation.MathTransform.Transform(bottomLeft);
var topRightLongLat = countryLayer.CoordinateTransformation.MathTransform.Transform(topRight);
map.ZoomToBox(new Envelope(bottomLeftLongLat, topRightLongLat));
             var img = map.GetMap();
return img;

Solution

    1. Start by drawing all countries on a new map, each on its own layer.
    2. Draw the country in which you're interested on its own layer.
    3. Set map center to the Envelope.Center of the layer from Step 2. Eg, if drawing Australia, the map will move to the left.
    4. Render map as image. Draw image on a drawing sufrace (System.Drawing.Graphics).
    5. Re-center the map, to cover the empty space. Eg, if drawing Australia, move map almost all the way to the right. You will need to work out these offsets programmatically.
    6. Render map from step 5 as image. Add image to the same drawing sufrace (see step 4).
    7. Repeat steps 5-6 covering empty space below/above the render made at step 3.

    Here is an example: Sample form with map rendering

    Note that:

    • Australia is in the center
    • There is a gap between map layers near the mouse pointer (gap in screenshot is intentional to demonstrate the logic)
    • Some countries are very large (eg Russia) and obtaining Envelope.Center will not work very well - consider centering based on the largest polygon only

    Here's a sample Windows Forms project. In the sample, I used maps from http://thematicmapping.org/downloads/world_borders.php.