Skip to content

Commit

Permalink
Merge pull request #15 from geoblocks/add_more_flexibility
Browse files Browse the repository at this point in the history
Add more flexibility
  • Loading branch information
ger-benjamin authored Feb 12, 2024
2 parents d1e6e9a + 367835d commit ecee2a2
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 38 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules/
lib/
docs/
*.tgz

/.idea
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @geoblocks/geoblocks changes

## 0.2.3
- Add utility functions.
- In `BaseCustomizer`, the printExtent can be now set and get/set are dedicated methods.
- `pdfA` (allow transparency) is now a spec.map optional param.
- spec.attributes are now partial and `datasource` attribute is removed.
- CreateSpecOptions accepts now every format.
- Add a timeout and manage errors on the `getDownloadUrl` utils function.

## v0.2.2
- Add optional MVTEncoder

## v0.2.0
- General refactor (rename classes / types)

Expand Down
10 changes: 5 additions & 5 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ document.querySelector('#print').addEventListener('click', async () => {
dpi: 254,
layout: layout,
format: 'pdf',
customAttributes: {},
customAttributes: {datasource: []},
customizer: customizer,
});

Expand All @@ -54,10 +54,10 @@ document.querySelector('#print').addEventListener('click', async () => {
document.location = url;
return url;
},
(err) => {
console.log('result', 'error', err);
resultEl.innerHTML = 'Error';
return err;
(error) => {
console.log('result', 'error', error);
resultEl.innerHTML = error;
return error;
},
);
});
17 changes: 10 additions & 7 deletions src/BaseCustomizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ import type {Feature as GeoJSONFeature} from 'geojson';
* It also defines the print extent.
*/
export default class BaseCustomizer {
readonly printExtent: number[];
private printExtent: number[];

/**
*
* @param printExtent The extent to print (useful for MVT / static image layers)
*/
constructor(printExtent: number[]) {
// FIXME: can not this be passed with the other options in createSpec?
constructor(printExtent?: number[]) {
this.setPrintExtent(printExtent || [0, 0, Infinity, Infinity]);
}

getPrintExtent(): number[] {
return this.printExtent;
}

setPrintExtent(printExtent: number[]) {
this.printExtent = printExtent;
}

Expand Down
15 changes: 6 additions & 9 deletions src/MFPEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface CreateSpecOptions {
printResolution: number;
dpi: number;
layout: string;
format: 'pdf' | 'jpg' | 'png';
format: string;
customAttributes: Record<string, any>;
customizer: BaseCustomizer;
}
Expand Down Expand Up @@ -80,7 +80,6 @@ export default class MFPBaseEncoder {
});
const attributes: MFPAttributes = {
map: mapSpec,
datasource: [],
};
Object.assign(attributes, options.customAttributes);

Expand All @@ -104,16 +103,14 @@ export default class MFPBaseEncoder {
const mapLayerGroup = options.map.getLayerGroup();
const layers = await this.encodeLayerGroup(mapLayerGroup, options.printResolution, options.customizer);

const spec = {
return {
center,
dpi: options.dpi,
pdfA: false,
projection,
rotation,
scale: options.scale,
layers,
} as MFPMap;
return spec;
};
}

/**
Expand Down Expand Up @@ -203,13 +200,13 @@ export default class MFPBaseEncoder {
const layer = layerState.layer as VectorTileLayer;
const {MVTEncoder} = await import('@geoblocks/print');
const encoder = new MVTEncoder();
const printExtent = customizer.printExtent;
const printExtent = customizer.getPrintExtent();
const width = getExtentWidth(printExtent) / printResolution;
const height = getExtentHeight(printExtent) / printResolution;
const canvasSize: [number, number] = [width, height];
const printOptions = {
layer,
printExtent: customizer.printExtent,
printExtent: customizer.getPrintExtent(),
tileResolution: printResolution,
styleResolution: printResolution,
canvasSize: canvasSize,
Expand Down Expand Up @@ -315,7 +312,7 @@ export default class MFPBaseEncoder {
additionalDraw: (cir: VectorContext, geometry: Geometry) => void,
): Promise<MFPImageLayer> {
const layer = layerState.layer as VectorLayer<VectorSource>;
const printExtent = customizer.printExtent;
const printExtent = customizer.getPrintExtent();
const width = getExtentWidth(printExtent) / resolution;
const height = getExtentHeight(printExtent) / resolution;
const size: [number, number] = [width, height];
Expand Down
2 changes: 1 addition & 1 deletion src/VectorEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default class VectorEncoder {
}
console.assert(source instanceof VectorSource);

const features = source.getFeaturesInExtent(this.customizer_.printExtent);
const features = source.getFeaturesInExtent(this.customizer_.getPrintExtent());

const geojsonFeatures: GeoJSONFeature[] = [];
const mapfishStyleObject: MFPVectorStyle = {
Expand Down
13 changes: 13 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const Constants = {
/** "Standardized rendering pixel size" is defined as 0.28 mm, see http://www.opengeospatial.org/standards/wmts */
WMTS_PIXEL_SIZE: 0.28e-3,
/** Standard DPI */
DOTS_PER_INCH: 72,
/** According to the "international yard" definition 1 inch is defined as exactly 2.54 cm. */
METERS_PER_INCH: 0.0254,
};

export const CalculatedConstants = {
/** Default to DPI / METERS per Inch */
DPI_PER_DISTANCE_UNIT: () => Constants.DOTS_PER_INCH / Constants.METERS_PER_INCH,
};
8 changes: 4 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,16 @@ export interface MFPMap {
projection: string;
rotation: number;
useNearestScale?: boolean;
/* Allow transparency property. Default to false */
pdfA?: boolean;
}

