Map.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. define("dojox/geo/openlayers/Map", ["dojo/_base/kernel",
  2. "dojo/_base/declare",
  3. "dojo/_base/lang",
  4. "dojo/_base/array",
  5. "dojo/_base/json",
  6. "dojo/_base/html",
  7. "dojox/main",
  8. "dojox/geo/openlayers/TouchInteractionSupport",
  9. "dojox/geo/openlayers/Layer",
  10. "dojox/geo/openlayers/Patch"], function(dojo, declare, lang, array, json, html, dojox, TouchInteractionSupport,
  11. Layer, Patch){
  12. dojo.experimental("dojox.geo.openlayers.Map");
  13. lang.getObject("geo.openlayers", true, dojox);
  14. dojox.geo.openlayers.BaseLayerType = {
  15. // summary:
  16. // Defines the base layer types to be used at Map construction time or
  17. // with the setBaseLayerType function.
  18. // description:
  19. // This object defines the base layer types to be used at Map construction
  20. // time or with the setBaseLayerType function.
  21. // OSM: String
  22. // The Open Street Map base layer type selector.
  23. OSM : "OSM",
  24. // WMS: String
  25. // The Web Map Server base layer type selector.
  26. WMS : "WMS",
  27. // GOOGLE: String
  28. // The Google base layer type selector.
  29. GOOGLE : "Google",
  30. // VIRTUAL_EARTH: String
  31. // The Virtual Earth base layer type selector.
  32. VIRTUAL_EARTH : "VirtualEarth",
  33. // BING: String
  34. // Same as Virtual Earth
  35. BING : "VirtualEarth",
  36. // YAHOO: String
  37. // The Yahoo base layer type selector.
  38. YAHOO : "Yahoo",
  39. // ARCGIS: String
  40. // The ESRI ARCGis base layer selector.
  41. ARCGIS : "ArcGIS"
  42. };
  43. dojox.geo.openlayers.EPSG4326 = new OpenLayers.Projection("EPSG:4326");
  44. 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;
  45. dojox.geo.openlayers.parseDMS = function(v, toDecimal){
  46. // summary:
  47. // Parses the specified string and returns degree minute second or decimal degree.
  48. // description:
  49. // Parses the specified string and returns degree minute second or decimal degree.
  50. // v: String
  51. // The string to parse
  52. // toDecimal: Boolean
  53. // Specifies if the result should be returned in decimal degrees or in an array
  54. // containg the degrees, minutes, seconds values.
  55. // returns: Float | Array
  56. // the parsed value in decimal degrees or an array containing the degrees, minutes, seconds values.
  57. var res = re.exec(v);
  58. if (res == null || res.length < 5)
  59. return parseFloat(v);
  60. var d = parseFloat(res[1]);
  61. var m = parseFloat(res[2]);
  62. var s = parseFloat(res[3]);
  63. var nsew = res[5];
  64. if (toDecimal) {
  65. var lc = nsew.toLowerCase();
  66. var dd = d + (m + s / 60.0) / 60.0;
  67. if (lc == "w" || lc == "s")
  68. dd = -dd;
  69. return dd;
  70. }
  71. return [d, m, s, nsew];
  72. };
  73. Patch.patchGFX();
  74. return declare("dojox.geo.openlayers.Map", null, {
  75. // summary:
  76. // A map viewer based on the OpenLayers library.
  77. //
  78. // description:
  79. // The `dojox.geo.openlayers.Map` object allows to view maps from various map providers.
  80. // It encapsulates an `OpenLayers.Map` object on which most operations are delegated.
  81. // GFX layers can be added to display GFX georeferenced shapes as well as Dojo widgets.
  82. // Parameters can be passed as argument at construction time to define the base layer
  83. // type and the base layer parameters such as url or options depending on the type
  84. // specified. These parameters can be any of :
  85. // <br />
  86. // _baseLayerType_: type of the base layer. Can be any of
  87. //
  88. // * `dojox.geo.openlayers.BaseLayerType.OSM`: Open Street Map base layer
  89. // * `dojox.geo.openlayers.BaseLayerType.WMS`: Web Map Service layer
  90. // * `dojox.geo.openlayers.BaseLayerType.GOOGLE`: Google layer
  91. // * `dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH`: Virtual Earth layer
  92. // * `dojox.geo.openlayers.BaseLayerType.BING`: Bing layer
  93. // * `dojox.geo.openlayers.BaseLayerType.YAHOO`: Yahoo layer
  94. // * `dojox.geo.openlayers.BaseLayerType.ARCGIS`: ESRI ArgGIS layer
  95. //
  96. // Note that access to commercial server such as Google, Virtual Earth or Yahoo may need specific licencing.
  97. //
  98. // The parameters value also include :
  99. //
  100. // * `baseLayerName`: The name of the base layer.
  101. // * `baseLayerUrl`: Some layer may need an url such as Web Map Server
  102. // * `baseLayerOptions`: Addtional specific options passed to OpensLayers layer,
  103. // such as The list of layer to display, for Web Map Server layer.
  104. //
  105. // example:
  106. //
  107. // | var map = new dojox.geo.openlayers.widget.Map(div, {
  108. // | baseLayerType : dojox.geo.openlayers.BaseLayerType.OSM,
  109. // | baseLayerName : 'Open Street Map Layer'
  110. // | });
  111. // summary:
  112. // The underlying OpenLayers.Map object.
  113. // Should be accessed on read mode only.
  114. olMap : null,
  115. _tp : null,
  116. constructor : function(div, options){
  117. // summary:
  118. // Constructs a new Map object
  119. if (!options)
  120. options = {};
  121. div = html.byId(div);
  122. this._tp = {
  123. x : 0,
  124. y : 0
  125. };
  126. var opts = options.openLayersMapOptions;
  127. if (!opts) {
  128. opts = {
  129. controls : [new OpenLayers.Control.ScaleLine({
  130. maxWidth : 200
  131. }), new OpenLayers.Control.Navigation()]
  132. };
  133. }
  134. if (options.accessible) {
  135. var kbd = new OpenLayers.Control.KeyboardDefaults();
  136. if (!opts.controls)
  137. opts.controls = [];
  138. opts.controls.push(kbd);
  139. }
  140. var baseLayerType = options.baseLayerType;
  141. if (!baseLayerType)
  142. baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM;
  143. html.style(div, {
  144. width : "100%",
  145. height : "100%",
  146. dir : "ltr"
  147. });
  148. var map = new OpenLayers.Map(div, opts);
  149. this.olMap = map;
  150. this._layerDictionary = {
  151. olLayers : [],
  152. layers : []
  153. };
  154. if (options.touchHandler)
  155. this._touchControl = new TouchInteractionSupport(map);
  156. var base = this._createBaseLayer(options);
  157. this.addLayer(base);
  158. this.initialFit(options);
  159. },
  160. initialFit : function(params){
  161. var o = params.initialLocation;
  162. if (!o)
  163. o = [-160, 70, 160, -70];
  164. this.fitTo(o);
  165. },
  166. setBaseLayerType : function(
  167. /* dojox.geo.openlayers.Map.BaseLayerType */type){
  168. // summary:
  169. // Set the base layer type, replacing the existing base layer
  170. // type: dojox.geo.openlayers.BaseLayerType
  171. // base layer type
  172. // returns: OpenLayers.Layer
  173. // The newly created layer.
  174. if (type == this.baseLayerType)
  175. return null;
  176. var o = null;
  177. if (typeof type == "string") {
  178. o = {
  179. baseLayerName : type,
  180. baseLayerType : type
  181. };
  182. this.baseLayerType = type;
  183. } else if (typeof type == "object") {
  184. o = type;
  185. this.baseLayerType = o.baseLayerType;
  186. }
  187. var bl = null;
  188. if (o != null) {
  189. bl = this._createBaseLayer(o);
  190. if (bl != null) {
  191. var olm = this.olMap;
  192. var ob = olm.getZoom();
  193. var oc = olm.getCenter();
  194. var recenter = !!oc && !!olm.baseLayer && !!olm.baseLayer.map;
  195. if (recenter) {
  196. var proj = olm.getProjectionObject();
  197. if (proj != null)
  198. oc = oc.transform(proj, dojox.geo.openlayers.EPSG4326);
  199. }
  200. var old = olm.baseLayer;
  201. if (old != null) {
  202. var l = this._getLayer(old);
  203. this.removeLayer(l);
  204. }
  205. if (bl != null)
  206. this.addLayer(bl);
  207. if (recenter) {
  208. proj = olm.getProjectionObject();
  209. if (proj != null)
  210. oc = oc.transform(dojox.geo.openlayers.EPSG4326, proj);
  211. olm.setCenter(oc, ob);
  212. }
  213. }
  214. }
  215. return bl;
  216. },
  217. getBaseLayerType : function(){
  218. // summary:
  219. // Retrieves the base layer type.
  220. // returns: dojox.geo.openlayers.BaseLayerType
  221. // The current base layer type.
  222. return this.baseLayerType;
  223. },
  224. getScale : function(geodesic){
  225. // summary:
  226. // Returns the current scale
  227. // geodesic: Boolean
  228. // Tell if geodesic calculation should be performed. If set to
  229. // true, the scale will be calculated based on the horizontal size of the
  230. // pixel in the center of the map viewport.
  231. // returns: Number
  232. // The current scale.
  233. var scale;
  234. var om = this.olMap;
  235. if (geodesic) {
  236. var units = om.getUnits();
  237. if (!units) {
  238. return null;
  239. }
  240. var inches = OpenLayers.INCHES_PER_UNIT;
  241. scale = (om.getGeodesicPixelSize().w || 0.000001) * inches["km"] * OpenLayers.DOTS_PER_INCH;
  242. } else {
  243. scale = om.getScale();
  244. }
  245. return scale;
  246. },
  247. getOLMap : function(){
  248. // summary:
  249. // gets the underlying OpenLayers map object.
  250. // returns : OpenLayers.Map
  251. // The underlying OpenLayers map object.
  252. return this.olMap;
  253. },
  254. _createBaseLayer : function(params){
  255. // summary:
  256. // Creates the base layer.
  257. // tags:
  258. // private
  259. var base = null;
  260. var type = params.baseLayerType;
  261. var url = params.baseLayerUrl;
  262. var name = params.baseLayerName;
  263. var options = params.baseLayerOptions;
  264. if (!name)
  265. name = type;
  266. if (!options)
  267. options = {};
  268. switch (type) {
  269. case dojox.geo.openlayers.BaseLayerType.OSM:
  270. options.transitionEffect = "resize";
  271. // base = new OpenLayers.Layer.OSM(name, url, options);
  272. base = new Layer(name, {
  273. olLayer : new OpenLayers.Layer.OSM(name, url, options)
  274. });
  275. break;
  276. case dojox.geo.openlayers.BaseLayerType.WMS:
  277. if (!url) {
  278. url = "http://labs.metacarta.com/wms/vmap0";
  279. if (!options.layers)
  280. options.layers = "basic";
  281. }
  282. base = new Layer(name, {
  283. olLayer : new OpenLayers.Layer.WMS(name, url, options, {
  284. transitionEffect : "resize"
  285. })
  286. });
  287. break;
  288. case dojox.geo.openlayers.BaseLayerType.GOOGLE:
  289. base = new Layer(name, {
  290. olLayer : new OpenLayers.Layer.Google(name, options)
  291. });
  292. break;
  293. case dojox.geo.openlayers.BaseLayerType.VIRTUAL_EARTH:
  294. base = new Layer(name, {
  295. olLayer : new OpenLayers.Layer.VirtualEarth(name, options)
  296. });
  297. break;
  298. case dojox.geo.openlayers.BaseLayerType.YAHOO:
  299. // base = new OpenLayers.Layer.Yahoo(name);
  300. base = new Layer(name, {
  301. olLayer : new OpenLayers.Layer.Yahoo(name, options)
  302. });
  303. break;
  304. case dojox.geo.openlayers.BaseLayerType.ARCGIS:
  305. if (!url)
  306. url = "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/export";
  307. base = new Layer(name, {
  308. olLayer : new OpenLayers.Layer.ArcGIS93Rest(name, url, options, {})
  309. });
  310. break;
  311. }
  312. if (base == null) {
  313. if (type instanceof OpenLayers.Layer)
  314. base = type;
  315. else {
  316. options.transitionEffect = "resize";
  317. base = new Layer(name, {
  318. olLayer : new OpenLayers.Layer.OSM(name, url, options)
  319. });
  320. this.baseLayerType = dojox.geo.openlayers.BaseLayerType.OSM;
  321. }
  322. }
  323. return base;
  324. },
  325. removeLayer : function(/* dojox.geo.openlayers.Layer */layer){
  326. // summary:
  327. // Remove the specified layer from the map.
  328. // layer: dojox.geo.openlayers.Layer
  329. // The layer to remove from the map.
  330. var om = this.olMap;
  331. var i = array.indexOf(this._layerDictionary.layers, layer);
  332. if (i > 0)
  333. this._layerDictionary.layers.splice(i, 1);
  334. var oll = layer.olLayer;
  335. var j = array.indexOf(this._layerDictionary.olLayers, oll);
  336. if (j > 0)
  337. this._layerDictionary.olLayers.splice(i, j);
  338. om.removeLayer(oll, false);
  339. },
  340. layerIndex : function(/* dojox.geo.openlayers.Layer */layer, index){
  341. // summary:
  342. // Set or retrieve the layer index.
  343. // description:
  344. // Set or get the layer index, that is the z-order of the layer.
  345. // if the index parameter is provided, the layer index is set to
  346. // this value. If the index parameter is not provided, the index of
  347. // the layer is returned.
  348. // index: undefined | int
  349. // index of the layer
  350. // returns: int
  351. // the index of the layer.
  352. var olm = this.olMap;
  353. if (!index)
  354. return olm.getLayerIndex(layer.olLayer);
  355. //olm.raiseLayer(layer.olLayer, index);
  356. olm.setLayerIndex(layer.olLayer, index);
  357. this._layerDictionary.layers.sort(function(l1, l2){
  358. return olm.getLayerIndex(l1.olLayer) - olm.getLayerIndex(l2.olLayer);
  359. });
  360. this._layerDictionary.olLayers.sort(function(l1, l2){
  361. return olm.getLayerIndex(l1) - olm.getLayerIndex(l2);
  362. });
  363. return index;
  364. },
  365. addLayer : function(/* dojox.geo.openlayers.Layer */layer){
  366. // summary:
  367. // Add the specified layer to the map.
  368. // layer: dojox.geo.openlayer.Layer
  369. // The layer to add to the map.
  370. layer.dojoMap = this;
  371. var om = this.olMap;
  372. var ol = layer.olLayer;
  373. this._layerDictionary.olLayers.push(ol);
  374. this._layerDictionary.layers.push(layer);
  375. om.addLayer(ol);
  376. layer.added();
  377. },
  378. _getLayer : function(/*OpenLayer.Layer */ol){
  379. // summary:
  380. // Retrieve the dojox.geo.openlayer.Layer from the OpenLayer.Layer
  381. // tags:
  382. // private
  383. var i = array.indexOf(this._layerDictionary.olLayers, ol);
  384. if (i != -1)
  385. return this._layerDictionary.layers[i];
  386. return null;
  387. },
  388. getLayer : function(property, value){
  389. // summary:
  390. // Returns the layer whose property matches the value.
  391. // property: String
  392. // The property to check
  393. // value: Object
  394. // The value to match
  395. // returns: dojox.geo.openlayer.Layer | Array
  396. // The layer(s) matching the property's value. Since multiple layers
  397. // match the property's value the return value is an array.
  398. // example:
  399. // var layers = map.getLayer("name", "Layer Name");
  400. var om = this.olMap;
  401. var ols = om.getBy("layers", property, value);
  402. var ret = new Array(); //[];
  403. array.forEach(ols, function(ol){
  404. ret.push(this._getLayer(ol));
  405. }, this);
  406. return ret;
  407. },
  408. getLayerCount : function(){
  409. // summary:
  410. // Returns the count of layers of this map.
  411. // returns: int
  412. // The number of layers of this map.
  413. var om = this.olMap;
  414. if (om.layers == null)
  415. return 0;
  416. return om.layers.length;
  417. },
  418. fitTo : function(o){
  419. // summary:
  420. // Fits the map on a point,or an area
  421. // description:
  422. // Fits the map on the point or extent specified as parameter.
  423. // o: Object
  424. // Object with key values fit parameters or a JSON string.
  425. // example:
  426. // Examples of arguments passed to the fitTo function :
  427. // | null
  428. // The map is fit on full extent
  429. //
  430. // | {
  431. // | bounds : [ulx, uly, lrx, lry]
  432. // | }
  433. // The map is fit on the specified bounds expressed as decimal degrees latitude and longitude.
  434. // The bounds are defined with their upper left and lower right corners coordinates.
  435. //
  436. // | {
  437. // | position : [longitude, latitude],
  438. // | extent : degrees
  439. // | }
  440. // The map is fit on the specified position showing the extent <extent> around
  441. // the specified center position.
  442. var map = this.olMap;
  443. var from = dojox.geo.openlayers.EPSG4326;
  444. if (o == null) {
  445. var c = this.transformXY(0, 0, from);
  446. map.setCenter(new OpenLayers.LonLat(c.x, c.y));
  447. return;
  448. }
  449. var b = null;
  450. if (typeof o == "string")
  451. var j = json.fromJson(o);
  452. else
  453. j = o;
  454. var ul;
  455. var lr;
  456. if (j.hasOwnProperty("bounds")) {
  457. var a = j.bounds;
  458. b = new OpenLayers.Bounds();
  459. ul = this.transformXY(a[0], a[1], from);
  460. b.left = ul.x;
  461. b.top = ul.y;
  462. lr = this.transformXY(a[2], a[3], from);
  463. b.right = lr.x;
  464. b.bottom = lr.y;
  465. }
  466. if (b == null) {
  467. if (j.hasOwnProperty("position")) {
  468. var p = j.position;
  469. var e = j.hasOwnProperty("extent") ? j.extent : 1;
  470. if (typeof e == "string")
  471. e = parseFloat(e);
  472. b = new OpenLayers.Bounds();
  473. ul = this.transformXY(p[0] - e, p[1] + e, from);
  474. b.left = ul.x;
  475. b.top = ul.y;
  476. lr = this.transformXY(p[0] + e, p[1] - e, from);
  477. b.right = lr.x;
  478. b.bottom = lr.y;
  479. }
  480. }
  481. if (b == null) {
  482. if (o.length == 4) {
  483. b = new OpenLayers.Bounds();
  484. // TODO Choose the correct method
  485. if (false) {
  486. b.left = o[0];
  487. b.top = o[1];
  488. b.right = o[2];
  489. b.bottom = o[3];
  490. } else {
  491. ul = this.transformXY(o[0], o[1], from);
  492. b.left = ul.x;
  493. b.top = ul.y;
  494. lr = this.transformXY(o[2], o[3], from);
  495. b.right = lr.x;
  496. b.bottom = lr.y;
  497. }
  498. }
  499. }
  500. if (b != null) {
  501. map.zoomToExtent(b, true);
  502. }
  503. },
  504. transform : function(p, from, to){
  505. // summary:
  506. // Transforms the point passed as argument, expressed in the <em>from</em>
  507. // coordinate system to the map coordinate system.
  508. // description:
  509. // Transforms the point passed as argument without modifying it. The point is supposed to be expressed
  510. // in the <em>from</em> coordinate system and is transformed to the map coordinate system.
  511. // p : Object {x, y}
  512. // The point to transform
  513. // from: OpenLayers.Projection
  514. // The projection in which the point is expressed.
  515. return this.transformXY(p.x, p.y, from, to);
  516. },
  517. transformXY : function(x, y, from, to){
  518. // summary
  519. // Transforms the coordinates passed as argument, expressed in the <em>from</em>
  520. // coordinate system to the map coordinate system.
  521. // description:
  522. // Transforms the coordinates passed as argument. The coordinate are supposed to be expressed
  523. // in the <em>from</em> coordinate system and are transformed to the map coordinate system.
  524. // x : Number
  525. // The longitude coordinate to transform.
  526. // y : Number
  527. // The latitude coordinate to transform.
  528. // from: OpenLayers.Projection
  529. // The projection in which the point is expressed.
  530. var tp = this._tp;
  531. tp.x = x;
  532. tp.y = y;
  533. if (!from)
  534. from = dojox.geo.openlayers.EPSG4326;
  535. if (!to)
  536. to = this.olMap.getProjectionObject();
  537. tp = OpenLayers.Projection.transform(tp, from, to);
  538. return tp;
  539. }
  540. });
  541. });