Skip to content

Commit

Permalink
refacto(Crs): cleanup unit handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Desplandis committed Oct 18, 2024
1 parent 33c57e4 commit 553960b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 25 deletions.
45 changes: 21 additions & 24 deletions src/Core/Geographic/Crs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import proj4 from 'proj4';

import type { ProjectionDefinition } from 'proj4';

proj4.defs('EPSG:4978', '+proj=geocent +datum=WGS84 +units=m +no_defs');

/**
Expand Down Expand Up @@ -50,10 +52,14 @@ function isGeocentric(crs: ProjectionLike) {
return !projection ? false : projection.projName == 'geocent';
}

function _unitFromProj4Unit(projunit: string) {
if (projunit === 'degrees') {
function _unitFromProj4Unit(proj: ProjectionDefinition) {
if (proj.units === 'degrees') {
return UNIT.DEGREE;
} else if (projunit === 'm') {
} else if (proj.units === 'm') {
return UNIT.METER;
} else if (proj.units === undefined && proj.to_meter === undefined) {
// See https://proj.org/en/9.4/usage/projections.html [17/10/2024]
// > The default unit for projected coordinates is the meter.
return UNIT.METER;
} else {
return undefined;
Expand All @@ -62,26 +68,11 @@ function _unitFromProj4Unit(projunit: string) {

function toUnit(crs: ProjectionLike) {
mustBeString(crs);
switch (crs) {
case 'EPSG:4326' : return UNIT.DEGREE;
case 'EPSG:4978' : return UNIT.METER;
default: {
const p = proj4.defs(formatToEPSG(crs));
if (!p?.units) {
return undefined;
}
return _unitFromProj4Unit(p.units);
}
}
}

function toUnitWithError(crs: ProjectionLike) {
mustBeString(crs);
const u = toUnit(crs);
if (u === undefined) {
throw new Error(`No unit found for crs: '${crs}'`);
const p = proj4.defs(formatToEPSG(crs));
if (!p) {
return undefined;
}
return u;
return _unitFromProj4Unit(p);
}

/**
Expand All @@ -101,7 +92,13 @@ export default {
* @throws {@link Error} if the CRS is not valid.
*/
isValid(crs: ProjectionLike) {
toUnitWithError(crs);
const proj = proj4.defs(crs);
if (!proj) {
throw new Error(`Undefined crs '${crs}'. Add it with proj4.defs('${crs}', string)`);
}
if (!_unitFromProj4Unit(proj)) {
throw new Error(`No valid unit found for crs '${crs}', found ${proj.units}`);
}
},

/**
Expand All @@ -111,7 +108,7 @@ export default {
* @throws {@link Error} if the CRS is not valid.
*/
isGeographic(crs: ProjectionLike) {
return (toUnitWithError(crs) == UNIT.DEGREE);
return (toUnit(crs) == UNIT.DEGREE);
},

/**
Expand Down
2 changes: 1 addition & 1 deletion test/unit/crs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import proj4 from 'proj4';
import CRS from 'Core/Geographic/Crs';

proj4.defs('EPSG:7133', '+proj=longlat +ellps=GRS80 +no_defs +units=degrees');
proj4.defs('EPSG:INVALID', '+no_defs');
proj4.defs('EPSG:INVALID', '+units=invalid +no_defs');

describe('CRS assertions', function () {
it('should assert that the CRS is valid', function () {
Expand Down

0 comments on commit 553960b

Please sign in to comment.