Skip to content

Support ArcGIS Rest Services #3263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions examples/arcgis-tiled.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Tiled ArcGIS MapServer example</title>
</head>
<body>

<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>

<div class="container-fluid">

<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>

<div class="row-fluid">

<div class="span12">
<h4 id="title">Tiled ArcGIS MapServer example</h4>
<p id="shortdesc">Example of a tiled ArcGIS layer.</p>
<div id="docs">
<p>See the <a href="arcgis-tiled.js" target="_blank">arcgis-tiled.js source</a> to see how this is done.</p>
</div>
<div id="tags">arcgis, tile, tilelayer</div>
</div>

</div>

</div>

<script src="../resources/jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=arcgis-tiled" type="text/javascript"></script>

</body>
</html>
28 changes: 28 additions & 0 deletions examples/arcgis-tiled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.source.MapQuest');
goog.require('ol.source.TileArcGISRest');

var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/' +
'Specialty/ESRI_StateCityHighway_USA/MapServer';

var layers = [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
new ol.layer.Tile({
extent: [-13884991, 2870341, -7455066, 6338219],
source: new ol.source.TileArcGISRest({
url: url
})
})
];
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [-10997148, 4569099],
zoom: 4
})
});
87 changes: 87 additions & 0 deletions externs/olx.js
Original file line number Diff line number Diff line change
Expand Up @@ -4978,6 +4978,93 @@ olx.source.ServerVectorOptions.prototype.logo;
*/
olx.source.ServerVectorOptions.prototype.projection;

/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* params: (Object.<string, *>|undefined),
* logo: (string|olx.LogoOptions|undefined),
* tileGrid: (ol.tilegrid.TileGrid|undefined),
* projection: ol.proj.ProjectionLike,
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
* url: (string|undefined),
* urls: (Array.<string>|undefined)}}
* @api
*/
olx.source.TileArcGISRestOptions;

/**
* Attributions.
* @type {Array.<ol.Attribution>|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.attributions;


/**
* ArcGIS Rest parameters. This field is optional. Service defaults will be
* used for any fields not specified. `FORMAT` is `PNG32` by default. `F` is `IMAGE` by
* default. `TRANSPARENT` is `true` by default. `BBOX, `SIZE`, `BBOXSR`,
* and `IMAGESR` will be set dynamically. Set `LAYERS` to
* override the default service layer visibility. See
* {@link http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Export_Map/02r3000000v7000000/}
* for further reference.
* @type {Object.<string,*>|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.params;


/**
* Logo.
* @type {string|olx.LogoOptions|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.logo;


/**
* Tile grid. Base this on the resolutions, tilesize and extent supported by the
* server.
* If this is not defined, a default grid will be used: if there is a projection
* extent, the grid will be based on that; if not, a grid based on a global
* extent with origin at 0,0 will be used.
* @type {ol.tilegrid.TileGrid|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.tileGrid;

/**
* Projection.
* @type {ol.proj.ProjectionLike}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.projection;


/**
* Optional function to load a tile given a URL.
* @type {ol.TileLoadFunctionType|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.tileLoadFunction;


/**
* ArcGIS Rest service URL for a Map Service or Image Service. The
* url should include /MapServer or /ImageServer.
* @type {string|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.url;


/**
* ArcGIS Rest service urls. Use this instead of `url` when the ArcGIS Service supports multiple
* urls for export requests.
* @type {Array.<string>|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.urls;


/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
Expand Down
218 changes: 218 additions & 0 deletions src/ol/source/tilearcgisrestsource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
goog.provide('ol.source.TileArcGISRest');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.uri.utils');
goog.require('ol');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.extent');
goog.require('ol.proj');
goog.require('ol.source.TileImage');
goog.require('ol.tilecoord');



/**
* @classdesc
* Layer source for tile data from ArcGIS Rest services. Map and Image
* Services are supported.
*
* For cached ArcGIS services, better performance is available using the
* {@link ol.source.XYZ} data source.
*
* @constructor
* @extends {ol.source.TileImage}
* @param {olx.source.TileArcGISRestOptions=} opt_options Tile ArcGIS Rest
* options.
* @api
*/
ol.source.TileArcGISRest = function(opt_options) {

var options = goog.isDef(opt_options) ? opt_options : {};

var params = goog.isDef(options.params) ? options.params : {};

goog.base(this, {
attributions: options.attributions,
logo: options.logo,
projection: options.projection,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
tileUrlFunction: goog.bind(this.tileUrlFunction_, this)
});

var urls = options.urls;
if (!goog.isDef(urls) && goog.isDef(options.url)) {
urls = ol.TileUrlFunction.expandUrl(options.url);
}

/**
* @private
* @type {!Array.<string>}
*/
this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];

