package org.ianturton.cookbook.output; import java.awt.event.ActionEvent; import java.awt.image.RenderedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.imageio.ImageIO; import javax.imageio.stream.ImageOutputStream; import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.JToolBar; import org.geotools.data.FileDataStore; import org.geotools.data.FileDataStoreFinder; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.grid.Grids; import org.geotools.map.FeatureLayer; import org.geotools.map.Layer; import org.geotools.map.MapContent; import org.geotools.map.event.MapBoundsEvent; import org.geotools.map.event.MapBoundsListener; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.styling.SLD; import org.geotools.styling.Style; import org.geotools.swing.JMapFrame; import org.geotools.swing.JMapPane; import org.geotools.swing.data.JFileDataStoreChooser; import org.opengis.metadata.extent.Extent; import org.opengis.metadata.extent.GeographicBoundingBox; import org.opengis.metadata.extent.GeographicExtent; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; /** * draw a map with graticules * * @author ian.turton * */ public class MapWithGrid implements MapBoundsListener { private JMapFrame frame; private MapContent mapContent; private FeatureLayer layer; private Layer gridLayer; private Style style; public static void main(String[] args) throws IOException { File file = null; if (args.length == 0) { // display a data store file chooser dialog for shapefiles file = JFileDataStoreChooser.showOpenFile("shp", null); if (file == null) { return; } } else { file = new File(args[0]); if (!file.exists()) { System.err.println(file + " doesn't exist"); return; } } new MapWithGrid(file); } public MapWithGrid(File file) throws IOException { FileDataStore store = FileDataStoreFinder.getDataStore(file); SimpleFeatureSource featureSource = store.getFeatureSource(); // Create a map content and add our shapefile to it mapContent = new MapContent(); mapContent.setTitle("GeoTools Mapping"); style = SLD.createSimpleStyle(featureSource.getSchema()); layer = new FeatureLayer(featureSource, style); ReferencedEnvelope gridBounds = layer.getBounds(); gridLayer = createGridLayer(style, gridBounds); mapContent.addLayer(layer); mapContent.addLayer(gridLayer); mapContent.addMapBoundsListener(this); frame = new JMapFrame(mapContent); frame.enableStatusBar(true); frame.enableToolBar(true); JToolBar toolBar = frame.getToolBar(); toolBar.addSeparator(); SaveAction save = new SaveAction("Save"); toolBar.add(save); frame.initComponents(); frame.setSize(1000, 500); frame.setVisible(true); } private Layer createGridLayer(Style style, ReferencedEnvelope gridBounds) throws IOException { double squareWidth = 20.0; double extent = gridBounds.maxExtent(); double ll = Math.log10(extent); if (ll > 0) { // there are ll 10's across the map while (ll-- > 4) { squareWidth *= 10; } } // max distance between vertices double vertexSpacing = squareWidth / 20; // grow to cover the whole map (and a bit). double left = gridBounds.getMinX(); double bottom = gridBounds.getMinY(); if (left % squareWidth != 0) { if (left > 0.0) { // east left -= Math.abs(left % squareWidth); } else { // west left += Math.abs(left % squareWidth); } } if (bottom % squareWidth != 0) { if (bottom > 0.0) { bottom -= Math.abs(bottom % squareWidth); } else { bottom += Math.abs(bottom % squareWidth); } } gridBounds.expandToInclude(left, bottom); double right = gridBounds.getMaxX(); double top = gridBounds.getMaxY(); if (right % squareWidth != 0) { if (right > 0.0) { // east right += Math.abs(right % squareWidth) + squareWidth; } else { // west right -= Math.abs(right % squareWidth) - squareWidth; } } if (top % squareWidth != 0) { if (top > 0.0) { // North top += Math.abs(top % squareWidth) + squareWidth; } else { // South top -= Math.abs(top % squareWidth) - squareWidth; } } gridBounds.expandToInclude(right, top); SimpleFeatureSource grid = Grids.createSquareGrid(gridBounds, squareWidth, vertexSpacing); Layer gridLayer = new FeatureLayer(grid.getFeatures(), style); return gridLayer; } public void drawMapToImage(File outputFile, String outputType) { JMapPane mapPane = frame.getMapPane(); ImageOutputStream outputImageFile = null; FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(outputFile); outputImageFile = ImageIO.createImageOutputStream(fileOutputStream); RenderedImage bufferedImage = mapPane.getBaseImage(); ImageIO.write(bufferedImage, outputType, outputImageFile); } catch (IOException ex) { ex.printStackTrace(); } finally { try { if (outputImageFile != null) { outputImageFile.flush(); outputImageFile.close(); fileOutputStream.flush(); fileOutputStream.close(); } } catch (IOException e) {// don't care now } } } private class SaveAction extends AbstractAction { /** * Private SaveAction */ private static final long serialVersionUID = 3071568727121984649L; public SaveAction(String text) { super(text); } public void actionPerformed(ActionEvent arg0) { String[] writers = ImageIO.getWriterFormatNames(); String format = (String) JOptionPane.showInputDialog(frame, "Choose output format:", "Customized Dialog", JOptionPane.PLAIN_MESSAGE, null, writers, "png"); drawMapToImage(new File("ian." + format), format); } } public void mapBoundsChanged(MapBoundsEvent event) { // this fires on a CRS change as well as a PAN/ZOOM if (event.getEventType().contains(MapBoundsEvent.Type.CRS)) { CoordinateReferenceSystem crs = event.getNewCoordinateReferenceSystem(); ReferencedEnvelope oldAoI = event.getOldAreaOfInterest(); ReferencedEnvelope newAoI = event.getNewAreaOfInterest(); System.out.println("going from " + oldAoI + "\nto " + newAoI + "\nfor CRS " + crs); Extent bounds = crs.getDomainOfValidity(); if (bounds == null) { return; } Extent crsExtent = crs.getDomainOfValidity(); for (GeographicExtent element : crsExtent.getGeographicElements()) { if (element instanceof GeographicBoundingBox) { GeographicBoundingBox env = (GeographicBoundingBox) element; ReferencedEnvelope bbox = new ReferencedEnvelope( env.getWestBoundLongitude(), env.getEastBoundLongitude(), env.getSouthBoundLatitude(), env.getNorthBoundLatitude(), DefaultGeographicCRS.WGS84); ReferencedEnvelope envelope = null; try { envelope = bbox.transform(crs, true); } catch (TransformException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FactoryException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(envelope); frame.getMapPane().getMapContent().getViewport().setBounds(envelope); } } // mapContent.removeLayer(gridLayer); /* * try { gridLayer = createGridLayer(style, res); } catch (IOException e) * { // TODO Auto-generated catch block e.printStackTrace(); return; } * mapContent.addLayer(gridLayer); */ } } }