Skip to content

Commit

Permalink
feat: handle out of bounds wgs84 coords
Browse files Browse the repository at this point in the history
  • Loading branch information
rgwozdz committed Mar 29, 2024
1 parent a66c255 commit dd5eaff
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 161 deletions.
4 changes: 2 additions & 2 deletions src/standardize-geometry-filter/clip-to-bounds.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { traverseCoordinates } from './traverse-coordinates';
import { transformCoordinates } from './traverse-coordinates';
import { Coordinates } from './common-types';
import { IEnvelope } from '@esri/arcgis-rest-types';

Expand All @@ -10,7 +10,7 @@ export function clipToEnvelope(coordinates: Coordinates , envelope: IEnvelope):
return [constrainNumber(lon, xmax, xmin), constrainNumber(lat, ymax, ymin)];
};

return traverseCoordinates(coordinates, repositionInvalidCoordinates);
return transformCoordinates(coordinates, repositionInvalidCoordinates);
}

function constrainNumber (num:number, max:number, min:number): number {
Expand Down
216 changes: 177 additions & 39 deletions src/standardize-geometry-filter/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
const { standardizeGeometryFilter } = require('./');
import { ISpatialReference } from '@esri/arcgis-rest-types';
import { standardizeGeometryFilter } from './';
import * as projCodes from '@esri/proj-codes';
import { GeometryFilter } from './common-types';

jest.mock('@esri/proj-codes', () => ({
__esModule: true,
// @ts-ignore
...jest.requireActual('@esri/proj-codes'),
}));

const mockLogger =
describe('standardizeGeometryFilter', () => {
afterAll(() => {
jest.resetAllMocks();
});
test('delimited point', () => {
const result = standardizeGeometryFilter({ geometry: '-123, 48' });
expect(result).toEqual({
Expand Down Expand Up @@ -132,7 +145,7 @@ describe('standardizeGeometryFilter', () => {
xmax: -122,
ymin: 48,
ymax: 49,
spatialReference: { wkid: 4326, latestWkid: 9999 },
spatialReference: { wkid: 4326 },
},
reprojectionSR: 3857,
});
Expand All @@ -157,15 +170,53 @@ describe('standardizeGeometryFilter', () => {
});
});

test('envelope object with unsupported spatial reference', () => {
try {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 49,
spatialReference: 'foo-bar' as unknown as ISpatialReference,
},
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Unsupported inSR format; must be a spatial reference ID or object',
);
}
});

test('envelope object with unsupported spatial reference wkt', () => {
try {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 49,
spatialReference: { wkt: 'foo-bar' },
},
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Spatial reference WKT is unparseable: "foo-bar"',
);
}
});

test('envelope object with unknown spatial reference', () => {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 49,
spatialReference: { wkid: 99999 },
},
inSR: 9999
});

expect(result).toEqual({
Expand All @@ -186,7 +237,7 @@ describe('standardizeGeometryFilter', () => {
});
});

test('envelope object with spatial reference and clip option', () => {
test('envelope object with WGS84 spatial reference and clip option', () => {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
Expand All @@ -195,7 +246,6 @@ describe('standardizeGeometryFilter', () => {
ymax: 95,
spatialReference: { wkid: 4326 },
},
clipToValidBounds: true,
});
expect(result).toEqual({
geometry: {
Expand Down Expand Up @@ -226,7 +276,6 @@ describe('standardizeGeometryFilter', () => {
ymin: 48,
ymax: 49,
},
clipToValidBounds: true,
});
expect(result).toEqual({
geometry: {
Expand Down Expand Up @@ -278,7 +327,46 @@ describe('standardizeGeometryFilter', () => {
});
});

test('envelope object with WKT spatial reference and clip option', () => {
test('envelope object with reprojection spatial reference, without source spatial reference', () => {
try {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 45,
ymax: 90,
},
reprojectionSR: 3857,
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Unknown geometry filter spatial reference; unable to reproject',
);
}
});

test('envelope object with unknown reprojection spatial reference', () => {
try {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 45,
ymax: 90,
},
inSR: 4326,
reprojectionSR: 99999,
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Unknown reprojection spatial reference; unable to reproject',
);
}
});

test('envelope object with WKT spatial reference', () => {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
Expand All @@ -289,7 +377,6 @@ describe('standardizeGeometryFilter', () => {
wkt: `GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]`,
},
},
clipToValidBounds: true,
});
expect(result).toEqual({
geometry: {
Expand All @@ -311,36 +398,6 @@ describe('standardizeGeometryFilter', () => {
});
});

test('envelope object with unknown spatial reference and clip option', () => {
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 49,
spatialReference: { wkid: 99999 },
},
clipToValidBounds: true,
});

expect(result).toEqual({
geometry: {
coordinates: [
[
[-122, 49],
[-123, 49],
[-123, 48],
[-122, 48],
[-122, 49],
],
],
type: 'Polygon',
},
relation: 'esriSpatialRelIntersects',
spatialReference: undefined,
});
});

test('geometry submitted as stringified JSON', () => {
const filter = {
geometry: JSON.stringify({
Expand Down Expand Up @@ -473,9 +530,90 @@ describe('standardizeGeometryFilter', () => {
});
});

test('envelope object with spatial reference that has no wkt will not reproject', () => {
jest.spyOn(projCodes, 'lookup').mockReturnValue({});

try {
standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 95,
},
inSR: 99999,
reprojectionSR: 3857,
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Unknown geometry filter spatial reference WKT; unable to reproject',
);
}
});

test('reprojection spatial reference that has no wkt will not reproject', () => {
jest
.spyOn(projCodes, 'lookup')
.mockReturnValueOnce({
wkt: `GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]`,
})
.mockReturnValueOnce({});

try {
standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 95,
spatialReference: { wkid: 4326 },
},
reprojectionSR: 3857,
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toBe(
'Unknown reprojection spatial reference WKT; unable to reproject',
);
}
});

test('envelope object with spatial reference that has no extent will not clip', () => {
jest.spyOn(projCodes, 'lookup').mockReturnValue({});
const result = standardizeGeometryFilter({
geometry: {
xmin: -123,
xmax: -122,
ymin: 48,
ymax: 95,
},
inSR: 99999
});

expect(result).toEqual({
geometry: {
coordinates: [
[
[-122, 95],
[-123, 95],
[-123, 48],
[-122, 48],
[-122, 95],
],
],
type: 'Polygon',
},
relation: 'esriSpatialRelIntersects',
spatialReference: { wkt: undefined, wkid: undefined },
});
});

test('unsupported filter format', () => {
try {
standardizeGeometryFilter({ geometry: { hello: 'world' } });
standardizeGeometryFilter({
geometry: { hello: 'world' } as unknown as GeometryFilter,
});
throw new Error('should have thrown');
} catch (error) {
expect(error.message).toEqual(
Expand Down
Loading

0 comments on commit dd5eaff

Please sign in to comment.