Skip to content

Commit

Permalink
Fixing extent densification (Canadian-Geospatial-Platform#2659)
Browse files Browse the repository at this point in the history
Fixing the reading of WMS extents from a GetCapabilities call
Added support for projection EPSG:4269 and 102100
Tweaking Drop-Down-Button styling
  • Loading branch information
Alex-NRCan authored Dec 13, 2024
1 parent e669a5a commit 654878e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 46 deletions.
31 changes: 14 additions & 17 deletions packages/geoview-core/src/geo/layer/gv-layers/raster/gv-wms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,6 @@ export class GVWMS extends AbstractGVRaster {
// TODO: Refactor - Layers refactoring. Remove the layerPath parameter once hybrid work is done
const layerConfig = this.getLayerConfig();

// Get the source projection
const sourceProjection = this.getOLSource().getProjection() || undefined;

// Get the layer config bounds
let layerConfigBounds = layerConfig?.initialSettings?.bounds;

Expand All @@ -577,8 +574,8 @@ export class GVWMS extends AbstractGVRaster {
layerConfigBounds = this.getMapViewer().convertExtentFromProjToMapProj(layerConfigBounds, 'EPSG:4326');
}

// Get the layer bounds from metadata
const metadataExtent = this.#getBoundsExtentFromMetadata(sourceProjection?.getCode() || '');
// Get the layer bounds from metadata, favoring a bounds in the same project as the map
const metadataExtent = this.#getBoundsExtentFromMetadata(this.getMapViewer().getProjection().getCode());

// If any
let layerBounds;
Expand Down Expand Up @@ -614,22 +611,22 @@ export class GVWMS extends AbstractGVRaster {
if (boundingBoxes) {
// Find the one with the right projection
for (let i = 0; i < (boundingBoxes.length as number); i++) {
if (boundingBoxes[i].crs === projection)
return [
boundingBoxes[i].crs as string,
// TODO: Check - Is it always in that order, 1, 0, 3, 2 or does that depend on the projection?
[boundingBoxes[i].extent[1], boundingBoxes[i].extent[0], boundingBoxes[i].extent[3], boundingBoxes[i].extent[2]] as Extent,
];
// Read the extent info from the GetCap
const { crs, extent } = boundingBoxes[i] as unknown as { crs: string; extent: Extent };

// If it's the crs we want
if (crs === projection) {
const extentSafe: Extent = Projection.readExtentCarefully(crs, extent);
return [crs, extentSafe];
}
}

// Not found. If any
// At this point, none could be found. If there's any to go with, we try our best...
if (boundingBoxes.length > 0) {
// Take the first one and return the bounds and projection
return [
boundingBoxes[0].crs as string,
// TODO: Check - Is it always in that order, 1, 0, 3, 2 or does that depend on the projection?
[boundingBoxes[0].extent[1], boundingBoxes[0].extent[0], boundingBoxes[0].extent[3], boundingBoxes[0].extent[2]] as Extent,
];
const { crs, extent } = boundingBoxes[0] as unknown as { crs: string; extent: Extent };
const extentSafe: Extent = Projection.readExtentCarefully(crs, extent);
return [crs, extentSafe];
}
}

Expand Down
13 changes: 9 additions & 4 deletions packages/geoview-core/src/geo/map/map-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ export class MapViewer {
// Minimum delay (in milliseconds) for map to be in loading state
static readonly #MIN_DELAY_LOADING = 2000;

// The default densification number when forming layer extents, to make ture to compensate for earth curvature
static DEFAULT_STOPS: number = 25;

// map config properties
mapFeaturesConfig: TypeMapFeaturesConfig;

Expand Down Expand Up @@ -1441,11 +1444,12 @@ export class MapViewer {
/**
* Transforms extent from LngLat to the current projection of the map.
* @param {Extent} extent - The LngLat extent
* @param {number} stops - The number of stops to perform densification on the extent
* @returns {Extent} The extent in the map projection
*/
convertExtentLngLatToMapProj(extent: Extent): Extent {
convertExtentLngLatToMapProj(extent: Extent, stops: number = MapViewer.DEFAULT_STOPS): Extent {
// Redirect
return this.convertExtentFromProjToMapProj(extent, Projection.PROJECTION_NAMES.LNGLAT);
return this.convertExtentFromProjToMapProj(extent, Projection.PROJECTION_NAMES.LNGLAT, stops);
}

/**
Expand Down Expand Up @@ -1494,12 +1498,13 @@ export class MapViewer {
* Transforms extent from given projection to the current projection of the map.
* @param {Extent} extent - The given extent
* @param {ProjectionLike} fromProj - The projection of the given extent
* @param {number} stops - The number of stops to perform densification on the extent
* @returns {Extent} The extent in the map projection
*/
convertExtentFromProjToMapProj(extent: Extent, fromProj: ProjectionLike): Extent {
convertExtentFromProjToMapProj(extent: Extent, fromProj: ProjectionLike, stops: number = MapViewer.DEFAULT_STOPS): Extent {
// If different projections
if (fromProj !== this.getProjection().getCode()) {
return Projection.transformExtentFromProj(extent, fromProj, this.getProjection());
return Projection.transformExtentFromProj(extent, fromProj, this.getProjection(), stops);
}

// Same projection
Expand Down
96 changes: 72 additions & 24 deletions packages/geoview-core/src/geo/utils/projection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { logger } from '@/core/utils/logger';
import { TypeJsonObject } from '@/core/types/global-types';

/**
* Class used to handle functions for trasforming projections
* Class used to handle functions for transforming projections
*
* @exports
* @class Projection
Expand All @@ -34,9 +34,11 @@ export abstract class Projection {
3578: 'EPSG:3578',
LCC: 'EPSG:3978',
3979: 'EPSG:3979',
102184: 'EPSG:102184', // TODO: Minor - This is technically supposed to be ESRI:102184, but more things would need to change in order to support this, works now
102190: 'EPSG:102190', // TODO: Minor - This is technically supposed to be ESRI:102190, but some things would need to change in order to support this, works now
102100: 'EPSG:102100', // TODO: Minor - The official name of this projection is ESRI:102100 (not EPSG:102100). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
102184: 'EPSG:102184', // TODO: Minor - The official name of this projection is ESRI:102184 (not EPSG:102184). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
102190: 'EPSG:102190', // TODO: Minor - The official name of this projection is ESRI:102190 (not EPSG:102190). However, for the purpose of simplification in GeoView code base, we name it with EPSG prefix.
WM: 'EPSG:3857',
4269: 'EPSG:4269',
LNGLAT: 'EPSG:4326',
CSRS: 'EPSG:4617',
CSRS98: 'EPSG:4140',
Expand Down Expand Up @@ -225,9 +227,14 @@ export abstract class Projection {
*/
static getProjectionFromObj(projection: TypeJsonObject | undefined): olProjection | undefined {
// If wkid
if (projection && projection.wkid) {
// Redirect
return Projection.getProjectionFromProj(`EPSG:${projection.wkid}`);
if (projection) {
if (projection.latestWkid) {
return Projection.getProjectionFromProj(`EPSG:${projection.latestWkid}`);
}
if (projection.wkid) {
// Redirect
return Projection.getProjectionFromProj(`EPSG:${projection.wkid}`);
}
}

// If wkt
Expand Down Expand Up @@ -289,11 +296,31 @@ export abstract class Projection {
static getResolution(projection: string, center: Coordinate): number {
return getPointResolution(projection, 1, center, 'm');
}

/**
* Reads an extent and verifies if it might be reversed (ymin,xmin,ymax,ymin) and when
* so puts it back in order (xmin,ymin,xmax,ymax).
* @param {string} projection The projection the extent is in
* @param {Extent} extent The extent to check
* @returns {Extent} The extent in order (xmin,ymin,xmax,ymax).
*/
static readExtentCarefully(projection: string, extent: Extent): Extent {
// Sometimes (e.g. with 4326, 4269, and others?) the extent coordinates might be in wrong order.
if (projection === 'EPSG:4326' || projection === 'EPSG:4269') {
// If any number in 1 and 3 position, as absolute, is greater than 90, it's reversed for sure
if (Math.abs(extent[1]) > 90 || Math.abs(extent[3]) > 90) {
// Careful!
return [extent[1], extent[0], extent[3], extent[2]];
}
}

// All good
return extent;
}
}

/**
* Initialize CRS84 Projection
* @private
* Initializes the CRS84 Projection
*/
function initCRS84Projection(): void {
const newDefinition = proj4.defs(Projection.PROJECTION_NAMES.LNGLAT);
Expand All @@ -306,17 +333,15 @@ function initCRS84Projection(): void {
}

/**
* Initialize WM Projection
* @private
* Initializes the WM Projection
*/
function initWMProjection(): void {
const projection = olGetProjection(Projection.PROJECTION_NAMES.WM);
if (projection) Projection.PROJECTIONS['3857'] = projection;
}

/**
* initialize LCC projection
* @private
* Initializes the LCC projection
*/
function initLCCProjection(): void {
// define 3978 projection
Expand All @@ -331,8 +356,7 @@ function initLCCProjection(): void {
}

/**
* initialize CSRS projection
* @private
* Initializes the CSRS projection
*/
function initCSRSProjection(): void {
// define 4617 projection
Expand All @@ -344,8 +368,7 @@ function initCSRSProjection(): void {
}

/**
* initialize CSRS98 projection
* @private
* Initializes the CSRS98 projection
*/
function initCSRS98Projection(): void {
// define 4140 projection
Expand All @@ -358,8 +381,7 @@ function initCSRS98Projection(): void {
}

/**
* initialize EPSG:3578 projection
* @private
* Initializes the EPSG:3578 projection
*/
function init3578Projection(): void {
proj4.defs(
Expand All @@ -374,8 +396,19 @@ function init3578Projection(): void {
}

/**
* initialize EPSG:3979 projection
* @private
* Initializes the EPSG:4269 projection
*/
function init4269Projection(): void {
proj4.defs(Projection.PROJECTION_NAMES[4269], '+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs +type=crs');
register(proj4);

const projection = olGetProjection(Projection.PROJECTION_NAMES[4269]);

if (projection) Projection.PROJECTIONS['4269'] = projection;
}

/**
* Initializes the EPSG:3979 projection
*/
function init3979Projection(): void {
proj4.defs(
Expand All @@ -390,8 +423,22 @@ function init3979Projection(): void {
}

/**
* initialize EPSG:102184 (ESRI:102184) projection
* @private
* Initializes the EPSG:102100 (ESRI:102100) projection
*/
function init102100Projection(): void {
proj4.defs(
Projection.PROJECTION_NAMES[102100],
'+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs'
);
register(proj4);

const projection = olGetProjection(Projection.PROJECTION_NAMES[102100]);

if (projection) Projection.PROJECTIONS['102100'] = projection;
}

/**
* Initializes the EPSG:102184 (ESRI:102184) projection
*/
function init102184Projection(): void {
proj4.defs(
Expand All @@ -406,8 +453,7 @@ function init102184Projection(): void {
}

/**
* initialize EPSG:102190 (ESRI:102190) projection
* @private
* Initializes the EPSG:102190 (ESRI:102190) projection
*/
function init102190Projection(): void {
proj4.defs(
Expand All @@ -429,6 +475,8 @@ initCSRSProjection();
initCSRS98Projection();
init3578Projection();
init3979Projection();
init4269Projection();
init102100Projection();
init102184Projection();
init102190Projection();
logger.logInfo('Projections initialized');
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export const getSxClasses = (theme: Theme): SxStyles => ({
buttonDropDown: {
display: 'flex',
fontSize: theme?.typography?.fontSize,
height: 50,
color: theme.palette.geoViewColor?.primary.dark,
backgroundColor: theme.palette.geoViewColor?.bgColor.dark[50],
},
buttonText: {},
buttonArrow: {
Expand Down

0 comments on commit 654878e

Please sign in to comment.