export interface MFPAttributes {
map: MFPMap;
// FIXME: I don't know what to put here
// See http://mapfish.github.io/mapfish-print-doc/attributes.html#!datasource
datasource: any[];
}

export interface MFPSpec {
attributes: MFPAttributes;
attributes: Partial<MFPAttributes>;
layout: string;
format: string;
smtp?: Record<string, string>;
Expand All @@ -150,6 +149,7 @@ export interface MFPStatusResponse {
done: boolean;
downloadURL: string;
elapsedTime: number;
error?: string;
status: string;
waitingTime: number;
}
49 changes: 43 additions & 6 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@ import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {toSize} from 'ol/size.js';
import type {MFPReportResponse, MFPSpec, MFPStatusResponse, MFPWmtsMatrix} from './types';
import type {WMTS} from 'ol/source.js';
import type {Extent} from 'ol/extent';
import {Constants, CalculatedConstants} from './constants';

// "Standardized rendering pixel size" is defined as 0.28 mm, see http://www.opengeospatial.org/standards/wmts
const WMTS_PIXEL_SIZE_ = 0.28e-3;
/**
* @param mapPageSize The page size in pixels (width, height)
* @param center The coordinate of the extent's center.
* @param scale The scale to calculate the extent width.
* @returns an extent that fit the page size. Calculated with DPI_PER_DISTANCE_UNIT (by default using meters)
*/
export function getPrintExtent(mapPageSize: number[], center: number[], scale: number): Extent {
const [mapPageWidthMeters, mapPageHeightMeters] = mapPageSize.map(
(side) => ((side / CalculatedConstants.DPI_PER_DISTANCE_UNIT()) * scale) / 2,
);
return [
center[0] - mapPageWidthMeters,
center[1] - mapPageHeightMeters,
center[0] + mapPageWidthMeters,
center[1] + mapPageHeightMeters,
];
}

/**
* Takes a hex value and prepends a zero if it's a single digit.
Expand Down Expand Up @@ -51,7 +68,7 @@ export function getWmtsMatrices(source: WMTS): MFPWmtsMatrix[] {
const resolutionMeters = tileGrid.getResolution(i) * metersPerUnit;
wmtsMatrices.push({
identifier: matrixIds[i],
scaleDenominator: resolutionMeters / WMTS_PIXEL_SIZE_,
scaleDenominator: resolutionMeters / Constants.WMTS_PIXEL_SIZE,
tileSize: toSize(tileGrid.getTileSize(i)),
topLeftCorner: tileGrid.getOrigin(i),
matrixSize: [tileRange.maxX - tileRange.minX, tileRange.maxY - tileRange.minY],
Expand Down Expand Up @@ -101,20 +118,40 @@ export async function requestReport(mfpBaseUrl: string, spec: MFPSpec): Promise<
return await report.json();
}

// FIXME: add timeout
// FIXME: handle errors
/**
* @param requestReport the name of the requested report
* @param response The initial print response.
* @param interval (s) the internal to poll the download url.
* @param timeout (s) A timeout for this operation.
* @returns a Promise with the download url once the document is printed or an error.
*/
export async function getDownloadUrl(
requestReport: string,
response: MFPReportResponse,
interval = 1000,
timeout = 30000,
): Promise<string> {
let totalDuration = 0 - interval;
return new Promise((resolve, reject) => {
const intervalId = setInterval(async () => {
const status = await getStatus(requestReport, response.ref);
let status: MFPStatusResponse | undefined;
try {
status = await getStatus(requestReport, response.ref);
if (status.error) {
throw new Error(status.error);
}
} catch (error) {
reject(error);
}
if (status.done) {
clearInterval(intervalId);
resolve(`${requestReport}/report/${response.ref}`);
}
totalDuration += interval;
if (totalDuration >= timeout) {
clearInterval(intervalId);
reject(new Error('Print duration exceeded'));
}
}, interval);
});
}
9 changes: 3 additions & 6 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,28 @@ test('Empty map', async (t) => {
dpi: 300,
layout: 'landscape_a4',
format: 'pdf',
customAttributes: {},
customAttributes: {title: 'My title'},
customizer: customizer,
});
assert.deepEqual(result, {
attributes: {
datasource: [],
map: {
center: [796612.417322277, 5836960.776101627],
dpi: 300,
layers: [],
pdfA: false,
projection: 'EPSG:3857',
rotation: 0,
scale: 1,
},
title: 'My title',
},
format: 'pdf',
layout: 'landscape_a4',
});
});

test('OSM map', async (t) => {
const MFP_URL = 'https://geomapfish-demo-2-5.camptocamp.com/printproxy';
const MFP_URL = 'https://geomapfish-demo-2-8.camptocamp.com/printproxy';
const layout = '1 A4 portrait'; // better take from MFP
const map = new Map({
target: 'map',
Expand Down Expand Up @@ -78,7 +77,6 @@ test('OSM map', async (t) => {

assert.deepEqual(spec, {
attributes: {
datasource: [],
map: {
center: [796612.417322277, 5836960.776101627],
dpi: 254,
Expand All @@ -90,7 +88,6 @@ test('OSM map', async (t) => {
type: 'osm',
},
],
pdfA: false,
projection: 'EPSG:3857',
rotation: 0,
scale: 1,
Expand Down

0 comments on commit ecee2a2

Please sign in to comment.