Skip to content

Commit

Permalink
Merge pull request #67 from county-of-simcoe-gis/feature/imagearcgisrest
Browse files Browse the repository at this point in the history
Feature/imagearcgisrest
  • Loading branch information
jahow authored May 16, 2024
2 parents 2c306bc + 7bdc89a commit ff7137e
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 1 deletion.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,17 @@ Additional options for `GeoJSON` layer type.
| `geojson` | `object` | Feature collection in GeoJSON format; coordinates are expected to be in the print job reference system. |
| `style` | `object` | JSON object in geostyler notation, defining the layer style. |

#### `ImageArcGISRest layer` type

Additional options for `ImageArcGISRest` layer type.

| field | type | description |
|---|---|---|
| `hidpi` | `boolean` | Use the ol/Map#pixelRatio value when requesting the image from the remote server. |
| `interpolate` | `boolean` | Use interpolated values when resampling. Set to false to use the nearest neighbor instead. |
| `tiled` | `boolean` | Indicates whether the WMS layer should be requested as tiles. Defaults to `false`. |
| `params` | `object` | ArcGIS Rest parameters. This field is optional. |

#### `projectionDefinition` type

A `projectionDefinition` object describes a projection to be registered in proj4.
Expand Down
15 changes: 14 additions & 1 deletion src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,20 @@ export { downloadBlob } from './utils';
*/

/**
* @typedef {WmsLayer|XyzLayer|WmtsLayer|WfsLayer|GeoJSONLayer} Layer
* @typedef {Object} ImageArcGISRest
* @property {'ImageArcGISRest'} type
* @property {string} url URL for the service.
* @property {boolean} [hidpi=true] Use the ol/Map#pixelRatio value when requesting the image from the remote server.
* @property {boolean} [interpolate=true] Use interpolated values when resampling. By default, linear interpolation is used when resampling. Set to false to use the nearest neighbor instead.
* @property {Object} params 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 https://developers.arcgis.com/rest/services-reference/export-map.htm for further reference.
* @property {number} ratio Ratio. 1 means image requests are the size of the map viewport, 2 means twice the size of the map viewport, and so on. (defaults to 1.5)
* @property {number} opacity Opacity, from 0 (hidden) to 1 (visible).
* @property {string} [attribution] Attribution for the data used in the layer
* @property {boolean} [legend=false] Whether a legend should be created for this layer.
*/

/**
* @typedef {WmsLayer|XyzLayer|WmtsLayer|WfsLayer|GeoJSONLayer|ImageArcGISRest} Layer
*/

/**
Expand Down
77 changes: 77 additions & 0 deletions src/printer/layers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import GeoJSON from 'ol/format/GeoJSON';
import VectorSource from 'ol/source/Vector';
import ImageLayer from 'ol/layer/Image';
import VectorLayer from 'ol/layer/Vector';
import ImageArcGISRest from 'ol/source/ImageArcGISRest';
import { bbox } from 'ol/loadingstrategy';
import { createCanvasContext2D } from 'ol/dom';
import { BehaviorSubject, interval, merge, Subject } from 'rxjs';
Expand Down Expand Up @@ -60,6 +61,8 @@ export function createLayer(jobId, layerSpec, rootFrameState) {
return createLayerWFS(jobId, layerSpec, rootFrameState);
case 'GeoJSON':
return createLayerGeoJSON(layerSpec, rootFrameState);
case 'ImageArcGISRest':
return createLayerImageArcGISRest(jobId, layerSpec, rootFrameState);
}
}

Expand Down Expand Up @@ -461,3 +464,77 @@ function createLayerWFS(jobId, layerSpec, rootFrameState) {

return progress$;
}

/**
* @param {number} jobId
* @param {import('../main/index.js').ImageArcGISRest} layerSpec
* @param {import('ol/Map').FrameState} rootFrameState
* @return {import('rxjs').Observable<LayerPrintStatus>}
*/
function createLayerImageArcGISRest(jobId, layerSpec, rootFrameState) {
const width = rootFrameState.size[0];
const height = rootFrameState.size[1];
const context = createCanvasContext2D(width, height);
// @ts-ignore
context.canvas.style = {};
let frameState;
let layer;
let renderer;

const source = new ImageArcGISRest({
...layerSpec,
crossOrigin: 'anonymous',
});
/** @type {import('rxjs').BehaviorSubject<LayerPrintStatus>} */
const progress$ = new BehaviorSubject([0, null, undefined]);

layer = new ImageLayer({
source: source,
});
source.setImageLoadFunction(function (layerImage, src) {
/** @type {HTMLImageElement} */
const image = /** @type {any} */ (layerImage).getImage();

if (isWorker()) {
// @ts-ignore
image.hintImageSize(width, height);
}

const blankSrc =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
cancel$
.pipe(
filter((canceledJobId) => canceledJobId === jobId),
take(1),
tap(() => {
progress$.next([-1, null, undefined]);
progress$.complete();
image.src = blankSrc;
})
)
.subscribe();

image.src = src;
});

frameState = makeLayerFrameState(rootFrameState, layer, layerSpec.opacity);

renderer = layer.getRenderer();
// @ts-ignore
renderer.useContainer = useContainer.bind(renderer, context);

layer.getSource().once('imageloaderror', function (e) {
const imageLoadErrorUrl = e.target.getUrl();
progress$.next([1, context.canvas, imageLoadErrorUrl]);
progress$.complete();
});
layer.getSource().once('imageloadend', () => {
renderer.prepareFrame({ ...frameState, time: Date.now() });
renderer.renderFrame({ ...frameState, time: Date.now() }, context.canvas);
progress$.next([1, context.canvas, undefined]);
progress$.complete();
});
renderer.prepareFrame({ ...frameState, time: Date.now() });

return progress$;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions test/rendering/cases/11-imagearcgisrest/spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"layers": [
{
"type": "ImageArcGISRest",
"url": "https://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
"ratio": 1,
"params": {
"LAYERS": "SHOW:0"
}
}
],
"size": [256, 256],
"center": [12, 48],
"dpi": 50,
"scale": 40000000,
"projection": "EPSG:3857"
}

0 comments on commit ff7137e

Please sign in to comment.