Contributor(s): Tom Benner
Printing an OpenLayers map with a browser is unreliable, since browsers don't always treat stacked, transparent images as one might expect during the printing process. As a result, it is recommended that an image be created of the map, which is then embedded in an HTML page that uses JavaScript to call the browser's print function.
The usual way of doing this is to use JavaScript to gather a list of the parameters that are sent to GeoServer to create each layer on the map (as well as other information, like the map's pixel size and bounds), and then POST this information to a PHP script, which makes the appropriate requests to GeoServer to gather of the image tiles for each layer. The PHP script then uses the GD library to stitch together those images into an image that contains exactly the same content as the OpenLayers map. Example code for this can be found here. This code can be modified to include multiple image types (e.g. JPEG, GIF, PNG), and extended to allow for other file types, like PDF.
Unlike the URLs of the tiled images that GeoServer serves up, the URLs of the tiled images that create a Google Maps base layer cannot easily be constructed, as Google purposefully changes the setup of their addresses periodically (apparently to discourage people from calling them directly, without going through the API). However, the Google Static Maps API can be used as an alternative way of getting tiled Google Maps images.
To do this, you can pass the pixel size, bounds, zoom level, and (optionally) the Google Maps type (satellite, hybrid, etc) as POST parameters to the PHP script that blits the GeoServer images. The maximum size that the Google Static Maps API allows for is 640x640, so the basic idea is to create images tiles of this size, starting at the bottom right corner of the map, so as to be sure that the copyright text is displayed in the final image.
Finding the proper center coordinates for tiles which have the same longitude is trivial, as pixels and longitude degrees have a direct relationship (or at least a relationship that is close enough to being direct for decent approximations). Moving vertically with tiles is more difficult, though, since the relationship between pixels and latitude degrees is not direct, but rather changes with latitude. The solution is to translate the system into a Cartesian-like coordinate system, find the appropriate center coordinates in that system, then translate those center coordinates back into the original system. Here's a PHP function that will find the latitude of a point, given four arguments: the map's top and bottom latitude values, the height of the map in pixels, and the displacement of the point from the bottom of the map in pixels:
function calculate_latitude_in_bbox($top, $bottom, $height_px, $y_px){
$percentage_from_bottom = $y_px / $height_px;
$top = deg2rad($top);
$bottom = deg2rad($bottom);
$top_c = log(tan($top)+(1/cos($top)));
$bottom_c = log(tan($bottom)+(1/cos($bottom)));
$lat_c = ($top_c - $bottom_c) * $percentage_from_bottom + $bottom_c;
$y = 2*atan(pow(M_E,$lat_c)) - (M_PI/2);
$lat = rad2deg($y);
return $lat;
}
To save the map as a PDF, the first step is to find an appropriate PHP PDF library. The most obvious options are:
FPDF is the simplest PDF library, and the one that the THL interactive map uses. It has limited functionality, but is the easiest to use and involves much less code than the other libraries. It can be used by just copying the library into a directory accessible by the calling code.
TCPDF offers a little more functionality than FPDF, but the library involves a much larger number of files, and more complex code to implement.
PDFlib is a family of PDF libraries, including a free version and a commercial version. To use PDFlib, it needs to be installed as a PHP extension on the server. The free version has somewhat limited functionality; it isn't terribly different than the two libraries listed above, which don't require a PHP extension to be installed. The commercial version allows for very in-depth functionality. It is the only PHP PDF library we could find that supports the creation of PDF layers (known formally as Optional Content Groups). However, it is very expensive; a server license costs $995 at the time of this writing.