//$HeadURL$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2008 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.framework.utils; import static org.deegree.framework.util.MapUtils.DEFAULT_PIXEL_SIZE; import static org.deegree.graphics.MapFactory.createMapView; import static org.deegree.igeo.views.LayerPane.createThemes; import static org.deegree.model.spatialschema.GeometryFactory.createEnvelope; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import javax.swing.SwingUtilities; import org.deegree.graphics.MapView; import org.deegree.graphics.Theme; import org.deegree.igeo.config.TargetDeviceType; import org.deegree.igeo.mapmodel.Layer; import org.deegree.igeo.mapmodel.LayerGroup; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.igeo.mapmodel.MapModelVisitor; import org.deegree.model.spatialschema.Envelope; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.Point; /** * * <code>NewMapHandler</code> * * @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ public class MapTools { /** * adjusts the size and extent of the mapModel to the size of the container * * @param width * the new with of the map model * @param height * the new height of the map model * @param mapModel * the map model to adjust */ public static void adjustMapModelExtent( int width, int height, MapModel mapModel ) { mapModel.getTargetDevice().setPixelHeight( height ); mapModel.getTargetDevice().setPixelWidth( width ); Envelope env = mapModel.getEnvelope(); double mapRatio = (double) width / (double) height; double envRatio = env.getWidth() / env.getHeight(); double minx, miny, maxx, maxy; if ( mapRatio > envRatio ) { miny = env.getMin().getY(); maxy = env.getMax().getY(); minx = env.getCentroid().getX() - env.getHeight() * mapRatio / 2d; maxx = env.getCentroid().getX() + env.getHeight() * mapRatio / 2d; } else { minx = env.getMin().getX(); maxx = env.getMax().getX(); miny = env.getCentroid().getY() - env.getWidth() / mapRatio / 2d; maxy = env.getCentroid().getY() + env.getWidth() / mapRatio / 2d; } mapModel.setEnvelope( createEnvelope( minx, miny, maxx, maxy, env.getCoordinateSystem() ) ); } /** * calculates the position of the mousecursor in the coordinatesystem of the mapmodel * * @param mapModel * the mapModel * @param mouseX * the x-position of the mousecursor * @param mouseY * the y-position of the mousecursor * @param componentWidth * the width of the component * @param componentHeight * the height of the component * @return */ public static Point calculateMouseCoord( MapModel mapModel, double mouseX, double mouseY, double componentWidth, double componentHeight ) { Envelope extent = mapModel.getEnvelope(); double deltaX = mouseX / componentWidth * extent.getWidth(); double deltaY = mouseY / componentHeight * extent.getHeight(); return GeometryFactory.createPoint( extent.getMin().getX() + deltaX, extent.getMax().getY() - deltaY, mapModel.getCoordinateSystem() ); } /** * adjust the point to the size of the given area (width/height), so that the resulting point lays inside of the * area * * @param point * the point to adjust * @param width * the width of the component * @param height * the height of the component * @return the adjusted point inside the area */ public static java.awt.Point adjustPointToPanelSize( java.awt.Point point, int width, int height ) { int x = Double.valueOf( point.getX() ).intValue(); int y = Double.valueOf( point.getY() ).intValue(); if ( x < 0 ) { x = 0; } else if ( x > width - 1 ) { x = width - 1; } if ( y < 0 ) { y = 0; } else if ( y > height - 1 ) { y = height - 1; } return new java.awt.Point( x, y ); } /** * renders legend for a map onto a buffered image * * @param mm * {@link MapModel} to be used * @param fourByte * <code>true</code> if a four byte image (e.g. for png) should be created * @return rendered legend * @throws Exception */ public static BufferedImage getLegendAsImage( final MapModel mm, boolean fourByte ) throws Exception { final List<Layer> layers = new ArrayList<Layer>(); mm.walkLayerTree( new MapModelVisitor() { public void visit( Layer layer ) throws Exception { if ( layer.isVisible() ) { layers.add( layer ); } } public void visit( LayerGroup layerGroup ) throws Exception { // not using grouping nodes } } ); int width = 0; int height = 0; for ( Layer layer : layers ) { BufferedImage bi = layer.getLegend(); Graphics g = bi.getGraphics(); int w = 0; // TODO remove this heuristic if ( bi.getHeight() < 40 ) { w = SwingUtilities.computeStringWidth( g.getFontMetrics(), layer.getTitle() ); } g.dispose(); if ( ( bi.getWidth() + w + 10 ) > width ) { width = ( bi.getWidth() + w + 10 ); } height += ( bi.getHeight() + 10 ); } BufferedImage img = null; if ( fourByte ) { img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); } else { img = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); } Graphics2D g = img.createGraphics(); g.setBackground( Color.WHITE ); g.setColor( Color.WHITE ); g.fillRect( 0, 0, width, height ); g.setColor( Color.BLACK ); int y = 0; for ( Layer layer : layers ) { BufferedImage bi = layer.getLegend(); g.drawImage( bi, 0, y, null ); g.drawString( layer.getTitle(), bi.getWidth() + 10, y + 10 ); y += ( bi.getHeight() + 10 ); } g.dispose(); return img; } /** * renders a map onto a buffered image * * @param mm * {@link MapModel} to be used * @param fourByte * <code>true</code> if a four byte image (e.g. for png) should be created * @param scale * scale factor for map size; scale = 1 means rendered image will have same size as defined in a map * models {@link TargetDeviceType} * @return rendered legend * @throws Exception */ public static BufferedImage getMapAsImage( final MapModel mm, boolean fourByte, float scale ) throws Exception { final List<Theme> themes = new ArrayList<Theme>(); mm.walkLayerTree( new MapModelVisitor() { public void visit( Layer layer ) throws Exception { double mis = layer.getMinScaleDenominator(); double mxs = layer.getMaxScaleDenominator(); if ( layer.isVisible() && mis <= mm.getScaleDenominator() && mxs >= mm.getScaleDenominator() ) { List<Theme> layerThemes = createThemes( layer.getCurrentStyle(), layer.getDataAccess(), mm.getCoordinateSystem() ); themes.addAll( layerThemes ); } } public void visit( LayerGroup layerGroup ) throws Exception { // not using grouping nodes } } ); List<Theme> tmp = new ArrayList<Theme>(); for ( int i = themes.size() - 1; i >= 0; i-- ) { tmp.add( themes.get( i ) ); } MapView mv = createMapView( "iGeoDesktop", mm.getEnvelope(), mm.getCoordinateSystem(), tmp.toArray( new Theme[tmp.size()] ), DEFAULT_PIXEL_SIZE ); int width = Math.round( mm.getTargetDevice().getPixelWidth() * scale ); int height = Math.round( mm.getTargetDevice().getPixelHeight() * scale ); if ( width < 50 || height < 50 ) { throw new Exception( "value of parameter scale is to small; ensure that " + "result map at least has a size of 50x50 pixel" ); } BufferedImage img = null; if ( fourByte ) { img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); } else { img = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); } Graphics2D g = img.createGraphics(); g.setBackground( new Color( 0 ) ); g.fillRect( 0, 0, width, height ); g.setClip( 0, 0, width, height ); mv.paint( g ); g.dispose(); return img; } }