Skip to content

Commit

Permalink
Merge pull request #4208 from rldhont/fix-proj-axis-orientation-neu
Browse files Browse the repository at this point in the history
[Bugfix] JS: Axis orientation projection detection
  • Loading branch information
rldhont authored Feb 15, 2024
2 parents 9148c40 + a115c70 commit 52b897e
Show file tree
Hide file tree
Showing 9 changed files with 5,460 additions and 6 deletions.
60 changes: 54 additions & 6 deletions assets/src/modules/Lizmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import Permalink from './Permalink.js';
import Search from './Search.js';

import WMSCapabilities from 'ol/format/WMSCapabilities.js';
import { transform as transformOL, transformExtent as transformExtentOL, get as getProjection } from 'ol/proj.js';
import {intersects as extentIntersects} from 'ol/extent.js';
import { transform as transformOL, transformExtent as transformExtentOL, get as getProjection, clearAllProjections } from 'ol/proj.js';
import { register } from 'ol/proj/proj4.js';

import proj4 from 'proj4';
Expand All @@ -46,19 +47,66 @@ export default class Lizmap {
// The initialConfig has been cloned because it will be freezed
this._initialConfig = new Config(structuredClone(configs.initialConfig), wmsCapabilities);
this._state = new State(this._initialConfig, configs.startupFeatures);
},
toolbarcreated: () => {
this._lizmap3 = lizMap;

// Register projections if unknown
for (const [ref, def] of Object.entries(lizProj4)) {
if (ref !== "" && !getProjection(ref)) {
if (ref !== "" && !proj4.defs(ref)) {
proj4.defs(ref, def);
}
}

// Register project projection if unknown
const configProj = this._initialConfig.options.projection;
if (configProj.ref !== "" && !proj4.defs(configProj.ref)) {
proj4.defs(configProj.ref, configProj.proj4);
}
// About axis orientation https://proj.org/en/9.3/usage/projections.html#axis-orientation
// Add CRS:84 projection, same as EPSG:4326 but with ENU axis orientation
proj4.defs("CRS:84","+proj=longlat +datum=WGS84 +no_defs +type=crs");
register(proj4);
// Update project projection if its axis orientation is not ENU
if (configProj.ref !== "") {
// loop through bounding boxes of the project provided by WMS capabilities
for (const bbox of wmsCapabilities.Capability.Layer.BoundingBox) {
// If the BBOX CRS is not the same of the project projection, continue.
if (bbox.crs !== configProj.ref) {
continue;
}
// Get project projection
const projectProj = getProjection(configProj.ref);
// Check axis orientation, if it is not ENU, break, we don't have to do anything
if (projectProj.getAxisOrientation() !== 'enu') {
break;
}
// Transform geographic extent to project projection
const extent = transformExtentOL(wmsCapabilities.Capability.Layer.EX_GeographicBoundingBox, 'CRS:84', bbox.crs);
// Check closest coordinates
if (Math.abs(extent[0] - bbox.extent[1]) < Math.abs(extent[0] - bbox.extent[0])
&& Math.abs(extent[1] - bbox.extent[0]) < Math.abs(extent[1] - bbox.extent[1])
&& Math.abs(extent[2] - bbox.extent[3]) < Math.abs(extent[2] - bbox.extent[2])
&& Math.abs(extent[3] - bbox.extent[2]) < Math.abs(extent[3] - bbox.extent[3])) {
// If inverted axis are closest, we have to update the projection definition
proj4.defs(configProj.ref, configProj.proj4+' +axis=neu');
clearAllProjections();
register(proj4);
break;
}
// Transform extent from project projection to CRS:84
const geoExtent = transformExtentOL(bbox.extent, bbox.crs, 'CRS:84');
// Check intersects between transform extent and provided extent by WMS Capapbilities
if (!extentIntersects(geoExtent, wmsCapabilities.Capability.Layer.EX_GeographicBoundingBox)) {
// if extents do not intersect, we have to update the projection definition
proj4.defs(configProj.ref, configProj.proj4+' +axis=neu');
clearAllProjections();
register(proj4);
break;
}
}
}
},
toolbarcreated: () => {
this._lizmap3 = lizMap;

// Register projections if unknown
if (!getProjection(this.projection)) {
const proj = this.config.options.projection;
proj4.defs(proj.ref, proj.proj4);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ public function outputHeader($builder)
*/
public function outputFooter($builder)
{
// Since jelix 1.8.7, we need to add `deprecatedDeclareFormBeforeControls` builder option
// because in the `outputHeader` we defined `jFormsJQ.declareForm(jFormsJQ.tForm);`
// and we use `parent::outputFooter($builder);`
$builder->setOptions(
array(
'errorDecorator' => $builder->getOption('errorDecorator'),
'modal' => $builder->getOption('modal'),
'deprecatedDeclareFormBeforeControls' => true,
)
);
if ($builder->getOption('modal')) {
echo '</div>';
}
Expand Down
101 changes: 101 additions & 0 deletions tests/end2end/playwright/axis_orientation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// @ts-check
const { test, expect } = require('@playwright/test');

test.describe('Axis Orientation', () => {

test('Axis Orientation NEU for EPSG:3044', async ({ page }) => {
const url = '/index.php/view/map/?repository=testsrepository&project=axis_orientation_neu_3044';
await page.goto(url, { waitUntil: 'networkidle' });

const getMapPromise = page.waitForRequest(/GetMap/);
await page.getByLabel('Bundesländer').check();
const getMapRequest = await getMapPromise;
const getMapUrl = getMapRequest.url();
expect(getMapUrl).toContain('SERVICE=WMS');
expect(getMapUrl).toContain('VERSION=1.3.0');
expect(getMapUrl).toContain('REQUEST=GetMap');
expect(getMapUrl).toContain('FORMAT=image%2Fpng');
expect(getMapUrl).toContain('TRANSPARENT=true');
expect(getMapUrl).toContain('LAYERS=Bundeslander');
expect(getMapUrl).toContain('CRS=EPSG%3A3044');
expect(getMapUrl).toContain('STYLES=default');
expect(getMapUrl).toContain('WIDTH=958');
expect(getMapUrl).toContain('HEIGHT=633');
expect(getMapUrl).toMatch(/BBOX=5276843.28\d+%2C-14455.54\d+%2C6114251.21\d+%2C1252901.15\d+/);

const getMapResponse = await getMapRequest.response();
expect(getMapResponse).not.toBeNull();
expect(getMapResponse?.ok()).toBe(true);
expect(await getMapResponse?.headerValue('Content-Type')).toBe('image/png');
// image size greater than transparent
const contentLength = await getMapResponse?.headerValue('Content-Length');
expect(parseInt(contentLength ? contentLength : '0')).toBeGreaterThan(5552);


// Catch GetTile request;
let GetTiles = [];
await page.route('https://tile.openstreetmap.org/*/*/*.png', (route) => {
const request = route.request();
GetTiles.push(request.url());
}, {times: 6});

await page.locator('#switcher-baselayer').getByRole('combobox').selectOption('OpenStreetMap');
await page.waitForTimeout(1000);
expect(GetTiles).toHaveLength(6);
expect(GetTiles[0]).toContain('6/33/20.png')
expect(GetTiles[1]).toContain('6/33/21.png')
expect(GetTiles[2]).toContain('6/34/20.png')
expect(GetTiles[3]).toContain('6/34/21.png')
expect(GetTiles[4]).toContain('6/33/22.png')
expect(GetTiles[5]).toContain('6/34/22.png')
await page.unroute('https://tile.openstreetmap.org/*/*/*.png')
});

test('Axis Orientation NEU for EPSG:3844', async ({ page }) => {
const url = '/index.php/view/map/?repository=testsrepository&project=axis_orientation_neu_3844';
await page.goto(url, { waitUntil: 'networkidle' });

const getMapPromise = page.waitForRequest(/GetMap/);
await page.getByLabel('județ').check();
const getMapRequest = await getMapPromise;
const getMapUrl = getMapRequest.url();
expect(getMapUrl).toContain('SERVICE=WMS');
expect(getMapUrl).toContain('VERSION=1.3.0');
expect(getMapUrl).toContain('REQUEST=GetMap');
expect(getMapUrl).toContain('FORMAT=image%2Fpng');
expect(getMapUrl).toContain('TRANSPARENT=true');
expect(getMapUrl).toContain('LAYERS=judet');
expect(getMapUrl).toContain('CRS=EPSG%3A3844');
expect(getMapUrl).toContain('STYLES=default');
expect(getMapUrl).toContain('WIDTH=958');
expect(getMapUrl).toContain('HEIGHT=633');
expect(getMapUrl).toMatch(/BBOX=72126.00\d+%2C-122200.57\d+%2C909533.92\d+%2C1145156.12\d+/);

const getMapResponse = await getMapRequest.response();
expect(getMapResponse).not.toBeNull();
expect(getMapResponse?.ok()).toBe(true);
expect(await getMapResponse?.headerValue('Content-Type')).toBe('image/png');
// image size greater than transparent
const contentLength = await getMapResponse?.headerValue('Content-Length');
expect(parseInt(contentLength ? contentLength : '0')).toBeGreaterThan(5552);
// image size lesser than disorder axis
expect(parseInt(contentLength ? contentLength : '0')).toBeLessThan(240115);

// Catch GetTile request;
let GetTiles = [];
await page.route('https://tile.openstreetmap.org/*/*/*.png', (route) => {
const request = route.request();
GetTiles.push(request.url());
}, {times: 6});
await page.locator('#switcher-baselayer').getByRole('combobox').selectOption('OpenStreetMap');
await page.waitForTimeout(1000);
expect(GetTiles).toHaveLength(6);
expect(GetTiles[0]).toContain('6/35/22.png')
expect(GetTiles[1]).toContain('6/35/23.png')
expect(GetTiles[2]).toContain('6/36/22.png')
expect(GetTiles[3]).toContain('6/36/23.png')
expect(GetTiles[4]).toContain('6/37/22.png')
expect(GetTiles[5]).toContain('6/37/23.png')
await page.unroute('https://tile.openstreetmap.org/*/*/*.png')
});
});
Binary file not shown.
Loading

0 comments on commit 52b897e

Please sign in to comment.