001 //$$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }