Skip to content
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

[Backport release_3_8] JS Map State: transform initial extent on projection changes #4808

Merged
merged 2 commits into from
Sep 27, 2024
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
25 changes: 20 additions & 5 deletions assets/src/modules/state/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { convertNumber, convertBoolean } from './../utils/Converters.js';
import { Extent } from './../utils/Extent.js';
import { OptionsConfig } from './../config/Options.js';
import Utils from './../Utils.js';
import { get as getProjection } from 'ol/proj.js';
import { get as getProjection, transformExtent } from 'ol/proj.js';

/**
* Build scales
Expand Down Expand Up @@ -153,10 +153,7 @@ export class MapState extends EventDispatcher {
this._maxZoom = this._scales.length - 1;
this._projection = options.projection.ref;
this._initialExtent = new Extent(...(options.initialExtent));
this._center = [
this._initialExtent.xmin + (this._initialExtent.xmax-this._initialExtent.xmin)/2,
this._initialExtent.ymin + (this._initialExtent.ymax-this._initialExtent.ymin)/2
];
this._center = this._initialExtent.center;
}

this._startupFeatures = startupFeatures;
Expand All @@ -178,6 +175,7 @@ export class MapState extends EventDispatcher {
* @fires MapState#map.state.changed
*/
update(evt) {
const oldProjection = this._projection;
let updatedProperties = {};
for (const prop in mapStateProperties) {
if (evt.hasOwnProperty(prop)) {
Expand Down Expand Up @@ -229,6 +227,23 @@ export class MapState extends EventDispatcher {
}
}
}

// If projection has changed some extents have to be updated
if (updatedProperties.hasOwnProperty('projection') && oldProjection && updatedProperties['projection']) {
const newProjection = updatedProperties['projection']
// The initial extent
if (this._initialExtent && !this._initialExtent.equals([0,0,0,0])) {
this._initialExtent = new Extent(...(transformExtent(this._initialExtent, oldProjection, newProjection)));
}
// The extent if it has not been yet updated
if (!updatedProperties.hasOwnProperty('extent') && this._extent && !this._extent.equals([0,0,0,0])) {
this._extent = new Extent(...(transformExtent(this._extent, oldProjection, newProjection)));
this._center = this._extent.center;
updatedProperties['extent'] = new Extent(...this._extent);
updatedProperties['center'] = [...this.center];
}
}

// Dispatch event only if something have changed
if (Object.getOwnPropertyNames(updatedProperties).length != 0) {
const neededProperties = ['center', 'size', 'extent', 'resolution'];
Expand Down
11 changes: 11 additions & 0 deletions assets/src/modules/utils/Extent.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ export class Extent extends Array {
return this[3];
}

/**
* @type {number[]}
*/
get center() {
return [
this.xmin + (this.xmax-this.xmin)/2,
this.ymin + (this.ymax-this.ymin)/2
];
}

/**
* Checks equality with an other extent or array
* @param {Extent|Array} anOther - An other extent or array with 4 values
Expand All @@ -76,4 +86,5 @@ export class Extent extends Array {
&& anOther[2] == this[2]
&& anOther[3] == this[3])
}

}
159 changes: 159 additions & 0 deletions tests/js-units/node/state/map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,165 @@ describe('MapState', function () {
expect(mapStateChangedEvt).to.be.null // event not dispatch
})

it('Transform', function () {
let mapState = new MapState();
expect(mapState).to.be.instanceOf(MapState)
expect(mapState).to.be.instanceOf(EventDispatcher)

// Update all properties
mapState.update({
"type": "map.state.changing",
"projection": "EPSG:3857",
"center": [
432082.33132450003,
5404877.667855
],
"zoom": 4,
"size": [
1822,
634
],
"extent": [
397265.26494544884,
5392762.398873487,
466899.3977035512,
5416992.936836514
],
"resolution": 38.218514137268066,
"scaleDenominator": 144447.63855208742,
"pointResolution": 27.673393466176645,
"pointScaleDenominator": 104592.14407328397
});

let mapStateChangedEvt = null

mapState.addListener(evt => {
mapStateChangedEvt = evt
}, 'map.state.changed');

// update projection
mapState.update({
"type": "map.state.changing",
"projection": "EPSG:4326"
});

expect(mapState.projection).to.be.eq('EPSG:4326')
expect(mapState.center).to.be.an('array').that.have.lengthOf(2).that.deep.equal([
3.881461622267935,
43.60729361373798
])
expect(mapState.extent).to.be.instanceOf(Extent).that.have.lengthOf(4).that.deep.equal([
3.568694593502878,
43.52848921560505,
4.194228651032991,
43.68609801187091,
])

expect(mapStateChangedEvt).to.not.be.null // event dispatch
expect(mapStateChangedEvt.projection).to.be.eq('EPSG:4326') // the projection has not changed
expect(mapStateChangedEvt.center).to.be.an('array').that.have.lengthOf(2).that.deep.equal([
3.881461622267935,
43.60729361373798
])
expect(mapStateChangedEvt.extent).to.be.an('array').that.have.lengthOf(4).that.deep.equal([
3.568694593502878,
43.52848921560505,
4.194228651032991,
43.68609801187091,
])


const opt = new OptionsConfig({
"projection": {
"proj4": "+proj=longlat +datum=WGS84 +no_defs",
"ref": "EPSG:4326"
},
"bbox": [
"-3.5",
"-1.0",
"3.5",
"1.0"
],
"mapScales": [
10000,
25000,
50000,
100000,
250000,
500000
],
"minScale": 10000,
"maxScale": 500000,
"initialExtent": [
-3.5,
-1.0,
3.5,
1.0
],
"popupLocation": "dock",
"pointTolerance": 25,
"lineTolerance": 10,
"polygonTolerance": 5,
"hideProject": "True",
"tmTimeFrameSize": 10,
"tmTimeFrameType": "seconds",
"tmAnimationFrameLength": 1000,
"datavizLocation": "dock",
"theme": "light",
//"wmsMaxHeight": 3000,
//"wmsMaxWidth": 3000,
//"fixed_scale_overview_map": true,
//"use_native_zoom_levels": false,
//"hide_numeric_scale_value": false,
//"hideGroupCheckbox": false,
//"activateFirstMapTheme": false,
})
mapState = new MapState(opt);

// Initial state
expect(mapState.projection).to.be.eq('EPSG:4326')
expect(mapState.center).to.be.an('array').that.have.lengthOf(2).that.deep.equal([
0,
0
])
expect(mapState.extent).to.be.instanceOf(Extent).that.have.lengthOf(4).that.deep.equal([
0,
0,
0,
0
])
expect(mapState.initialExtent).to.be.instanceOf(Extent).that.have.lengthOf(4).that.deep.equal([
-3.5,
-1.0,
3.5,
1.0
])

// update projection
mapState.update({
"type": "map.state.changing",
"projection": "EPSG:3857"
});

expect(mapState.projection).to.be.eq('EPSG:3857')
expect(mapState.center).to.be.an('array').that.have.lengthOf(2).that.deep.equal([
0,
0
])
expect(mapState.extent).to.be.instanceOf(Extent).that.have.lengthOf(4).that.deep.equal([
0,
0,
0,
0
])
expect(mapState.initialExtent).to.be.instanceOf(Extent).that.have.lengthOf(4).that.deep.equal([
-389618.21777645755,
-111325.14286638453,
389618.21777645755,
111325.14286638486,
])
})

it('ConversionError && ValidationError', function () {
let mapState = new MapState();
expect(mapState).to.be.instanceOf(MapState)
Expand Down
3 changes: 3 additions & 0 deletions tests/js-units/node/utils/extent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('Extent', function () {
expect(ext.ymin).to.be.eq(-1)
expect(ext.xmax).to.be.eq(1)
expect(ext.ymax).to.be.eq(1)
expect(ext.center).to.be.deep.eq([0, 0])

ext = new Extent('-2','-2.0','2','2.0')
expect(ext.length).to.be.eq(4)
Expand All @@ -26,6 +27,7 @@ describe('Extent', function () {
expect(ext.ymin).to.be.eq(-2)
expect(ext.xmax).to.be.eq(2)
expect(ext.ymax).to.be.eq(2)
expect(ext.center).to.be.deep.eq([0, 0])

ext = new Extent(...[-1,-1,1,1])
expect(ext.length).to.be.eq(4)
Expand All @@ -37,6 +39,7 @@ describe('Extent', function () {
expect(ext.ymin).to.be.eq(-1)
expect(ext.xmax).to.be.eq(1)
expect(ext.ymax).to.be.eq(1)
expect(ext.center).to.be.deep.eq([0, 0])
})

it('Equals', function () {
Expand Down
Loading