Step 3b: Create the Client Code for the Mapping Service
The next step is to create a map image with the found subway stations using Toronto as the base map. We need to use the RenderNamedMapWithOverlay method of the Mapping Service.
The steps are:
- Create an instance of RenderNamedMapWithOverlayRequest.
- Set the desired width and height of the image.
- Set the view (bounds) of the map.
- Set the named map to render.
- Set the MIME type (image format) to generate.
- Create a FeatureLayer overlay based on the specified FeatureCollection.
- Set some label properties to label each subway station with its name and distance in meters.
- Create a theme to give the subway stations a recognizable style.
- Execute the request and return the image's bytes.
Here is the code:
/**
* Returns the image of the map overlayed with Features in the specified FeatureCollection.
* @param fc the FeatureCollection to render on top of the map.
* @param centerLongitude the longitude of the center of the map
* @param centerLatitude the latitude of the center of the map
* @param zoom the zoom (distance across the map) assumed to be kilometers.
* @return the image of the map overlayed with Features in the specified FeatureCollection.
*/
private byte[] createMap(FeatureCollection fc, double centerLongitude, double centerLatitude, double zoom) {
RenderNamedMapWithOverlayRequest request = new RenderNamedMapWithOverlayRequest();
ZoomAndCenterMapView mapView = new ZoomAndCenterMapView();
// set the dimensions of the returned image to be 640 x 480
mapView.setWidth(640);
mapView.setHeight(480);
// set the view. in this case we are using the zoom/center view
Point center = new Point();
center.setSrsName("epsg:4326");
center.setPos(new Pos());
center.getPos().setX(centerLatitude);
center.getPos().setY(centerLongitude);
mapView.setMapCenter(center);
Distance zoomLevel = new Distance();
zoomLevel.setValue(zoom);
zoomLevel.setUom(DistanceUnit.KILOMETER);
mapView.setZoomLevel(zoomLevel);
request.setMapView(mapView);
// use the /demo/namedmaps/ontario Named Map for the background
String namedMap = "/demo/namedmaps/ontario";
request.setNamedMap(namedMap);
// we want a GIF
String mimeType = "image/gif";
request.setImageMimeType(mimeType);
// return the image NOT a URL to the image
request.setReturnImage(true);
// now create the FeatureCollection overlay using a MemoryTable and a FeatureLayer
OverlayList overlayList = new OverlayList();
List<Layer> overlays = overlayList.getOverlay();
MemoryTable table = new MemoryTable();
table.setFeatureCollection(fc);
FeatureLayer layer = new FeatureLayer();
layer.setTable(table);
{
// create the label properties
MapBasicPointStyle style = new MapBasicPointStyle();
MapBasicFontSymbol mapBasicSymbol;
mapBasicSymbol = new MapBasicFontSymbol();
mapBasicSymbol.setBold(true);
mapBasicSymbol.setColor("black");
mapBasicSymbol.setFontName("Arial");
mapBasicSymbol.setSize((short) 14);
mapBasicSymbol.setShape(33);
style.setMapBasicSymbol(mapBasicSymbol);
LabelProperties labelProperties = new LabelProperties();
// the label expression is an MI SQL fragment
labelProperties.setExpression("name + '(' + round(distance) + ' m)'");
labelProperties.setAllowDuplicate(AllowDuplicateType.ALL);
labelProperties.setAllowOverlap(true);
labelProperties.setXOffset(10.0); // a small offset in the X direction so the label does not overwrite the symbol
layer.setLabelProperties(labelProperties);
}
overlays.add(layer);
request.setOverlayList(overlayList);
// add theme to set the style of the overlay
OverrideTheme theme = new OverrideTheme();
MapBasicPointStyle featureStyle = new MapBasicPointStyle();
MapBasicFontSymbol mapBasicFontSymbol = new MapBasicFontSymbol();
mapBasicFontSymbol.setShape(64);
mapBasicFontSymbol.setColor("red");
mapBasicFontSymbol.setFontName("MapInfo Transportation");
mapBasicFontSymbol.setSize((short) 14);
featureStyle.setMapBasicSymbol(mapBasicFontSymbol);
theme.setStyle(featureStyle);
ThemeList themeList = new ThemeList();
themeList.getTheme().add(theme);
layer.setThemeList(themeList);
// create the client-side instance/interface to the FeatureService and specify the security settings to access the service
MappingService mappingServiceBootstrap = new MappingService();
MappingServiceInterface servicePort = mappingServiceBootstrap.getPort(MappingServiceInterface.class);
((BindingProvider)servicePort).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, ADMIN_USERNAME);
((BindingProvider)servicePort).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, ADMIN_PASSWORD);
RenderNamedMapWithOverlayResponse response;
try {
response = servicePort.renderNamedMapWithOverlay(request);
} catch (com.mapinfo.midev.service.mapping.ws.v1.ServiceException e) {
throw new RuntimeException(e);
}
MapImage mapImage = response.getMapImage();
return mapImage.getImage();
}