ThinkGeo.com    |     Blog    |     Wiki    |     Support

Rendering Map Image

Hi,


I wrote a quick web service which renders a map and then generates an image of that map to send back to the client.  I am having some issues with using the World Map Kit with it.  If I use Google as the base layer then it works fine but if I try to render the world map kit layers I get a blank map.  See the attached.  Any ideas what might be going wrong?  Doesn't seem to make any sense to me.


Here is the code that I am using for WorldMapKit:



[WebMethod]
public byte[] GetSignSearchResultMapImage(float latitude, float longitude, int imageWidth, int imageHeight) {
List<Layer> layers = new List<Layer>();
//GoogleMapsLayer google = new GoogleMapsLayer(ConfigurationManager.AppSettings["GoogleKey"]);
//google.MapType = GoogleMapsMapType.RoadMap;
//layers.Add(google);

if(Application["worldMapKit"] == null) {
WebServicesRenderMap renderMaps = new WebServicesRenderMap(ConfigurationManager.AppSettings["MapDataDirectory"]);
renderMaps.LoadLayers(layers);
Application["worldMapKit"] = layers;
}
layers = (List<Layer>)Application["worldMapKit"];

InMemoryFeatureLayer signLayer = (InMemoryFeatureLayer)this.buildSignSearchResultLayer(latitude, longitude);
signLayer.Open();
RectangleShape worldExtent = signLayer.GetBoundingBox();
signLayer.Close();
worldExtent.ScaleUp(20);
layers.Add(signLayer);

GeoImage geoImage = GdiPlusGeoCanvas.CreateGeoImage(imageWidth, imageHeight);
GdiPlusGeoCanvas.FillBackground(geoImage, new GeoSolidBrush(GeoColor.GeographicColors.DeepOcean));
GdiPlusGeoCanvas gdiPlusGeoCanvas = new GdiPlusGeoCanvas();
gdiPlusGeoCanvas.BeginDrawing(geoImage, worldExtent, GeographyUnit.Meter);

for(int i = 0; i < layers.Count; i++) {
Layer layer = layers[i];
lock(layer) {
try {
layer.Open();
layer.Draw(gdiPlusGeoCanvas, new Collection<SimpleCandidate>());
} finally {
layer.Close();
}
}
}
if(gdiPlusGeoCanvas.IsDrawing) {
gdiPlusGeoCanvas.EndDrawing();
}

return GdiPlusGeoCanvas.ConvertGeoImageToMemoryStream(geoImage).ToArray();
}

private Layer buildSignSearchResultLayer(float latitude, float longitude) {
int distance = 300;
List<Sign> signs = SignInventoryDAL.SearchSigns(latitude, longitude, distance);

InMemoryFeatureLayer pointLayer = new InMemoryFeatureLayer();
pointLayer.Open();
pointLayer.Columns.Add(new FeatureSourceColumn("SignId"));
pointLayer.Columns.Add(new FeatureSourceColumn("Description"));
pointLayer.Columns.Add(new FeatureSourceColumn("Latitude"));
pointLayer.Columns.Add(new FeatureSourceColumn("Longitude"));
pointLayer.Close();
pointLayer.Name = "PointLayer";
pointLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
pointLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("Description", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 10, 10);
pointLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(Server.MapPath("../images/Stop.png")));

//Sets the projection parameters to go from Geodetic (EPSG 4326) or decimal degrees to Google Map projection (Spherical Mercator).
//Proj4Projection proj4 = new Proj4Projection();
//proj4.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
//proj4.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();

////Applies the projection to the InMemoryFeatureLayer so that the point in decimal degrees (Longitude/Latitude) can be 
////match the projection of Google Map.
//pointLayer.FeatureSource.Projection = proj4;

for(int i = 0; i < signs.Count; i++) {
Sign sign = signs[i];
Vertex vertex = new Vertex(this.convertToDecimalDegrees(sign.Longitude), this.convertToDecimalDegrees(sign.Latitude));

// Add position to the point layer, also need to check whether a marker should be rendered.
PointShape pointShape = new PointShape(vertex);
Feature feature = new Feature(pointShape);
feature.ColumnValues.Add("Sign", sign.SignId.ToString());
feature.ColumnValues.Add("Description", sign.Description);
feature.ColumnValues.Add("Latitude", sign.Latitude);
feature.ColumnValues.Add("Longitude", sign.Longitude);
pointLayer.InternalFeatures.Add(feature);
}

return pointLayer;
}

And this for Google:



