From 60825f0f997f18242fd19f61add21ae51ca66eb4 Mon Sep 17 00:00:00 2001 From: Jackie Ng Date: Wed, 6 Nov 2013 00:14:57 +1100 Subject: [PATCH] Add MapGuide untiled map support to ol3. This adds a new ol.source.MapGuide class that is initialized with an options object that can contain the following values: - projection: The projection of the Map Definition in EPSG format - url: The mapagent URL - useOverlay: Determines whether the GETMAPIMAGE (false) or GETDYNAMICMAPOVERLAYIMAGE (true) will be used for requesting the map image. When using GETMAPIMAGE, you must include a valid MAPDEFINITION parameter in the 'params' option property. When using GETDYNAMICMAPOVERLAYIMAGE, you must include a valid SESSION and MAPNAME parameters in the 'params' option property. - metersPerUnit: A required value used for calculating the map scale needed by the image request. This value can be calculated using the MapGuide Web API or obtained through the new CREATERUNTIMEMAP operation in MapGuide Open Source 2.6 - params: A set of key-value pairs to append to the mapagent request - extent: The bounds of the layer An example is included to demonstrate this new layer source. Like ol2, this example uses the MapGuide Server on data.mapguide.com --- examples/mapguide-untiled.html | 50 +++++++++++ examples/mapguide-untiled.js | 39 +++++++++ src/objectliterals.jsdoc | 12 +++ src/ol/source/mapguidesource.exports | 1 + src/ol/source/mapguidesource.js | 125 +++++++++++++++++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 examples/mapguide-untiled.html create mode 100644 examples/mapguide-untiled.js create mode 100644 src/ol/source/mapguidesource.exports create mode 100644 src/ol/source/mapguidesource.js diff --git a/examples/mapguide-untiled.html b/examples/mapguide-untiled.html new file mode 100644 index 0000000000..0d80284c1b --- /dev/null +++ b/examples/mapguide-untiled.html @@ -0,0 +1,50 @@ + + + + + + + + + + + MapGuide untiled example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

MapGuide untiled example

+

Example of a untiled MapGuide map.

+
+

See the mapguide-untiled.js source to see how this is done.

