Skip to content

Commit f63a856

Browse files
committed
Add support for ArcGIS Rest Services
Adding a data source to support ArcGIS Map Server and Image Server. Functionality is similar to the ArcGIS93Rest Layer in OpenLayers 2.
1 parent 3fbc6fa commit f63a856

File tree

5 files changed

+626
-0
lines changed

5 files changed

+626
-0
lines changed

examples/arcgis-tiled.html

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="chrome=1">
6+
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
7+
<link rel="stylesheet" href="../css/ol.css" type="text/css">
8+
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
9+
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
10+
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
11+
<title>Tiled ArcGIS MapServer example</title>
12+
</head>
13+
<body>
14+
15+
<div class="navbar navbar-inverse navbar-fixed-top">
16+
<div class="navbar-inner">
17+
<div class="container">
18+
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
19+
</div>
20+
</div>
21+
</div>
22+
23+
<div class="container-fluid">
24+
25+
<div class="row-fluid">
26+
<div class="span12">
27+
<div id="map" class="map"></div>
28+
</div>
29+
</div>
30+
31+
<div class="row-fluid">
32+
33+
<div class="span12">
34+
<h4 id="title">Tiled ArcGIS MapServer example</h4>
35+
<p id="shortdesc">Example of a tiled ArcGIS layer.</p>
36+
<div id="docs">
37+
<p>See the <a href="arcgis-tiled.js" target="_blank">arcgis-tiled.js source</a> to see how this is done.</p>
38+
</div>
39+
<div id="tags">arcgis, tile, tilelayer</div>
40+
</div>
41+
42+
</div>
43+
44+
</div>
45+
46+
<script src="../resources/jquery.min.js" type="text/javascript"></script>
47+
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
48+
<script src="loader.js?id=arcgis-tiled" type="text/javascript"></script>
49+
50+
</body>
51+
</html>

examples/arcgis-tiled.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
goog.require('ol.Map');
2+
goog.require('ol.View');
3+
goog.require('ol.layer.Tile');
4+
goog.require('ol.source.MapQuest');
5+
goog.require('ol.source.TileArcGISRest');
6+
7+
var url = 'http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/' +
8+
'Specialty/ESRI_StateCityHighway_USA/MapServer';
9+
10+
var layers = [
11+
new ol.layer.Tile({
12+
source: new ol.source.MapQuest({layer: 'sat'})
13+
}),
14+
new ol.layer.Tile({
15+
extent: [-13884991, 2870341, -7455066, 6338219],
16+
source: new ol.source.TileArcGISRest({
17+
url: url
18+
})
19+
})
20+
];
21+
var map = new ol.Map({
22+
layers: layers,
23+
target: 'map',
24+
view: new ol.View({
25+
center: [-10997148, 4569099],
26+
zoom: 4
27+
})
28+
});

externs/olx.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4978,6 +4978,93 @@ olx.source.ServerVectorOptions.prototype.logo;
49784978
*/
49794979
olx.source.ServerVectorOptions.prototype.projection;
49804980