/**
* @private
* @type {Object}
*/
this.params_ = params;

/**
* @private
* @type {ol.Extent}
*/
this.tmpExtent_ = ol.extent.createEmpty();

};
goog.inherits(ol.source.TileArcGISRest, ol.source.TileImage);


/**
* Get the user-provided params, i.e. those passed to the constructor through
* the "params" option, and possibly updated using the updateParams method.
* @return {Object} Params.
* @api
*/
ol.source.TileArcGISRest.prototype.getParams = function() {
return this.params_;
};


/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} tileSize Tile size.
* @param {ol.Extent} tileExtent Tile extent.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @param {Object} params Params.
* @return {string|undefined} Request URL.
* @private
*/
ol.source.TileArcGISRest.prototype.getRequestUrl_ =
function(tileCoord, tileSize, tileExtent,
pixelRatio, projection, params) {

var urls = this.urls_;
if (goog.array.isEmpty(urls)) {
return undefined;
}

// ArcGIS Server only wants the numeric portion of the projection ID.
var srid = projection.getCode().split(':').pop();

params['SIZE'] = tileSize + ',' + tileSize;
params['BBOX'] = tileExtent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;

var url;
if (urls.length == 1) {
url = urls[0];
} else {
var index = goog.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
url = urls[index];
}

if (!goog.string.endsWith(url, '/')) {
url = url + '/';
}

// If a MapServer, use export. If an ImageServer, use exportImage.
if (goog.string.endsWith(url, 'MapServer/')) {
url = url + 'export';
}
else if (goog.string.endsWith(url, 'ImageServer/')) {
url = url + 'exportImage';
}
else {
goog.asserts.fail('Unknown Rest Service', url);
}

return goog.uri.utils.appendParamsFromMap(url, params);
};


/**
* Return the URLs used for this ArcGIS source.
* @return {!Array.<string>} URLs.
* @api stable
*/
ol.source.TileArcGISRest.prototype.getUrls = function() {
return this.urls_;
};


/**
* @param {string|undefined} url URL.
* @api stable
*/
ol.source.TileArcGISRest.prototype.setUrl = function(url) {
var urls = goog.isDef(url) ? ol.TileUrlFunction.expandUrl(url) : null;
this.setUrls(urls);
};


/**
* @param {Array.<string>|undefined} urls URLs.
* @api stable
*/
ol.source.TileArcGISRest.prototype.setUrls = function(urls) {
this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];
this.changed();
};


/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
* @private
*/
ol.source.TileArcGISRest.prototype.tileUrlFunction_ =
function(tileCoord, pixelRatio, projection) {

var tileGrid = this.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = this.getTileGridForProjection(projection);
}

if (tileGrid.getResolutions().length <= tileCoord[0]) {
return undefined;
}

var tileExtent = tileGrid.getTileCoordExtent(
tileCoord, this.tmpExtent_);
var tileSize = tileGrid.getTileSize(tileCoord[0]);

if (pixelRatio != 1) {
tileSize = (tileSize * pixelRatio + 0.5) | 0;
}

// Apply default params and override with user specified values.
var baseParams = {
'F': 'image',
'FORMAT': 'PNG32',
'TRANSPARENT': true
};
goog.object.extend(baseParams, this.params_);

return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
pixelRatio, projection, baseParams);
};


/**
* Update the user-provided params.
* @param {Object} params Params.
* @api stable
*/
ol.source.TileArcGISRest.prototype.updateParams = function(params) {
goog.object.extend(this.params_, params);
this.changed();
};
Loading