001 //$$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/wms/control/ScaleSwitcherListener.java $$ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.portal.standard.wms.control; 038 039 import java.util.ResourceBundle; 040 041 import javax.servlet.ServletRequest; 042 043 import org.deegree.enterprise.control.FormEvent; 044 import org.deegree.enterprise.control.RPCMethodCall; 045 import org.deegree.enterprise.control.RPCParameter; 046 import org.deegree.enterprise.control.RPCStruct; 047 import org.deegree.enterprise.control.RPCWebEvent; 048 import org.deegree.framework.util.MapUtils; 049 import org.deegree.model.crs.CRSFactory; 050 import org.deegree.model.crs.CoordinateSystem; 051 import org.deegree.model.crs.UnknownCRSException; 052 import org.deegree.model.spatialschema.Envelope; 053 import org.deegree.model.spatialschema.GeometryFactory; 054 import org.deegree.portal.Constants; 055 import org.deegree.portal.PortalException; 056 057 /** 058 * The ScaleSwitcherListner handles switching the values of the scales from igeoportal 059 * 060 * @author <a href="mailto:ncho@lat-lon.de">Serge N'Cho</a> 061 * @author last edited by: $Author: mschneider $ 062 * 063 * @version $Revision: 18195 $, $Date: 2007-12-27 17:59:14 +0100 (Do, 27 Dez 2007)$ 064 */ 065 public class ScaleSwitcherListener extends AbstractMapListener { 066 067 private static double PIXEL_SIZE = 0.00028; 068 069 static { 070 final ResourceBundle bundle = ResourceBundle.getBundle( "org.deegree.portal.standard.wms.control.map_listener" ); //$NON-NLS-1$ 071 String ps = bundle.getString( "ScaleSwitcher.pixelSize" ); 072 if ( ps != null ) { 073 PIXEL_SIZE = Double.valueOf( ps ); 074 } 075 } 076 077 /** 078 * Constant for "taskFromListener" 079 */ 080 public static final String TASK_FROM_LISTENER = "taskFromListener"; 081 082 /** 083 * Constant for "BBOX" 084 */ 085 public static final String BBOX = "BBOX"; 086 087 /** 088 * Constant for "zoomToFullExtent" 089 */ 090 public static final String FULL_EXTENT = "zoomToFullExtent"; 091 092 /** 093 * Constant for "scaleValue" 094 */ 095 public static final String SCALE_VALUE = "scaleValue"; 096 097 /** 098 * Constant for "newScaleValue" 099 */ 100 public static final String NEW_SCALE_VALUE = "newScaleValue"; 101 102 /** 103 * Constant for "newBBox" 104 */ 105 public static final String NEW_BBOX = "newBBox"; 106 107 /** 108 * Constant for "crs" 109 */ 110 private static final String CRS = "crs"; 111 112 /** 113 * Constant for "mapWidth" 114 */ 115 private static final String MAP_WIDTH = "mapWidth"; 116 117 /** 118 * Constant for "mapHeight" 119 */ 120 private static final String MAP_HEIGHT = "mapHeight"; 121 122 /** 123 * Constant for "taskFromJSObject" 124 */ 125 private static final String JS_TAK = "taskFromJSObject"; 126 127 /** 128 * Constant for "requestedScale" 129 */ 130 private static final String REQUESTED_SCALE = "requestedScale"; 131 132 /** 133 * Constant for "getNewBBOX" 134 */ 135 private static final String GET_NEW_BBOX = "getNewBBOX"; 136 137 /** 138 * Constant for "savedScaleValue" 139 */ 140 private static final String SAVED_SCALE = "savedScaleValue"; 141 142 /** 143 * Constant for "getActualScaleValue" 144 */ 145 private static final String GET_CURRENT_SCALE = "getActualScaleValue"; 146 147 /** 148 * @see org.deegree.enterprise.control .WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent) 149 */ 150 @Override 151 public void actionPerformed( FormEvent event ) { 152 153 RPCWebEvent rpc = (RPCWebEvent) event; 154 RPCMethodCall mc = rpc.getRPCMethodCall(); 155 RPCParameter param = mc.getParameters()[0]; 156 RPCStruct struct = (RPCStruct) param.getValue(); 157 double minx = (Double) struct.getMember( Constants.RPC_BBOXMINX ).getValue(); 158 double miny = (Double) struct.getMember( Constants.RPC_BBOXMINY ).getValue(); 159 double maxx = (Double) struct.getMember( Constants.RPC_BBOXMAXX ).getValue(); 160 double maxy = (Double) struct.getMember( Constants.RPC_BBOXMAXY ).getValue(); 161 String crs = struct.getMember( CRS ).getValue().toString(); 162 CoordinateSystem cs; 163 try { 164 cs = CRSFactory.create( crs ); 165 } catch ( UnknownCRSException e1 ) { 166 gotoErrorPage( e1.getMessage() ); 167 return; 168 } 169 Envelope actualBBox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, cs ); 170 double mapWidth = (Double) struct.getMember( MAP_WIDTH ).getValue(); 171 double mapHeight = (Double) struct.getMember( MAP_HEIGHT ).getValue(); 172 String taskFromJSObject = struct.getMember( JS_TAK ).getValue().toString(); 173 ServletRequest request = this.getRequest(); 174 175 try { 176 177 double currentScaleValue = MapUtils.calcScale( (int) mapWidth, (int) mapHeight, actualBBox, 178 actualBBox.getCoordinateSystem(), PIXEL_SIZE ); 179 180 if ( GET_NEW_BBOX.equals( taskFromJSObject ) ) { 181 182 String scaleRequestString = struct.getMember( REQUESTED_SCALE ).getValue().toString(); 183 184 double requestedScale = Double.parseDouble( scaleRequestString.substring( 2, 185 scaleRequestString.length() ) ); 186 187 double savedScaleValue = (Double) struct.getMember( SAVED_SCALE ).getValue(); 188 Envelope newBbox = calcNewBBox( actualBBox, requestedScale, currentScaleValue, savedScaleValue ); 189 190 double[] bbox = { newBbox.getMin().getX(), newBbox.getMin().getY(), newBbox.getMax().getX(), 191 newBbox.getMax().getY() }; 192 193 Integer scaleValue = new Integer( (int) ( requestedScale ) ); 194 request.setAttribute( SCALE_VALUE, scaleValue ); 195 request.setAttribute( BBOX, bbox ); 196 request.setAttribute( TASK_FROM_LISTENER, NEW_BBOX ); 197 198 } else if ( GET_CURRENT_SCALE.equals( taskFromJSObject ) ) { 199 200 Integer scaleValue = new Integer( (int) currentScaleValue ); 201 request.setAttribute( SCALE_VALUE, scaleValue ); 202 request.setAttribute( TASK_FROM_LISTENER, NEW_SCALE_VALUE ); 203 204 } else { 205 String message = "Unknown task from ScaleSwitcher module" + taskFromJSObject; 206 throw new PortalException( message ); 207 } 208 } catch ( PortalException e ) { 209 request.setAttribute( TASK_FROM_LISTENER, FULL_EXTENT ); 210 211 } catch ( Exception e ) { 212 e.printStackTrace(); 213 } 214 215 } 216 217 /** 218 * The methode <code>calcNewBBox</code> calculates a new boundingbox for a requested scale. It will either zoom in 219 * or zoom out of the <code>actualBBOX<code> depending 220 * on the ratio of the <code>requestedScale</code> to the <code>actualScale</code> 221 * 222 * @param currentBBOX 223 * @param requestedScale 224 * @param currentScale 225 * @param savedScaleValue 226 * @return Envelope of the new BBox 227 * @throws Exception 228 */ 229 private Envelope calcNewBBox( Envelope currentBBOX, double requestedScale, double currentScale, 230 double savedScaleValue ) 231 throws Exception { 232 233 Envelope newBBox = null; 234 double ratio = requestedScale / currentScale; 235 // NaN ration will return a null Envelope 236 if ( Double.isNaN( ratio ) ) { 237 // FIXME when does this occurs? and how should this be handle? 238 throw new PortalException( "ratio is not a number" ); 239 } 240 241 if ( Double.isInfinite( ratio ) ) {// infinite ratio will return infinite Envelope 242 // the actualScale calculated was probably 0: use the saveScaleValue 243 if ( savedScaleValue > 1 ) { 244 ratio = requestedScale / savedScaleValue; 245 } 246 if ( Double.isInfinite( ratio ) ) { 247 throw new PortalException( "ratio is infinite" ); 248 } 249 } 250 double newWidth = currentBBOX.getWidth() * ratio; 251 double newHeight = currentBBOX.getHeight() * ratio; 252 double midX = currentBBOX.getMin().getX() + ( currentBBOX.getWidth() / 2d ); 253 double midY = currentBBOX.getMin().getY() + ( currentBBOX.getHeight() / 2d ); 254 double minx = midX - newWidth / 2d; 255 double maxx = midX + newWidth / 2d; 256 double miny = midY - newHeight / 2d; 257 double maxy = midY + newHeight / 2d; 258 newBBox = GeometryFactory.createEnvelope( minx, miny, maxx, maxy, currentBBOX.getCoordinateSystem() ); 259 260 return newBBox; 261 } 262 263 }