4981+
/**
4982+
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
4983+
* params: (Object.<string, *>|undefined),
4984+
* logo: (string|olx.LogoOptions|undefined),
4985+
* tileGrid: (ol.tilegrid.TileGrid|undefined),
4986+
* projection: ol.proj.ProjectionLike,
4987+
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
4988+
* url: (string|undefined),
4989+
* urls: (Array.<string>|undefined)}}
4990+
* @api
4991+
*/
4992+
olx.source.TileArcGISRestOptions;
4993+
4994+
/**
4995+
* Attributions.
4996+
* @type {Array.<ol.Attribution>|undefined}
4997+
* @api
4998+
*/
4999+
olx.source.TileArcGISRestOptions.prototype.attributions;
5000+
5001+
5002+
/**
5003+
* ArcGIS Rest parameters. This field is optional. Service defaults will be
5004+
* used for any fields not specified. `FORMAT` is `PNG32` by default. `F` is `IMAGE` by
5005+
* default. `TRANSPARENT` is `true` by default. `BBOX, `SIZE`, `BBOXSR`,
5006+
* and `IMAGESR` will be set dynamically. Set `LAYERS` to
5007+
* override the default service layer visibility. See
5008+
* {@link http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Export_Map/02r3000000v7000000/}
5009+
* for further reference.
5010+
* @type {Object.<string,*>|undefined}
5011+
* @api
5012+
*/
5013+
olx.source.TileArcGISRestOptions.prototype.params;
5014+
5015+
5016+
/**
5017+
* Logo.
5018+
* @type {string|olx.LogoOptions|undefined}
5019+
* @api
5020+
*/
5021+
olx.source.TileArcGISRestOptions.prototype.logo;
5022+
5023+
5024+
/**
5025+
* Tile grid. Base this on the resolutions, tilesize and extent supported by the
5026+
* server.
5027+
* If this is not defined, a default grid will be used: if there is a projection
5028+
* extent, the grid will be based on that; if not, a grid based on a global
5029+
* extent with origin at 0,0 will be used.
5030+
* @type {ol.tilegrid.TileGrid|undefined}
5031+
* @api
5032+
*/
5033+
olx.source.TileArcGISRestOptions.prototype.tileGrid;
5034+
5035+
/**
5036+
* Projection.
5037+
* @type {ol.proj.ProjectionLike}
5038+
* @api
5039+
*/
5040+
olx.source.TileArcGISRestOptions.prototype.projection;
5041+
5042+
5043+
/**
5044+
* Optional function to load a tile given a URL.
5045+
* @type {ol.TileLoadFunctionType|undefined}
5046+
* @api
5047+
*/
5048+
olx.source.TileArcGISRestOptions.prototype.tileLoadFunction;
5049+
5050+
5051+
/**
5052+
* ArcGIS Rest service URL for a Map Service or Image Service. The
5053+
* url should include /MapServer or /ImageServer.
5054+
* @type {string|undefined}
5055+
* @api
5056+
*/
5057+
olx.source.TileArcGISRestOptions.prototype.url;
5058+
5059+
5060+
/**
5061+
* ArcGIS Rest service urls. Use this instead of `url` when the ArcGIS Service supports multiple
5062+
* urls for export requests.
5063+
* @type {Array.<string>|undefined}
5064+
* @api
5065+
*/
5066+
olx.source.TileArcGISRestOptions.prototype.urls;
5067+
49815068

