//>>built
define("dojox/geo/openlayers/Map", ["dojo/_base/kernel",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/array",
"dojo/_base/json",
"dojo/_base/html",
"dojox/main",
"dojox/geo/openlayers/TouchInteractionSupport",
"dojox/geo/openlayers/Layer",
"dojox/geo/openlayers/Patch"], function(dojo, declare, lang, array, json, html, dojox, TouchInteractionSupport,
Layer, Patch){
dojo.experimental("dojox.geo.openlayers.Map");
lang.getObject("geo.openlayers", true, dojox);
dojox.geo.openlayers.BaseLayerType = {
// summary:
// Defines the base layer types to be used at Map construction time or
// with the setBaseLayerType function.
// description:
// This object defines the base layer types to be used at Map construction
// time or with the setBaseLayerType function.
// OSM: String
// The Open Street Map base layer type selector.
OSM : "OSM",
// WMS: String
// The Web Map Server base layer type selector.
WMS : "WMS",
// GOOGLE: String
// The Google base layer type selector.
GOOGLE : "Google",
// VIRTUAL_EARTH: String
// The Virtual Earth base layer type selector.
VIRTUAL_EARTH : "VirtualEarth",
// BING: String
// Same as Virtual Earth
BING : "VirtualEarth",
// YAHOO: String
// The Yahoo base layer type selector.
YAHOO : "Yahoo",
// ARCGIS: String
// The ESRI ARCGis base layer selector.
ARCGIS : "ArcGIS"
};
dojox.geo.openlayers.EPSG4326 = new OpenLayers.Projection("EPSG:4326");
var re = /^\s*(\d{1,3})[D°]\s*(\d{1,2})[M']\s*(\d{1,2}\.?\d*)\s*(S|"|'')\s*([NSEWnsew]{0,1})\s*$/i;
dojox.geo.openlayers.parseDMS = function(v, toDecimal){
// summary:
// Parses the specified string and returns degree minute second or decimal degree.
// description:
// Parses the specified string and returns degree minute second or decimal degree.
// v: String
// The string to parse
// toDecimal: Boolean
// Specifies if the result should be returned in decimal degrees or in an array
// containg the degrees, minutes, seconds values.
// returns: Float | Array
// the parsed value in decimal degrees or an array containing the degrees, minutes, seconds values.
var res = re.exec(v);
if (res == null || res.length < 5)
return parseFloat(v);
var d = parseFloat(res[1]);
var m = parseFloat(res[2]);
var s = parseFloat(res[3]);
var nsew = res[5];
if (toDecimal) {
var lc = nsew.toLowerCase();
var dd = d + (m + s / 60.0) / 60.0;
if (lc == "w" || lc == "s")
dd = -dd;
return dd;
}
return [d, m, s, nsew];
};
Patch.patchGFX();
return declare("dojox.geo.openlayers.Map", null, {
// summary:
// A map viewer based on the OpenLayers library.
//
// description:
// The `dojox.geo.openlayers.Map` object allows to view maps from various map providers.
// It encapsulates an `OpenLayers.Map` object on which most operations are delegated.
// GFX layers can be added to display GFX georeferenced shapes as well as Dojo widgets.
// Parameters can be passed as argument at construction time to define the base layer
// type and the base layer parameters such as url or options depending on the type
// specified. These parameters can be any of :
//
// _baseLayerType_: type of the base layer. Can be any of
//
// * `dojox.geo.openlayers.BaseLayerType.OSM`: Open Street Map base layer
// * `dojox.geo.openlayers.BaseLayerType.WMS`: Web Map Service layer
// * `dojox.geo.openlayers.BaseLayerType.GOOGLE`: Google layer
// * `dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH`: Virtual Earth layer
// * `dojox.geo.openlayers.BaseLayerType.BING`: Bing layer
// * `dojox.geo.openlayers.BaseLayerType.YAHOO`: Yahoo layer
// * `dojox.geo.openlayers.BaseLayerType.ARCGIS`: ESRI ArgGIS layer
//
// Note that access to commercial server such as Google, Virtual Earth or Yahoo may need specific licencing.
//
// The parameters value also include :
//
// * `baseLayerName`: The name of the base layer.
// * `baseLayerUrl`: Some layer may need an url such as Web Map Server
// * `baseLayerOptions`: Addtional specific options passed to OpensLayers layer,
// such as The list of layer to display, for Web Map Server layer.
//
// example:
//
// | var map = new dojox.geo.openlayers.widget.Map(div, {
// | baseLayerType : dojox.geo.openlayers.BaseLayerType.OSM,
// | baseLayerName : 'Open Street Map Layer'
// | });
// summary:
// The underlying OpenLayers.Map object.
// Should be accessed on read mode only.
olMap : null,
_tp : null,
constructor : function(div, options){
// summary:
// Constructs a new Map object
if (!options)
options = {};
div = html.byId(div);
this._tp = {
x : 0,
y : 0
};
var opts = options.openLayersMapOptions;
if (!opts) {
opts = {
controls : [new OpenLayers.Control.ScaleLine({
maxWidth : 200
}), new OpenLayers.Control.Navigation()]
};
}
if (options.accessible) {
var kbd = new OpenLayers.Control.KeyboardDefaults();
if (!opts.controls)
opts.controls = [];
opts.controls.push(kbd);
}
var baseLayerType = options.baseLayerType;
if (!baseLayerType)
baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM;
html.style(div, {
width : "100%",
height : "100%",
dir : "ltr"
});
var map = new OpenLayers.Map(div, opts);
this.olMap = map;
this._layerDictionary = {
olLayers : [],
layers : []
};
if (options.touchHandler)
this._touchControl = new TouchInteractionSupport(map);
var base = this._createBaseLayer(options);
this.addLayer(base);
this.initialFit(options);
},
initialFit : function(params){
var o = params.initialLocation;
if (!o)
o = [-160, 70, 160, -70];
this.fitTo(o);
},
setBaseLayerType : function(
/* dojox.geo.openlayers.Map.BaseLayerType */type){
// summary:
// Set the base layer type, replacing the existing base layer
// type: dojox.geo.openlayers.BaseLayerType
// base layer type
// returns: OpenLayers.Layer
// The newly created layer.
if (type == this.baseLayerType)
return null;
var o = null;
if (typeof type == "string") {
o = {
baseLayerName : type,
baseLayerType : type
};
this.baseLayerType = type;
} else if (typeof type == "object") {
o = type;
this.baseLayerType = o.baseLayerType;
}
var bl = null;
if (o != null) {
bl = this._createBaseLayer(o);
if (bl != null) {
var olm = this.olMap;
var ob = olm.getZoom();
var oc = olm.getCenter();
var recenter = !!oc && !!olm.baseLayer && !!olm.baseLayer.map;
if (recenter) {
var proj = olm.getProjectionObject();
if (proj != null)
oc = oc.transform(proj, dojox.geo.openlayers.EPSG4326);
}
var old = olm.baseLayer;
if (old != null) {
var l = this._getLayer(old);
this.removeLayer(l);
}
if (bl != null)
this.addLayer(bl);
if (recenter) {
proj = olm.getProjectionObject();
if (proj != null)
oc = oc.transform(dojox.geo.openlayers.EPSG4326, proj);
olm.setCenter(oc, ob);
}
}
}
return bl;
},
getBaseLayerType : function(){
// summary:
// Retrieves the base layer type.
// returns: dojox.geo.openlayers.BaseLayerType
// The current base layer type.
return this.baseLayerType;
},
getScale : function(geodesic){
// summary:
// Returns the current scale
// geodesic: Boolean
// Tell if geodesic calculation should be performed. If set to
// true, the scale will be calculated based on the horizontal size of the
// pixel in the center of the map viewport.
// returns: Number
// The current scale.
var scale;
var om = this.olMap;
if (geodesic) {
var units = om.getUnits();
if (!units) {
return null;
}
var inches = OpenLayers.INCHES_PER_UNIT;
scale = (om.getGeodesicPixelSize().w || 0.000001) * inches["km"] * OpenLayers.DOTS_PER_INCH;
} else {
scale = om.getScale();
}
return scale;
},
getOLMap : function(){
// summary:
// gets the underlying OpenLayers map object.
// returns : OpenLayers.Map
// The underlying OpenLayers map object.
return this.olMap;
},
_createBaseLayer : function(params){
// summary:
// Creates the base layer.
// tags:
// private
var base = null;
var type = params.baseLayerType;
var url = params.baseLayerUrl;
var name = params.baseLayerName;
var options = params.baseLayerOptions;
if (!name)
name = type;
if (!options)
options = {};
switch (type) {
case dojox.geo.openlayers.BaseLayerType.OSM:
options.transitionEffect = "resize";
// base = new OpenLayers.Layer.OSM(name, url, options);
base = new Layer(name, {
olLayer : new OpenLayers.Layer.OSM(name, url, options)
});
break;
case dojox.geo.openlayers.BaseLayerType.WMS:
if (!url) {
url = "http://labs.metacarta.com/wms/vmap0";
if (!options.layers)
options.layers = "basic";
}
base = new Layer(name, {
olLayer : new OpenLayers.Layer.WMS(name, url, options, {
transitionEffect : "resize"
})
});
break;
case dojox.geo.openlayers.BaseLayerType.GOOGLE:
base = new Layer(name, {
olLayer : new OpenLayers.Layer.Google(name, options)
});
break;
case dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH:
base = new Layer(name, {
olLayer : new OpenLayers.Layer.VirtualEarth(name, options)
});
break;
case dojox.geo.openlayers.BaseLayerType.YAHOO:
// base = new OpenLayers.Layer.Yahoo(name);
base = new Layer(name, {
olLayer : new OpenLayers.Layer.Yahoo(name, options)
});
break;
case dojox.geo.openlayers.BaseLayerType.ARCGIS:
if (!url)
url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/export";
base = new Layer(name, {
olLayer : new OpenLayers.Layer.ArcGIS93Rest(name, url, options, {})
});
break;
}
if (base == null) {
if (type instanceof OpenLayers.Layer)
base = type;
else {
options.transitionEffect = "resize";
base = new Layer(name, {
olLayer : new OpenLayers.Layer.OSM(name, url, options)
});
this.baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM;
}
}
return base;
},
removeLayer : function(/* dojox.geo.openlayers.Layer */layer){
// summary:
// Remove the specified layer from the map.
// layer: dojox.geo.openlayers.Layer
// The layer to remove from the map.
var om = this.olMap;
var i = array.indexOf(this._layerDictionary.layers, layer);
if (i > 0)
this._layerDictionary.layers.splice(i, 1);
var oll = layer.olLayer;
var j = array.indexOf(this._layerDictionary.olLayers, oll);
if (j > 0)
this._layerDictionary.olLayers.splice(i, j);
om.removeLayer(oll, false);
},
layerIndex : function(/* dojox.geo.openlayers.Layer */layer, index){
// summary:
// Set or retrieve the layer index.
// description:
// Set or get the layer index, that is the z-order of the layer.
// if the index parameter is provided, the layer index is set to
// this value. If the index parameter is not provided, the index of
// the layer is returned.
// index: undefined | int
// index of the layer
// returns: int
// the index of the layer.
var olm = this.olMap;
if (!index)
return olm.getLayerIndex(layer.olLayer);
//olm.raiseLayer(layer.olLayer, index);
olm.setLayerIndex(layer.olLayer, index);
this._layerDictionary.layers.sort(function(l1, l2){
return olm.getLayerIndex(l1.olLayer) - olm.getLayerIndex(l2.olLayer);
});
this._layerDictionary.olLayers.sort(function(l1, l2){
return olm.getLayerIndex(l1) - olm.getLayerIndex(l2);
});
return index;
},
addLayer : function(/* dojox.geo.openlayers.Layer */layer){
// summary:
// Add the specified layer to the map.
// layer: dojox.geo.openlayer.Layer
// The layer to add to the map.
layer.dojoMap = this;
var om = this.olMap;
var ol = layer.olLayer;
this._layerDictionary.olLayers.push(ol);
this._layerDictionary.layers.push(layer);
om.addLayer(ol);
layer.added();
},
_getLayer : function(/*OpenLayer.Layer */ol){
// summary:
// Retrieve the dojox.geo.openlayer.Layer from the OpenLayer.Layer
// tags:
// private
var i = array.indexOf(this._layerDictionary.olLayers, ol);
if (i != -1)
return this._layerDictionary.layers[i];
return null;
},
getLayer : function(property, value){
// summary:
// Returns the layer whose property matches the value.
// property: String
// The property to check
// value: Object
// The value to match
// returns: dojox.geo.openlayer.Layer | Array
// The layer(s) matching the property's value. Since multiple layers
// match the property's value the return value is an array.
// example:
// var layers = map.getLayer("name", "Layer Name");
var om = this.olMap;
var ols = om.getBy("layers", property, value);
var ret = new Array(); //[];
array.forEach(ols, function(ol){
ret.push(this._getLayer(ol));
}, this);
return ret;
},
getLayerCount : function(){
// summary:
// Returns the count of layers of this map.
// returns: int
// The number of layers of this map.
var om = this.olMap;
if (om.layers == null)
return 0;
return om.layers.length;
},
fitTo : function(o){
// summary:
// Fits the map on a point,or an area
// description:
// Fits the map on the point or extent specified as parameter.
// o: Object
// Object with key values fit parameters or a JSON string.
// example:
// Examples of arguments passed to the fitTo function :
// | null
// The map is fit on full extent
//
// | {
// | bounds : [ulx, uly, lrx, lry]
// | }
// The map is fit on the specified bounds expressed as decimal degrees latitude and longitude.
// The bounds are defined with their upper left and lower right corners coordinates.
//
// | {
// | position : [longitude, latitude],
// | extent : degrees
// | }
// The map is fit on the specified position showing the extent around
// the specified center position.
var map = this.olMap;
var from = dojox.geo.openlayers.EPSG4326;
if (o == null) {
var c = this.transformXY(0, 0, from);
map.setCenter(new OpenLayers.LonLat(c.x, c.y));
return;
}
var b = null;
if (typeof o == "string")
var j = json.fromJson(o);
else
j = o;
var ul;
var lr;
if (j.hasOwnProperty("bounds")) {
var a = j.bounds;
b = new OpenLayers.Bounds();
ul = this.transformXY(a[0], a[1], from);
b.left = ul.x;
b.top = ul.y;
lr = this.transformXY(a[2], a[3], from);
b.right = lr.x;
b.bottom = lr.y;
}
if (b == null) {
if (j.hasOwnProperty("position")) {
var p = j.position;
var e = j.hasOwnProperty("extent") ? j.extent : 1;
if (typeof e == "string")
e = parseFloat(e);
b = new OpenLayers.Bounds();
ul = this.transformXY(p[0] - e, p[1] + e, from);
b.left = ul.x;
b.top = ul.y;
lr = this.transformXY(p[0] + e, p[1] - e, from);
b.right = lr.x;
b.bottom = lr.y;
}
}
if (b == null) {
if (o.length == 4) {
b = new OpenLayers.Bounds();
// TODO Choose the correct method
if (false) {
b.left = o[0];
b.top = o[1];
b.right = o[2];
b.bottom = o[3];
} else {
ul = this.transformXY(o[0], o[1], from);
b.left = ul.x;
b.top = ul.y;
lr = this.transformXY(o[2], o[3], from);
b.right = lr.x;
b.bottom = lr.y;
}
}
}
if (b != null) {
map.zoomToExtent(b, true);
}
},
transform : function(p, from, to){
// summary:
// Transforms the point passed as argument, expressed in the from
// coordinate system to the map coordinate system.
// description:
// Transforms the point passed as argument without modifying it. The point is supposed to be expressed
// in the from coordinate system and is transformed to the map coordinate system.
// p : Object {x, y}
// The point to transform
// from: OpenLayers.Projection
// The projection in which the point is expressed.
return this.transformXY(p.x, p.y, from, to);
},
transformXY : function(x, y, from, to){
// summary
// Transforms the coordinates passed as argument, expressed in the from
// coordinate system to the map coordinate system.
// description:
// Transforms the coordinates passed as argument. The coordinate are supposed to be expressed
// in the from coordinate system and are transformed to the map coordinate system.
// x : Number
// The longitude coordinate to transform.
// y : Number
// The latitude coordinate to transform.
// from: OpenLayers.Projection
// The projection in which the point is expressed.
var tp = this._tp;
tp.x = x;
tp.y = y;
if (!from)
from = dojox.geo.openlayers.EPSG4326;
if (!to)
to = this.olMap.getProjectionObject();
tp = OpenLayers.Projection.transform(tp, from, to);
return tp;
}
});
});