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