49825069
/**
49835070
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),

src/ol/source/tilearcgisrestsource.js

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
goog.provide('ol.source.TileArcGISRest');
2+
3+
goog.require('goog.array');
4+
goog.require('goog.asserts');
5+
goog.require('goog.math');
6+
goog.require('goog.object');
7+
goog.require('goog.string');
8+
goog.require('goog.uri.utils');
9+
goog.require('ol');
10+
goog.require('ol.TileCoord');
11+
goog.require('ol.TileUrlFunction');
12+
goog.require('ol.extent');
13+
goog.require('ol.proj');
14+
goog.require('ol.source.TileImage');
15+
goog.require('ol.tilecoord');
16+
17+
18+
19+
/**
20+
* @classdesc
21+
* Layer source for tile data from ArcGIS Rest services. Map and Image
22+
* Services are supported.
23+
*
24+
* For cached ArcGIS services, better performance is available using the
25+
* {@link ol.source.XYZ} data source.
26+
*
27+
* @constructor
28+
* @extends {ol.source.TileImage}
29+
* @param {olx.source.TileArcGISRestOptions=} opt_options Tile ArcGIS Rest
30+
* options.
31+
* @api
32+
*/
33+
ol.source.TileArcGISRest = function(opt_options) {
34+
35+
var options = goog.isDef(opt_options) ? opt_options : {};
36+
37+
var params = goog.isDef(options.params) ? options.params : {};
38+
39+
goog.base(this, {
40+
attributions: options.attributions,
41+
logo: options.logo,
42+
projection: options.projection,
43+
tileGrid: options.tileGrid,
44+
tileLoadFunction: options.tileLoadFunction,
45+
tileUrlFunction: goog.bind(this.tileUrlFunction_, this)
46+
});
47+
48+
var urls = options.urls;
49+
if (!goog.isDef(urls) && goog.isDef(options.url)) {
50+
urls = ol.TileUrlFunction.expandUrl(options.url);
51+
}
52+
53+
/**
54+
* @private
55+
* @type {!Array.<string>}
56+
*/
57+
this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];
58+
59+
/**
60+
* @private
61+
* @type {Object}
62+
*/
63+
this.params_ = params;
64+
65+
/**
66+
* @private
67+
* @type {ol.Extent}
68+
*/
69+
this.tmpExtent_ = ol.extent.createEmpty();
70+
71+
};
72+
goog.inherits(ol.source.TileArcGISRest, ol.source.TileImage);
73+
74+
75+
/**
76+
* Get the user-provided params, i.e. those passed to the constructor through
77+
* the "params" option, and possibly updated using the updateParams method.
78+
* @return {Object} Params.
79+
* @api
80+
*/
81+
ol.source.TileArcGISRest.prototype.getParams = function() {
82+
return this.params_;
83+
};
84+
85+
86+
/**
87+
* @param {ol.TileCoord} tileCoord Tile coordinate.
88+
* @param {number} tileSize Tile size.
89+
* @param {ol.Extent} tileExtent Tile extent.
90+
* @param {number} pixelRatio Pixel ratio.
91+
* @param {ol.proj.Projection} projection Projection.
92+
* @param {Object} params Params.
93+
* @return {string|undefined} Request URL.
94+
* @private
95+
*/
96+
ol.source.TileArcGISRest.prototype.getRequestUrl_ =
97+
function(tileCoord, tileSize, tileExtent,
98+
pixelRatio, projection, params) {
99+
100+
var urls = this.urls_;
101+
if (goog.array.isEmpty(urls)) {
102+
return undefined;
103+
}
104+
105+
// ArcGIS Server only wants the numeric portion of the projection ID.
106+
var srid = projection.getCode().split(':').pop();
107+
108+
params['SIZE'] = tileSize + ',' + tileSize;
109+
params['BBOX'] = tileExtent.join(',');
110+
params['BBOXSR'] = srid;
111+
params['IMAGESR'] = srid;
112+
113+
var url;
114+
if (urls.length == 1) {
115+
url = urls[0];
116+
} else {
117+
var index = goog.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
118+
url = urls[index];
119+
}
120+
121+
if (!goog.string.endsWith(url, '/')) {
122+
url = url + '/';
123+
}
124+
125+
// If a MapServer, use export. If an ImageServer, use exportImage.
126+
if (goog.string.endsWith(url, 'MapServer/')) {
127+
url = url + 'export';
128+
}
129+
else if (goog.string.endsWith(url, 'ImageServer/')) {
130+
url = url + 'exportImage';
131+
}
132+
else {
133+
goog.asserts.fail('Unknown Rest Service', url);
134+
}
135+
136+
return goog.uri.utils.appendParamsFromMap(url, params);
137+
};
138+
139+
140+
/**
141+
* Return the URLs used for this ArcGIS source.
142+
* @return {!Array.<string>} URLs.
143+
* @api stable
144+
*/
145+
ol.source.TileArcGISRest.prototype.getUrls = function() {
146+
return this.urls_;
147+
};
148+
149+
150+
/**
151+
* @param {string|undefined} url URL.
152+
* @api stable
153+
*/
154+
ol.source.TileArcGISRest.prototype.setUrl = function(url) {
155+
var urls = goog.isDef(url) ? ol.TileUrlFunction.expandUrl(url) : null;
156+
this.setUrls(urls);
157+
};
158+
159+
160+
/**
161+
* @param {Array.<string>|undefined} urls URLs.
162+
* @api stable
163+
*/
164+
ol.source.TileArcGISRest.prototype.setUrls = function(urls) {
165+
this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];
166+
this.changed();
167+
};
168+
169+
170+
/**
171+
* @param {ol.TileCoord} tileCoord Tile coordinate.
172+
* @param {number} pixelRatio Pixel ratio.
173+
* @param {ol.proj.Projection} projection Projection.
174+
* @return {string|undefined} Tile URL.
175+
* @private
176+
*/
177+
ol.source.TileArcGISRest.prototype.tileUrlFunction_ =
178+
function(tileCoord, pixelRatio, projection) {
179+
180+
var tileGrid = this.getTileGrid();
181+
if (goog.isNull(tileGrid)) {
182+
tileGrid = this.getTileGridForProjection(projection);
183+
}
184+
185+
if (tileGrid.getResolutions().length <= tileCoord[0]) {
186+
return undefined;
187+
}
188+
189+
var tileExtent = tileGrid.getTileCoordExtent(
190+
tileCoord, this.tmpExtent_);
191+
var tileSize = tileGrid.getTileSize(tileCoord[0]);
192+
193+
if (pixelRatio != 1) {
194+
tileSize = (tileSize * pixelRatio + 0.5) | 0;
195+
}
196+
197+
// Apply default params and override with user specified values.
198+
var baseParams = {
199+
'F': 'image',
200+
'FORMAT': 'PNG32',
201+
'TRANSPARENT': true
202+
};
203+
goog.object.extend(baseParams, this.params_);
204+
205+
return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
206+
pixelRatio, projection, baseParams);
207+
};
208+
209+
210+
/**
211+
* Update the user-provided params.
212+
* @param {Object} params Params.
213+
* @api stable
214+
*/
215+
ol.source.TileArcGISRest.prototype.updateParams = function(params) {
216+
goog.object.extend(this.params_, params);
217+
this.changed();
218+
};

0 commit comments

Comments
 (0)