[WebMethod]
public byte[] GetSignSearchResultMapImage(float latitude, float longitude, int imageWidth, int imageHeight) {
List<Layer> layers = new List<Layer>();
GoogleMapsLayer google = new GoogleMapsLayer(ConfigurationManager.AppSettings["GoogleKey"]);
google.MapType = GoogleMapsMapType.RoadMap;
layers.Add(google);

//if(Application["worldMapKit"] == null) {
//    WebServicesRenderMap renderMaps = new WebServicesRenderMap(ConfigurationManager.AppSettings["MapDataDirectory"]);
//    renderMaps.LoadLayers(layers);
//    Application["worldMapKit"] = layers;
//}
//layers = (List<Layer>)Application["worldMapKit"];

InMemoryFeatureLayer signLayer = (InMemoryFeatureLayer)this.buildSignSearchResultLayer(latitude, longitude);
signLayer.Open();
RectangleShape worldExtent = signLayer.GetBoundingBox();
signLayer.Close();
worldExtent.ScaleUp(20);
layers.Add(signLayer);

GeoImage geoImage = GdiPlusGeoCanvas.CreateGeoImage(imageWidth, imageHeight);
GdiPlusGeoCanvas.FillBackground(geoImage, new GeoSolidBrush(GeoColor.GeographicColors.DeepOcean));
GdiPlusGeoCanvas gdiPlusGeoCanvas = new GdiPlusGeoCanvas();
gdiPlusGeoCanvas.BeginDrawing(geoImage, worldExtent, GeographyUnit.Meter);

for(int i = 0; i < layers.Count; i++) {
Layer layer = layers<i>;
lock(layer) {
try {
layer.Open();
layer.Draw(gdiPlusGeoCanvas, new Collection<SimpleCandidate>());
} finally {
layer.Close();
}
}
}
if(gdiPlusGeoCanvas.IsDrawing) {
gdiPlusGeoCanvas.EndDrawing();
}

return GdiPlusGeoCanvas.ConvertGeoImageToMemoryStream(geoImage).ToArray();
}

private Layer buildSignSearchResultLayer(float latitude, float longitude) {
int distance = 300;
List<Sign> signs = SignInventoryDAL.SearchSigns(latitude, longitude, distance);

InMemoryFeatureLayer pointLayer = new InMemoryFeatureLayer();
pointLayer.Open();
pointLayer.Columns.Add(new FeatureSourceColumn("SignId"));
pointLayer.Columns.Add(new FeatureSourceColumn("Description"));
pointLayer.Columns.Add(new FeatureSourceColumn("Latitude"));
pointLayer.Columns.Add(new FeatureSourceColumn("Longitude"));
pointLayer.Close();
pointLayer.Name = "PointLayer";
pointLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
pointLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("Description", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 10, 10);
pointLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(Server.MapPath("../images/Stop.png")));

//Sets the projection parameters to go from Geodetic (EPSG 4326) or decimal degrees to Google Map projection (Spherical Mercator).
Proj4Projection proj4 = new Proj4Projection();
proj4.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
proj4.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();

//Applies the projection to the InMemoryFeatureLayer so that the point in decimal degrees (Longitude/Latitude) can be 
//match the projection of Google Map.
pointLayer.FeatureSource.Projection = proj4;

for(int i = 0; i < signs.Count; i++) {
Sign sign = signs<i>;
Vertex vertex = new Vertex(this.convertToDecimalDegrees(sign.Longitude), this.convertToDecimalDegrees(sign.Latitude));

// Add position to the point layer, also need to check whether a marker should be rendered.
PointShape pointShape = new PointShape(vertex);
Feature feature = new Feature(pointShape);
feature.ColumnValues.Add("Sign", sign.SignId.ToString());
feature.ColumnValues.Add("Description", sign.Description);
feature.ColumnValues.Add("Latitude", sign.Latitude);
feature.ColumnValues.Add("Longitude", sign.Longitude);
pointLayer.InternalFeatures.Add(feature);
}

return pointLayer;
}

 


Thanks

Curtis



Curtis, 
  
 WorldMapKit is using DecimalDegrees as its Map Unit, can you change the unit in following line from Meter to DecimalDegrees? 
 
gdiPlusGeoCanvas.BeginDrawing(geoImage, worldExtent, GeographyUnit.Meter);
 
  
 If that doesn’t help, can you try one ShapeFile to simplify the problem and have another try? 
  
 Also, new WorldMapKit is released a couple weeks ago with TIGER 2009 data integrated, please contact your sale represent if you want to get the latest one. You use layer.Draw() that’s fine, you can also use MapEngine to draw which makes the codes simpler, please see the sample code alone with the WorldMapKit Source for detail. 
  
 Thanks, 
  
 Ben