/*---------------- FILE HEADER --------------------------------------- This file is part of Geoide. Copyright (C) 2005-2006 by: IDgis B.V. http://www.idgis.nl 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: Herman Assink IDgis bv P.O. Box 15 7450 AA Holten The Netherlands E-Mail: herman.assink@idgis.nl * @version 1.4.0 * @author IDgis team * ------------------------------------------------------------------------*/ import nl.idgis.giclient.util.ArrayTools; import nl.idgis.giclient.geoma.Envelope; import nl.idgis.giclient.geoma.Geometry; import nl.idgis.giclient.geoma.GeometryTools; import nl.idgis.giclient.geoma.NullGeometry; import nl.idgis.giclient.geoma.MultiPoint; import nl.idgis.giclient.GIContext; import nl.idgis.giclient.GIClient; import nl.idgis.giclient.gis.CentreScale; import nl.idgis.giclient.gis.Coordinate; import nl.idgis.giclient.gis.Feature; import nl.idgis.giclient.gis.GISEventDispatcher; import nl.idgis.giclient.gis.Layer; import nl.idgis.giclient.gis.GILayer; import nl.idgis.giclient.gis.Map; import nl.idgis.giclient.gis.UnboundFeatureLayer; import nl.idgis.giclient.util.SynchListener; import nl.idgis.giclient.io.XMLServer; import nl.idgis.giclient.timeanimation.AnimationEventDispatcher; import nl.idgis.giclient.gis.AnimationLayer; import nl.idgis.giclient.gui.mapviewer.MapLayer; import nl.idgis.giclient.modes.Mode; import nl.idgis.giclient.gis.TimeRangeScale; import nl.idgis.giclient.gis.TimeRange; import nl.idgis.giclient.gis.SelectableLayer; import nl.idgis.giclient.gis.TransformCentreScales; import nl.idgis.giclient.webserviceconnector.TransformConnector; import nl.idgis.giclient.util.SRSInfo; import nl.idgis.giclient.gis.ZoomResponseHandler; import nl.idgis.giclient.gis.TransformFeature; import nl.idgis.giclient.event.StateEventListener; import nl.idgis.giclient.event.StateEvent; import nl.idgis.giclient.geoma.Point; import nl.idgis.giclient.webserviceconnector.TransformConnectorListener; class nl.idgis.giclient.gis.GIS implements SynchListener, StateEventListener { private var giClient:GIClient = null; private var giContext:GIContext = null; private var srsInfo:SRSInfo = null; private var transformConnector:TransformConnector = null; private var coordPixFactor:Number = 0.00028; //see "CentreScale.toEnvelope", "Envelope.toCentreScale" private var scaleStep:Number = 2; private var minAutoZoomScale:Number = 1000; private var maps:Array = null; private var activeMap:Map = null; private var activeLayer:SelectableLayer = null; private var unboundFeatureLayer:UnboundFeatureLayer = null; private var editing:Boolean = false; private var centreScales:Array = new Array(); private var currentCentreScaleIndex:Number = 0; private var currentCentreScaleWGS84:CentreScale = null; private var currentTimeStamp:Date = null; private var playing:Boolean = false; private var featuresToZoomTo:Array = null; private var numLoadingLayers:Number = 0; private var landMarks:Array = new Array(); private var popUpInfoFeature:Feature = null; private var intervalID:Number = -1; private var intervalMoreRecentThanResize:Boolean = false; private var waitingForLayerSelectedFeatures:Boolean = false; var gisEventDispatcher:GISEventDispatcher = null; var animationEventDispatcher:AnimationEventDispatcher = null; var new_context:GIContext = null; private var selectionGeometry : Geometry; private var buffer : Number; private var bufferedSelectionGeometry : Geometry; private var measureFeature : Feature; function GIS(giClient:GIClient, giContext:GIContext, srsInfo:SRSInfo, mapName:String) { this.giClient = giClient; this.giContext = giContext; this.srsInfo = srsInfo; transformConnector = giContext.getTransformConnector(); gisEventDispatcher = new GISEventDispatcher(); animationEventDispatcher = new AnimationEventDispatcher(); maps = giContext.getMaps(); var mapNr = 0; for(var i:Number = 0; i < maps.length; i++) { if(maps[i].getName() == mapName) { mapNr = i; break; } } setActiveMap(maps[mapNr]); unboundFeatureLayer = new UnboundFeatureLayer(); //currentTimeStamp = getTimeRangeBegin(); setCurrentTimeStamp(0); recalcCurrentTimeRange(); Stage.addListener(this); } function onResize():Void { if (intervalID == -1) { intervalID = setInterval(this, "onInterval", 1000); } intervalMoreRecentThanResize = false; } function onInterval():Void { if (intervalMoreRecentThanResize) { clearInterval(intervalID); intervalID = -1; intervalMoreRecentThanResize = false; gisEventDispatcher.zoom(); } else { intervalMoreRecentThanResize = true; } } function getTransformConnector():TransformConnector{ return transformConnector; } /*public function getGICapabilities():GICapabilities { return giCapabilities; }*/ /** * @return the coordPixFactor, which is a constant for the resolution of the 'virtual' monitor. * It assumes there are 72 pixels in an inch (2,54 cm) --> 72 pixels/2,54 cm = 28 pixels/cm */ function getCoordPixFactor():Number { return getCoordPixFactorForSrs(getActiveMap().getSRS()); } function getCoordPixFactorForSrs(srs:String):Number { if(srsInfo.isProjection(srs)) return coordPixFactor; else return coordPixFactor / 111248.23835493479; } function getMap(mapName:String):Map { for (var i:Number = 0; i < maps.length; i++) { if (maps[i].getName() == mapName) { return maps[i]; //returns only first hit } } } function getMaps():Array { return maps; } /** * Sets the active map and fills the convenience array with layer of the new active map. Broadcasts and * event if the setting is actually a changing. */ function setActiveMap(activeMap:Map):Void { if (this.activeMap != activeMap) { gisEventDispatcher.beforeChangeActiveMap(); if (this.activeMap == null) { this.activeMap = activeMap; zoomToActiveMapInitEnvelope(); } else { var envelope:Envelope = activeMap.getInitEnvelope(); // activeMap is "new" one. if ((getCurrentCentreX() < envelope.getMinX()) || (getCurrentCentreX() > envelope.getMaxX()) || (getCurrentCentreY() < envelope.getMinY()) || (getCurrentCentreY() > envelope.getMaxY())) { this.activeMap = activeMap; zoomToActiveMapInitEnvelope(); } else { this.activeMap = activeMap; setCurrentCentreScale(getCurrentCentreX(), getCurrentCentreY(), getCurrentScale()); } } gisEventDispatcher.afterChangeActiveMap(); } } function getActiveMap():Map { return activeMap; } /** * Sets the active layer. The active layer may be null. The active layer may or may not be in the active map. */ function setActiveLayer(activeLayer:Layer):Void { if (this.activeLayer == activeLayer) { return; } if ((activeLayer != null) && (!(activeLayer instanceof SelectableLayer))) { // EXCEPTION return; } var currentMode:Mode = giClient.ruler.getActiveMode(); if (currentMode.isEditMode()) { if (((!activeMap.getUnboundFeatureLayer()) && ((activeLayer == null) || (!activeLayer.isEditable()))) || ((GILayer(activeLayer).getGeometryType() != null) && (currentMode.getGeometryType() != null) && (GILayer(activeLayer).getGeometryType() != currentMode.getGeometryType()))) { //trace("GIS.setActiveLayer(): cannot set the active layer, because the given layer is null or is not editable."); //throw new Error("GIS.setActiveLayer(): cannot set the active layer, because the given layer is null or is not editable."); return; } //trace("setActiveLayer, authorized = " + SelectableLayer(activeLayer).authorized()); //if (!SelectableLayer(activeLayer).authorized()) { // return; //} } if (editing) { var editLayer:SelectableLayer = getEditLayer(); if (editLayer != null) { editLayer.setEditing(false); } } this.activeLayer = SelectableLayer(activeLayer); if (editing) { var editLayer:SelectableLayer = getEditLayer(); if (editLayer != null) { editLayer.setEditing(true); } } gisEventDispatcher.changeActiveLayer(); } /** * Retrieves the active layer. The active layer may be null. The active layer may or may not be in the active map. */ function getActiveLayer():Layer { return activeLayer; } function getUnboundFeatureLayer():UnboundFeatureLayer { return unboundFeatureLayer; } /** * Retrieves the layer with the given name. The layer must be in the current map. */ function getLayer(layerName:String):Layer { if(layerName == "internal:UnboundFeatureLayer") { return this.getUnboundFeatureLayer(); } var index:Number = layerName.indexOf(":"); var prefix:String = null; if(index != -1) { prefix = layerName.substr(0, index); layerName = layerName.substr(index + 1); } var layers:Array = getLayers(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i].getName() == layerName) { if(prefix == null || (layers[i].getMapConnector().getTitle() == prefix)) { return layers[i]; } } } return null; } /** * Retrieves a flat representation of all layers and sublayers in the active map. */ function getLayers():Array { if (activeMap != null) { return activeMap.getAllLayers(); } else { return null; } } /** * Retrieves a flat representation of all layers and sublayers in the active map that are * selectable. From these layers can be chosen when a feature search is commented. */ function getSelectableLayers():Array { var layers:Array = getLayers(); var selectableLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i].isSelectable()) { selectableLayers.push(layers[i]); } } return selectableLayers; } /** * Retrieves a flat representation of all layers and sublayers in the active map that are * editable. From these layers can be chosen when a feature search is commented. */ function getEditableLayers():Array { var layers:Array = getLayers(); var editableLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i].isEditable()) { editableLayers.push(layers[i]); } } return editableLayers; } /** * Retrieves a flat representation of all layers and sublayers in the active map that have * attribute info columns. For these layers attribute info can be shown in the attribute viewer. */ function getAttrInfoLayers():Array { var layers:Array = getLayers(); var attrInfoLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if(layers[i].getAttrInfoColumns()!=null){ attrInfoLayers.push(layers[i]); } } return attrInfoLayers; } /** * Retrieves a flat representation of all layers and sublayers in the active map whose scalehint is * within the current scale, and also the layers and sublayers that have selected features. */ function getZoomVisibleOrSelectedLayers():Array { var layers:Array = getLayers(); var zoomVisibleOrSelectedLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { var layer:Layer = Layer(layers[i]); if(isZoomVisibleLayer(layer)) { zoomVisibleOrSelectedLayers.push(layer); continue; } if(layer instanceof SelectableLayer) { if(SelectableLayer(layer).getSelectedFeatures().length > 0) { zoomVisibleOrSelectedLayers.push(layer); } } } return zoomVisibleOrSelectedLayers; } /** * Retrieves a flat representation of all layers and sublayers in the active map whose scalehint is * within the current scale. */ function getZoomVisibleLayers():Array { var layers:Array = getLayers(); var zoomVisibleLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if(isZoomVisibleLayer(layers[i])) { zoomVisibleLayers.push(layers[i]); } } return zoomVisibleLayers; } /** * Retrieves a flat representation of all layers and sublayers in the active map whose scalehint is * within the GIVEN scale. */ function getZoomVisibleLayersForScale(scale:Number):Array { var layers:Array = getLayers(); var zoomVisibleLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if(isZoomVisibleLayerForScale(Layer(layers[i]), scale)) { zoomVisibleLayers.push(layers[i]); } } return zoomVisibleLayers; } /** * Retrieves a flat representation of all layers and sublayers that follow these criteria: * 1. They must be in the active map. * 2. Their scalehint is within the current scale OR they currently have a selection. * 3. Their superlayers are expanded. * 4. Their noLegendLayer property is set to false. * These are the layers that are usually shown in a legend viewer. */ function getZoomVisibleExpandedLayers():Array { var zoomVisibleLayers:Array = getZoomVisibleOrSelectedLayers(); var zoomVisibleExpandedLayers:Array = new Array(); for (var i:Number = 0; i < zoomVisibleLayers.length; i++) { if (((zoomVisibleLayers[i].getSuperLayer() == null) || (zoomVisibleLayers[i].getSuperLayer().isExpanded())) && (!zoomVisibleLayers[i].getNoLegendLayer())) { zoomVisibleExpandedLayers.push(zoomVisibleLayers[i]); } } return zoomVisibleExpandedLayers; } /** * Retrieves a flat representation of all layers and sublayers that follow these criteria: * 1. They must be in the active map. * 2. Their superlayers are expanded. * 3. Their noLegendLayer property is set to false. * These are the layers that are usually shown in a legend viewer. */ function getExpandedLayers():Array { var layers:Array = getLayers(); var expandedLayers:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if (((layers[i].getSuperLayer() == null) || (layers[i].getSuperLayer().isExpanded())) && (!layers[i].getNoLegendLayer())) { expandedLayers.push(layers[i]); } } return expandedLayers; } /** * Retrieves a flat representation of layers that follow these criteria: * 1. They must be in the active map. * 2. Their schalehint is within the current scale. * 3. Their visible property is set to true. * 4. The visible property of their superlayers is set to true. * 5. They may not have sublayers. Layers that have sublayers have no map representation of their own. * These are the layers that are usually shown in a map viewer. */ function getVisibleLayers():Array { var zoomVisibleLayers:Array = getZoomVisibleLayers(); var visibleLayers:Array = new Array(); for (var i:Number = 0; i < zoomVisibleLayers.length; i++) { if ((zoomVisibleLayers[i].isVisible()) && (zoomVisibleLayers[i].areSuperLayersVisible()) && (zoomVisibleLayers[i].getLayers().length == 0)) { visibleLayers.push(zoomVisibleLayers[i]); } } return visibleLayers; } /** * get all AnimationLayers */ function getAnimationLayers():Array { var animationLayers:Array = new Array(); var layers:Array = getLayers(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i] instanceof AnimationLayer) { animationLayers.push(layers[i]); } } return animationLayers; } function isZoomVisibleLayer(layer:Layer):Boolean { return isZoomVisibleLayerForScale(layer, getCurrentScale()); } function isZoomVisibleLayerForScale(layer:Layer, scale:Number):Boolean { var currentLayer:Layer = layer; while(currentLayer != null) { if(scale <= currentLayer.getMinScale() || scale > currentLayer.getMaxScale()) { return false; } currentLayer = currentLayer.getSuperLayer(); } return true; } function isVisibleLayer(layer:Layer):Boolean { return isVisibleLayerForScale(layer, getCurrentScale()); } function isVisibleLayerForScale(layer:Layer, scale:Number):Boolean { var currentLayer:Layer = layer; while(currentLayer != null) { if(!currentLayer.isVisible() || scale <= currentLayer.getMinScale() || scale > currentLayer.getMaxScale()) { return false; } currentLayer = currentLayer.getSuperLayer(); } return true; } /** * Retrieves a flat representation of layers that follow these criteria: * 1. They must be in the active map. * 2. Their schalehint is within the GIVEN scale. * 3. Their visible property is set to true. * 4. The visible property of their superlayers is set to true. * 5. They may not have sublayers. Layers that have sublayers have no map representation of their own. */ function getVisibleLayersForScale(scale:Number):Array { var zoomVisibleLayers:Array = getZoomVisibleLayersForScale(scale); var visibleLayers:Array = new Array(); for (var i:Number = 0; i < zoomVisibleLayers.length; i++) { if ((zoomVisibleLayers[i].isVisible()) && (zoomVisibleLayers[i].areSuperLayersVisible()) && (zoomVisibleLayers[i].getLayers().length == 0)) { visibleLayers.push(zoomVisibleLayers[i]); } } return visibleLayers; } function selectByGeometry(geometry:Geometry, selectionLayer:SelectableLayer):Void{ var layer:SelectableLayer = activeLayer; if (layer != null) { // First applies to active layer. layer.setSelectedFeaturesByGeometry(geometry); } else { // Then applies to selectable and visible layers. Must also be zoomvisible. var layers:Array = getVisibleLayers(); for (var i:String in layers) { if (layers[i] instanceof SelectableLayer) { if(selectionLayer!=null&&selectionLayer==layers[i]){ //do nothing } else { SelectableLayer(layers[i]).setSelectedFeaturesByGeometry(geometry); } } } } } /** * Moves the given layer backward in its array of layers within the active map or one of its layers. * Broadcasts an event so that the map viewer and the legend viewer can reorder their representations of * the layers as well. If the "end" parameter is set to true, the layer will be moved all the way to the * back. Moving layers always happens within the context of their superlayers. */ function moveLayerBackward(layer:Layer, end:Boolean):Void { if (activeMap != null) { activeMap.moveLayerBackward(layer, end); // if returnvalue == 0 gisEventDispatcher.shuffle(); } } /** * Moves the given layer frontward in its array of layers within the active map or one of its layers. * Broadcasts an event so that the map viewer and the legend viewer can reorder their representations of * the layers as well. If the "end" parameter is set to true, the layer will be moved all the way to the * front. Moving layers always happens within the context of their superlayers. */ function moveLayerFrontward(layer:Layer, end:Boolean):Void { if (activeMap != null) { activeMap.moveLayerFrontward(layer, end); // if returnvalue == 0 gisEventDispatcher.shuffle(); } } /** * Swaps two layers as to change their order in their array of layers within the active map or one of its * layers. The two layers must be in the same superlayer context. Broadcasts an event so that the map * viewer and the legend viewer can reorder their representations of the layers as well. */ function moveLayerTo(fromLayer:Layer, toLayer:Layer):Void { //only exchanges now if (activeMap != null) { activeMap.moveLayerTo(fromLayer, toLayer); // if returnvalue == 0 gisEventDispatcher.shuffle(); } } function selectFeaturesAndZoom(layer:Layer, ids:Array) { waitingForLayerSelectedFeatures = true; SelectableLayer(layer).setSelectedFeatures(ids, false, this); // To onSynch; } function getActiveFeature():Feature { if (activeLayer != null) { return activeLayer.getCurrentFeature(); } else { return null; } } function setEditing(editing:Boolean, save:Boolean):Void { if (this.editing == editing) { return; } if (!editing) { var editLayer:SelectableLayer = getEditLayer(); editLayer.addEventListener(this, "SelectableLayer", StateEvent.CHANGE, "editingStatus"); if (editLayer != null) { editLayer.setEditing(false, save); } } else { this.editing = editing; var editLayer:SelectableLayer = getEditLayer(); giClient.ruler.rulerEventDispatcher.changeEditing(); if (editLayer != null) { editLayer.setVisible(true); editLayer.setEditing(true); } } } function isEditing():Boolean { return editing; } function getEditLayer():SelectableLayer { if (editing) { if ((activeLayer != null) && (activeLayer.isEditable())) { //trace("activeLayer"); return activeLayer; } else { //trace("unboundfeaturelayer: " + unboundFeatureLayer); return unboundFeatureLayer; } } else { //trace("Not in editing mode"); return null; } } /** * Changes the current centre and scale of the map after which the zoom event is fired as to make * sure the MapViewer and LegendViewer will refresh. * @param centreScale, the new centreScale of the map. */ function setCurrentCentreScale(centreX:Number, centreY:Number, scale:Number):Void { //if ((activeMap.getMinScale() > -1) && (scale < activeMap.getMinScale())) { // scale = activeMap.getMinScale(); //} if ((activeMap.getMaxScale() > -1) && (scale > activeMap.getMaxScale())) { scale = activeMap.getMaxScale(); } if (activeMap.getMinScale() > -1 && scale < activeMap.getMinScale()) { scale = activeMap.getMinScale(); } var previousScale:Number = getCurrentScale(); var centreScale:CentreScale = new CentreScale(activeMap.getSRS(), centreX, centreY, scale); if (centreScales.length == 0) { currentCentreScaleIndex = 0; } else { centreScales.splice(currentCentreScaleIndex + 1); currentCentreScaleIndex++; } centreScales.push(centreScale); gisEventDispatcher.zoom(); if (scale != previousScale) { setLayersCurrentScale(scale); } currentCentreScaleWGS84 = null; } /** * changes the scale of the mapViewer * @param scale, the new scale of the mapViewer */ function setCurrentScale(scale:Number):Void { setCurrentCentreScale(getCurrentCentreX(), getCurrentCentreY(), scale); } /** * changes the x coordinate of centre of the mapViewer * @param x, the new x coordinate of the mapViewer */ function setCurrentCentreX(x:Number):Void { setCurrentCentreScale(x, getCurrentCentreY(), getCurrentScale()); } /** * changes the y coordinate of centre of the mapViewer * @param y, the new y coordinate of the mapViewer */ function setCurrentCentreY(y:Number) { setCurrentCentreScale(getCurrentCentreX(), y, getCurrentScale()); } function getCurrentSrs():String { return activeMap.getSRS(); } function getCurrentCentreScaleWGS84():CentreScale { return currentCentreScaleWGS84; } function calculateCurrentCentreScaleWGS84(callback:Function) { var centreScale:CentreScale = getCurrentCentreScale(); if(centreScale.getSRS() == "EPSG:4326") { currentCentreScaleWGS84 = centreScale; callback(); } else { var obj:TransformConnectorListener = new TransformConnectorListener(); obj["gis"] = this; obj["centreScale"] = centreScale; obj["callback"] = callback; obj["transformed"] = function(geom : Geometry) : Void { this.gis["currentCentreScaleWGS84"] = new CentreScale(geom.getSRS(), Point(geom).getX(), Point(geom).getY(), this.centreScale.getScale()); this["callback"](); }; getTransformConnector().transform(new Point(centreScale.getSRS(), centreScale.getCentreX(), centreScale.getCentreY()), centreScale.getSRS(), "EPSG:4326", obj); } } /** * @return the CentreScale instance which represents the centre and scale in the mapViewer. */ function getCurrentCentreScale():CentreScale { return centreScales[currentCentreScaleIndex]; } /** * @return the scale in the mapViewer. */ function getCurrentScale():Number { return centreScales[currentCentreScaleIndex].getScale(); } /** * @return the x coordinate of the centre in the mapViewer. */ function getCurrentCentreX():Number { return centreScales[currentCentreScaleIndex].getCentreX(); } /** * @return the y coordinate of the centre in the mapViewer. */ function getCurrentCentreY():Number { return centreScales[currentCentreScaleIndex].getCentreY(); } private function transformCentreScales(fromSrs:String, toSrs:String):Void { var tcs:TransformCentreScales = new TransformCentreScales(fromSrs, toSrs, this, transformConnector, this.centreScales, getActiveMap()); tcs.transform(); } private function transformFeatures(fromSrs:String, toSrs:String):Void { var layers:Array = this.getSelectableLayers(); for(var i:Number = 0; i < layers.length; i++) { var layer:SelectableLayer = SelectableLayer(layers[i]); var features:Array = layer.getSelectedFeatures(); for(var j:Number = 0; j < features.length; j++) { var transformFeature:TransformFeature = new TransformFeature(features[j], toSrs, transformConnector); transformFeature.transform(); } } gisEventDispatcher.changeSRS(); } public function setSRS(srs:String) { //clear selection geoemetries setSelectionGeometry(null); setBufferedSelectionGeometry(null); setBuffer(0); //clear selection in all layers clearSelectedFeatures(null); var currentSrs:String = getActiveMap().getSRS(); getActiveMap().setSRS(srs); transformCentreScales(currentSrs, srs); } /** * catches the pan event: the centre and scale of the mapViewer are changed after which * the mapViewer will zoom. * @param x, the x coordinate of the new centre of the mapViewer * @param y, the y coordinate of the new centre of the mapViewer */ function pan(x:Number, y:Number):Void { setCurrentCentreScale(x, y, getCurrentScale()); } /** * A history of centreScales is remembered and this allows to go back and forward to * the previous and next zoom. This method sets the zoom to the next zoom. */ function zoomToNextCentreScale():Void { if (currentCentreScaleIndex + 1 == centreScales.length) { // There is no next view to zoom to. return; } var previousScale:Number = getCurrentScale(); currentCentreScaleIndex++; var currentScale:Number = getCurrentScale(); gisEventDispatcher.zoom(); if (currentScale != previousScale) { setLayersCurrentScale(currentScale); } currentCentreScaleWGS84 = null; } /** * A history of centreScales is remembered and this allows to go back and forward to * the previous and next zoom. This method sets the zoom to the previous zoom. */ function zoomToPreviousCentreScale():Void { if (currentCentreScaleIndex == 0) { // There is no previous view to zoom to. return; } var previousScale:Number = getCurrentScale(); currentCentreScaleIndex--; var currentScale:Number = getCurrentScale(); gisEventDispatcher.zoom(); if (currentScale != previousScale) { setLayersCurrentScale(currentScale); } currentCentreScaleWGS84 = null; } /** * Divides the scale by a factor scaleStep after which the zoom event is fired as to make * sure the MapViewer and LegendViewer will refresh. * @param x, the x coordinate of the new centre of the map * @param y, the y coordinate of the new centre of the map */ function zoomIn(x:Number, y:Number):Void { if ((x == null) || (y == null)) { x = getCurrentCentreX(); y = getCurrentCentreY(); } var powerScale:Number = activeMap.getPowerScale(); if ((powerScale > -1) && (getCurrentScale() / scaleStep > powerScale)) { setCurrentCentreScale(x, y, powerScale); } else { setCurrentCentreScale(x, y, getCurrentScale() / scaleStep); } } /** * Multiplies the scale by a factor scaleStep after which the zoom event is fired as to make * sure the MapViewer and LegendViewer will refresh. * @param x, the x coordinate of the new centre of the map * @param y, the y coordinate of the new centre of the map */ function zoomOut(x:Number, y:Number):Void { if ((x == null) || (y == null)) { x = getCurrentCentreX(); y = getCurrentCentreY(); } setCurrentCentreScale(x, y, getCurrentScale() * scaleStep); } function zoomToActiveMapInitEnvelope():Void { if (activeMap != null) { var envelope:Envelope = activeMap.getInitEnvelope(); if (envelope != null) { zoomToEnvelope(envelope); } } } function zoomToLayers(layers:Array):Void { var envelopes:Array = new Array(); for (var i:String in layers) { envelopes.push(GILayer(layers[i]).getEnvelope()); } var envelope:Envelope = GeometryTools.getEnvelope(envelopes); zoomToEnvelope(envelope); } function zoomToEnvelope(envelope:Envelope):Void { if (envelope != null) { var centreScale:CentreScale = envelope.toCentreScale(Stage.width, Stage.height - 100, getCoordPixFactor()); setCurrentCentreScale(centreScale.getCentreX(), centreScale.getCentreY(), centreScale.getScale()); } else { zoomToActiveMapInitEnvelope(); } } public function zoomToXY(xInput : Number, yInput : Number) : Void { this.setCurrentCentreX(xInput); this.setCurrentCentreY(yInput); var zoomScale:Number = this.getActiveMap().getZoomToScale(); zoomScale = this.adaptScaleToBounds(zoomScale); this.setCurrentScale(zoomScale); } function zoomToFilteredFeatures(layers:Array):Void { if (layers != null) { var filteredFeatures:Array = new Array(); for (var i:String in layers) { filteredFeatures = ArrayTools.concat(filteredFeatures, layers[i].getFilteredFeatures()); } zoomToFeatures(filteredFeatures); } } function zoomToSelectedFeatures(layer:Layer):Void { if (layer != null) { //apply to active layer var selectedFeatures:Array = SelectableLayer(layer).getSelectedFeatures(); zoomToFeatures(selectedFeatures); } else { //apply to all selectable and visible layers var layers:Array = getLayers(); var selectedFeatures:Array = new Array(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i].isSelectable() && layers[i].isVisible()) { selectedFeatures = ArrayTools.concat(selectedFeatures, layers[i].getSelectedFeatures()); } } zoomToFeatures(selectedFeatures); } } function clearSelectedFeatures(layer:Layer):Void { if (layer != null) { SelectableLayer(layer).setSelectedFeatures(new Array(), false, null); } else { //apply to all selectable and visible layers var layers:Array = getLayers(); for (var i:Number = 0; i < layers.length; i++) { if (layers[i].isSelectable() && layers[i].isVisible()) { layers[i].setSelectedFeatures(new Array(), false, null); } } } } function clearFilteredFeatures(layer:Layer):Void { if (layer != null) { SelectableLayer(layer).setFilteredFeatures(new Array(), false, null); } else { var layers:Array = getLayers(); for (var i:Number = 0; i < layers.length; i++) { //if (layers[i].isSelectable() && layers[i].isVisible()) { layers[i].setFilteredFeatures(new Array(), false, null); //} } } } function zoomToCurrentFeature(layer:Layer):Void { if (layer != null) { var currentFeature:Feature = SelectableLayer(layer).getCurrentFeature(); if (currentFeature != null) { zoomToFeatures(new Array(currentFeature)); } } } function zoomToFeatures(features:Array):Void { if ((features == null) || (features.length == 0)) { return; } var feature:Feature = null; var featuresWithoutEnvelope:Array = new Array(); for (var i:String in features) { feature = features[i]; if (feature.getEnvelope() == null){ featuresWithoutEnvelope.push(feature); } } if (featuresWithoutEnvelope.length == 0) { featuresToZoomTo = null; doZoomToFeatures(features); } else { featuresToZoomTo = features; // Creates a data structure of layers and features in order to support data retrieval from multiple layers. A GetFeature request to the server cannot handle more than 1 layer at once. var layersAndFeatures:Object = new Object(); // Used as an associative array. var layer:Layer = null; var layerName:String = null; for (var i:String in featuresWithoutEnvelope) { feature = featuresWithoutEnvelope[i]; layer = feature.getLayer(); layerName = layer.getName(); if (layersAndFeatures[layerName] == null) { layersAndFeatures[layerName] = new Object(); layersAndFeatures[layerName]["layer"] = layer; layersAndFeatures[layerName]["features"] = new Array(); numLoadingLayers++; // Increments for every new layer. An onSynch call will be made for every layer, too. //trace("loadEnvelopes for layer: " + layer.getName()); } layersAndFeatures[layerName]["features"].push(feature); } for (var i:String in layersAndFeatures) { layer = Layer(layersAndFeatures[i]["layer"]); features = layersAndFeatures[i]["features"]; layer.loadFeatureEnvelopes(features, this); // To onSynch. } } } private function doZoomToFeatures(features:Array):Void { // Number of features is at least 1, and they all have envelopes in place. var envelope:Envelope = null; var envelopes:Array = new Array(); for (var i:String in features) { envelope = Feature(features[i]).getEnvelope(); if (!(envelope instanceof NullGeometry) && envelope != null) envelopes.push(envelope); } var zoomEnvelope:Envelope = GeometryTools.getEnvelope(envelopes); //trace("envelope: " + zoomEnvelope.getSRS()); if (zoomEnvelope != null) { if(zoomEnvelope.getSRS() != activeMap.getSRS()) { transformConnector.transform(new MultiPoint( zoomEnvelope.getSRS(), zoomEnvelope.getCoords()), zoomEnvelope.getSRS(), activeMap.getSRS(), new ZoomResponseHandler(this)); } else { var zoomCentreScale:CentreScale = zoomEnvelope.toCentreScale(Stage.width, Stage.height - 100, getCoordPixFactor()); var zoomScale:Number = zoomCentreScale.getScale() * 1.3; zoomScale = adaptScaleToBounds(zoomScale); setCurrentCentreScale(zoomCentreScale.getCentreX(), zoomCentreScale.getCentreY(), zoomScale); } } } function adaptScaleToBounds(scale:Number):Number { var zoomToScale:Number = activeMap.getZoomToScale(); var minScale:Number = activeMap.getMinScale(); var maxScale:Number = activeMap.getMaxScale(); //trace("scale = " + scale + " zoomToScale = " + zoomToScale + " minScale = " + minScale + " maxScale = " + maxScale ); if (scale == 0) { //it's a point scale = zoomToScale; } if (scale < minScale) { scale = minScale; } if (scale > maxScale && maxScale > 0) { scale = maxScale; } return scale; } function onSynch(target:Object, action:String):Void { if (action.indexOf("SELECT") > -1) { if (waitingForLayerSelectedFeatures) { // REDUNDANT? var layer:SelectableLayer = SelectableLayer(target); waitingForLayerSelectedFeatures = false; if (layer.getSelectedFeatures().length > 0) { layer.setVisible(true); zoomToSelectedFeatures(layer); } } } else { // "ENVELOPES" if ((--numLoadingLayers == 0) && (featuresToZoomTo != null)) { zoomToFeatures(featuresToZoomTo); // zoomToFeatures, NOT doZoomToFeatures, because we can't be sure at this point that the featuresToZoomTo all have envelopes in place. } } } private function setLayersCurrentScale(currentScale):Void { var layers:Array = getLayers(); for (var i:String in layers) { Layer(layers[i]).setCurrentScale(currentScale); } } function getLandMarks():Array { return landMarks; } function addLandMark(x:Number, y:Number):Coordinate { var landMark:Coordinate = new Coordinate(x, y); landMarks.push(landMark); gisEventDispatcher.changeLandMarks(); return landMark; } function removeLandMark(landMark:Coordinate):Void { if (landMark == null) { return; } for (var i:Number = 0; i < landMarks.length; i++) { if (landMarks[i] == landMark) { landMarks.splice(i, 1); gisEventDispatcher.changeLandMarks(); return; } } } function setPopUpInfoFeature(layer:Layer, featureId:String, dateTime:Date):Void { if(layer==null||featureId==null||!(layer instanceof GILayer)){ popUpInfoFeature = null; } else { var giLayer:GILayer = GILayer(layer); popUpInfoFeature = new Feature(featureId, giLayer, null, false, true); } gisEventDispatcher.changePopUpInfoFeature(popUpInfoFeature, dateTime); } function getPopUpInfoFeature():Feature { return popUpInfoFeature; } function movieControl(command:Number):Void { if (command == MapLayer.PLAY) { if(getPlayedPercentage() == 1) { animationEventDispatcher.doTimelineCommand(MapLayer.STOP); } playing = true; } if ((command == MapLayer.STOP) || (command == MapLayer.PAUSE)) { playing = false; } animationEventDispatcher.doTimelineCommand(command); } function setCurrentTimeStamp(percentage:Number):Void { var beginUTC:Number = getCurrentTimeRangeBegin().getTime(); var endUTC:Number = getCurrentTimeRangeEnd().getTime(); if(beginUTC == null|| endUTC== null){ currentTimeStamp = null; } else { currentTimeStamp = new Date(beginUTC + (endUTC - beginUTC) * percentage); } animationEventDispatcher.progressUpdate(percentage); } function getCurrentTimeStamp():Date { return currentTimeStamp; } function getPlayedPercentage():Number { var beginUTC:Number = getCurrentTimeRangeBegin().getTime(); var endUTC:Number = getCurrentTimeRangeEnd().getTime(); var currentUTC:Number = currentTimeStamp.getTime(); return (currentUTC - beginUTC) / (endUTC - beginUTC); } function setPlaying(playing:Boolean):Void { if (this.playing == playing) { return; } this.playing = playing; if (playing) { animationEventDispatcher.doTimelineCommand(MapLayer.PLAY); } else { animationEventDispatcher.doTimelineCommand(MapLayer.PAUSE); } } function isPlaying():Boolean { return playing; } function setInitialTimeRangeScale(timeRangeScale:TimeRangeScale):Void{ var oldTimeRangeScale:TimeRangeScale = this.activeMap.getInitialTimeRangeScale(); if(oldTimeRangeScale!=timeRangeScale){ this.activeMap.setInitialTimeRangeScale(timeRangeScale); this.setCurrentTimeRangeScale(timeRangeScale); } } function setCurrentTimeRangeScale(timeRangeScale:TimeRangeScale):Void{ var oldTimeRangeScale:TimeRangeScale = this.activeMap.getCurrentTimeRangeScale(); if(oldTimeRangeScale!=timeRangeScale){ this.activeMap.setCurrentTimeRangeScale(timeRangeScale); this.gisEventDispatcher.timeZoom(); if (currentTimeStamp < timeRangeScale.getBegin()) { setCurrentTimeStamp(0); } else if (currentTimeStamp > timeRangeScale.getEnd()) { setCurrentTimeStamp(1); } } } function recalcCurrentTimeRange():Void{ var oldBegin:Date = this.activeMap.getCurrentTimeRangeBegin(); var oldEnd:Date = this.activeMap.getCurrentTimeRangeEnd(); this.activeMap.recalcCurrentTimeRange(); var newBegin:Date = this.activeMap.getCurrentTimeRangeBegin(); var newEnd:Date = this.activeMap.getCurrentTimeRangeEnd(); if (oldBegin != newBegin || oldEnd != newEnd) { this.gisEventDispatcher.timeZoom(); } } //function setInitialTimeRange(start:Date, end:Date):Void { //var oldStart:Date = this.activeMap.getInitialTimeRangeStart(); //var oldEnd:Date = this.activeMap.getInitialTimeRangeEnd(); //if (oldStart != start || oldEnd != end ) { //this.activeMap.setInitialTimeRange(start, end); //this.gisEventDispatcher.timeZoom(); //} //} //function setInitialTimeScale(scale:Number):Void { //var oldScale:Number = this.activeMap.getInitialTimeScale(); //if (oldScale != scale ) { //this.activeMap.setInitialTimeScale(scale); //this.gisEventDispatcher.timeZoom(); //} //} //function setInitialFPS(fps:Number) { //var oldFps:Number = this.activeMap.getInitialFPS(); //if (oldFps != fps) { //this.activeMap.setInitialFPS(fps); //this.gisEventDispatcher.timeZoom(); //} //} function getCurrentTimeRangeScale():TimeRangeScale { return this.activeMap.getCurrentTimeRangeScale(); } function getCurrentTimeRangeBegin():Date { return this.activeMap.getCurrentTimeRangeBegin(); } function getCurrentTimeRangeEnd():Date { return this.activeMap.getCurrentTimeRangeEnd(); } function getCurrentTimeScale():Number{ return this.activeMap.getCurrentTimeScale(); } function getCurrentFPS():Number{ return this.activeMap.getCurrentFPS(); } function getInitialTimeRangeScale():TimeRangeScale{ return this.activeMap.getInitialTimeRangeScale(); } function getInitialFPS():Number{ return this.activeMap.getInitialFPS(); } function getTimeLimit():TimeRange{ return this.activeMap.getTimeLimit(); } function getMaxAnimationFrames(){ var animLayers:Array = getAnimationLayers(); //TODO:maxFrames should be a property of map but it is still a property of animation layer //to get the maxFrames loop through the animation layers and select the smallest //of the maxFrame values var maxFrames:Number = 20000; /* for (var i = 0; i < animLayers.length; i++ ) { if (animLayers[i].getMaxFrames() < maxFrames){ maxFrames = animLayers[i].getMaxFrames(); } } */ return maxFrames; } function getGIClient():GIClient { return giClient; } function onStateEvent(stateEvent : StateEvent) : Void { var layer:SelectableLayer = SelectableLayer(stateEvent.getSource()); if(!layer.isEditing()) { giClient.ruler.setActiveMode(giClient.ruler.getDefaultMode()); this.editing = false; giClient.ruler.rulerEventDispatcher.changeEditing(); layer.removeEventListener(this, "SelectableLayer", StateEvent.CHANGE, "editingStatus"); } } public function setMeasureFeature(measureFeature : Feature) : Void { this.measureFeature = measureFeature; } public function getMeasureFeature() : Feature { return this.measureFeature; } public function setSelectionGeometry(selectionGeometry : Geometry) : Void { this.selectionGeometry = selectionGeometry; } public function getSelectionGeometry() : Geometry { return this.selectionGeometry; } public function setBufferedSelectionGeometry(bufferGeometry : Geometry) : Void { this.bufferedSelectionGeometry = bufferGeometry; } public function getBufferedSelectionGeometry() : Geometry { return this.bufferedSelectionGeometry; } public function setBuffer(buffer : Number) : Void { this.buffer = buffer; } public function getBuffer() : Number { return this.buffer; } }