+
+
mapguide
+
+ +
+ +
+ + + + + + diff --git a/examples/mapguide-untiled.js b/examples/mapguide-untiled.js new file mode 100644 index 0000000000..b4d3358351 --- /dev/null +++ b/examples/mapguide-untiled.js @@ -0,0 +1,39 @@ +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.Image'); +goog.require('ol.source.MapGuide'); + +var mdf = 'Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition'; +var agentUrl = + 'http://data.mapguide.com/mapguide/mapagent/mapagent.fcgi?USERNAME=Anonymous'; +var bounds = [ + -87.865114442365922, + 43.665065564837931, + -87.595394059497067, + 43.823852564430069 +]; +var map = new ol.Map({ + layers: [ + new ol.layer.Image({ + source: new ol.source.MapGuide({ + projection: 'EPSG:4326', + url: agentUrl, + useOverlay: false, + metersPerUnit: 111319.4908, //value returned from mapguide + params: { + MAPDEFINITION: mdf, + FORMAT: 'PNG' + }, + extent: bounds + }) + }) + ], + renderer: ol.RendererHint.CANVAS, + target: 'map', + view: new ol.View2D({ + center: [-87.7302542509315, 43.744459064634], + projection: 'EPSG:4326', + zoom: 12 + }) +}); diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 0c6c3b03fc..2799a01053 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -578,6 +578,18 @@ * @todo stability experimental */ +/** + * @typedef {Object} ol.source.MapGuideOptions + * @property {string} url The mapagent url + * @property {number} metersPerUnit The meters-per-unit value + * @property {ol.Extent|undefined} extent Extent. + * @property {boolean} useOverlay If true, will use GETDYNAMICMAPOVERLAYIMAGE + * @property {ol.proj.ProjectionLike} projection Projection. + * @property {Array.|undefined} resolutions Resolutions. If specified, + * requests will be made for these resolutions only. + * @property {Object} params additional parameters + */ + /** * @typedef {Object} ol.source.MapQuestOptions * @property {ol.TileLoadFunctionType|undefined} tileLoadFunction Optional diff --git a/src/ol/source/mapguidesource.exports b/src/ol/source/mapguidesource.exports new file mode 100644 index 0000000000..c386f721e0 --- /dev/null +++ b/src/ol/source/mapguidesource.exports @@ -0,0 +1 @@ +@exportSymbol ol.source.MapGuide diff --git a/src/ol/source/mapguidesource.js b/src/ol/source/mapguidesource.js new file mode 100644 index 0000000000..7fa5a742ed --- /dev/null +++ b/src/ol/source/mapguidesource.js @@ -0,0 +1,125 @@ +goog.provide('ol.source.MapGuide'); + +goog.require('goog.object'); +goog.require('goog.uri.utils'); +goog.require('ol.ImageUrlFunction'); +goog.require('ol.extent'); +goog.require('ol.source.Image'); + + + +/** + * @constructor + * @extends {ol.source.Image} + * @param {ol.source.MapGuideOptions} options Options. + */ +ol.source.MapGuide = function(options) { + var imageUrlFunction = goog.isDef(options.url) ? + ol.ImageUrlFunction.createFromParamsFunction( + options.url, + options.params, + goog.bind(this.getUrl, this)) : + ol.ImageUrlFunction.nullImageUrlFunction; + + /** + * @private + * @type {number} + */ + this.metersPerUnit_ = options.metersPerUnit; + + /** + * @private + * @type {boolean} + */ + this.useOverlay_ = options.useOverlay; + + /** + * @private + * @type {ol.Image} + */ + this.image_ = null; + + goog.base(this, { + extent: options.extent, + projection: options.projection, + resolutions: options.resolutions, + imageUrlFunction: imageUrlFunction + }); +}; +goog.inherits(ol.source.MapGuide, ol.source.Image); + + +/** + * @inheritDoc + */ +ol.source.MapGuide.prototype.getImage = + function(extent, resolution, projection) { + resolution = this.findNearestResolution(resolution); + + var image = this.image_; + if (!goog.isNull(image) && + image.getResolution() == resolution && + ol.extent.containsExtent(image.getExtent(), extent)) { + return image; + } + + extent = extent.slice(); + ol.extent.scaleFromCenter(extent, 1.0); //this.ratio_); + var width = (extent[2] - extent[0]) / resolution; + var height = (extent[3] - extent[1]) / resolution; + var size = [width, height]; + + this.image_ = this.createImage(extent, resolution, size, projection); + return this.image_; +}; + + +/** + * @param {ol.Extent} extent The map extents + * @param {ol.Size} size the viewport size + * @return {number} The computed map scale + */ +ol.source.MapGuide.prototype.getScale = function(extent, size) { + var mcsW = extent[2] - extent[0]; + var mcsH = extent[3] - extent[1]; + var devW = size[0]; + var devH = size[1]; + var dpi = 96; + var mpu = this.metersPerUnit_; + var mpp = 0.0254 / dpi; + var scale = 0.0; + if (devH * mcsW > devW * mcsH) + scale = mcsW * mpu / (devW * mpp); //width-limited + else + scale = mcsH * mpu / (devH * mpp); //height-limited + return scale; +}; + + +/** + * @param {string} baseUrl The mapagent url. + * @param {Object.} params Request parameters. + * @param {ol.Extent} extent Extent. + * @param {ol.Size} size Size. + * @param {ol.proj.Projection} projection Projection. + * @return {string} The mapagent map image request URL. + */ +ol.source.MapGuide.prototype.getUrl = + function(baseUrl, params, extent, size, projection) { + var scale = this.getScale(extent, size); + var baseParams = { + 'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE', + 'VERSION': '2.0.0', + 'LOCALE': 'en', + 'CLIENTAGENT': 'ol.source.MapGuide source', + 'CLIP': '1', + 'SETDISPLAYDPI': 96, + 'SETDISPLAYWIDTH': Math.round(size[0]), + 'SETDISPLAYHEIGHT': Math.round(size[1]), + 'SETVIEWSCALE': scale, + 'SETVIEWCENTERX': (extent[0] + extent[2]) / 2, + 'SETVIEWCENTERY': (extent[1] + extent[3]) / 2 + }; + goog.object.extend(baseParams, params); + return goog.uri.utils.appendParamsFromMap(baseUrl, baseParams); +};