UNPKG

@itwin/core-backend

Version:
876 lines • 49.8 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert } from "chai"; import { Helmert2DWithZOffset, } from "@itwin/core-common"; import { IModelNative } from "../../internal/NativePlatform"; import { Geometry, Point3d, Range2d } from "@itwin/core-geometry"; import { GeoCoordConfig } from "../../GeoCoordConfig"; import { getAvailableCoordinateReferenceSystems } from "../../GeographicCRSServices"; // spell-checker: disable describe("GeoServices", () => { before(() => { GeoCoordConfig.loadDefaultDatabases(); }); const completionTest = async (incompleteGCS, completeCRS) => { const requestProps = { format: "JSON", geographicCRSDef: JSON.stringify(incompleteGCS) }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); assert.isTrue(response.status === 0); assert.isTrue(response.geographicCRS !== undefined); if (response.geographicCRS !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS !== undefined && completeCRS.horizontalCRS !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.id === completeCRS.horizontalCRS.id); assert.isTrue(response.geographicCRS.horizontalCRS.projection !== undefined && completeCRS.horizontalCRS.projection !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.projection.method === completeCRS.horizontalCRS.projection.method); if (completeCRS.horizontalCRS.projection.falseEasting !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS.projection.falseEasting !== undefined); assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS.projection.falseEasting - completeCRS.horizontalCRS.projection.falseEasting) < Geometry.smallMetricDistance); } if (completeCRS.horizontalCRS.projection.falseNorthing !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS.projection.falseNorthing !== undefined); assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS.projection.falseNorthing - completeCRS.horizontalCRS.projection.falseNorthing) < Geometry.smallMetricDistance); } assert.isTrue(response.geographicCRS.horizontalCRS.datum !== undefined && completeCRS.horizontalCRS.datum !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.datum.id === completeCRS.horizontalCRS.datum.id); assert.isTrue(response.geographicCRS.horizontalCRS.datum.ellipsoid !== undefined && completeCRS.horizontalCRS.datum.ellipsoid !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.datum.ellipsoid.id === completeCRS.horizontalCRS.datum.ellipsoid.id); if (response.geographicCRS.additionalTransform !== undefined) { assert.isTrue(completeCRS.additionalTransform !== undefined); assert.isTrue(response.geographicCRS.additionalTransform.helmert2DWithZOffset !== undefined); assert.isTrue(completeCRS.additionalTransform.helmert2DWithZOffset !== undefined); assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset.rotDeg - completeCRS.additionalTransform.helmert2DWithZOffset.rotDeg) < Geometry.smallAngleDegrees); assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset.translationX - completeCRS.additionalTransform.helmert2DWithZOffset.translationX) < Geometry.smallMetricDistance); assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset.translationY - completeCRS.additionalTransform.helmert2DWithZOffset.translationY) < Geometry.smallMetricDistance); assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset.translationZ - completeCRS.additionalTransform.helmert2DWithZOffset.translationZ) < Geometry.smallMetricDistance); assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset.scale - completeCRS.additionalTransform.helmert2DWithZOffset.scale) < Geometry.smallFraction); } assert.isTrue(response.geographicCRS.verticalCRS !== undefined && completeCRS.verticalCRS !== undefined); assert.isTrue(response.geographicCRS.verticalCRS.id === completeCRS.verticalCRS.id); } }; describe("Interpret to completion an incomplete GeographicCRS", async () => { it("should be able to interpret to completion britishNationalGridOld", async () => { const britishNationalGridOld = { horizontalCRS: { datum: { deprecated: true, description: "OSGB36 - Use OSGB-7P-2. Consider OSGB/OSTN15 instead", ellipsoid: { description: "Airy 1830", equatorialRadius: 6377563.396, id: "EPSG:7001", polarRadius: 6356256.909237, source: "EPSG, Version 6 [EPSG]", }, ellipsoidId: "EPSG:7001", id: "EPSG:6277", source: "EPSG V6.12 operation EPSG:1314 [EPSG]", transforms: [ { method: "PositionalVector", positionalVector: { delta: { x: 446.448, y: -125.157, z: 542.06, }, rotation: { x: 0.15, y: 0.247, z: 0.842, }, scalePPM: -20.489, }, sourceEllipsoid: { equatorialRadius: 6377563.396, id: "EPSG:7001", polarRadius: 6356256.909237, }, targetEllipsoid: { equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, }, } ], }, datumId: "EPSG:6277", deprecated: true, description: "Use other variant - OSGB British National Grid", extent: { northEast: { latitude: 60.84, longitude: 1.78, }, southWest: { latitude: 49.96, longitude: -7.56, }, }, id: "EPSG:27700", projection: { centralMeridian: -2, falseEasting: 400000, falseNorthing: -100000, latitudeOfOrigin: 49, method: "TransverseMercator", scaleFactor: 0.999601272737422, }, source: "EPSG", unit: "Meter", }, verticalCRS: { id: "ELLIPSOID", }, }; await completionTest({ horizontalCRS: { id: "EPSG:27700" }, verticalCRS: { id: "ELLIPSOID" } }, britishNationalGridOld); }); it("should be able to interpret to completion EWRGCS", async () => { const EWRGCS = { horizontalCRS: { id: "EPSG:27700", description: "OSGB 1936 / British National Grid", source: "EPSG V6 [Large and medium scale topographic mapping and engin]", datumId: "EPSG:6277", datum: { id: "EPSG:6277", description: "OSGB36 - Use OSGB-7P-2. Consider OSGB/OSTN15 instead", deprecated: true, source: "EPSG V6.12 operation EPSG:1314 [EPSG]", ellipsoidId: "EPSG:7001", ellipsoid: { equatorialRadius: 6377563.396, polarRadius: 6356256.909237, id: "EPSG:7001", description: "Airy 1830", source: "EPSG, Version 6 [EPSG]", }, transforms: [ { method: "PositionalVector", sourceEllipsoid: { equatorialRadius: 6377563.396, polarRadius: 6356256.909237, id: "EPSG:7001", }, targetEllipsoid: { equatorialRadius: 6378137, polarRadius: 6356752.3142, id: "WGS84", }, positionalVector: { delta: { x: 446.448, y: -125.157, z: 542.06, }, rotation: { x: 0.15, y: 0.247, z: 0.842, }, scalePPM: -20.489, }, } ], }, unit: "Meter", projection: { method: "TransverseMercator", falseEasting: 400000, falseNorthing: -100000, centralMeridian: -2, latitudeOfOrigin: 49, scaleFactor: 0.999601272737422, }, extent: { southWest: { latitude: 49.96, longitude: -7.56, }, northEast: { latitude: 60.84, longitude: 1.78, }, }, }, verticalCRS: { id: "ELLIPSOID", }, additionalTransform: { helmert2DWithZOffset: { translationX: 284597.3343, translationY: 79859.4651, translationZ: 0, rotDeg: 0.5263624458992088, scale: 0.9996703340508721, }, }, }; await completionTest({ horizontalCRS: { id: "EPSG:27700" }, verticalCRS: { id: "ELLIPSOID" }, additionalTransform: { helmert2DWithZOffset: { translationX: 284597.3343, translationY: 79859.4651, translationZ: 0, rotDeg: 0.5263624458992088, scale: 0.9996703340508721 } } }, EWRGCS); }); it("should be able to interpret to completion UTM27Z10", async () => { const UTM27Z10 = { horizontalCRS: { datum: { description: "North American Datum of 1927 (US48, AK, HI, and Canada)", ellipsoid: { description: "Clarke 1866, Benoit Ratio", epsg: 7008, equatorialRadius: 6378206.4, id: "CLRK66", polarRadius: 6356583.8, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "CLRK66", epsg: 6267, id: "NAD27", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { gridFile: { files: [ { direction: "Direct", fileName: "./Usa/Nadcon/conus.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/alaska.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/prvi.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/hawaii.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stgeorge.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stlrnc.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stpaul.l?s", format: "NADCON", } ], }, method: "GridFiles", sourceEllipsoid: { equatorialRadius: 6378206.4, id: "CLRK66", polarRadius: 6356583.8, }, targetEllipsoid: { equatorialRadius: 6378137, id: "GRS1980", polarRadius: 6356752.314140348, }, } ], }, datumId: "NAD27", description: "UTM with NAD27 datum, Zone 10, Meter; Central Meridian 123d W", epsg: 26710, extent: { northEast: { latitude: 84, longitude: -119.5, }, southWest: { latitude: -1, longitude: -126.5, }, }, id: "UTM27-10", projection: { hemisphere: "North", method: "UniversalTransverseMercator", zoneNumber: 10, }, source: "Snyder, J.P, 1987, Map Projections - A Working Manual", unit: "Meter", }, verticalCRS: { id: "NGVD29", }, }; await completionTest({ horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "NGVD29" } }, UTM27Z10); }); it("should be able to interpret to completion UTM27Z10B", async () => { const UTM27Z10B = { horizontalCRS: { datum: { description: "North American Datum of 1927 (US48, AK, HI, and Canada)", ellipsoid: { description: "Clarke 1866, Benoit Ratio", epsg: 7008, equatorialRadius: 6378206.4, id: "CLRK66", polarRadius: 6356583.8, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "CLRK66", epsg: 6267, id: "NAD27", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { gridFile: { files: [ { direction: "Direct", fileName: "./Usa/Nadcon/conus.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/alaska.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/prvi.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/hawaii.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stgeorge.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stlrnc.l?s", format: "NADCON", }, { direction: "Direct", fileName: "./Usa/Nadcon/stpaul.l?s", format: "NADCON", }, ], }, method: "GridFiles", sourceEllipsoid: { equatorialRadius: 6378206.4, id: "CLRK66", polarRadius: 6356583.8, }, targetEllipsoid: { equatorialRadius: 6378137, id: "GRS1980", polarRadius: 6356752.314140348, }, }, ], }, datumId: "NAD27", description: "NAD27 / UTM zone 10N", epsg: 26710, extent: { northEast: { latitude: 77, longitude: -120, }, southWest: { latitude: 34.4, longitude: -126, }, }, id: "EPSG:26710", projection: { centralMeridian: -123, falseEasting: 500000, falseNorthing: 0, latitudeOfOrigin: 0, method: "TransverseMercator", scaleFactor: 0.9996, }, source: "EPSG V6 [Large and medium scale topographic mapping and engin]", unit: "Meter", }, verticalCRS: { id: "NGVD29", }, }; await completionTest({ horizontalCRS: { epsg: 26710 }, verticalCRS: { id: "NGVD29" } }, UTM27Z10B); }); }); describe("Interpretation of WKT GeographicCRS", async () => { const interpretWKTTest = async (testWKT, completeCRS) => { const requestProps = { format: "WKT", geographicCRSDef: testWKT }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); assert.isTrue(response.status === 0); assert.isTrue(response.geographicCRS !== undefined); if (response.geographicCRS !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS !== undefined && completeCRS.horizontalCRS !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.id === completeCRS.horizontalCRS.id); assert.isTrue(response.geographicCRS.horizontalCRS.projection !== undefined && completeCRS.horizontalCRS.projection !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.projection.method === completeCRS.horizontalCRS.projection.method); if (completeCRS.horizontalCRS.projection.falseEasting !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS.projection.falseEasting !== undefined); assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS.projection.falseEasting - completeCRS.horizontalCRS.projection.falseEasting) < Geometry.smallMetricDistance); } if (completeCRS.horizontalCRS.projection.falseNorthing !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS.projection.falseNorthing !== undefined); assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS.projection.falseNorthing - completeCRS.horizontalCRS.projection.falseNorthing) < Geometry.smallMetricDistance); } assert.isTrue(response.geographicCRS.horizontalCRS.datum !== undefined && completeCRS.horizontalCRS.datum !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.datum.id === completeCRS.horizontalCRS.datum.id); assert.isTrue(response.geographicCRS.horizontalCRS.datum.ellipsoid !== undefined && completeCRS.horizontalCRS.datum.ellipsoid !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS.datum.ellipsoid.id === completeCRS.horizontalCRS.datum.ellipsoid.id); assert.isTrue(response.geographicCRS.verticalCRS !== undefined && completeCRS.verticalCRS !== undefined); assert.isTrue(response.geographicCRS.verticalCRS.id === completeCRS.verticalCRS.id); // WKTs cannot define an additional transform assert.isTrue(response.geographicCRS.additionalTransform === undefined); } }; it("should be able to interpret airportGrid2007 WKT", async () => { const airportGrid2007 = { horizontalCRS: { datum: { description: "Heathrow T5 Datum", ellipsoid: { description: "Airy, 1830", epsg: 7001, equatorialRadius: 6377563.396, id: "AIRY30", polarRadius: 6356256.909, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "AIRY30", id: "HeathrowT5", source: "Bentley Client", transforms: [ { method: "PositionalVector", positionalVector: { delta: { x: 358.398212181898, y: -213.702844870731, z: 495.318319769716, }, rotation: { x: 668.806139320047, y: -4.72664217602752, z: 719.671097181396, }, scalePPM: -6.26386076385543, }, sourceEllipsoid: { equatorialRadius: 6377563.396, id: "AIRY30", polarRadius: 6356256.909, }, targetEllipsoid: { equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, }, }, ], }, datumId: "HeathrowT5", description: "AirportGrid2007", id: "AirportGrid2007", projection: { centralMeridian: -0.41832591666666674, falseEasting: 7334.81, falseNorthing: 5637.423, latitudeOfOrigin: 51.47011065555556, method: "TransverseMercator", scaleFactor: 0.999995, }, source: "WKT", unit: "Meter", }, verticalCRS: { id: "ELLIPSOID", }, }; await interpretWKTTest('PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",DATUM["Heathrow T5", SPHEROID["AIRY30",6377563.396,299.32496127],358.398,-213.7028,495.3183,-668.80613932004700,4.72664217602752,-719.67109718139600,-6.26386076385543],PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],PROJECTION["Transverse Mercator"],PARAMETER["latitude_of_origin",51.470110655555558],PARAMETER["central_meridian",-0.41832591666666669],PARAMETER["scale_factor",0.999995],PARAMETER["false_easting",7334.810],PARAMETER["false_northing",5637.423],UNIT["Meter",1.00000000000000]]', airportGrid2007); }); it("should be able to interpret denmarkED50 WKT", async () => { const denmarkED50 = { horizontalCRS: { datum: { description: "European 1950, Denmark, for System 34", ellipsoid: { description: "Hayford, 1924 (aka 1909); same as International 1924", epsg: 7022, equatorialRadius: 6378388, id: "HAYFORD", polarRadius: 6356911.9461279465, source: "Snyder, J.P., 1987, Map Projections - A Working Manual", }, ellipsoidId: "HAYFORD", id: "ED50-DK34", source: "KMSTrans, by Kort-og Matrikelstyrelsen (Nov 1999)", transforms: [ { method: "PositionalVector", positionalVector: { delta: { x: -81.0703, y: -89.3603, z: -115.7526, }, rotation: { x: 0.48488, y: 0.02436, z: 0.41321, }, scalePPM: -0.540645, }, sourceEllipsoid: { equatorialRadius: 6378388, id: "HAYFORD", polarRadius: 6356911.9461279465, }, targetEllipsoid: { equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, }, }, ], }, datumId: "ED50-DK34", description: "DummyName", extent: { northEast: { latitude: 90, longitude: 180, }, southWest: { latitude: -90, longitude: -180, }, }, id: "DummyName", projection: { method: "None", }, source: "Extracted from WKT string; description field carries WKT name.", unit: "Degree", }, verticalCRS: { id: "ELLIPSOID", }, }; await interpretWKTTest('GEOGCS[ "DummyName", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]', denmarkED50); }); it("should be able to interpret californiaStateZone2 WKT", async () => { const californiaStateZone2 = { horizontalCRS: { datum: { description: "North American Datum of 1983", ellipsoid: { description: "Geodetic Reference System of 1980", epsg: 7019, equatorialRadius: 6378137, id: "GRS1980", polarRadius: 6356752.314140348, source: "Stem, L.E., Jan 1989, State Plane Coordinate System of 1983", }, ellipsoidId: "GRS1980", epsg: 6269, id: "NAD83", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { method: "None", }, ], }, datumId: "NAD83", description: "NAD_1983_StatePlane_California_II_FIPS_0402_Feet", id: "NAD_1983_StatePlane_Cal", projection: { falseEasting: 6561666.666666666, falseNorthing: 1640416.666666667, latitudeOfOrigin: 37.66666666666666, longitudeOfOrigin: -122, method: "LambertConformalConicTwoParallels", standardParallel1: 38.33333333333334, standardParallel2: 39.83333333333334, }, source: "WKT", unit: "USSurveyFoot", }, verticalCRS: { id: "NAVD88", }, }; await interpretWKTTest('PROJCS["NAD_1983_StatePlane_California_II_FIPS_0402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.30480060960121924]]', californiaStateZone2); }); it("should be able to interpret utm84Zone34S WKT", async () => { const utm84Zone34S = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", ellipsoid: { description: "World Geodetic System of 1984, GEM 10C", epsg: 7030, equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "WGS84", epsg: 6326, id: "WGS84", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { method: "None", }, ], }, datumId: "WGS84", description: "WGS 84 / UTM zone 34S", id: "WGS 84 / UTM zone 34S", projection: { centralMeridian: 20.999999999999982, falseEasting: 500000, falseNorthing: 10000000, latitudeOfOrigin: 0, method: "TransverseMercator", scaleFactor: 0.9996, }, source: "WKT", unit: "Meter", }, verticalCRS: { id: "ELLIPSOID", }, }; await interpretWKTTest('PROJCS["WGS 84 / UTM zone 34S", GEOGCS [ "WGS 84", DATUM ["World Geodetic System 1984 (EPSG ID 6326)", SPHEROID ["WGS 84 (EPSG ID 7030)", 6378137, 298.257223563]], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994328]], PROJECTION ["UTM zone 34S (EPSG OP 16134)"], PARAMETER ["Latitude_Of_Origin", 0], PARAMETER ["Central_Meridian", 21], PARAMETER ["Scale_Factor", .9996], PARAMETER ["False_Easting", 500000], PARAMETER ["False_Northing", 10000000], UNIT ["Meter", 1]]', utm84Zone34S); }); it("should be able to interpret utm84Zone32NGeoid WKT", async () => { const utm84Zone32NGeoid = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", ellipsoid: { description: "World Geodetic System of 1984, GEM 10C", epsg: 7030, equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "WGS84", epsg: 6326, id: "WGS84", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { method: "None", }, ], }, datumId: "WGS84", description: "WGS 84 / UTM zone32N", id: "WGS 84 / UTM zone32N", projection: { centralMeridian: 9, falseEasting: 500000, falseNorthing: 0, latitudeOfOrigin: 0, method: "TransverseMercator", scaleFactor: 0.9996, }, source: "WKT", unit: "Meter", }, verticalCRS: { id: "GEOID", }, }; await interpretWKTTest('COMPD_CS["WGS 84 / UTM zone 32N + EGM96 geoid height",PROJCS["WGS 84 / UTM zone32N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",9],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32632"]],VERT_CS["EGM96 geoid height",VERT_DATUM["EGM96 geoid",2005,EXTENSION["PROJ4_GRIDS","egm96_15.gtx"],AUTHORITY["EPSG","5171"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Up",UP],AUTHORITY["EPSG","5773"]]]', utm84Zone32NGeoid); }); it("should be able to interpret utm84Zone18NGeoid WKT", async () => { const utm84Zone18NGeoid = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", ellipsoid: { description: "World Geodetic System of 1984, GEM 10C", epsg: 7030, equatorialRadius: 6378137, id: "WGS84", polarRadius: 6356752.3142, source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", }, ellipsoidId: "WGS84", epsg: 6326, id: "WGS84", source: "US Defense Mapping Agency, TR-8350.2-B, December 1987", transforms: [ { method: "None", }, ], }, datumId: "WGS84", description: "UTM84-18N", id: "UTM84-18N", projection: { hemisphere: "North", method: "UniversalTransverseMercator", zoneNumber: 18, }, source: "WKT", unit: "Meter", }, verticalCRS: { id: "GEOID", }, }; await interpretWKTTest('COMPD_CS["UTM84-18N",PROJCS["UTM84-18N",GEOGCS["LL84",DATUM["WGS84",SPHEROID["WGS84",6378137.000,298.25722293]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Universal Transverse Mercator System"],PARAMETER["UTM Zone Number (1 - 60)",18.0],PARAMETER["Hemisphere, North or South",1.0],UNIT["Meter",1.00000000000000]],VERT_CS["Geoid Height",VERT_DATUM["EGM96 geoid",2005],UNIT["METER",1.000000]]]', utm84Zone18NGeoid); }); }); describe("Verify list of CRS", async () => { const validationRange = 50; const validationRangeSmall = 10; const validateCRSList = async (options) => { const { expectedCount, allowedRange, extent, includeWorld } = options; const listOfCRS = await getAvailableCoordinateReferenceSystems({ extent, includeWorld }); // Check fields of returned coordinate reference systems const extentRange = Range2d.fromJSON(extent); for (const crs of listOfCRS) { // Validate extent if (extent !== undefined) { const crsExtentRange = Range2d.fromJSON(crs.crsExtent); const intersects = extentRange.intersectsRange(crsExtentRange); assert.isTrue(intersects); } // These fields should always be present assert.isTrue(crs.name !== undefined); assert.isTrue(crs.description !== undefined); assert.isTrue(crs.deprecated === true || crs.deprecated === false); } assert.isTrue(listOfCRS.length > expectedCount - allowedRange && listOfCRS.length < expectedCount + allowedRange); }; const validateExtent = (expectedExtent, crsExtent) => { const crsExtentRange = Range2d.fromJSON(crsExtent); assert.equal(crsExtentRange.low.x, expectedExtent.low.x); assert.equal(crsExtentRange.low.y, expectedExtent.low.y); assert.equal(crsExtentRange.high.x, expectedExtent.high.x); assert.equal(crsExtentRange.high.y, expectedExtent.high.y); }; it("should get all CRS", async () => { await validateCRSList({ expectedCount: 12_332, allowedRange: validationRange, includeWorld: true }); }); it("should get all CRS, excluding world crs", async () => { await validateCRSList({ expectedCount: 11_975, allowedRange: validationRange }); }); it("should return CRS that are in the specified range (1)", async () => { const extent = { low: { x: 60.1, y: 61.2 }, high: { x: 62.3, y: 63.4 } }; await validateCRSList({ expectedCount: 82, allowedRange: validationRangeSmall, extent }); await validateCRSList({ expectedCount: 439, allowedRange: validationRangeSmall, extent, includeWorld: true }); }); it("should return CRS that are in the specified range (2)", async () => { const extent = { low: { x: 0, y: 2 }, high: { x: 1, y: 3 } }; await validateCRSList({ expectedCount: 67, allowedRange: validationRangeSmall, extent }); await validateCRSList({ expectedCount: 424, allowedRange: validationRangeSmall, extent, includeWorld: true }); }); it("should return CRS that are in the specified range (3)", async () => { const extent = { low: { x: 0.3, y: 2.4 }, high: { x: 1.6, y: 3.77 } }; await validateCRSList({ expectedCount: 62, allowedRange: validationRangeSmall, extent }); await validateCRSList({ expectedCount: 419, allowedRange: validationRangeSmall, extent, includeWorld: true }); }); it("should retrieve the whole list of CRS and validate the properties for a few selected CRS.", async () => { const listOfCRS = await getAvailableCoordinateReferenceSystems({ includeWorld: true }); let nbFound = 0; for (const crs of listOfCRS) { switch (crs.name) { case "3TM111-83": nbFound++; assert.equal(crs.description, "Use NAD83-AB/3TM-111 instead."); assert.equal(crs.deprecated, true); validateExtent(Range2d.fromJSON({ low: { x: -113, y: 48 }, high: { x: -109, y: 84 } }), crs.crsExtent); break; case "NAD27-CAN.MTM-1": nbFound++; assert.equal(crs.description, "NAD27 / MTM zone 1"); assert.equal(crs.deprecated, false); validateExtent(Range2d.fromJSON({ low: { x: -54.5, y: 45 }, high: { x: -50.5, y: 55 } }), crs.crsExtent); break; case "AL83-EF": nbFound++; assert.equal(crs.description, "NAD83 Alabama State Plane, East Zone, US Foot"); assert.equal(crs.deprecated, false); validateExtent(Range2d.fromJSON({ low: { x: -87.5, y: 30 }, high: { x: -84, y: 35.75 } }), crs.crsExtent); break; case "ME-E": nbFound++; assert.equal(crs.description, "NAD27 Maine State Plane, East Zone(1801), US Foot"); assert.equal(crs.deprecated, false); validateExtent(Range2d.fromJSON({ low: { x: -71, y: 43.5 }, high: { x: -66, y: 48 } }), crs.crsExtent); break; // world CRS case "EPSG:4326": nbFound++; assert.equal(crs.description, "WGS 84"); assert.equal(crs.deprecated, false); validateExtent(Range2d.fromJSON({ low: { x: -180, y: -90 }, high: { x: 180, y: 90 } }), crs.crsExtent); break; } } assert.equal(nbFound, 5); }); }); it("should not be able to interpret an invalid GeographicCRS", async () => { const interpretInvalidTest = async (formatCRS, testInvalid) => { const requestProps = { format: formatCRS, geographicCRSDef: testInvalid }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); // At the moment return codes are not really error specific (we mostly return 32768) so we do not validate // actual error code for now. assert.isFalse(response.status === 0); }; // WKT Without datum or projection clause await interpretInvalidTest("WKT", 'PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],UNIT["Meter",1.00000000000000]]'); // Plain garbage await interpretInvalidTest("WKT", "Some invalid content"); // Format is JSON but content is WKT await interpretInvalidTest("JSON", 'GEOGCS[ "Longitude / Latitude (ED 50 Denmark)", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]'); // Vertical datum invalid for horizontal definition await interpretInvalidTest("JSON", '{ horizontalCRS: { id: "EPSG:27700" }, verticalCRS: { id: "NAVD29" } }'); // No horizontal CRS await interpretInvalidTest("JSON", '{ verticalCRS: { id: "NAVD29" } }'); // Unknown identifier await interpretInvalidTest("JSON", '{ horizontalCRS: { id: "UNKNOWN" }, verticalCRS: { id: "NAVD29" } }'); }); it("should return expected Transform from Helmert2DWithZOffset object", async () => { const helmertTransform = new Helmert2DWithZOffset({ translationX: 1, translationY: 1, translationZ: 1, rotDeg: 90, scale: 2 }); const convertedTransform = helmertTransform.convertHelmertToTransform(); const originExpected = Point3d.fromJSON({ x: 1, y: 1, z: 1 }); assert(convertedTransform.origin.isAlmostEqual(originExpected)); const expectedCoffs = [0, -2, 0, 2, 0, 0, 0, 0, 1]; const actualCoffs = Array.from(convertedTransform.matrix.coffs); for (let i = 0; i < expectedCoffs.length; ++i) { assert(Math.abs(actualCoffs[i] - expectedCoffs[i]) < 1e-12, `Matrix coefficient at index ${i} differs: expected ${expectedCoffs[i]}, got ${actualCoffs[i]}`); } }); }); //# sourceMappingURL=GeoServices.test.js.map