├── .github └── workflows │ └── pullrequest.yml ├── .gitignore ├── LICENSE.md ├── PROJJSONBuilder2015.js ├── PROJJSONBuilder2019.js ├── PROJJSONBuilderBase.js ├── PUBLISHING.md ├── README.md ├── buildPROJJSON.js ├── detectWKTVersion.js ├── eslint.config.js ├── index.js ├── package-lock.json ├── package.json ├── parser.js ├── process.js ├── publish.sh ├── rollup.config.mjs ├── test-fixtures.json ├── test.js ├── transformPROJJSON.js ├── util.js ├── wkt2_parser.js ├── wkt2_tokenizer.js └── wkt_node.js /.github/workflows/pullrequest.yml: -------------------------------------------------------------------------------- 1 | name: Run Tests on Pull Request 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | test: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v3 15 | 16 | - name: Set up Node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: '20' 20 | 21 | - name: Install dependencies 22 | run: npm ci 23 | 24 | - name: Run tests 25 | run: npm test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## Proj4js -- Javascript reprojection library. 2 | 3 | Authors: 4 | - Mike Adair madairATdmsolutions.ca 5 | - Richard Greenwood richATgreenwoodmap.com 6 | - Didier Richard didier.richardATign.fr 7 | - Stephen Irons stephen.ironsATclear.net.nz 8 | - Olivier Terral oterralATgmail.com 9 | - Calvin Metcalf cmetcalfATappgeo.com 10 | 11 | Copyright (c) 2014, Mike Adair, Richard Greenwood, Didier Richard, Stephen Irons, Olivier Terral and Calvin Metcalf 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a 14 | copy of this software and associated documentation files (the "Software"), 15 | to deal in the Software without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included 21 | in all copies or substantial portions of the Software. 22 | 23 | _THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE._ 30 | -------------------------------------------------------------------------------- /PROJJSONBuilder2015.js: -------------------------------------------------------------------------------- 1 | import PROJJSONBuilderBase from './PROJJSONBuilderBase.js'; 2 | 3 | class PROJJSONBuilder2015 extends PROJJSONBuilderBase { 4 | static convert(node, result = {}) { 5 | super.convert(node, result); 6 | 7 | // Skip `CS` and `USAGE` nodes for WKT2-2015 8 | if (result.coordinate_system && result.coordinate_system.subtype === 'Cartesian') { 9 | delete result.coordinate_system; 10 | } 11 | if (result.usage) { 12 | delete result.usage; 13 | } 14 | 15 | return result; 16 | } 17 | } 18 | 19 | export default PROJJSONBuilder2015; -------------------------------------------------------------------------------- /PROJJSONBuilder2019.js: -------------------------------------------------------------------------------- 1 | import PROJJSONBuilderBase from './PROJJSONBuilderBase.js'; 2 | 3 | class PROJJSONBuilder2019 extends PROJJSONBuilderBase { 4 | static convert(node, result = {}) { 5 | super.convert(node, result); 6 | 7 | // Handle `CS` node for WKT2-2019 8 | const csNode = node.find((child) => Array.isArray(child) && child[0] === 'CS'); 9 | if (csNode) { 10 | result.coordinate_system = { 11 | subtype: csNode[1], 12 | axis: this.extractAxes(node), 13 | }; 14 | } 15 | 16 | // Handle `USAGE` node for WKT2-2019 17 | const usageNode = node.find((child) => Array.isArray(child) && child[0] === 'USAGE'); 18 | if (usageNode) { 19 | const scope = usageNode.find((child) => Array.isArray(child) && child[0] === 'SCOPE'); 20 | const area = usageNode.find((child) => Array.isArray(child) && child[0] === 'AREA'); 21 | const bbox = usageNode.find((child) => Array.isArray(child) && child[0] === 'BBOX'); 22 | result.usage = {}; 23 | if (scope) { 24 | result.usage.scope = scope[1]; 25 | } 26 | if (area) { 27 | result.usage.area = area[1]; 28 | } 29 | if (bbox) { 30 | result.usage.bbox = bbox.slice(1); 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | } 37 | 38 | export default PROJJSONBuilder2019; -------------------------------------------------------------------------------- /PROJJSONBuilderBase.js: -------------------------------------------------------------------------------- 1 | class PROJJSONBuilderBase { 2 | static getId(node) { 3 | const idNode = node.find((child) => Array.isArray(child) && child[0] === 'ID'); 4 | if (idNode && idNode.length >= 3) { 5 | return { 6 | authority: idNode[1], 7 | code: parseInt(idNode[2], 10), 8 | }; 9 | } 10 | return null; 11 | } 12 | 13 | static convertUnit(node, type = 'unit') { 14 | if (!node || node.length < 3) { 15 | return { type, name: 'unknown', conversion_factor: null }; 16 | } 17 | 18 | const name = node[1]; 19 | const conversionFactor = parseFloat(node[2]) || null; 20 | 21 | const idNode = node.find((child) => Array.isArray(child) && child[0] === 'ID'); 22 | const id = idNode 23 | ? { 24 | authority: idNode[1], 25 | code: parseInt(idNode[2], 10), 26 | } 27 | : null; 28 | 29 | return { 30 | type, 31 | name, 32 | conversion_factor: conversionFactor, 33 | id, 34 | }; 35 | } 36 | 37 | static convertAxis(node) { 38 | const name = node[1] || 'Unknown'; 39 | 40 | // Determine the direction 41 | let direction; 42 | const abbreviationMatch = name.match(/^\((.)\)$/); // Match abbreviations like "(E)" or "(N)" 43 | if (abbreviationMatch) { 44 | // Use the abbreviation to determine the direction 45 | const abbreviation = abbreviationMatch[1].toUpperCase(); 46 | if (abbreviation === 'E') direction = 'east'; 47 | else if (abbreviation === 'N') direction = 'north'; 48 | else if (abbreviation === 'U') direction = 'up'; 49 | else throw new Error(`Unknown axis abbreviation: ${abbreviation}`); 50 | } else { 51 | // Use the explicit direction provided in the AXIS node 52 | direction = node[2] ? node[2].toLowerCase() : 'unknown'; 53 | } 54 | 55 | const orderNode = node.find((child) => Array.isArray(child) && child[0] === 'ORDER'); 56 | const order = orderNode ? parseInt(orderNode[1], 10) : null; 57 | 58 | const unitNode = node.find( 59 | (child) => 60 | Array.isArray(child) && 61 | (child[0] === 'LENGTHUNIT' || child[0] === 'ANGLEUNIT' || child[0] === 'SCALEUNIT') 62 | ); 63 | const unit = this.convertUnit(unitNode); 64 | 65 | return { 66 | name, 67 | direction, // Use the valid PROJJSON direction value 68 | unit, 69 | order, 70 | }; 71 | } 72 | 73 | static extractAxes(node) { 74 | return node 75 | .filter((child) => Array.isArray(child) && child[0] === 'AXIS') 76 | .map((axis) => this.convertAxis(axis)) 77 | .sort((a, b) => (a.order || 0) - (b.order || 0)); // Sort by the "order" property 78 | } 79 | 80 | static convert(node, result = {}) { 81 | 82 | switch (node[0]) { 83 | case 'PROJCRS': 84 | result.type = 'ProjectedCRS'; 85 | result.name = node[1]; 86 | result.base_crs = node.find((child) => Array.isArray(child) && child[0] === 'BASEGEOGCRS') 87 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'BASEGEOGCRS')) 88 | : null; 89 | result.conversion = node.find((child) => Array.isArray(child) && child[0] === 'CONVERSION') 90 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'CONVERSION')) 91 | : null; 92 | 93 | const csNode = node.find((child) => Array.isArray(child) && child[0] === 'CS'); 94 | if (csNode) { 95 | result.coordinate_system = { 96 | type: csNode[1], 97 | axis: this.extractAxes(node), 98 | }; 99 | } 100 | 101 | const lengthUnitNode = node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT'); 102 | if (lengthUnitNode) { 103 | const unit = this.convertUnit(lengthUnitNode); 104 | result.coordinate_system.unit = unit; // Add unit to coordinate_system 105 | } 106 | 107 | result.id = this.getId(node); 108 | break; 109 | 110 | case 'BASEGEOGCRS': 111 | case 'GEOGCRS': 112 | result.type = 'GeographicCRS'; 113 | result.name = node[1]; 114 | 115 | // Handle DATUM or ENSEMBLE 116 | const datumOrEnsembleNode = node.find( 117 | (child) => Array.isArray(child) && (child[0] === 'DATUM' || child[0] === 'ENSEMBLE') 118 | ); 119 | if (datumOrEnsembleNode) { 120 | const datumOrEnsemble = this.convert(datumOrEnsembleNode); 121 | if (datumOrEnsembleNode[0] === 'ENSEMBLE') { 122 | result.datum_ensemble = datumOrEnsemble; 123 | } else { 124 | result.datum = datumOrEnsemble; 125 | } 126 | const primem = node.find((child) => Array.isArray(child) && child[0] === 'PRIMEM'); 127 | if (primem && primem[1] !== 'Greenwich') { 128 | datumOrEnsemble.prime_meridian = { 129 | name: primem[1], 130 | longitude: parseFloat(primem[2]), 131 | } 132 | } 133 | } 134 | 135 | result.coordinate_system = { 136 | type: 'ellipsoidal', 137 | axis: this.extractAxes(node), 138 | }; 139 | 140 | result.id = this.getId(node); 141 | break; 142 | 143 | case 'DATUM': 144 | result.type = 'GeodeticReferenceFrame'; 145 | result.name = node[1]; 146 | result.ellipsoid = node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID') 147 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID')) 148 | : null; 149 | break; 150 | 151 | case 'ENSEMBLE': 152 | result.type = 'DatumEnsemble'; 153 | result.name = node[1]; 154 | 155 | // Extract ensemble members 156 | result.members = node 157 | .filter((child) => Array.isArray(child) && child[0] === 'MEMBER') 158 | .map((member) => ({ 159 | type: 'DatumEnsembleMember', 160 | name: member[1], 161 | id: this.getId(member), // Extract ID as { authority, code } 162 | })); 163 | 164 | // Extract accuracy 165 | const accuracyNode = node.find((child) => Array.isArray(child) && child[0] === 'ENSEMBLEACCURACY'); 166 | if (accuracyNode) { 167 | result.accuracy = parseFloat(accuracyNode[1]); 168 | } 169 | 170 | // Extract ellipsoid 171 | const ellipsoidNode = node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID'); 172 | if (ellipsoidNode) { 173 | result.ellipsoid = this.convert(ellipsoidNode); // Convert the ellipsoid node 174 | } 175 | 176 | // Extract identifier for the ensemble 177 | result.id = this.getId(node); 178 | break; 179 | 180 | case 'ELLIPSOID': 181 | result.type = 'Ellipsoid'; 182 | result.name = node[1]; 183 | result.semi_major_axis = parseFloat(node[2]); 184 | result.inverse_flattening = parseFloat(node[3]); 185 | const units = node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT') 186 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT'), result) 187 | : null; 188 | break; 189 | 190 | case 'CONVERSION': 191 | result.type = 'Conversion'; 192 | result.name = node[1]; 193 | result.method = node.find((child) => Array.isArray(child) && child[0] === 'METHOD') 194 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'METHOD')) 195 | : null; 196 | result.parameters = node 197 | .filter((child) => Array.isArray(child) && child[0] === 'PARAMETER') 198 | .map((param) => this.convert(param)); 199 | break; 200 | 201 | case 'METHOD': 202 | result.type = 'Method'; 203 | result.name = node[1]; 204 | result.id = this.getId(node); 205 | break; 206 | 207 | case 'PARAMETER': 208 | result.type = 'Parameter'; 209 | result.name = node[1]; 210 | result.value = parseFloat(node[2]); 211 | result.unit = this.convertUnit( 212 | node.find( 213 | (child) => 214 | Array.isArray(child) && 215 | (child[0] === 'LENGTHUNIT' || child[0] === 'ANGLEUNIT' || child[0] === 'SCALEUNIT') 216 | ) 217 | ); 218 | result.id = this.getId(node); 219 | break; 220 | 221 | case 'BOUNDCRS': 222 | result.type = 'BoundCRS'; 223 | 224 | // Process SOURCECRS 225 | const sourceCrsNode = node.find((child) => Array.isArray(child) && child[0] === 'SOURCECRS'); 226 | if (sourceCrsNode) { 227 | const sourceCrsContent = sourceCrsNode.find((child) => Array.isArray(child)); 228 | result.source_crs = sourceCrsContent ? this.convert(sourceCrsContent) : null; 229 | } 230 | 231 | // Process TARGETCRS 232 | const targetCrsNode = node.find((child) => Array.isArray(child) && child[0] === 'TARGETCRS'); 233 | if (targetCrsNode) { 234 | const targetCrsContent = targetCrsNode.find((child) => Array.isArray(child)); 235 | result.target_crs = targetCrsContent ? this.convert(targetCrsContent) : null; 236 | } 237 | 238 | // Process ABRIDGEDTRANSFORMATION 239 | const transformationNode = node.find((child) => Array.isArray(child) && child[0] === 'ABRIDGEDTRANSFORMATION'); 240 | if (transformationNode) { 241 | result.transformation = this.convert(transformationNode); 242 | } else { 243 | result.transformation = null; 244 | } 245 | break; 246 | 247 | case 'ABRIDGEDTRANSFORMATION': 248 | result.type = 'Transformation'; 249 | result.name = node[1]; 250 | result.method = node.find((child) => Array.isArray(child) && child[0] === 'METHOD') 251 | ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'METHOD')) 252 | : null; 253 | 254 | result.parameters = node 255 | .filter((child) => Array.isArray(child) && (child[0] === 'PARAMETER' || child[0] === 'PARAMETERFILE')) 256 | .map((param) => { 257 | if (param[0] === 'PARAMETER') { 258 | return this.convert(param); 259 | } else if (param[0] === 'PARAMETERFILE') { 260 | return { 261 | name: param[1], 262 | value: param[2], 263 | id: { 264 | 'authority': 'EPSG', 265 | 'code': 8656 266 | } 267 | }; 268 | } 269 | }); 270 | 271 | // Adjust the Scale difference parameter if present 272 | if (result.parameters.length === 7) { 273 | const scaleDifference = result.parameters[6]; 274 | if (scaleDifference.name === 'Scale difference') { 275 | scaleDifference.value = Math.round((scaleDifference.value - 1) * 1e12) / 1e6; 276 | } 277 | } 278 | 279 | result.id = this.getId(node); 280 | break; 281 | 282 | case 'AXIS': 283 | if (!result.coordinate_system) { 284 | result.coordinate_system = { type: 'unspecified', axis: [] }; 285 | } 286 | result.coordinate_system.axis.push(this.convertAxis(node)); 287 | break; 288 | 289 | case 'LENGTHUNIT': 290 | const unit = this.convertUnit(node, 'LinearUnit'); 291 | if (result.coordinate_system && result.coordinate_system.axis) { 292 | result.coordinate_system.axis.forEach((axis) => { 293 | if (!axis.unit) { 294 | axis.unit = unit; 295 | } 296 | }); 297 | } 298 | if (unit.conversion_factor && unit.conversion_factor !== 1) { 299 | if (result.semi_major_axis) { 300 | result.semi_major_axis = { 301 | value: result.semi_major_axis, 302 | unit, 303 | } 304 | } 305 | } 306 | break; 307 | 308 | default: 309 | result.keyword = node[0]; 310 | break; 311 | } 312 | 313 | return result; 314 | } 315 | } 316 | 317 | export default PROJJSONBuilderBase; -------------------------------------------------------------------------------- /PUBLISHING.md: -------------------------------------------------------------------------------- 1 | # Publishing 2 | 3 | Make sure you have the latest from the main branch: 4 | 5 | git pull origin main 6 | 7 | Use `npm version` to update the version number in the `package.json`. 8 | 9 | npm version {patch|minor|major} --no-git-tag-version 10 | 11 | Then run the publish script 12 | 13 | ./publish.sh 14 | 15 | afterwards don't forget to update the versions to be a prerelease of the next version, so if you just published 1.1.1 then: 16 | 17 | npm version 1.1.2-dev 18 | git push --follow-tags 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wkt-parser 2 | 3 | The wkt parser pulled out of proj4 so it can be hacked on. Supports WKT1, WKT2 and PROJJSON. 4 | 5 | It does not support geocentric currently (`GEOCCS`). `COMPOUNDCS` is only supported for WKT1. 6 | -------------------------------------------------------------------------------- /buildPROJJSON.js: -------------------------------------------------------------------------------- 1 | import PROJJSONBuilder2015 from './PROJJSONBuilder2015.js'; 2 | import PROJJSONBuilder2019 from './PROJJSONBuilder2019.js'; 3 | 4 | /** 5 | * Detects the WKT2 version based on the structure of the WKT. 6 | * @param {Array} root The root WKT array node. 7 | * @returns {string} The detected version ("2015" or "2019"). 8 | */ 9 | function detectWKT2Version(root) { 10 | // Check for WKT2-2019-specific nodes 11 | if (root.find((child) => Array.isArray(child) && child[0] === 'USAGE')) { 12 | return '2019'; // `USAGE` is specific to WKT2-2019 13 | } 14 | 15 | // Check for WKT2-2015-specific nodes 16 | if (root.find((child) => Array.isArray(child) && child[0] === 'CS')) { 17 | return '2015'; // `CS` is valid in both, but default to 2015 unless `USAGE` is present 18 | } 19 | 20 | if (root[0] === 'BOUNDCRS' || root[0] === 'PROJCRS' || root[0] === 'GEOGCRS') { 21 | return '2015'; // These are valid in both, but default to 2015 22 | } 23 | 24 | // Default to WKT2-2015 if no specific indicators are found 25 | return '2015'; 26 | } 27 | 28 | /** 29 | * Builds a PROJJSON object from a WKT array structure. 30 | * @param {Array} root The root WKT array node. 31 | * @returns {Object} The PROJJSON object. 32 | */ 33 | export function buildPROJJSON(root) { 34 | const version = detectWKT2Version(root); 35 | const builder = version === '2019' ? PROJJSONBuilder2019 : PROJJSONBuilder2015; 36 | return builder.convert(root); 37 | } 38 | -------------------------------------------------------------------------------- /detectWKTVersion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Detects whether the WKT string is WKT1 or WKT2. 3 | * @param {string} wkt The WKT string. 4 | * @returns {string} The detected version ("WKT1" or "WKT2"). 5 | */ 6 | export function detectWKTVersion(wkt) { 7 | // Normalize the WKT string for easier keyword matching 8 | const normalizedWKT = wkt.toUpperCase(); 9 | 10 | // Check for WKT2-specific keywords 11 | if ( 12 | normalizedWKT.includes('PROJCRS') || 13 | normalizedWKT.includes('GEOGCRS') || 14 | normalizedWKT.includes('BOUNDCRS') || 15 | normalizedWKT.includes('VERTCRS') || 16 | normalizedWKT.includes('LENGTHUNIT') || 17 | normalizedWKT.includes('ANGLEUNIT') || 18 | normalizedWKT.includes('SCALEUNIT') 19 | ) { 20 | return 'WKT2'; 21 | } 22 | 23 | // Check for WKT1-specific keywords 24 | if ( 25 | normalizedWKT.includes('PROJCS') || 26 | normalizedWKT.includes('GEOGCS') || 27 | normalizedWKT.includes('LOCAL_CS') || 28 | normalizedWKT.includes('VERT_CS') || 29 | normalizedWKT.includes('UNIT') 30 | ) { 31 | return 'WKT1'; 32 | } 33 | 34 | // Default to WKT1 if no specific indicators are found 35 | return 'WKT1'; 36 | } -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { FlatCompat } from '@eslint/eslintrc'; 2 | 3 | const compat = new FlatCompat({ 4 | recommendedConfigs: { 5 | 'eslint:recommended': { 6 | rules: { 7 | 'no-unused-vars': [ 8 | 'error', 9 | { vars: 'all', args: 'after-used', ignoreRestSiblings: true }, 10 | ], 11 | }, 12 | }, 13 | }, 14 | }); 15 | 16 | export default [ 17 | { 18 | files: ['**/*.js'], 19 | languageOptions: { 20 | ecmaVersion: 2015, 21 | sourceType: 'module', 22 | globals: { 23 | browser: true, 24 | node: true, 25 | }, 26 | }, 27 | rules: { 28 | indent: ['error', 2, { SwitchCase: 1 }], 29 | 'brace-style': ['error', '1tbs'], 30 | quotes: ['error', 'single'], 31 | 'no-console': 'off', 32 | 'no-shadow': 'off', 33 | 'no-use-before-define': ['error', { functions: false }], 34 | 'no-underscore-dangle': 'off', 35 | 'no-constant-condition': 'off', 36 | 'space-after-function-name': 'off', 37 | 'consistent-return': 'off', 38 | }, 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { buildPROJJSON } from './buildPROJJSON.js'; 2 | import { detectWKTVersion } from './detectWKTVersion.js'; 3 | import parser from './parser.js'; 4 | import {sExpr} from './process.js'; 5 | import { transformPROJJSON } from './transformPROJJSON.js'; 6 | import { applyProjectionDefaults, d2r } from './util.js'; 7 | 8 | var knownTypes = ['PROJECTEDCRS', 'PROJCRS', 'GEOGCS', 'GEOCCS', 'PROJCS', 'LOCAL_CS', 'GEODCRS', 9 | 'GEODETICCRS', 'GEODETICDATUM', 'ENGCRS', 'ENGINEERINGCRS']; 10 | 11 | function rename(obj, params) { 12 | var outName = params[0]; 13 | var inName = params[1]; 14 | if (!(outName in obj) && (inName in obj)) { 15 | obj[outName] = obj[inName]; 16 | if (params.length === 3) { 17 | obj[outName] = params[2](obj[outName]); 18 | } 19 | } 20 | } 21 | 22 | function cleanWKT(wkt) { 23 | var keys = Object.keys(wkt); 24 | for (var i = 0, ii = keys.length; i = this.text.length) { 32 | return; 33 | } 34 | char = this.text[this.place++]; 35 | } 36 | } 37 | switch (this.state) { 38 | case NEUTRAL: 39 | return this.neutral(char); 40 | case KEYWORD: 41 | return this.keyword(char) 42 | case QUOTED: 43 | return this.quoted(char); 44 | case AFTERQUOTE: 45 | return this.afterquote(char); 46 | case NUMBER: 47 | return this.number(char); 48 | case ENDED: 49 | return; 50 | } 51 | }; 52 | Parser.prototype.afterquote = function(char) { 53 | if (char === '"') { 54 | this.word += '"'; 55 | this.state = QUOTED; 56 | return; 57 | } 58 | if (endThings.test(char)) { 59 | this.word = this.word.trim(); 60 | this.afterItem(char); 61 | return; 62 | } 63 | throw new Error('havn\'t handled "' +char + '" in afterquote yet, index ' + this.place); 64 | }; 65 | Parser.prototype.afterItem = function(char) { 66 | if (char === ',') { 67 | if (this.word !== null) { 68 | this.currentObject.push(this.word); 69 | } 70 | this.word = null; 71 | this.state = NEUTRAL; 72 | return; 73 | } 74 | if (char === ']') { 75 | this.level--; 76 | if (this.word !== null) { 77 | this.currentObject.push(this.word); 78 | this.word = null; 79 | } 80 | this.state = NEUTRAL; 81 | this.currentObject = this.stack.pop(); 82 | if (!this.currentObject) { 83 | this.state = ENDED; 84 | } 85 | 86 | return; 87 | } 88 | }; 89 | Parser.prototype.number = function(char) { 90 | if (digets.test(char)) { 91 | this.word += char; 92 | return; 93 | } 94 | if (endThings.test(char)) { 95 | this.word = parseFloat(this.word); 96 | this.afterItem(char); 97 | return; 98 | } 99 | throw new Error('havn\'t handled "' +char + '" in number yet, index ' + this.place); 100 | }; 101 | Parser.prototype.quoted = function(char) { 102 | if (char === '"') { 103 | this.state = AFTERQUOTE; 104 | return; 105 | } 106 | this.word += char; 107 | return; 108 | }; 109 | Parser.prototype.keyword = function(char) { 110 | if (keyword.test(char)) { 111 | this.word += char; 112 | return; 113 | } 114 | if (char === '[') { 115 | var newObjects = []; 116 | newObjects.push(this.word); 117 | this.level++; 118 | if (this.root === null) { 119 | this.root = newObjects; 120 | } else { 121 | this.currentObject.push(newObjects); 122 | } 123 | this.stack.push(this.currentObject); 124 | this.currentObject = newObjects; 125 | this.state = NEUTRAL; 126 | return; 127 | } 128 | if (endThings.test(char)) { 129 | this.afterItem(char); 130 | return; 131 | } 132 | throw new Error('havn\'t handled "' +char + '" in keyword yet, index ' + this.place); 133 | }; 134 | Parser.prototype.neutral = function(char) { 135 | if (latin.test(char)) { 136 | this.word = char; 137 | this.state = KEYWORD; 138 | return; 139 | } 140 | if (char === '"') { 141 | this.word = ''; 142 | this.state = QUOTED; 143 | return; 144 | } 145 | if (digets.test(char)) { 146 | this.word = char; 147 | this.state = NUMBER; 148 | return; 149 | } 150 | if (endThings.test(char)) { 151 | this.afterItem(char); 152 | return; 153 | } 154 | throw new Error('havn\'t handled "' +char + '" in neutral yet, index ' + this.place); 155 | }; 156 | Parser.prototype.output = function() { 157 | while (this.place < this.text.length) { 158 | this.readCharicter(); 159 | } 160 | if (this.state === ENDED) { 161 | return this.root; 162 | } 163 | throw new Error('unable to parse string "' +this.text + '". State is ' + this.state); 164 | }; 165 | 166 | function parseString(txt) { 167 | var parser = new Parser(txt); 168 | return parser.output(); 169 | } 170 | -------------------------------------------------------------------------------- /process.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function mapit(obj, key, value) { 4 | if (Array.isArray(key)) { 5 | value.unshift(key); 6 | key = null; 7 | } 8 | var thing = key ? {} : obj; 9 | 10 | var out = value.reduce(function(newObj, item) { 11 | sExpr(item, newObj); 12 | return newObj 13 | }, thing); 14 | if (key) { 15 | obj[key] = out; 16 | } 17 | } 18 | 19 | export function sExpr(v, obj) { 20 | if (!Array.isArray(v)) { 21 | obj[v] = true; 22 | return; 23 | } 24 | var key = v.shift(); 25 | if (key === 'PARAMETER') { 26 | key = v.shift(); 27 | } 28 | if (v.length === 1) { 29 | if (Array.isArray(v[0])) { 30 | obj[key] = {}; 31 | sExpr(v[0], obj[key]); 32 | return; 33 | } 34 | obj[key] = v[0]; 35 | return; 36 | } 37 | if (!v.length) { 38 | obj[key] = true; 39 | return; 40 | } 41 | if (key === 'TOWGS84') { 42 | obj[key] = v; 43 | return; 44 | } 45 | if (key === 'AXIS') { 46 | if (!(key in obj)) { 47 | obj[key] = []; 48 | } 49 | obj[key].push(v); 50 | return; 51 | } 52 | if (!Array.isArray(key)) { 53 | obj[key] = {}; 54 | } 55 | 56 | var i; 57 | switch (key) { 58 | case 'UNIT': 59 | case 'PRIMEM': 60 | case 'VERT_DATUM': 61 | obj[key] = { 62 | name: v[0].toLowerCase(), 63 | convert: v[1] 64 | }; 65 | if (v.length === 3) { 66 | sExpr(v[2], obj[key]); 67 | } 68 | return; 69 | case 'SPHEROID': 70 | case 'ELLIPSOID': 71 | obj[key] = { 72 | name: v[0], 73 | a: v[1], 74 | rf: v[2] 75 | }; 76 | if (v.length === 4) { 77 | sExpr(v[3], obj[key]); 78 | } 79 | return; 80 | case 'EDATUM': 81 | case 'ENGINEERINGDATUM': 82 | case 'LOCAL_DATUM': 83 | case 'DATUM': 84 | case 'VERT_CS': 85 | case 'VERTCRS': 86 | case 'VERTICALCRS': 87 | v[0] = ['name', v[0]]; 88 | mapit(obj, key, v); 89 | return; 90 | case 'COMPD_CS': 91 | case 'COMPOUNDCRS': 92 | case 'FITTED_CS': 93 | // the followings are the crs defined in 94 | // https://github.com/proj4js/proj4js/blob/1da4ed0b865d0fcb51c136090569210cdcc9019e/lib/parseCode.js#L11 95 | case 'PROJECTEDCRS': 96 | case 'PROJCRS': 97 | case 'GEOGCS': 98 | case 'GEOCCS': 99 | case 'PROJCS': 100 | case 'LOCAL_CS': 101 | case 'GEODCRS': 102 | case 'GEODETICCRS': 103 | case 'GEODETICDATUM': 104 | case 'ENGCRS': 105 | case 'ENGINEERINGCRS': 106 | v[0] = ['name', v[0]]; 107 | mapit(obj, key, v); 108 | obj[key].type = key; 109 | return; 110 | default: 111 | i = -1; 112 | while (++i < v.length) { 113 | if (!Array.isArray(v[i])) { 114 | return sExpr(v, obj[key]); 115 | } 116 | } 117 | return mapit(obj, key, v); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get current version 4 | VERSION=$(node -e "console.log(require('./package.json').version)") 5 | 6 | # Build 7 | git checkout -b build 8 | npm run build 9 | git add dist -f 10 | git commit -m "build $VERSION" 11 | 12 | # Tag and push 13 | git tag -f v$VERSION -m "$VERSION" 14 | git push --tags git@github.com:proj4js/wkt-parser.git $VERSION 15 | 16 | # Publish 17 | npm publish 18 | 19 | # Cleanup 20 | git checkout main 21 | git branch -D build 22 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | input: 'index.js', 4 | output: { 5 | file: 'dist/wkt.cjs', 6 | format: 'cjs' 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /test-fixtures.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "code": "PROJCS[\"NZGD49 / New Zealand Map Grid\",GEOGCS[\"NZGD49\",DATUM[\"New_Zealand_Geodetic_Datum_1949\",SPHEROID[\"International 1924\",6378388,297,AUTHORITY[\"EPSG\",\"7022\"]],TOWGS84[59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993],AUTHORITY[\"EPSG\",\"6272\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4272\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"New_Zealand_Map_Grid\"],PARAMETER[\"latitude_of_origin\",-41],PARAMETER[\"central_meridian\",173],PARAMETER[\"false_easting\",2510000],PARAMETER[\"false_northing\",6023150],AUTHORITY[\"EPSG\",\"27200\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", 3 | "value": { 4 | "type": "PROJCS", 5 | "name": "NZGD49 / New Zealand Map Grid", 6 | "GEOGCS": { 7 | "type": "GEOGCS", 8 | "name": "NZGD49", 9 | "DATUM": { 10 | "name": "New_Zealand_Geodetic_Datum_1949", 11 | "SPHEROID": { 12 | "name": "International 1924", 13 | "a": 6378388, 14 | "rf": 297, 15 | "AUTHORITY": { 16 | "EPSG": "7022" 17 | } 18 | }, 19 | "TOWGS84": [ 20 | 59.47, -5.04, 21 | 187.44, 22 | 0.47, -0.1, 23 | 1.024, -4.5993 24 | ], 25 | "AUTHORITY": { 26 | "EPSG": "6272" 27 | } 28 | }, 29 | "PRIMEM": { 30 | "name": "greenwich", 31 | "convert": 0, 32 | "AUTHORITY": { 33 | "EPSG": "8901" 34 | } 35 | }, 36 | "UNIT": { 37 | "name": "degree", 38 | "convert": 0.01745329251994328, 39 | "AUTHORITY": { 40 | "EPSG": "9122" 41 | } 42 | }, 43 | "AUTHORITY": { 44 | "EPSG": "4272" 45 | }, 46 | "title": "EPSG:4272", 47 | "projName": "longlat", 48 | "units": "degree", 49 | "to_meter": 111323.87156969598, 50 | "datumCode": "new_zealand_geodetic_datum_1949", 51 | "ellps": "intl", 52 | "a": 6378388, 53 | "rf": 297, 54 | "datum_params": [ 55 | 59.47, 56 | -5.04, 57 | 187.44, 58 | 0.47, 59 | -0.1, 60 | 1.024, 61 | -4.5993 62 | ], 63 | "srsCode": "NZGD49" 64 | }, 65 | "UNIT": { 66 | "name": "metre", 67 | "convert": 1, 68 | "AUTHORITY": { 69 | "EPSG": "9001" 70 | } 71 | }, 72 | "PROJECTION": "New_Zealand_Map_Grid", 73 | "latitude_of_origin": -41, 74 | "central_meridian": 173, 75 | "false_easting": 2510000, 76 | "false_northing": 6023150, 77 | "AUTHORITY": { 78 | "EPSG": "27200" 79 | }, 80 | "AXIS": [ 81 | ["Easting", "EAST"], 82 | ["Northing", "NORTH"] 83 | ], 84 | "title": "EPSG:27200", 85 | "projName": "New_Zealand_Map_Grid", 86 | "units": "meter", 87 | "to_meter": 1, 88 | "datumCode": "new_zealand_geodetic_datum_1949", 89 | "datum_params": [ 90 | 59.47, -5.04, 91 | 187.44, 0.47, 92 | -0.1, 1.024, 93 | -4.5993 94 | ], 95 | "ellps": "intl", 96 | "a": 6378388, 97 | "rf": 297, 98 | "x0": 2510000, 99 | "y0": 6023150, 100 | "long0": 3.01941960595019, 101 | "lat0": -0.7155849933176751, 102 | "axis": "enu", 103 | "srsCode": "NZGD49 / New Zealand Map Grid" 104 | } 105 | }, { 106 | "code": "PROJCRS[\"NAD83 / Massachusetts Mainland\",BASEGEOGCRS[\"NAD83\",DATUM[\"North American Datum 1983\",ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4269]],CONVERSION[\"SPCS83 Massachusetts Mainland zone (meter)\",METHOD[\"Lambert Conic Conformal (2SP)\",ID[\"EPSG\",9802]],PARAMETER[\"Latitude of false origin\",41,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8821]],PARAMETER[\"Longitude of false origin\",-71.5,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8822]],PARAMETER[\"Latitude of 1st standard parallel\",42.6833333333333,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8823]],PARAMETER[\"Latitude of 2nd standard parallel\",41.7166666666667,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8824]],PARAMETER[\"Easting at false origin\",200000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8826]],PARAMETER[\"Northing at false origin\",750000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8827]]],CS[Cartesian,2],AXIS[\"easting (X)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (Y)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Engineering survey, topographic mapping.\"],AREA[\"United States (USA) - Massachusetts onshore - counties of Barnstable; Berkshire; Bristol; Essex; Franklin; Hampden; Hampshire; Middlesex; Norfolk; Plymouth; Suffolk; Worcester.\"],BBOX[41.46,-73.5,42.89,-69.86]],ID[\"EPSG\",26986]]", 107 | "value": { 108 | "projName": "Lambert Conic Conformal (2SP)", 109 | "name": "NAD83 / Massachusetts Mainland", 110 | "srsCode": "NAD83 / Massachusetts Mainland", 111 | "datumCode": "EPSG_4269", 112 | "ellps": "GRS 1980", 113 | "a": 6378137, 114 | "rf": 298.257222101, 115 | "axis": "enu", 116 | "title": "EPSG:26986", 117 | "latitude_of_false_origin": 0.7155849933176752, 118 | "longitude_of_false_origin": -1.247910415175946, 119 | "latitude_of_1st_standard_parallel": 0.7449647023929126, 120 | "latitude_of_2nd_standard_parallel": 0.7280931862903018, 121 | "easting_at_false_origin": 200000, 122 | "northing_at_false_origin": 750000, 123 | "units": "meter", 124 | "to_meter": 1, 125 | "lat0": 0.7155849933176752, 126 | "long0": -1.247910415175946, 127 | "lat1": 0.7449647023929126, 128 | "lat2": 0.7280931862903018, 129 | "x0": 200000, 130 | "y0": 750000 131 | } 132 | }, { 133 | "code": "PROJCRS[\"NAD83 / Massachusetts Mainland\",BASEGEOGCRS[\"NAD83\",DATUM[\"North American Datum 1983\",ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4269]],CONVERSION[\"SPCS83 Massachusetts Mainland zone (meter)\",METHOD[\"Lambert Conic Conformal (2SP)\",ID[\"EPSG\",9802]],PARAMETER[\"Latitude of false origin\",41,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8821]],PARAMETER[\"Longitude of false origin\",-71.5,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8822]],PARAMETER[\"Latitude of 1st standard parallel\",42.6833333333333,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8823]],PARAMETER[\"Latitude of 2nd standard parallel\",41.7166666666667,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8824]],PARAMETER[\"Easting at false origin\",200000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8826]],PARAMETER[\"Northing at false origin\",750000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8827]]],CS[Cartesian,2],AXIS[\"easting (X)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (Y)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Engineering survey, topographic mapping.\"],AREA[\"United States (USA) - Massachusetts onshore - counties of Barnstable; Berkshire; Bristol; Essex; Franklin; Hampden; Hampshire; Middlesex; Norfolk; Plymouth; Suffolk; Worcester.\"],BBOX[41.46,-73.5,42.89,-69.86]],ID[\"EPSG\",26986]]", 134 | "value": { 135 | "projName": "Lambert Conic Conformal (2SP)", 136 | "name": "NAD83 / Massachusetts Mainland", 137 | "srsCode": "NAD83 / Massachusetts Mainland", 138 | "datumCode": "EPSG_4269", 139 | "ellps": "GRS 1980", 140 | "a": 6378137, 141 | "rf": 298.257222101, 142 | "axis": "enu", 143 | "title": "EPSG:26986", 144 | "latitude_of_false_origin": 0.7155849933176752, 145 | "longitude_of_false_origin": -1.247910415175946, 146 | "latitude_of_1st_standard_parallel": 0.7449647023929126, 147 | "latitude_of_2nd_standard_parallel": 0.7280931862903018, 148 | "easting_at_false_origin": 200000, 149 | "northing_at_false_origin": 750000, 150 | "units": "meter", 151 | "to_meter": 1, 152 | "lat0": 0.7155849933176752, 153 | "long0": -1.247910415175946, 154 | "lat1": 0.7449647023929126, 155 | "lat2": 0.7280931862903018, 156 | "x0": 200000, 157 | "y0": 750000 158 | } 159 | }, { 160 | "code": {"$schema":"https://proj.org/schemas/v0.7/projjson.schema.json","type":"ProjectedCRS","name":"NAD83 / Massachusetts Mainland","base_crs":{"type":"GeographicCRS","name":"NAD83","datum":{"type":"GeodeticReferenceFrame","name":"North American Datum 1983","ellipsoid":{"name":"GRS 1980","semi_major_axis":6378137,"inverse_flattening":298.257222101}},"coordinate_system":{"subtype":"ellipsoidal","axis":[{"name":"Geodetic latitude","abbreviation":"Lat","direction":"north","unit":"degree"},{"name":"Geodetic longitude","abbreviation":"Lon","direction":"east","unit":"degree"}]},"id":{"authority":"EPSG","code":4269}},"conversion":{"name":"SPCS83 Massachusetts Mainland zone (meter)","method":{"name":"Lambert Conic Conformal (2SP)","id":{"authority":"EPSG","code":9802}},"parameters":[{"name":"Latitude of false origin","value":41,"unit":"degree","id":{"authority":"EPSG","code":8821}},{"name":"Longitude of false origin","value":-71.5,"unit":"degree","id":{"authority":"EPSG","code":8822}},{"name":"Latitude of 1st standard parallel","value":42.6833333333333,"unit":"degree","id":{"authority":"EPSG","code":8823}},{"name":"Latitude of 2nd standard parallel","value":41.7166666666667,"unit":"degree","id":{"authority":"EPSG","code":8824}},{"name":"Easting at false origin","value":200000,"unit":"metre","id":{"authority":"EPSG","code":8826}},{"name":"Northing at false origin","value":750000,"unit":"metre","id":{"authority":"EPSG","code":8827}}]},"coordinate_system":{"subtype":"Cartesian","axis":[{"name":"Easting","abbreviation":"X","direction":"east","unit":"metre"},{"name":"Northing","abbreviation":"Y","direction":"north","unit":"metre"}]},"scope":"Engineering survey, topographic mapping.","area":"United States (USA) - Massachusetts onshore - counties of Barnstable; Berkshire; Bristol; Essex; Franklin; Hampden; Hampshire; Middlesex; Norfolk; Plymouth; Suffolk; Worcester.","bbox":{"south_latitude":41.46,"west_longitude":-73.5,"north_latitude":42.89,"east_longitude":-69.86},"id":{"authority":"EPSG","code":26986}}, 161 | "value": { 162 | "projName": "Lambert Conic Conformal (2SP)", 163 | "name": "NAD83 / Massachusetts Mainland", 164 | "srsCode": "NAD83 / Massachusetts Mainland", 165 | "datumCode": "EPSG_4269", 166 | "ellps": "GRS 1980", 167 | "a": 6378137, 168 | "rf": 298.257222101, 169 | "axis": "enu", 170 | "units": "meter", 171 | "title": "EPSG:26986", 172 | "latitude_of_false_origin": 0.715584993317675, 173 | "longitude_of_false_origin": -1.2479104151759457, 174 | "latitude_of_1st_standard_parallel": 0.7449647023929125, 175 | "latitude_of_2nd_standard_parallel": 0.7280931862903017, 176 | "easting_at_false_origin": 200000, 177 | "northing_at_false_origin": 750000, 178 | "to_meter": 1, 179 | "lat0": 0.715584993317675, 180 | "long0": -1.2479104151759457, 181 | "lat1": 0.7449647023929125, 182 | "lat2": 0.7280931862903017, 183 | "x0": 200000, 184 | "y0": 750000 185 | } 186 | }, { 187 | "code": "PROJCS[\"NAD83 / Massachusetts Mainland\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",42.68333333333333],PARAMETER[\"standard_parallel_2\",41.71666666666667],PARAMETER[\"latitude_of_origin\",41],PARAMETER[\"central_meridian\",-71.5],PARAMETER[\"false_easting\",200000],PARAMETER[\"false_northing\",750000],AUTHORITY[\"EPSG\",\"26986\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]", 188 | "value": { 189 | "type": "PROJCS", 190 | "name": "NAD83 / Massachusetts Mainland", 191 | "GEOGCS": { 192 | "type": "GEOGCS", 193 | "name": "NAD83", 194 | "DATUM": { 195 | "name": "North_American_Datum_1983", 196 | "SPHEROID": { 197 | "name": "GRS 1980", 198 | "a": 6378137, 199 | "rf": 298.257222101, 200 | "AUTHORITY": { 201 | "EPSG": "7019" 202 | } 203 | }, 204 | "AUTHORITY": { 205 | "EPSG": "6269" 206 | } 207 | }, 208 | "PRIMEM": { 209 | "name": "greenwich", 210 | "convert": 0, 211 | "AUTHORITY": { 212 | "EPSG": "8901" 213 | } 214 | }, 215 | "UNIT": { 216 | "name": "degree", 217 | "convert": 0.01745329251994328, 218 | "AUTHORITY": { 219 | "EPSG": "9122" 220 | } 221 | }, 222 | "AUTHORITY": { 223 | "EPSG": "4269" 224 | }, 225 | "title": "EPSG:4269", 226 | "projName": "longlat", 227 | "units": "degree", 228 | "to_meter": 111319.49079327348, 229 | "datumCode": "north_american_datum_1983", 230 | "ellps": "GRS 1980", 231 | "a": 6378137, 232 | "rf": 298.257222101, 233 | "srsCode": "NAD83" 234 | }, 235 | "UNIT": { 236 | "name": "metre", 237 | "convert": 1, 238 | "AUTHORITY": { 239 | "EPSG": "9001" 240 | } 241 | }, 242 | "PROJECTION": "Lambert_Conformal_Conic_2SP", 243 | "standard_parallel_1": 42.68333333333333, 244 | "standard_parallel_2": 41.71666666666667, 245 | "latitude_of_origin": 41, 246 | "central_meridian": -71.5, 247 | "false_easting": 200000, 248 | "false_northing": 750000, 249 | "AUTHORITY": { 250 | "EPSG": "26986" 251 | }, 252 | "AXIS": [ 253 | ["X", "EAST"], 254 | ["Y", "NORTH"] 255 | ], 256 | "title": "EPSG:26986", 257 | "projName": "Lambert_Conformal_Conic_2SP", 258 | "units": "meter", 259 | "to_meter": 1, 260 | "datumCode": "north_american_datum_1983", 261 | "ellps": "GRS 1980", 262 | "a": 6378137, 263 | "rf": 298.257222101, 264 | "x0": 200000, 265 | "y0": 750000, 266 | "long0": -1.2479104151759457, 267 | "lat0": 0.7155849933176751, 268 | "lat1": 0.7449647023929129, 269 | "lat2": 0.7280931862903012, 270 | "axis": "enu", 271 | "srsCode": "NAD83 / Massachusetts Mainland" 272 | } 273 | }, { 274 | "code": "PROJCRS[\"ETRS89-extended / LAEA Europe\",BASEGEOGCRS[\"ETRS89\",ENSEMBLE[\"European Terrestrial Reference System 1989 ensemble\",MEMBER[\"European Terrestrial Reference Frame 1989\"],MEMBER[\"European Terrestrial Reference Frame 1990\"],MEMBER[\"European Terrestrial Reference Frame 1991\"],MEMBER[\"European Terrestrial Reference Frame 1992\"],MEMBER[\"European Terrestrial Reference Frame 1993\"],MEMBER[\"European Terrestrial Reference Frame 1994\"],MEMBER[\"European Terrestrial Reference Frame 1996\"],MEMBER[\"European Terrestrial Reference Frame 1997\"],MEMBER[\"European Terrestrial Reference Frame 2000\"],MEMBER[\"European Terrestrial Reference Frame 2005\"],MEMBER[\"European Terrestrial Reference Frame 2014\"],MEMBER[\"European Terrestrial Reference Frame 2020\"],ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1]],ENSEMBLEACCURACY[0.1]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4258]],CONVERSION[\"Europe Equal Area 2001\",METHOD[\"Lambert Azimuthal Equal Area\",ID[\"EPSG\",9820]],PARAMETER[\"Latitude of natural origin\",52,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8801]],PARAMETER[\"Longitude of natural origin\",10,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8802]],PARAMETER[\"False easting\",4321000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",3210000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8807]]],CS[Cartesian,2],AXIS[\"northing (Y)\",north,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"easting (X)\",east,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Statistical analysis.\"],AREA[\"Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Türkiye (Turkey); United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.\"],BBOX[24.6,-35.58,84.73,44.83]],ID[\"EPSG\",3035]]", 275 | "value": { 276 | "projName": "Lambert Azimuthal Equal Area", 277 | "axis": "neu", 278 | "units": "meter", 279 | "to_meter": 1, 280 | "datumCode": "EPSG_4258", 281 | "ellps": "GRS 1980", 282 | "a": 6378137, 283 | "rf": 298.257222101, 284 | "x0": 4321000, 285 | "y0": 3210000, 286 | "long0": 0.17453292519943298, 287 | "lat0": 0.9075712110370515, 288 | "srsCode": "ETRS89-extended / LAEA Europe", 289 | "name": "ETRS89-extended / LAEA Europe", 290 | "title": "EPSG:3035" 291 | } 292 | }, { 293 | "code": "PROJCRS[\"ETRS89-extended / LAEA Europe\",BASEGEOGCRS[\"ETRS89\",ENSEMBLE[\"European Terrestrial Reference System 1989 ensemble\", MEMBER[\"European Terrestrial Reference Frame 1989\", ID[\"EPSG\",1178]], MEMBER[\"European Terrestrial Reference Frame 1990\", ID[\"EPSG\",1179]], MEMBER[\"European Terrestrial Reference Frame 1991\", ID[\"EPSG\",1180]], MEMBER[\"European Terrestrial Reference Frame 1992\", ID[\"EPSG\",1181]], MEMBER[\"European Terrestrial Reference Frame 1993\", ID[\"EPSG\",1182]], MEMBER[\"European Terrestrial Reference Frame 1994\", ID[\"EPSG\",1183]], MEMBER[\"European Terrestrial Reference Frame 1996\", ID[\"EPSG\",1184]], MEMBER[\"European Terrestrial Reference Frame 1997\", ID[\"EPSG\",1185]], MEMBER[\"European Terrestrial Reference Frame 2000\", ID[\"EPSG\",1186]], MEMBER[\"European Terrestrial Reference Frame 2005\", ID[\"EPSG\",1204]], MEMBER[\"European Terrestrial Reference Frame 2014\", ID[\"EPSG\",1206]], MEMBER[\"European Terrestrial Reference Frame 2020\", ID[\"EPSG\",1382]], ELLIPSOID[\"GRS 1980\",6378137,298.257222101,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",7019]], ENSEMBLEACCURACY[0.1],ID[\"EPSG\",6258]],ID[\"EPSG\",4258]],CONVERSION[\"Europe Equal Area 2001\",METHOD[\"Lambert Azimuthal Equal Area\",ID[\"EPSG\",9820]],PARAMETER[\"Latitude of natural origin\",52,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8801]],PARAMETER[\"Longitude of natural origin\",10,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8802]],PARAMETER[\"False easting\",4321000,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",3210000,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",8807]],ID[\"EPSG\",19986]],CS[Cartesian,2,ID[\"EPSG\",4532]],AXIS[\"Northing (Y)\",north],AXIS[\"Easting (X)\",east],LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",3035]]", 294 | "value": { 295 | "projName": "Lambert Azimuthal Equal Area", 296 | "axis": "neu", 297 | "units": "meter", 298 | "to_meter": 1, 299 | "datumCode": "EPSG_4258", 300 | "ellps": "GRS 1980", 301 | "a": 6378137, 302 | "rf": 298.257222101, 303 | "x0": 4321000, 304 | "y0": 3210000, 305 | "long0": 0.17453292519943298, 306 | "lat0": 0.9075712110370515, 307 | "srsCode": "ETRS89-extended / LAEA Europe", 308 | "name": "ETRS89-extended / LAEA Europe", 309 | "title": "EPSG:3035" 310 | } 311 | }, { 312 | "code": {"$schema":"https://proj.org/schemas/v0.7/projjson.schema.json","type":"ProjectedCRS","name":"ETRS89-extended / LAEA Europe","base_crs":{"type":"GeographicCRS","name":"ETRS89","datum_ensemble":{"name":"European Terrestrial Reference System 1989 ensemble","members":[{"name":"European Terrestrial Reference Frame 1989","id":{"authority":"EPSG","code":1178}},{"name":"European Terrestrial Reference Frame 1990","id":{"authority":"EPSG","code":1179}},{"name":"European Terrestrial Reference Frame 1991","id":{"authority":"EPSG","code":1180}},{"name":"European Terrestrial Reference Frame 1992","id":{"authority":"EPSG","code":1181}},{"name":"European Terrestrial Reference Frame 1993","id":{"authority":"EPSG","code":1182}},{"name":"European Terrestrial Reference Frame 1994","id":{"authority":"EPSG","code":1183}},{"name":"European Terrestrial Reference Frame 1996","id":{"authority":"EPSG","code":1184}},{"name":"European Terrestrial Reference Frame 1997","id":{"authority":"EPSG","code":1185}},{"name":"European Terrestrial Reference Frame 2000","id":{"authority":"EPSG","code":1186}},{"name":"European Terrestrial Reference Frame 2005","id":{"authority":"EPSG","code":1204}},{"name":"European Terrestrial Reference Frame 2014","id":{"authority":"EPSG","code":1206}},{"name":"European Terrestrial Reference Frame 2020","id":{"authority":"EPSG","code":1382}}],"ellipsoid":{"name":"GRS 1980","semi_major_axis":6378137,"inverse_flattening":298.257222101},"accuracy":"0.1","id":{"authority":"EPSG","code":6258}},"coordinate_system":{"subtype":"ellipsoidal","axis":[{"name":"Geodetic latitude","abbreviation":"Lat","direction":"north","unit":"degree"},{"name":"Geodetic longitude","abbreviation":"Lon","direction":"east","unit":"degree"}]},"id":{"authority":"EPSG","code":4258}},"conversion":{"name":"Europe Equal Area 2001","method":{"name":"Lambert Azimuthal Equal Area","id":{"authority":"EPSG","code":9820}},"parameters":[{"name":"Latitude of natural origin","value":52,"unit":"degree","id":{"authority":"EPSG","code":8801}},{"name":"Longitude of natural origin","value":10,"unit":"degree","id":{"authority":"EPSG","code":8802}},{"name":"False easting","value":4321000,"unit":"metre","id":{"authority":"EPSG","code":8806}},{"name":"False northing","value":3210000,"unit":"metre","id":{"authority":"EPSG","code":8807}}]},"coordinate_system":{"subtype":"Cartesian","axis":[{"name":"Northing","abbreviation":"Y","direction":"north","unit":"metre"},{"name":"Easting","abbreviation":"X","direction":"east","unit":"metre"}]},"scope":"Statistical analysis.","area":"Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Türkiye (Turkey); United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.","bbox":{"south_latitude":24.6,"west_longitude":-35.58,"north_latitude":84.73,"east_longitude":44.83},"id":{"authority":"EPSG","code":3035}}, 313 | "value": { 314 | "projName": "Lambert Azimuthal Equal Area", 315 | "axis": "neu", 316 | "units": "meter", 317 | "to_meter": 1, 318 | "datumCode": "EPSG_4258", 319 | "ellps": "GRS 1980", 320 | "a": 6378137, 321 | "rf": 298.257222101, 322 | "x0": 4321000, 323 | "y0": 3210000, 324 | "long0": 0.17453292519943295, 325 | "lat0": 0.9075712110370514, 326 | "srsCode": "ETRS89-extended / LAEA Europe", 327 | "name": "ETRS89-extended / LAEA Europe", 328 | "title": "EPSG:3035" 329 | } 330 | }, { 331 | "code": "PROJCS[\"ETRS89 / ETRS-LAEA\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",52],PARAMETER[\"longitude_of_center\",10],PARAMETER[\"false_easting\",4321000],PARAMETER[\"false_northing\",3210000],AUTHORITY[\"EPSG\",\"3035\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]", 332 | "value": { 333 | "type": "PROJCS", 334 | "name": "ETRS89 / ETRS-LAEA", 335 | "GEOGCS": { 336 | "type": "GEOGCS", 337 | "name": "ETRS89", 338 | "DATUM": { 339 | "name": "European_Terrestrial_Reference_System_1989", 340 | "SPHEROID": { 341 | "name": "GRS 1980", 342 | "a": 6378137, 343 | "rf": 298.257222101, 344 | "AUTHORITY": { 345 | "EPSG": "7019" 346 | } 347 | }, 348 | "AUTHORITY": { 349 | "EPSG": "6258" 350 | } 351 | }, 352 | "PRIMEM": { 353 | "name": "greenwich", 354 | "convert": 0, 355 | "AUTHORITY": { 356 | "EPSG": "8901" 357 | } 358 | }, 359 | "UNIT": { 360 | "name": "degree", 361 | "convert": 0.01745329251994328, 362 | "AUTHORITY": { 363 | "EPSG": "9122" 364 | } 365 | }, 366 | "AUTHORITY": { 367 | "EPSG": "4258" 368 | }, 369 | "title": "EPSG:4258", 370 | "projName": "longlat", 371 | "units": "degree", 372 | "to_meter": 111319.49079327348, 373 | "datumCode": "european_terrestrial_reference_system_1989", 374 | "ellps": "GRS 1980", 375 | "a": 6378137, 376 | "rf": 298.257222101, 377 | "srsCode": "ETRS89" 378 | 379 | }, 380 | "UNIT": { 381 | "name": "metre", 382 | "convert": 1, 383 | "AUTHORITY": { 384 | "EPSG": "9001" 385 | } 386 | }, 387 | "PROJECTION": "Lambert_Azimuthal_Equal_Area", 388 | "latitude_of_center": 52, 389 | "longitude_of_center": 10, 390 | "false_easting": 4321000, 391 | "false_northing": 3210000, 392 | "AUTHORITY": { 393 | "EPSG": "3035" 394 | }, 395 | "AXIS": [ 396 | [ 397 | "X", 398 | "EAST" 399 | ], 400 | [ 401 | "Y", 402 | "NORTH" 403 | ] 404 | ], 405 | "title": "EPSG:3035", 406 | "projName": "Lambert_Azimuthal_Equal_Area", 407 | "axis": "enu", 408 | "units": "meter", 409 | "to_meter": 1, 410 | "datumCode": "european_terrestrial_reference_system_1989", 411 | "ellps": "GRS 1980", 412 | "a": 6378137, 413 | "rf": 298.257222101, 414 | "lat0": 0.9075712110370514, 415 | "longc": 0.17453292519943295, 416 | "x0": 4321000, 417 | "y0": 3210000, 418 | "srsCode": "ETRS89 / ETRS-LAEA", 419 | "long0": 0.17453292519943295 420 | } 421 | }, { 422 | "code": "GEOGCS[\"ETRS89\",DATUM[\"European Terrestrial Reference System 1989 ensemble\",SPHEROID[\"GRS 1980\",6378137,298.2572221,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9102\"]],AXIS[\"Lat\",north],AXIS[\"Lon\",east],AUTHORITY[\"EPSG\",\"4258\"]]", 423 | "value": { 424 | "type": "GEOGCS", 425 | "name": "ETRS89", 426 | "DATUM": { 427 | "name": "European Terrestrial Reference System 1989 ensemble", 428 | "SPHEROID": { 429 | "name": "GRS 1980", 430 | "a": 6378137, 431 | "rf": 298.2572221, 432 | "AUTHORITY": { 433 | "EPSG": "7019" 434 | } 435 | }, 436 | "AUTHORITY": { 437 | "EPSG": "6258" 438 | } 439 | }, 440 | "PRIMEM": { 441 | "name": "greenwich", 442 | "convert": 0, 443 | "AUTHORITY": { 444 | "EPSG": "8901" 445 | } 446 | }, 447 | "UNIT": { 448 | "name": "degree", 449 | "convert": 0.0174532925199433, 450 | "AUTHORITY": { 451 | "EPSG": "9102" 452 | } 453 | }, 454 | "AXIS": [ 455 | [ 456 | "Lat", 457 | "north" 458 | ], 459 | [ 460 | "Lon", 461 | "east" 462 | ] 463 | ], 464 | "AUTHORITY": { 465 | "EPSG": "4258" 466 | }, 467 | "title": "EPSG:4258", 468 | "projName": "longlat", 469 | "units": "degree", 470 | "to_meter": 111319.4907932736, 471 | "datumCode": "european terrestrial reference system 1989 ensemble", 472 | "ellps": "GRS 1980", 473 | "a": 6378137, 474 | "rf": 298.2572221, 475 | "axis": "neu", 476 | "srsCode": "ETRS89" 477 | } 478 | }, { 479 | "strict": true, 480 | "code": "COMPD_CS[\"unknown\",PROJCS[\"NAD83 / Texas North Central\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101004,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"latitude_of_origin\",31.6666666666667],PARAMETER[\"central_meridian\",-98.5],PARAMETER[\"standard_parallel_1\",32.1333333333333],PARAMETER[\"standard_parallel_2\",33.9666666666667],PARAMETER[\"false_easting\",1968500],PARAMETER[\"false_northing\",6561666.66666667],UNIT[\"US survey foot\",0.304800609601219,AUTHORITY[\"EPSG\",\"9003\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"32138\"]],VERT_CS[\"NAVD88 height (ftUS)\",VERT_DATUM[\"North American Vertical Datum 1988\",2005,AUTHORITY[\"EPSG\",\"5103\"]],UNIT[\"US survey foot\",0.304800609601219,AUTHORITY[\"EPSG\",\"9003\"]],AXIS[\"Up\",UP],AUTHORITY[\"EPSG\",\"6360\"]]]", 481 | "value": { 482 | "type": "COMPD_CS", 483 | "name": "unknown", 484 | "PROJCS": { 485 | "type": "PROJCS", 486 | "name": "NAD83 / Texas North Central", 487 | "GEOGCS": { 488 | "type": "GEOGCS", 489 | "name": "NAD83", 490 | "DATUM": { 491 | "name": "North_American_Datum_1983", 492 | "SPHEROID": { 493 | "name": "GRS 1980", 494 | "a": 6378137, 495 | "rf": 298.257222101004, 496 | "AUTHORITY": { 497 | "EPSG": "7019" 498 | } 499 | }, 500 | "AUTHORITY": { 501 | "EPSG": "6269" 502 | } 503 | }, 504 | "PRIMEM": { 505 | "name": "greenwich", 506 | "convert": 0 507 | }, 508 | "UNIT": { 509 | "name": "degree", 510 | "convert": 0.0174532925199433, 511 | "AUTHORITY": { 512 | "EPSG": "9122" 513 | } 514 | }, 515 | "AUTHORITY": { 516 | "EPSG": "4269" 517 | }, 518 | "title": "EPSG:4269", 519 | "projName": "longlat", 520 | "units": "degree", 521 | "to_meter": 111319.4907932736, 522 | "datumCode": "north_american_datum_1983", 523 | "ellps": "GRS 1980", 524 | "a": 6378137, 525 | "rf": 298.257222101004, 526 | "srsCode": "NAD83" 527 | }, 528 | "PROJECTION": "Lambert_Conformal_Conic_2SP", 529 | "latitude_of_origin": 31.6666666666667, 530 | "central_meridian": -98.5, 531 | "standard_parallel_1": 32.1333333333333, 532 | "standard_parallel_2": 33.9666666666667, 533 | "false_easting": 1968500, 534 | "false_northing": 6561666.66666667, 535 | "UNIT": { 536 | "name": "us survey foot", 537 | "convert": 0.304800609601219, 538 | "AUTHORITY": { 539 | "EPSG": "9003" 540 | } 541 | }, 542 | "AXIS": [ 543 | [ 544 | "Easting", 545 | "EAST" 546 | ], 547 | [ 548 | "Northing", 549 | "NORTH" 550 | ] 551 | ], 552 | "AUTHORITY": { 553 | "EPSG": "32138" 554 | }, 555 | "title": "EPSG:32138", 556 | "projName": "Lambert_Conformal_Conic_2SP", 557 | "axis": "enu", 558 | "units": "us survey foot", 559 | "to_meter": 0.304800609601219, 560 | "datumCode": "north_american_datum_1983", 561 | "ellps": "GRS 1980", 562 | "a": 6378137, 563 | "rf": 298.257222101004, 564 | "x0": 599999.9999999997, 565 | "y0": 1999999.9999999998, 566 | "long0": -1.7191493132144147, 567 | "lat0": 0.5526875964648716, 568 | "lat1": 0.5608324663075106, 569 | "lat2": 0.5928301692607412, 570 | "srsCode": "NAD83 / Texas North Central" 571 | }, 572 | "VERT_CS": { 573 | "name": "NAVD88 height (ftUS)", 574 | "VERT_DATUM": { 575 | "name": "north american vertical datum 1988", 576 | "convert": 2005, 577 | "AUTHORITY": { 578 | "EPSG": "5103" 579 | } 580 | }, 581 | "UNIT": { 582 | "name": "us survey foot", 583 | "convert": 0.304800609601219, 584 | "AUTHORITY": { 585 | "EPSG": "9003" 586 | } 587 | }, 588 | "AXIS": [ 589 | [ 590 | "Up", 591 | "UP" 592 | ] 593 | ], 594 | "AUTHORITY": { 595 | "EPSG": "6360" 596 | } 597 | } 598 | } 599 | }, { 600 | "code": "PROJCRS[\"WGS 84 / Antarctic Polar Stereographic\",BASEGEOGCRS[\"WGS 84\",ENSEMBLE[\"World Geodetic System 1984 ensemble\",MEMBER[\"World Geodetic System 1984 (Transit)\"],MEMBER[\"World Geodetic System 1984 (G730)\"],MEMBER[\"World Geodetic System 1984 (G873)\"],MEMBER[\"World Geodetic System 1984 (G1150)\"],MEMBER[\"World Geodetic System 1984 (G1674)\"],MEMBER[\"World Geodetic System 1984 (G1762)\"],MEMBER[\"World Geodetic System 1984 (G2139)\"],MEMBER[\"World Geodetic System 1984 (G2296)\"],ELLIPSOID[\"WGS 84\",6378137,298.257223563,LENGTHUNIT[\"metre\",1]],ENSEMBLEACCURACY[2.0]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4326]],CONVERSION[\"Antarctic Polar Stereographic\",METHOD[\"Polar Stereographic (variant B)\",ID[\"EPSG\",9829]],PARAMETER[\"Latitude of standard parallel\",-71,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8832]],PARAMETER[\"Longitude of origin\",0,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8833]],PARAMETER[\"False easting\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8807]]],CS[Cartesian,2],AXIS[\"(E)\",north,MERIDIAN[90,ANGLEUNIT[\"degree\",0.0174532925199433]],ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"(N)\",north,MERIDIAN[0,ANGLEUNIT[\"degree\",0.0174532925199433]],ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Antarctic Digital Database and small scale topographic mapping.\"],AREA[\"Antarctica.\"],BBOX[-90,-180,-60,180]],ID[\"EPSG\",3031]]", 601 | "value": { 602 | "projName": "Polar Stereographic (variant B)", 603 | "axis": "enu", 604 | "units": "meter", 605 | "to_meter": 1, 606 | "datumCode": "EPSG_4326", 607 | "ellps": "WGS 84", 608 | "a": 6378137, 609 | "rf": 298.257223563, 610 | "x0": 0, 611 | "y0": 0, 612 | "long0": 0, 613 | "lat0": -1.5707963267948966, 614 | "lat_ts": -1.2391837689159741, 615 | "srsCode": "WGS 84 / Antarctic Polar Stereographic", 616 | "name": "WGS 84 / Antarctic Polar Stereographic", 617 | "title": "EPSG:3031" 618 | } 619 | }, { 620 | "code": "PROJCS[\"WGS 84 / Antarctic Polar Stereographic\",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.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Polar_Stereographic\"],PARAMETER[\"latitude_of_origin\",-71],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"3031\"],AXIS[\"Easting\",UNKNOWN],AXIS[\"Northing\",UNKNOWN]]", 621 | "value": { 622 | "type": "PROJCS", 623 | "name": "WGS 84 / Antarctic Polar Stereographic", 624 | "GEOGCS": { 625 | "type": "GEOGCS", 626 | "name": "WGS 84", 627 | "DATUM": { 628 | "name": "WGS_1984", 629 | "SPHEROID": { 630 | "name": "WGS 84", 631 | "a": 6378137, 632 | "rf": 298.257223563, 633 | "AUTHORITY": { 634 | "EPSG": "7030" 635 | } 636 | }, 637 | "AUTHORITY": { 638 | "EPSG": "6326" 639 | } 640 | }, 641 | "PRIMEM": { 642 | "name": "greenwich", 643 | "convert": 0, 644 | "AUTHORITY": { 645 | "EPSG": "8901" 646 | } 647 | }, 648 | "UNIT": { 649 | "name": "degree", 650 | "convert": 0.01745329251994328, 651 | "AUTHORITY": { 652 | "EPSG": "9122" 653 | } 654 | }, 655 | "AUTHORITY": { 656 | "EPSG": "4326" 657 | }, 658 | "title": "EPSG:4326", 659 | "projName": "longlat", 660 | "units": "degree", 661 | "to_meter": 111319.49079327348, 662 | "datumCode": "wgs84", 663 | "ellps": "WGS 84", 664 | "a": 6378137, 665 | "rf": 298.257223563, 666 | "srsCode": "WGS 84" 667 | }, 668 | "UNIT": { 669 | "name": "metre", 670 | "convert": 1, 671 | "AUTHORITY": { 672 | "EPSG": "9001" 673 | } 674 | }, 675 | "PROJECTION": "Polar_Stereographic", 676 | "latitude_of_origin": -71, 677 | "central_meridian": 0, 678 | "scale_factor": 1, 679 | "false_easting": 0, 680 | "false_northing": 0, 681 | "AUTHORITY": { 682 | "EPSG": "3031" 683 | }, 684 | "AXIS": [ 685 | [ 686 | "Easting", 687 | "UNKNOWN" 688 | ], 689 | [ 690 | "Northing", 691 | "UNKNOWN" 692 | ] 693 | ], 694 | "title": "EPSG:3031", 695 | "projName": "Polar_Stereographic", 696 | "axis": "enu", 697 | "units": "meter", 698 | "to_meter": 1, 699 | "datumCode": "wgs84", 700 | "ellps": "WGS 84", 701 | "a": 6378137, 702 | "rf": 298.257223563, 703 | "k0": 1, 704 | "x0": 0, 705 | "y0": 0, 706 | "long0": 0, 707 | "lat0": -1.5707963267948966, 708 | "srsCode": "WGS 84 / Antarctic Polar Stereographic", 709 | "lat_ts": -1.239183768915974 710 | } 711 | }, { 712 | "code": "PROJCRS[\"CH1903 / LV03\",BASEGEOGCRS[\"CH1903\",DATUM[\"CH1903\",ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4149]],CONVERSION[\"Swiss Oblique Mercator 1903M\",METHOD[\"Hotine Oblique Mercator (variant B)\",ID[\"EPSG\",9815]],PARAMETER[\"Latitude of projection centre\",46.9524055555556,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8811]],PARAMETER[\"Longitude of projection centre\",7.43958333333333,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8812]],PARAMETER[\"Azimuth at projection centre\",90,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8813]],PARAMETER[\"Angle from Rectified to Skew Grid\",90,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8814]],PARAMETER[\"Scale factor at projection centre\",1,SCALEUNIT[\"unity\",1],ID[\"EPSG\",8815]],PARAMETER[\"Easting at projection centre\",600000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8816]],PARAMETER[\"Northing at projection centre\",200000,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8817]]],CS[Cartesian,2],AXIS[\"easting (Y)\",east,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"northing (X)\",north,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Cadastre, engineering survey, topographic mapping (large and medium scale).\"],AREA[\"Liechtenstein; Switzerland.\"],BBOX[45.82,5.96,47.81,10.49]],ID[\"EPSG\",21781]]", 713 | "value": { 714 | "projName": "Hotine Oblique Mercator (variant B)", 715 | "axis": "enu", 716 | "units": "meter", 717 | "to_meter": 1, 718 | "datumCode": "EPSG_4149", 719 | "ellps": "Bessel 1841", 720 | "a": 6377397.155, 721 | "rf": 299.1528128, 722 | "k0": 1, 723 | "x0": 600000, 724 | "y0": 200000, 725 | "longc": 0.12984522414316144, 726 | "lat0": 0.8194740686761227, 727 | "alpha": 1.570796326794897, 728 | "rectified_grid_angle": 1.570796326794897, 729 | "srsCode": "CH1903 / LV03", 730 | "name": "CH1903 / LV03", 731 | "title": "EPSG:21781" 732 | } 733 | }, { 734 | "code": "PROJCRS[\"CH1903 / LV03\",BASEGEOGCRS[\"CH1903\",DATUM[\"CH1903\",ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",7004]],ID[\"EPSG\",6149]],ID[\"EPSG\",4149]],CONVERSION[\"Swiss Oblique Mercator 1903M\",METHOD[\"Hotine Oblique Mercator (variant B)\",ID[\"EPSG\",9815]],PARAMETER[\"Latitude of projection centre\",46.9524055555558,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8811]],PARAMETER[\"Longitude of projection centre\",7.43958333333361,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8812]],PARAMETER[\"Azimuth at projection centre\",90,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8813]],PARAMETER[\"Angle from Rectified to Skew Grid\",90,ANGLEUNIT[\"degree\",0.0174532925199433,ID[\"EPSG\",9102]],ID[\"EPSG\",8814]],PARAMETER[\"Scale factor at projection centre\",1,SCALEUNIT[\"unity\",1,ID[\"EPSG\",9201]],ID[\"EPSG\",8815]],PARAMETER[\"Easting at projection centre\",600000,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",8816]],PARAMETER[\"Northing at projection centre\",200000,LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",8817]],ID[\"EPSG\",19922]],CS[Cartesian,2,ID[\"EPSG\",4498]],AXIS[\"Easting (Y)\",east],AXIS[\"Northing (X)\",north],LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],ID[\"EPSG\",21781]]", 735 | "value": { 736 | "projName": "Hotine Oblique Mercator (variant B)", 737 | "axis": "enu", 738 | "units": "meter", 739 | "to_meter": 1, 740 | "datumCode": "EPSG_4149", 741 | "ellps": "Bessel 1841", 742 | "a": 6377397.155, 743 | "rf": 299.1528128, 744 | "k0": 1, 745 | "x0": 600000, 746 | "y0": 200000, 747 | "longc": 0.12984522414316635, 748 | "lat0": 0.8194740686761263, 749 | "alpha": 1.570796326794897, 750 | "rectified_grid_angle": 1.570796326794897, 751 | "srsCode": "CH1903 / LV03", 752 | "name": "CH1903 / LV03", 753 | "title": "EPSG:21781" 754 | } 755 | }, { 756 | "code": {"$schema":"https://proj.org/schemas/v0.7/projjson.schema.json","type":"ProjectedCRS","name":"CH1903 / LV03","base_crs":{"type":"GeographicCRS","name":"CH1903","datum":{"type":"GeodeticReferenceFrame","name":"CH1903","ellipsoid":{"name":"Bessel 1841","semi_major_axis":6377397.155,"inverse_flattening":299.1528128}},"coordinate_system":{"subtype":"ellipsoidal","axis":[{"name":"Geodetic latitude","abbreviation":"Lat","direction":"north","unit":"degree"},{"name":"Geodetic longitude","abbreviation":"Lon","direction":"east","unit":"degree"}]},"id":{"authority":"EPSG","code":4149}},"conversion":{"name":"Swiss Oblique Mercator 1903M","method":{"name":"Hotine Oblique Mercator (variant B)","id":{"authority":"EPSG","code":9815}},"parameters":[{"name":"Latitude of projection centre","value":46.9524055555556,"unit":"degree","id":{"authority":"EPSG","code":8811}},{"name":"Longitude of projection centre","value":7.43958333333333,"unit":"degree","id":{"authority":"EPSG","code":8812}},{"name":"Azimuth at projection centre","value":90,"unit":"degree","id":{"authority":"EPSG","code":8813}},{"name":"Angle from Rectified to Skew Grid","value":90,"unit":"degree","id":{"authority":"EPSG","code":8814}},{"name":"Scale factor at projection centre","value":1,"unit":"unity","id":{"authority":"EPSG","code":8815}},{"name":"Easting at projection centre","value":600000,"unit":"metre","id":{"authority":"EPSG","code":8816}},{"name":"Northing at projection centre","value":200000,"unit":"metre","id":{"authority":"EPSG","code":8817}}]},"coordinate_system":{"subtype":"Cartesian","axis":[{"name":"Easting","abbreviation":"Y","direction":"east","unit":"metre"},{"name":"Northing","abbreviation":"X","direction":"north","unit":"metre"}]},"scope":"Cadastre, engineering survey, topographic mapping (large and medium scale).","area":"Liechtenstein; Switzerland.","bbox":{"south_latitude":45.82,"west_longitude":5.96,"north_latitude":47.81,"east_longitude":10.49},"id":{"authority":"EPSG","code":21781}}, 757 | "value": { 758 | "projName": "Hotine Oblique Mercator (variant B)", 759 | "axis": "enu", 760 | "units": "meter", 761 | "to_meter": 1, 762 | "datumCode": "EPSG_4149", 763 | "ellps": "Bessel 1841", 764 | "a": 6377397.155, 765 | "rf": 299.1528128, 766 | "k0": 1, 767 | "x0": 600000, 768 | "y0": 200000, 769 | "longc": 0.1298452241431614, 770 | "lat0": 0.8194740686761226, 771 | "alpha": 1.5707963267948966, 772 | "rectified_grid_angle": 1.5707963267948966, 773 | "srsCode": "CH1903 / LV03", 774 | "name": "CH1903 / LV03", 775 | "title": "EPSG:21781" 776 | } 777 | }, { 778 | "code": "PROJCS[\"CH1903 / LV03\",GEOGCS[\"CH1903\",DATUM[\"CH1903\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],TOWGS84[674.4,15.1,405.3,0,0,0,0],AUTHORITY[\"EPSG\",\"6149\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4149\"]],PROJECTION[\"Hotine_Oblique_Mercator_Azimuth_Center\"],PARAMETER[\"latitude_of_center\",46.95240555555556],PARAMETER[\"longitude_of_center\",7.439583333333333],PARAMETER[\"azimuth\",90],PARAMETER[\"rectified_grid_angle\",90],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",600000],PARAMETER[\"false_northing\",200000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Y\",EAST],AXIS[\"X\",NORTH],AUTHORITY[\"EPSG\",\"21781\"]]", 779 | "value": { 780 | "projName": "Hotine_Oblique_Mercator_Azimuth_Center", 781 | "units": "meter", 782 | "to_meter": 1, 783 | "datumCode": "ch1903", 784 | "datum_params": [ 785 | 674.4, 15.1, 405.3, 786 | 0, 0, 0, 787 | 0 788 | ], 789 | "ellps": "Bessel 1841", 790 | "a": 6377397.155, 791 | "rf": 299.1528128, 792 | "k0": 1, 793 | "x0": 600000, 794 | "y0": 200000, 795 | "longc": 0.12984522414316146, 796 | "lat0": 0.8194740686761218, 797 | "alpha": 1.5707963267948966, 798 | "rectified_grid_angle": 1.5707963267948966, 799 | "srsCode": "CH1903 / LV03", 800 | "name": "CH1903 / LV03", 801 | "title": "EPSG:21781" 802 | } 803 | }, { 804 | "code": "PROJCRS[\"Mount Dillon / Tobago Grid\",BASEGEOGCRS[\"Mount Dillon\",DATUM[\"Mount Dillon\",ELLIPSOID[\"Clarke 1858\",20926348,294.260676369261,LENGTHUNIT[\"Clarke's foot\",0.3047972654]]],PRIMEM[\"Greenwich\",0,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4157]],CONVERSION[\"Tobago Grid\",METHOD[\"Cassini-Soldner\",ID[\"EPSG\",9806]],PARAMETER[\"Latitude of natural origin\",11.2521786111111,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8801]],PARAMETER[\"Longitude of natural origin\",-60.6860088888889,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8802]],PARAMETER[\"False easting\",187500,LENGTHUNIT[\"Clarke's link\",0.201166195164],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",180000,LENGTHUNIT[\"Clarke's link\",0.201166195164],ID[\"EPSG\",8807]]],CS[Cartesian,2],AXIS[\"(E)\",east,ORDER[1],LENGTHUNIT[\"Clarke's link\",0.201166195164]],AXIS[\"(N)\",north,ORDER[2],LENGTHUNIT[\"Clarke's link\",0.201166195164]],USAGE[SCOPE[\"Engineering survey, topographic mapping.\"],AREA[\"Trinidad and Tobago - Tobago - onshore.\"],BBOX[11.08,-60.9,11.41,-60.44]],ID[\"EPSG\",2066]]", 805 | "value": { 806 | "projName": "Cassini-Soldner", 807 | "axis": "enu", 808 | "units": "clarke's link", 809 | "to_meter": 0.201166195164, 810 | "datumCode": "EPSG_4157", 811 | "ellps": "Clarke 1858", 812 | "a": 6378293.645208759, 813 | "rf": 294.260676369261, 814 | "x0": 37718.66159325, 815 | "y0": 36209.91512952, 816 | "long0": -1.0591706650056572, 817 | "lat0": 0.19638756478637134, 818 | "srsCode": "Mount Dillon / Tobago Grid", 819 | "name": "Mount Dillon / Tobago Grid", 820 | "title": "EPSG:2066" 821 | } 822 | }, { 823 | "code": {"$schema":"https://proj.org/schemas/v0.7/projjson.schema.json","type":"ProjectedCRS","name":"Mount Dillon / Tobago Grid","base_crs":{"type":"GeographicCRS","name":"Mount Dillon","datum":{"type":"GeodeticReferenceFrame","name":"Mount Dillon","ellipsoid":{"name":"Clarke 1858","semi_major_axis":{"value":20926348,"unit":{"type":"LinearUnit","name":"Clarke's foot","conversion_factor":0.3047972654}},"semi_minor_axis":{"value":20855233,"unit":{"type":"LinearUnit","name":"Clarke's foot","conversion_factor":0.3047972654}}}},"coordinate_system":{"subtype":"ellipsoidal","axis":[{"name":"Geodetic latitude","abbreviation":"Lat","direction":"north","unit":"degree"},{"name":"Geodetic longitude","abbreviation":"Lon","direction":"east","unit":"degree"}]},"id":{"authority":"EPSG","code":4157}},"conversion":{"name":"Tobago Grid","method":{"name":"Cassini-Soldner","id":{"authority":"EPSG","code":9806}},"parameters":[{"name":"Latitude of natural origin","value":11.2521786111111,"unit":"degree","id":{"authority":"EPSG","code":8801}},{"name":"Longitude of natural origin","value":-60.6860088888889,"unit":"degree","id":{"authority":"EPSG","code":8802}},{"name":"False easting","value":187500,"unit":{"type":"LinearUnit","name":"Clarke's link","conversion_factor":0.201166195164},"id":{"authority":"EPSG","code":8806}},{"name":"False northing","value":180000,"unit":{"type":"LinearUnit","name":"Clarke's link","conversion_factor":0.201166195164},"id":{"authority":"EPSG","code":8807}}]},"coordinate_system":{"subtype":"Cartesian","axis":[{"name":"Easting","abbreviation":"E","direction":"east","unit":{"type":"LinearUnit","name":"Clarke's link","conversion_factor":0.201166195164}},{"name":"Northing","abbreviation":"N","direction":"north","unit":{"type":"LinearUnit","name":"Clarke's link","conversion_factor":0.201166195164}}]},"scope":"Engineering survey, topographic mapping.","area":"Trinidad and Tobago - Tobago - onshore.","bbox":{"south_latitude":11.08,"west_longitude":-60.9,"north_latitude":11.41,"east_longitude":-60.44},"id":{"authority":"EPSG","code":2066}}, 824 | "value": { 825 | "projName": "Cassini-Soldner", 826 | "axis": "enu", 827 | "units": "clarke's link", 828 | "to_meter": 0.201166195164, 829 | "datumCode": "EPSG_4157", 830 | "ellps": "Clarke 1858", 831 | "a": 6378293.645208759, 832 | "rf": 294.26067636926064, 833 | "x0": 37718.66159325, 834 | "y0": 36209.91512952, 835 | "long0": -1.059170665005657, 836 | "lat0": 0.19638756478637132, 837 | "srsCode": "Mount Dillon / Tobago Grid", 838 | "name": "Mount Dillon / Tobago Grid", 839 | "title": "EPSG:2066" 840 | } 841 | }, { 842 | "code": "PROJCS[\"Mount Dillon / Tobago Grid\",GEOGCS[\"Mount Dillon\",DATUM[\"Mount_Dillon\",SPHEROID[\"Clarke 1858\",6378293.645208759,294.2606763692654,AUTHORITY[\"EPSG\",\"7007\"]],AUTHORITY[\"EPSG\",\"6157\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4157\"]],UNIT[\"Clarke's link\",0.201166195164,AUTHORITY[\"EPSG\",\"9039\"]],PROJECTION[\"Cassini_Soldner\"],PARAMETER[\"latitude_of_origin\",11.25217861111111],PARAMETER[\"central_meridian\",-60.68600888888889],PARAMETER[\"false_easting\",187500],PARAMETER[\"false_northing\",180000],AUTHORITY[\"EPSG\",\"2066\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", 843 | "value": { 844 | "projName": "Cassini_Soldner", 845 | "axis": "enu", 846 | "units": "clarke's link", 847 | "to_meter": 0.201166195164, 848 | "datumCode": "mount_dillon", 849 | "ellps": "Clarke 1858", 850 | "a": 6378293.645208759, 851 | "rf": 294.2606763692654, 852 | "x0": 37718.66159325, 853 | "y0": 36209.91512952, 854 | "long0": -1.059170665005657, 855 | "lat0": 0.19638756478637148, 856 | "srsCode": "Mount Dillon / Tobago Grid", 857 | "name": "Mount Dillon / Tobago Grid", 858 | "title": "EPSG:2066" 859 | } 860 | }, { 861 | "code": {"$schema":"https://proj.org/schemas/v0.7/projjson.schema.json","type":"ProjectedCRS","name":"World Equidistant Cylindrical (Sphere)","base_crs":{"type":"GeographicCRS","name":"Unspecified datum based upon the GRS 1980 Authalic Sphere","datum":{"type":"GeodeticReferenceFrame","name":"Not specified (based on GRS 1980 Authalic Sphere)","ellipsoid":{"name":"GRS 1980 Authalic Sphere","radius":6371007}},"coordinate_system":{"subtype":"ellipsoidal","axis":[{"name":"Geodetic latitude","abbreviation":"Lat","direction":"north","unit":"degree"},{"name":"Geodetic longitude","abbreviation":"Lon","direction":"east","unit":"degree"}]},"id":{"authority":"EPSG","code":4047}},"conversion":{"name":"World Equidistant Cylindrical (Sphere)","method":{"name":"Equidistant Cylindrical (Spherical)","id":{"authority":"EPSG","code":1029}},"parameters":[{"name":"Latitude of 1st standard parallel","value":0,"unit":"degree","id":{"authority":"EPSG","code":8823}},{"name":"Longitude of natural origin","value":0,"unit":"degree","id":{"authority":"EPSG","code":8802}},{"name":"False easting","value":0,"unit":"metre","id":{"authority":"EPSG","code":8806}},{"name":"False northing","value":0,"unit":"metre","id":{"authority":"EPSG","code":8807}}]},"coordinate_system":{"subtype":"Cartesian","axis":[{"name":"Easting","abbreviation":"X","direction":"east","unit":"metre"},{"name":"Northing","abbreviation":"Y","direction":"north","unit":"metre"}]},"scope":"Web mapping and visualisation.","area":"World.","bbox":{"south_latitude":-90,"west_longitude":-180,"north_latitude":90,"east_longitude":180},"id":{"authority":"EPSG","code":4088}}, 862 | "value": { 863 | "projName": "Equidistant Cylindrical (Spherical)", 864 | "axis": "enu", 865 | "units": "meter", 866 | "to_meter": 1, 867 | "datumCode": "EPSG_4047", 868 | "ellps": "GRS 1980 Authalic Sphere", 869 | "a": 6371007, 870 | "rf": 0, 871 | "x0": 0, 872 | "y0": 0, 873 | "lat1": 0, 874 | "long0": 0, 875 | "srsCode": "World Equidistant Cylindrical (Sphere)", 876 | "name": "World Equidistant Cylindrical (Sphere)", 877 | "title": "EPSG:4088" 878 | } 879 | }, 880 | { 881 | "code": "PROJCS[\"World Equidistant Cylindrical (Sphere)\",GEOGCS[\"Unspecified datum based upon the GRS 1980 Authalic Sphere\",DATUM[\"D_\",SPHEROID[\"GRS_1980_Authalic_Sphere\",6371007,0]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]],PROJECTION[\"Equidistant_Cylindrical\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]", 882 | "value": { 883 | "projName": "Equidistant_Cylindrical", 884 | "units": "meter", 885 | "to_meter": 1, 886 | "datumCode": "", 887 | "ellps": "GRS80_Authalic_Sphere", 888 | "a": 6371007, 889 | "rf": 0, 890 | "x0": 0, 891 | "y0": 0, 892 | "long0": 0, 893 | "srsCode": "World Equidistant Cylindrical (Sphere)", 894 | "name": "World Equidistant Cylindrical (Sphere)" 895 | } 896 | }, { 897 | "code": "PROJCRS[\"S-JTSK (Ferro) / Krovak\",BASEGEOGCRS[\"S-JTSK (Ferro)\",DATUM[\"System of the Unified Trigonometrical Cadastral Network (Ferro)\",ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,LENGTHUNIT[\"metre\",1]]],PRIMEM[\"Ferro\",-17.6666666666667,ANGLEUNIT[\"degree\",0.0174532925199433]],ID[\"EPSG\",4818]],CONVERSION[\"Krovak\",METHOD[\"Krovak\",ID[\"EPSG\",9819]],PARAMETER[\"Latitude of projection centre\",49.5,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8811]],PARAMETER[\"Longitude of origin\",42.5,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8833]],PARAMETER[\"Co-latitude of cone axis\",30.2881397527778,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",1036]],PARAMETER[\"Latitude of pseudo standard parallel\",78.5,ANGLEUNIT[\"degree\",0.0174532925199433],ID[\"EPSG\",8818]],PARAMETER[\"Scale factor on pseudo standard parallel\",0.9999,SCALEUNIT[\"unity\",1],ID[\"EPSG\",8819]],PARAMETER[\"False easting\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8806]],PARAMETER[\"False northing\",0,LENGTHUNIT[\"metre\",1],ID[\"EPSG\",8807]]],CS[Cartesian,2],AXIS[\"southing (X)\",south,ORDER[1],LENGTHUNIT[\"metre\",1]],AXIS[\"westing (Y)\",west,ORDER[2],LENGTHUNIT[\"metre\",1]],USAGE[SCOPE[\"Cadastre in Czechia.\"],AREA[\"Czechia; Slovakia.\"],BBOX[47.73,12.09,51.06,22.56]],ID[\"EPSG\",2065]]", 898 | "value": { 899 | "projName": "Krovak", 900 | "axis": "swu", 901 | "units": "meter", 902 | "to_meter": 1, 903 | "datumCode": "EPSG_4818", 904 | "ellps": "Bessel 1841", 905 | "from_greenwich": -0.30834150118566545, 906 | "a": 6377397.155, 907 | "rf": 299.1528128, 908 | "k0": 0.9999, 909 | "x0": 0, 910 | "y0": 0, 911 | "long0": 0.7417649320975902, 912 | "lat0": 0.8639379797371933, 913 | "srsCode": "S-JTSK (Ferro) / Krovak", 914 | "name": "S-JTSK (Ferro) / Krovak", 915 | "title": "EPSG:2065" 916 | } 917 | }, { 918 | "code": "PROJCS[\"GDM2000 / Peninsula RSO\", GEOGCS[\"GDM2000\", DATUM[\"Geodetic_Datum_of_Malaysia_2000\", SPHEROID[\"GRS 1980\",6378137,298.257222101, AUTHORITY[\"EPSG\",\"7019\"]], AUTHORITY[\"EPSG\",\"6742\"]], PRIMEM[\"Greenwich\",0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\",0.0174532925199433, AUTHORITY[\"EPSG\",\"9122\"]], AUTHORITY[\"EPSG\",\"4742\"]], PROJECTION[\"Hotine_Oblique_Mercator\"], PARAMETER[\"latitude_of_center\",4], PARAMETER[\"longitude_of_center\",102.25], PARAMETER[\"azimuth\",323.0257964666666], PARAMETER[\"rectified_grid_angle\",323.1301023611111], PARAMETER[\"scale_factor\",0.99984], PARAMETER[\"false_easting\",804671], PARAMETER[\"false_northing\",0], UNIT[\"metre\",1, AUTHORITY[\"EPSG\",\"9001\"]], AXIS[\"Easting\",EAST], AXIS[\"Northing\",NORTH], AUTHORITY[\"EPSG\",\"3375\"]]", 919 | "value": { 920 | "projName": "Hotine_Oblique_Mercator", 921 | "axis": "enu", 922 | "units": "meter", 923 | "to_meter": 1, 924 | "datumCode": "geodetic_datum_of_malaysia_2000", 925 | "ellps": "GRS 1980", 926 | "a": 6378137, 927 | "rf": 298.257222101, 928 | "k0": 0.99984, 929 | "x0": 804671, 930 | "y0": 0, 931 | "longc": 1.784599160164202, 932 | "lat0": 0.06981317007977318, 933 | "alpha": 5.637863717220397, 934 | "rectified_grid_angle": 5.639684198507691, 935 | "srsCode": "GDM2000 / Peninsula RSO", 936 | "name": "GDM2000 / Peninsula RSO", 937 | "title": "EPSG:3375" 938 | } 939 | }, { 940 | "code": { 941 | "$schema": "https://proj.org/schemas/v0.7/projjson.schema.json", 942 | "type": "ProjectedCRS", 943 | "name": "GDM2000 / Peninsula RSO", 944 | "base_crs": { 945 | "type": "GeographicCRS", 946 | "name": "GDM2000", 947 | "datum": { 948 | "type": "GeodeticReferenceFrame", 949 | "name": "Geodetic Datum of Malaysia 2000", 950 | "ellipsoid": { 951 | "name": "GRS 1980", 952 | "semi_major_axis": 6378137, 953 | "inverse_flattening": 298.257222101 954 | } 955 | }, 956 | "coordinate_system": { 957 | "subtype": "ellipsoidal", 958 | "axis": [ 959 | { 960 | "name": "Geodetic latitude", 961 | "abbreviation": "Lat", 962 | "direction": "north", 963 | "unit": "degree" 964 | }, 965 | { 966 | "name": "Geodetic longitude", 967 | "abbreviation": "Lon", 968 | "direction": "east", 969 | "unit": "degree" 970 | } 971 | ] 972 | }, 973 | "id": { 974 | "authority": "EPSG", 975 | "code": 4742 976 | } 977 | }, 978 | "conversion": { 979 | "name": "Peninsular RSO", 980 | "method": { 981 | "name": "Hotine Oblique Mercator (variant A)", 982 | "id": { 983 | "authority": "EPSG", 984 | "code": 9812 985 | } 986 | }, 987 | "parameters": [ 988 | { 989 | "name": "Latitude of projection centre", 990 | "value": 4, 991 | "unit": "degree", 992 | "id": { 993 | "authority": "EPSG", 994 | "code": 8811 995 | } 996 | }, 997 | { 998 | "name": "Longitude of projection centre", 999 | "value": 102.25, 1000 | "unit": "degree", 1001 | "id": { 1002 | "authority": "EPSG", 1003 | "code": 8812 1004 | } 1005 | }, 1006 | { 1007 | "name": "Azimuth at projection centre", 1008 | "value": 323.025796466667, 1009 | "unit": "degree", 1010 | "id": { 1011 | "authority": "EPSG", 1012 | "code": 8813 1013 | } 1014 | }, 1015 | { 1016 | "name": "Angle from Rectified to Skew Grid", 1017 | "value": 323.130102361111, 1018 | "unit": "degree", 1019 | "id": { 1020 | "authority": "EPSG", 1021 | "code": 8814 1022 | } 1023 | }, 1024 | { 1025 | "name": "Scale factor at projection centre", 1026 | "value": 0.99984, 1027 | "unit": "unity", 1028 | "id": { 1029 | "authority": "EPSG", 1030 | "code": 8815 1031 | } 1032 | }, 1033 | { 1034 | "name": "False easting", 1035 | "value": 804671, 1036 | "unit": "metre", 1037 | "id": { 1038 | "authority": "EPSG", 1039 | "code": 8806 1040 | } 1041 | }, 1042 | { 1043 | "name": "False northing", 1044 | "value": 0, 1045 | "unit": "metre", 1046 | "id": { 1047 | "authority": "EPSG", 1048 | "code": 8807 1049 | } 1050 | } 1051 | ] 1052 | }, 1053 | "coordinate_system": { 1054 | "subtype": "Cartesian", 1055 | "axis": [ 1056 | { 1057 | "name": "Easting", 1058 | "abbreviation": "E", 1059 | "direction": "east", 1060 | "unit": "metre" 1061 | }, 1062 | { 1063 | "name": "Northing", 1064 | "abbreviation": "N", 1065 | "direction": "north", 1066 | "unit": "metre" 1067 | } 1068 | ] 1069 | }, 1070 | "scope": "Engineering survey, topographic mapping.", 1071 | "area": "Malaysia - West Malaysia onshore and offshore.", 1072 | "bbox": { 1073 | "south_latitude": 1.13, 1074 | "west_longitude": 98.02, 1075 | "north_latitude": 7.81, 1076 | "east_longitude": 105.82 1077 | }, 1078 | "id": { 1079 | "authority": "EPSG", 1080 | "code": 3375 1081 | } 1082 | }, 1083 | "value": { 1084 | "projName": "Hotine Oblique Mercator (variant A)", 1085 | "axis": "enu", 1086 | "units": "meter", 1087 | "to_meter": 1, 1088 | "datumCode": "EPSG_4742", 1089 | "ellps": "GRS 1980", 1090 | "a": 6378137, 1091 | "rf": 298.257222101, 1092 | "k0": 0.99984, 1093 | "x0": 804671, 1094 | "y0": 0, 1095 | "longc": 1.784599160164202, 1096 | "lat0": 0.06981317007977318, 1097 | "alpha": 5.637863717220403, 1098 | "rectified_grid_angle": 5.63968419850769, 1099 | "srsCode": "GDM2000 / Peninsula RSO", 1100 | "name": "GDM2000 / Peninsula RSO", 1101 | "title": "EPSG:3375" 1102 | } 1103 | }, { 1104 | "code": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"Unknown based on Bessel 1841 ellipsoid\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128],TOWGS84[601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",16.3333333333333],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",750000],PARAMETER[\"false_northing\",-5000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", 1105 | "value": { 1106 | "projName": "Transverse_Mercator", 1107 | "axis": "enu", 1108 | "units": "meter", 1109 | "to_meter": 1, 1110 | "datumCode": "unknown based on bessel 1841 ellipsoid", 1111 | "datum_params": [ 1112 | 601.705, 1113 | 84.263, 1114 | 485.227, 1115 | -4.7354, 1116 | -1.3145, 1117 | -5.393, 1118 | -2.3887 1119 | ], 1120 | "ellps": "Bessel 1841", 1121 | "a": 6377397.155, 1122 | "rf": 299.1528128, 1123 | "k0": 1, 1124 | "x0": 750000, 1125 | "y0": -5000000, 1126 | "long0": 0.2850704444924066, 1127 | "lat0": 0, 1128 | "srsCode": "unknown", 1129 | "name": "unknown" 1130 | } 1131 | }, { 1132 | "code": "BOUNDCRS[ SOURCECRS[ PROJCRS[\"unknown\", BASEGEOGCRS[\"unknown\", DATUM[\"Unknown based on Bessel 1841 ellipsoid\", ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128, LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]]], PRIMEM[\"Greenwich\",0, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8901]]], CONVERSION[\"unknown\", METHOD[\"Transverse Mercator\", ID[\"EPSG\",9807]], PARAMETER[\"Latitude of natural origin\",0, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8801]], PARAMETER[\"Longitude of natural origin\",16.3333333333333, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8802]], PARAMETER[\"Scale factor at natural origin\",1, SCALEUNIT[\"unity\",1], ID[\"EPSG\",8805]], PARAMETER[\"False easting\",750000, LENGTHUNIT[\"metre\",1], ID[\"EPSG\",8806]], PARAMETER[\"False northing\",-5000000, LENGTHUNIT[\"metre\",1], ID[\"EPSG\",8807]]], CS[Cartesian,2], AXIS[\"(E)\",east, ORDER[1], LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]], AXIS[\"(N)\",north, ORDER[2], LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]]]], TARGETCRS[ GEOGCRS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", ELLIPSOID[\"WGS 84\",6378137,298.257223563, LENGTHUNIT[\"metre\",1]]], PRIMEM[\"Greenwich\",0, ANGLEUNIT[\"degree\",0.0174532925199433]], CS[ellipsoidal,2], AXIS[\"latitude\",north, ORDER[1], ANGLEUNIT[\"degree\",0.0174532925199433]], AXIS[\"longitude\",east, ORDER[2], ANGLEUNIT[\"degree\",0.0174532925199433]], ID[\"EPSG\",4326]]], ABRIDGEDTRANSFORMATION[\"Transformation from unknown to WGS84\", METHOD[\"Position Vector transformation (geog2D domain)\", ID[\"EPSG\",9606]], PARAMETER[\"X-axis translation\",601.705, ID[\"EPSG\",8605]], PARAMETER[\"Y-axis translation\",84.263, ID[\"EPSG\",8606]], PARAMETER[\"Z-axis translation\",485.227, ID[\"EPSG\",8607]], PARAMETER[\"X-axis rotation\",-4.7354, ID[\"EPSG\",8608]], PARAMETER[\"Y-axis rotation\",-1.3145, ID[\"EPSG\",8609]], PARAMETER[\"Z-axis rotation\",-5.393, ID[\"EPSG\",8610]], PARAMETER[\"Scale difference\",0.9999976113, ID[\"EPSG\",8611]]]]", 1133 | "value": { 1134 | "projName": "Transverse Mercator", 1135 | "axis": "enu", 1136 | "units": "meter", 1137 | "to_meter": 1, 1138 | "datumCode": "unknown", 1139 | "datum_params": [601.705, 84.263, 485.227, -4.7354, -1.3145, -5.393, -2.3887], 1140 | "ellps": "Bessel 1841", 1141 | "a": 6377397.155, 1142 | "rf": 299.1528128, 1143 | "k0": 1, 1144 | "x0": 750000, 1145 | "y0": -5000000, 1146 | "long0": 0.28507044449240665, 1147 | "lat0": 0, 1148 | "srsCode": "unknown", 1149 | "name": "unknown" 1150 | } 1151 | }, { 1152 | "code": { 1153 | "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", 1154 | "type": "BoundCRS", 1155 | "source_crs": { 1156 | "type": "ProjectedCRS", 1157 | "name": "unknown", 1158 | "base_crs": { 1159 | "name": "unknown", 1160 | "datum": { 1161 | "type": "GeodeticReferenceFrame", 1162 | "name": "Unknown based on Bessel 1841 ellipsoid", 1163 | "ellipsoid": { 1164 | "name": "Bessel 1841", 1165 | "semi_major_axis": 6377397.155, 1166 | "inverse_flattening": 299.1528128 1167 | } 1168 | }, 1169 | "coordinate_system": { 1170 | "subtype": "ellipsoidal", 1171 | "axis": [ 1172 | { 1173 | "name": "Longitude", 1174 | "abbreviation": "lon", 1175 | "direction": "east", 1176 | "unit": "degree" 1177 | }, 1178 | { 1179 | "name": "Latitude", 1180 | "abbreviation": "lat", 1181 | "direction": "north", 1182 | "unit": "degree" 1183 | } 1184 | ] 1185 | } 1186 | }, 1187 | "conversion": { 1188 | "name": "unknown", 1189 | "method": { 1190 | "name": "Transverse Mercator", 1191 | "id": { 1192 | "authority": "EPSG", 1193 | "code": 9807 1194 | } 1195 | }, 1196 | "parameters": [ 1197 | { 1198 | "name": "Latitude of natural origin", 1199 | "value": 0, 1200 | "unit": "degree", 1201 | "id": { 1202 | "authority": "EPSG", 1203 | "code": 8801 1204 | } 1205 | }, 1206 | { 1207 | "name": "Longitude of natural origin", 1208 | "value": 16.3333333333333, 1209 | "unit": "degree", 1210 | "id": { 1211 | "authority": "EPSG", 1212 | "code": 8802 1213 | } 1214 | }, 1215 | { 1216 | "name": "Scale factor at natural origin", 1217 | "value": 1, 1218 | "unit": "unity", 1219 | "id": { 1220 | "authority": "EPSG", 1221 | "code": 8805 1222 | } 1223 | }, 1224 | { 1225 | "name": "False easting", 1226 | "value": 750000, 1227 | "unit": "metre", 1228 | "id": { 1229 | "authority": "EPSG", 1230 | "code": 8806 1231 | } 1232 | }, 1233 | { 1234 | "name": "False northing", 1235 | "value": -5000000, 1236 | "unit": "metre", 1237 | "id": { 1238 | "authority": "EPSG", 1239 | "code": 8807 1240 | } 1241 | } 1242 | ] 1243 | }, 1244 | "coordinate_system": { 1245 | "subtype": "Cartesian", 1246 | "axis": [ 1247 | { 1248 | "name": "Easting", 1249 | "abbreviation": "E", 1250 | "direction": "east", 1251 | "unit": "metre" 1252 | }, 1253 | { 1254 | "name": "Northing", 1255 | "abbreviation": "N", 1256 | "direction": "north", 1257 | "unit": "metre" 1258 | } 1259 | ] 1260 | } 1261 | }, 1262 | "target_crs": { 1263 | "type": "GeographicCRS", 1264 | "name": "WGS 84", 1265 | "datum": { 1266 | "type": "GeodeticReferenceFrame", 1267 | "name": "World Geodetic System 1984", 1268 | "ellipsoid": { 1269 | "name": "WGS 84", 1270 | "semi_major_axis": 6378137, 1271 | "inverse_flattening": 298.257223563 1272 | } 1273 | }, 1274 | "coordinate_system": { 1275 | "subtype": "ellipsoidal", 1276 | "axis": [ 1277 | { 1278 | "name": "Latitude", 1279 | "abbreviation": "lat", 1280 | "direction": "north", 1281 | "unit": "degree" 1282 | }, 1283 | { 1284 | "name": "Longitude", 1285 | "abbreviation": "lon", 1286 | "direction": "east", 1287 | "unit": "degree" 1288 | } 1289 | ] 1290 | }, 1291 | "id": { 1292 | "authority": "EPSG", 1293 | "code": 4326 1294 | } 1295 | }, 1296 | "transformation": { 1297 | "name": "Transformation from unknown to WGS84", 1298 | "method": { 1299 | "name": "Position Vector transformation (geog2D domain)", 1300 | "id": { 1301 | "authority": "EPSG", 1302 | "code": 9606 1303 | } 1304 | }, 1305 | "parameters": [ 1306 | { 1307 | "name": "X-axis translation", 1308 | "value": 601.705, 1309 | "unit": "metre", 1310 | "id": { 1311 | "authority": "EPSG", 1312 | "code": 8605 1313 | } 1314 | }, 1315 | { 1316 | "name": "Y-axis translation", 1317 | "value": 84.263, 1318 | "unit": "metre", 1319 | "id": { 1320 | "authority": "EPSG", 1321 | "code": 8606 1322 | } 1323 | }, 1324 | { 1325 | "name": "Z-axis translation", 1326 | "value": 485.227, 1327 | "unit": "metre", 1328 | "id": { 1329 | "authority": "EPSG", 1330 | "code": 8607 1331 | } 1332 | }, 1333 | { 1334 | "name": "X-axis rotation", 1335 | "value": -4.7354, 1336 | "unit": { 1337 | "type": "AngularUnit", 1338 | "name": "arc-second", 1339 | "conversion_factor": 4.84813681109536e-06 1340 | }, 1341 | "id": { 1342 | "authority": "EPSG", 1343 | "code": 8608 1344 | } 1345 | }, 1346 | { 1347 | "name": "Y-axis rotation", 1348 | "value": -1.3145, 1349 | "unit": { 1350 | "type": "AngularUnit", 1351 | "name": "arc-second", 1352 | "conversion_factor": 4.84813681109536e-06 1353 | }, 1354 | "id": { 1355 | "authority": "EPSG", 1356 | "code": 8609 1357 | } 1358 | }, 1359 | { 1360 | "name": "Z-axis rotation", 1361 | "value": -5.393, 1362 | "unit": { 1363 | "type": "AngularUnit", 1364 | "name": "arc-second", 1365 | "conversion_factor": 4.84813681109536e-06 1366 | }, 1367 | "id": { 1368 | "authority": "EPSG", 1369 | "code": 8610 1370 | } 1371 | }, 1372 | { 1373 | "name": "Scale difference", 1374 | "value": -2.3887, 1375 | "unit": { 1376 | "type": "ScaleUnit", 1377 | "name": "parts per million", 1378 | "conversion_factor": 1e-06 1379 | }, 1380 | "id": { 1381 | "authority": "EPSG", 1382 | "code": 8611 1383 | } 1384 | } 1385 | ] 1386 | } 1387 | }, 1388 | "value": { 1389 | "projName": "Transverse Mercator", 1390 | "axis": "enu", 1391 | "units": "meter", 1392 | "to_meter": 1, 1393 | "datumCode": "unknown", 1394 | "datum_params": [601.705, 84.263, 485.227, -4.7354, -1.3145, -5.393, -2.3887], 1395 | "ellps": "Bessel 1841", 1396 | "a": 6377397.155, 1397 | "rf": 299.1528128, 1398 | "k0": 1, 1399 | "x0": 750000, 1400 | "y0": -5000000, 1401 | "long0": 0.2850704444924066, 1402 | "lat0": 0, 1403 | "srsCode": "unknown", 1404 | "name": "unknown" 1405 | } 1406 | }, { 1407 | "code": "BOUNDCRS[ SOURCECRS[ PROJCRS[\"unknown\", BASEGEOGCRS[\"unknown\", DATUM[\"Unknown based on Bessel 1841 ellipsoid\", ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128, LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]]], PRIMEM[\"Greenwich\",0, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8901]]], CONVERSION[\"unknown\", METHOD[\"Lambert Conic Conformal (2SP)\", ID[\"EPSG\",9802]], PARAMETER[\"Latitude of false origin\",47.5, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8821]], PARAMETER[\"Longitude of false origin\",13.3333333333333, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8822]], PARAMETER[\"Latitude of 1st standard parallel\",49, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8823]], PARAMETER[\"Latitude of 2nd standard parallel\",46, ANGLEUNIT[\"degree\",0.0174532925199433], ID[\"EPSG\",8824]], PARAMETER[\"Easting at false origin\",400000, LENGTHUNIT[\"metre\",1], ID[\"EPSG\",8826]], PARAMETER[\"Northing at false origin\",400000, LENGTHUNIT[\"metre\",1], ID[\"EPSG\",8827]]], CS[Cartesian,2], AXIS[\"(E)\",east, ORDER[1], LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]], AXIS[\"(N)\",north, ORDER[2], LENGTHUNIT[\"metre\",1, ID[\"EPSG\",9001]]]]], TARGETCRS[ GEOGCRS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", ELLIPSOID[\"WGS 84\",6378137,298.257223563, LENGTHUNIT[\"metre\",1]]], PRIMEM[\"Greenwich\",0, ANGLEUNIT[\"degree\",0.0174532925199433]], CS[ellipsoidal,2], AXIS[\"latitude\",north, ORDER[1], ANGLEUNIT[\"degree\",0.0174532925199433]], AXIS[\"longitude\",east, ORDER[2], ANGLEUNIT[\"degree\",0.0174532925199433]], ID[\"EPSG\",4326]]], ABRIDGEDTRANSFORMATION[\"unknown to WGS84\", METHOD[\"NTv2\", ID[\"EPSG\",9615]], PARAMETERFILE[\"Latitude and longitude difference file\",\"AT_GIS_GRID.gsb\", ID[\"EPSG\",8656]]]]", 1408 | "value": { 1409 | "projName": "Lambert Conic Conformal (2SP)", 1410 | "axis": "enu", 1411 | "units": "meter", 1412 | "to_meter": 1, 1413 | "datumCode": "unknown", 1414 | "nadgrids": "AT_GIS_GRID.gsb", 1415 | "ellps": "Bessel 1841", 1416 | "a": 6377397.155, 1417 | "rf": 299.1528128, 1418 | "x0": 400000, 1419 | "y0": 400000, 1420 | "long0": 0.23271056693257675, 1421 | "lat0": 0.8290313946973067, 1422 | "lat1": 0.8552113334772217, 1423 | "lat2": 0.8028514559173917, 1424 | "srsCode": "unknown", 1425 | "name": "unknown" 1426 | } 1427 | }, { 1428 | "code": { 1429 | "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", 1430 | "type": "BoundCRS", 1431 | "source_crs": { 1432 | "type": "ProjectedCRS", 1433 | "name": "unknown", 1434 | "base_crs": { 1435 | "name": "unknown", 1436 | "datum": { 1437 | "type": "GeodeticReferenceFrame", 1438 | "name": "Unknown based on Bessel 1841 ellipsoid", 1439 | "ellipsoid": { 1440 | "name": "Bessel 1841", 1441 | "semi_major_axis": 6377397.155, 1442 | "inverse_flattening": 299.1528128 1443 | } 1444 | }, 1445 | "coordinate_system": { 1446 | "subtype": "ellipsoidal", 1447 | "axis": [ 1448 | { 1449 | "name": "Longitude", 1450 | "abbreviation": "lon", 1451 | "direction": "east", 1452 | "unit": "degree" 1453 | }, 1454 | { 1455 | "name": "Latitude", 1456 | "abbreviation": "lat", 1457 | "direction": "north", 1458 | "unit": "degree" 1459 | } 1460 | ] 1461 | } 1462 | }, 1463 | "conversion": { 1464 | "name": "unknown", 1465 | "method": { 1466 | "name": "Lambert Conic Conformal (2SP)", 1467 | "id": { 1468 | "authority": "EPSG", 1469 | "code": 9802 1470 | } 1471 | }, 1472 | "parameters": [ 1473 | { 1474 | "name": "Latitude of false origin", 1475 | "value": 47.5, 1476 | "unit": "degree", 1477 | "id": { 1478 | "authority": "EPSG", 1479 | "code": 8821 1480 | } 1481 | }, 1482 | { 1483 | "name": "Longitude of false origin", 1484 | "value": 13.3333333333333, 1485 | "unit": "degree", 1486 | "id": { 1487 | "authority": "EPSG", 1488 | "code": 8822 1489 | } 1490 | }, 1491 | { 1492 | "name": "Latitude of 1st standard parallel", 1493 | "value": 49, 1494 | "unit": "degree", 1495 | "id": { 1496 | "authority": "EPSG", 1497 | "code": 8823 1498 | } 1499 | }, 1500 | { 1501 | "name": "Latitude of 2nd standard parallel", 1502 | "value": 46, 1503 | "unit": "degree", 1504 | "id": { 1505 | "authority": "EPSG", 1506 | "code": 8824 1507 | } 1508 | }, 1509 | { 1510 | "name": "Easting at false origin", 1511 | "value": 400000, 1512 | "unit": "metre", 1513 | "id": { 1514 | "authority": "EPSG", 1515 | "code": 8826 1516 | } 1517 | }, 1518 | { 1519 | "name": "Northing at false origin", 1520 | "value": 400000, 1521 | "unit": "metre", 1522 | "id": { 1523 | "authority": "EPSG", 1524 | "code": 8827 1525 | } 1526 | } 1527 | ] 1528 | }, 1529 | "coordinate_system": { 1530 | "subtype": "Cartesian", 1531 | "axis": [ 1532 | { 1533 | "name": "Easting", 1534 | "abbreviation": "E", 1535 | "direction": "east", 1536 | "unit": "metre" 1537 | }, 1538 | { 1539 | "name": "Northing", 1540 | "abbreviation": "N", 1541 | "direction": "north", 1542 | "unit": "metre" 1543 | } 1544 | ] 1545 | } 1546 | }, 1547 | "target_crs": { 1548 | "type": "GeographicCRS", 1549 | "name": "WGS 84", 1550 | "datum": { 1551 | "type": "GeodeticReferenceFrame", 1552 | "name": "World Geodetic System 1984", 1553 | "ellipsoid": { 1554 | "name": "WGS 84", 1555 | "semi_major_axis": 6378137, 1556 | "inverse_flattening": 298.257223563 1557 | } 1558 | }, 1559 | "coordinate_system": { 1560 | "subtype": "ellipsoidal", 1561 | "axis": [ 1562 | { 1563 | "name": "Latitude", 1564 | "abbreviation": "lat", 1565 | "direction": "north", 1566 | "unit": "degree" 1567 | }, 1568 | { 1569 | "name": "Longitude", 1570 | "abbreviation": "lon", 1571 | "direction": "east", 1572 | "unit": "degree" 1573 | } 1574 | ] 1575 | }, 1576 | "id": { 1577 | "authority": "EPSG", 1578 | "code": 4326 1579 | } 1580 | }, 1581 | "transformation": { 1582 | "name": "unknown to WGS84", 1583 | "method": { 1584 | "name": "NTv2", 1585 | "id": { 1586 | "authority": "EPSG", 1587 | "code": 9615 1588 | } 1589 | }, 1590 | "parameters": [ 1591 | { 1592 | "name": "Latitude and longitude difference file", 1593 | "value": "AT_GIS_GRID.gsb" 1594 | } 1595 | ] 1596 | } 1597 | }, 1598 | "value": { 1599 | "projName": "Lambert Conic Conformal (2SP)", 1600 | "axis": "enu", 1601 | "units": "meter", 1602 | "to_meter": 1, 1603 | "datumCode": "unknown", 1604 | "nadgrids": "AT_GIS_GRID.gsb", 1605 | "ellps": "Bessel 1841", 1606 | "a": 6377397.155, 1607 | "rf": 299.1528128, 1608 | "x0": 400000, 1609 | "y0": 400000, 1610 | "long0": 0.2327105669325767, 1611 | "lat0": 0.8290313946973066, 1612 | "lat1": 0.8552113334772214, 1613 | "lat2": 0.8028514559173915, 1614 | "srsCode": "unknown", 1615 | "name": "unknown" 1616 | } 1617 | } 1618 | ] 1619 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import compare from 'js-struct-compare'; 3 | import wktParser from './dist/wkt.cjs'; 4 | import fixtures from './test-fixtures.json' with {type: 'json'}; //eslint-disable-line 5 | 6 | function derivedPropertiesOnly(input) { 7 | const derivedProperties = (({ 8 | projName, 9 | axis, 10 | units, 11 | to_meter, 12 | datumCode, 13 | datum_params, 14 | nadgrids, 15 | ellps, 16 | from_greenwich, 17 | a, 18 | rf, 19 | k0, 20 | x0, 21 | y0, 22 | long0, 23 | longc, 24 | lat0, 25 | lat1, 26 | lat2, 27 | lat_ts, 28 | alpha, 29 | rectified_grid_angle, 30 | srsCode, 31 | name, 32 | title, 33 | sphere 34 | }) => ({ 35 | projName, 36 | axis, 37 | units, 38 | to_meter, 39 | datumCode, 40 | datum_params, 41 | nadgrids, 42 | ellps, 43 | from_greenwich, 44 | a, 45 | rf, 46 | k0, 47 | x0, 48 | y0, 49 | long0, 50 | longc, 51 | lat0, 52 | lat1, 53 | lat2, 54 | lat_ts, 55 | alpha, 56 | rectified_grid_angle, 57 | srsCode, 58 | name, 59 | title, 60 | sphere 61 | }))(input); 62 | for (const key in derivedProperties) { 63 | if (derivedProperties[key] === undefined) { 64 | delete derivedProperties[key]; 65 | } 66 | } 67 | return derivedProperties; 68 | } 69 | 70 | fixtures.forEach((item, i) => { 71 | test(`fixture ${i + 1}`, t => { 72 | const got = item.strict ? wktParser(item.code) : derivedPropertiesOnly(wktParser(item.code)); 73 | const expected = item.strict ? item.value : derivedPropertiesOnly(item.value); 74 | const diff = compare(got, expected); 75 | if (diff.length > 0) { 76 | console.log('got', got, 'expected', expected); 77 | } 78 | t.deepEqual(diff, []); 79 | t.end(); 80 | }); 81 | }); -------------------------------------------------------------------------------- /transformPROJJSON.js: -------------------------------------------------------------------------------- 1 | import { applyProjectionDefaults } from './util.js'; 2 | 3 | // Helper function to process units and to_meter 4 | function processUnit(unit) { 5 | let result = { units: null, to_meter: undefined }; 6 | 7 | if (typeof unit === 'string') { 8 | result.units = unit.toLowerCase(); 9 | if (result.units === 'metre') { 10 | result.units = 'meter'; // Normalize 'metre' to 'meter' 11 | } 12 | if (result.units === 'meter') { 13 | result.to_meter = 1; // Only set to_meter if units are 'meter' 14 | } 15 | } else if (unit && unit.name) { 16 | result.units = unit.name.toLowerCase(); 17 | if (result.units === 'metre') { 18 | result.units = 'meter'; // Normalize 'metre' to 'meter' 19 | } 20 | result.to_meter = unit.conversion_factor; 21 | } 22 | 23 | return result; 24 | } 25 | 26 | function toValue(valueOrObject) { 27 | if (typeof valueOrObject === 'object') { 28 | return valueOrObject.value * valueOrObject.unit.conversion_factor; 29 | } 30 | return valueOrObject; 31 | } 32 | 33 | function calculateEllipsoid(value, result) { 34 | if (value.ellipsoid.radius) { 35 | result.a = value.ellipsoid.radius; 36 | result.rf = 0; 37 | } else { 38 | result.a = toValue(value.ellipsoid.semi_major_axis); 39 | if (value.ellipsoid.inverse_flattening !== undefined) { 40 | result.rf = value.ellipsoid.inverse_flattening; 41 | } else if (value.ellipsoid.semi_major_axis !== undefined && value.ellipsoid.semi_minor_axis !== undefined) { 42 | result.rf = result.a / (result.a - toValue(value.ellipsoid.semi_minor_axis)); 43 | } 44 | } 45 | } 46 | 47 | export function transformPROJJSON(projjson, result = {}) { 48 | if (!projjson || typeof projjson !== 'object') { 49 | return projjson; // Return primitive values as-is 50 | } 51 | 52 | if (projjson.type === 'BoundCRS') { 53 | transformPROJJSON(projjson.source_crs, result); 54 | 55 | if (projjson.transformation) { 56 | if (projjson.transformation.method && projjson.transformation.method.name === 'NTv2') { 57 | // Set nadgrids to the filename from the parameterfile 58 | result.nadgrids = projjson.transformation.parameters[0].value; 59 | } else { 60 | // Populate datum_params if no parameterfile is found 61 | result.datum_params = projjson.transformation.parameters.map((param) => param.value); 62 | } 63 | } 64 | return result; // Return early for BoundCRS 65 | } 66 | 67 | // Handle specific keys in PROJJSON 68 | Object.keys(projjson).forEach((key) => { 69 | const value = projjson[key]; 70 | if (value === null) { 71 | return; 72 | } 73 | 74 | switch (key) { 75 | case 'name': 76 | if (result.srsCode) { 77 | break; 78 | } 79 | result.name = value; 80 | result.srsCode = value; // Map `name` to `srsCode` 81 | break; 82 | 83 | case 'type': 84 | if (value === 'GeographicCRS') { 85 | result.projName = 'longlat'; 86 | } else if (value === 'ProjectedCRS' && projjson.conversion && projjson.conversion.method) { 87 | result.projName = projjson.conversion.method.name; // Retain original capitalization 88 | } 89 | break; 90 | 91 | case 'datum': 92 | case 'datum_ensemble': // Handle both datum and ensemble 93 | if (value.ellipsoid) { 94 | // Extract ellipsoid properties 95 | result.ellps = value.ellipsoid.name; 96 | calculateEllipsoid(value, result); 97 | } 98 | if (value.prime_meridian) { 99 | result.from_greenwich = value.prime_meridian.longitude * Math.PI / 180; // Convert to radians 100 | } 101 | break; 102 | 103 | case 'ellipsoid': 104 | result.ellps = value.name; 105 | calculateEllipsoid(value, result); 106 | break; 107 | 108 | case 'prime_meridian': 109 | result.long0 = (value.longitude || 0) * Math.PI / 180; // Convert to radians 110 | break; 111 | 112 | case 'coordinate_system': 113 | if (value.axis) { 114 | result.axis = value.axis 115 | .map((axis) => { 116 | const direction = axis.direction; 117 | if (direction === 'east') return 'e'; 118 | if (direction === 'north') return 'n'; 119 | if (direction === 'west') return 'w'; 120 | if (direction === 'south') return 's'; 121 | throw new Error(`Unknown axis direction: ${direction}`); 122 | }) 123 | .join('') + 'u'; // Combine into a single string (e.g., "enu") 124 | 125 | if (value.unit) { 126 | const { units, to_meter } = processUnit(value.unit); 127 | result.units = units; 128 | result.to_meter = to_meter; 129 | } else if (value.axis[0] && value.axis[0].unit) { 130 | const { units, to_meter } = processUnit(value.axis[0].unit); 131 | result.units = units; 132 | result.to_meter = to_meter; 133 | } 134 | } 135 | break; 136 | 137 | case 'id': 138 | if (value.authority && value.code) { 139 | result.title = value.authority + ':' + value.code; 140 | } 141 | break; 142 | 143 | case 'conversion': 144 | if (value.method && value.method.name) { 145 | result.projName = value.method.name; // Retain original capitalization 146 | } 147 | if (value.parameters) { 148 | value.parameters.forEach((param) => { 149 | const paramName = param.name.toLowerCase().replace(/\s+/g, '_'); 150 | const paramValue = param.value; 151 | if (param.unit && param.unit.conversion_factor) { 152 | result[paramName] = paramValue * param.unit.conversion_factor; // Convert to radians or meters 153 | } else if (param.unit === 'degree') { 154 | result[paramName] = paramValue * Math.PI / 180; // Convert to radians 155 | } else { 156 | result[paramName] = paramValue; 157 | } 158 | }); 159 | } 160 | break; 161 | 162 | case 'unit': 163 | if (value.name) { 164 | result.units = value.name.toLowerCase(); 165 | if (result.units === 'metre') { 166 | result.units = 'meter'; 167 | } 168 | } 169 | if (value.conversion_factor) { 170 | result.to_meter = value.conversion_factor; 171 | } 172 | break; 173 | 174 | case 'base_crs': 175 | transformPROJJSON(value, result); // Pass `result` directly 176 | result.datumCode = value.id ? value.id.authority + '_' + value.id.code : value.name; // Set datumCode 177 | break; 178 | 179 | default: 180 | // Ignore irrelevant or unneeded properties 181 | break; 182 | } 183 | }); 184 | 185 | // Additional calculated properties 186 | if (result.latitude_of_false_origin !== undefined) { 187 | result.lat0 = result.latitude_of_false_origin; // Already in radians 188 | } 189 | if (result.longitude_of_false_origin !== undefined) { 190 | result.long0 = result.longitude_of_false_origin; 191 | } 192 | if (result.latitude_of_standard_parallel !== undefined) { 193 | result.lat0 = result.latitude_of_standard_parallel; 194 | result.lat1 = result.latitude_of_standard_parallel; 195 | } 196 | if (result.latitude_of_1st_standard_parallel !== undefined) { 197 | result.lat1 = result.latitude_of_1st_standard_parallel; 198 | } 199 | if (result.latitude_of_2nd_standard_parallel !== undefined) { 200 | result.lat2 = result.latitude_of_2nd_standard_parallel; 201 | } 202 | if (result.latitude_of_projection_centre !== undefined) { 203 | result.lat0 = result.latitude_of_projection_centre; 204 | } 205 | if (result.longitude_of_projection_centre !== undefined) { 206 | result.longc = result.longitude_of_projection_centre; 207 | } 208 | if (result.easting_at_false_origin !== undefined) { 209 | result.x0 = result.easting_at_false_origin; 210 | } 211 | if (result.northing_at_false_origin !== undefined) { 212 | result.y0 = result.northing_at_false_origin; 213 | } 214 | if (result.latitude_of_natural_origin !== undefined) { 215 | result.lat0 = result.latitude_of_natural_origin; 216 | } 217 | if (result.longitude_of_natural_origin !== undefined) { 218 | result.long0 = result.longitude_of_natural_origin; 219 | } 220 | if (result.longitude_of_origin !== undefined) { 221 | result.long0 = result.longitude_of_origin; 222 | } 223 | if (result.false_easting !== undefined) { 224 | result.x0 = result.false_easting; 225 | } 226 | if (result.easting_at_projection_centre) { 227 | result.x0 = result.easting_at_projection_centre; 228 | } 229 | if (result.false_northing !== undefined) { 230 | result.y0 = result.false_northing; 231 | } 232 | if (result.northing_at_projection_centre) { 233 | result.y0 = result.northing_at_projection_centre; 234 | } 235 | if (result.standard_parallel_1 !== undefined) { 236 | result.lat1 = result.standard_parallel_1; 237 | } 238 | if (result.standard_parallel_2 !== undefined) { 239 | result.lat2 = result.standard_parallel_2; 240 | } 241 | if (result.scale_factor_at_natural_origin !== undefined) { 242 | result.k0 = result.scale_factor_at_natural_origin; 243 | } 244 | if (result.scale_factor_at_projection_centre !== undefined) { 245 | result.k0 = result.scale_factor_at_projection_centre; 246 | } 247 | if (result.scale_factor_on_pseudo_standard_parallel !== undefined) { 248 | result.k0 = result.scale_factor_on_pseudo_standard_parallel; 249 | } 250 | if (result.azimuth !== undefined) { 251 | result.alpha = result.azimuth; 252 | } 253 | if (result.azimuth_at_projection_centre !== undefined) { 254 | result.alpha = result.azimuth_at_projection_centre; 255 | } 256 | if (result.angle_from_rectified_to_skew_grid) { 257 | result.rectified_grid_angle = result.angle_from_rectified_to_skew_grid; 258 | } 259 | 260 | // Apply projection defaults 261 | applyProjectionDefaults(result); 262 | 263 | return result; 264 | } -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | var D2R = 0.01745329251994329577; 2 | 3 | export function d2r(input) { 4 | return input * D2R; 5 | } 6 | 7 | export function applyProjectionDefaults(wkt) { 8 | // Normalize projName for WKT2 compatibility 9 | const normalizedProjName = (wkt.projName || '').toLowerCase().replace(/_/g, ' '); 10 | 11 | if (!wkt.long0 && wkt.longc && (normalizedProjName === 'albers conic equal area' || normalizedProjName === 'lambert azimuthal equal area')) { 12 | wkt.long0 = wkt.longc; 13 | } 14 | if (!wkt.lat_ts && wkt.lat1 && (normalizedProjName === 'stereographic south pole' || normalizedProjName === 'polar stereographic (variant b)')) { 15 | wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90); 16 | wkt.lat_ts = wkt.lat1; 17 | delete wkt.lat1; 18 | } else if (!wkt.lat_ts && wkt.lat0 && (normalizedProjName === 'polar stereographic' || normalizedProjName === 'polar stereographic (variant a)')) { 19 | wkt.lat_ts = wkt.lat0; 20 | wkt.lat0 = d2r(wkt.lat0 > 0 ? 90 : -90); 21 | delete wkt.lat1; 22 | } 23 | } -------------------------------------------------------------------------------- /wkt2_parser.js: -------------------------------------------------------------------------------- 1 | import PROJJSONBuilder from './PROJJSONBuilderBase.js'; 2 | import Tokenizer from './wkt2_tokenizer.js' 3 | import WKTNode from './wkt_node.js'; 4 | 5 | /** 6 | * @typedef {Object} Token 7 | * @property {string} type 8 | * @property {string} value 9 | * @property {number} position 10 | */ 11 | 12 | /** 13 | * Custom error type for WKT parsing errors. 14 | */ 15 | class WKTParsingError extends Error { 16 | /** 17 | * @param {string} message 18 | * @param {number} position 19 | */ 20 | constructor(message, position) { 21 | super(`WKT Parsing Error at position ${position}: ${message}`); 22 | this.name = 'WKTParsingError'; 23 | this.position = position; 24 | } 25 | } 26 | 27 | /** 28 | * Main parser for WKT2 strings. 29 | */ 30 | class WKTParser { 31 | /** 32 | * @param {string} input 33 | */ 34 | constructor(input) { 35 | this.tokenizer = new Tokenizer(input); 36 | this.currentToken = null; 37 | this.advance(); 38 | } 39 | 40 | advance() { 41 | this.currentToken = this.tokenizer.nextToken(); 42 | } 43 | 44 | /** 45 | * @param {string} type 46 | * @param {string} [value] 47 | */ 48 | expect(type, value) { 49 | if ( 50 | !this.currentToken || 51 | this.currentToken.type !== type || 52 | (value && this.currentToken.value !== value) 53 | ) { 54 | throw new WKTParsingError( 55 | `Expected token type '${type}'` + (value ? ` with value '${value}'` : ''), 56 | this.tokenizer.pos 57 | ); 58 | } 59 | this.advance(); 60 | } 61 | 62 | /** @returns {WKTNode} */ 63 | parse() { 64 | const token = this.currentToken; 65 | 66 | if (!token) { 67 | throw new WKTParsingError('Unexpected end of input', this.tokenizer.pos); 68 | } 69 | 70 | switch (token.value) { 71 | case 'GEODCRS': 72 | case 'PROJCRS': 73 | return this.parseNode(); // Parse CRS definitions as nodes 74 | case 'CS': // CoordinateSystem (example) 75 | return this.parseNode(); 76 | // Add more cases as needed for other WKT2 root types 77 | default: 78 | throw new WKTParsingError(`Unexpected root keyword: ${token.value}`, this.tokenizer.pos); 79 | } 80 | } 81 | 82 | peek() { 83 | return this.tokenizer.peekToken(); 84 | } 85 | 86 | /** @returns {WKTNode} */ 87 | parseNode() { 88 | const token = this.currentToken; 89 | 90 | if (!token || token.type !== 'keyword') { 91 | throw new WKTParsingError('Expected keyword at start of node', this.tokenizer.pos); 92 | } 93 | 94 | const keyword = token.value; 95 | this.advance(); 96 | 97 | this.expect('punctuation', '['); 98 | 99 | const node = new WKTNode(keyword); 100 | 101 | let expectingValue = true; 102 | 103 | while (this.currentToken && !(this.currentToken.type === 'punctuation' && this.currentToken.value === ']')) { 104 | const t = this.currentToken; 105 | 106 | if (t.type === 'string' || t.type === 'number') { 107 | if (expectingValue && node.value === null) { 108 | node.value = t.value; 109 | } else { 110 | node.addChild(new WKTNode(t.value)); 111 | } 112 | this.advance(); 113 | } else if (t.type === 'keyword') { 114 | const next = this.peek(); 115 | 116 | if (expectingValue && !node.value && (!next || next.type !== 'punctuation' || next.value !== '[')) { 117 | node.value = t.value; 118 | this.advance(); 119 | } else if (next && next.type === 'punctuation' && next.value === '[') { 120 | const childNode = this.parseNode(); 121 | console.log(`Parsed child node: ${JSON.stringify(childNode, null, 2)}`); // Debug log 122 | node.addChild(childNode); 123 | } else { 124 | node.addChild(new WKTNode(t.value)); 125 | this.advance(); 126 | } 127 | } else if (t.type === 'punctuation' && t.value === ',') { 128 | this.advance(); 129 | } else { 130 | throw new WKTParsingError(`Unexpected token ${t.type}`, t.position); 131 | } 132 | 133 | expectingValue = false; 134 | } 135 | 136 | this.expect('punctuation', ']'); 137 | 138 | return node; 139 | } 140 | 141 | } 142 | 143 | // Example usage 144 | const parser = new WKTParser('PROJCRS["MGI / Austria GK M28",BASEGEOGCRS["MGI",DATUM["Militar-Geographische Institut",ELLIPSOID["Bessel 1841",6377397.155,299.1528128,LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",7004]],ID["EPSG",6312]],ID["EPSG",4312]],CONVERSION["Austria Gauss-Kruger M28",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",10.3333333333336,ANGLEUNIT["degree",0.0174532925199433,ID["EPSG",9102]],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1,ID["EPSG",9201]],ID["EPSG",8805]],PARAMETER["False easting",150000,LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",8806]],PARAMETER["False northing",-5000000,LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",8807]],ID["EPSG",18007]],CS[Cartesian,2,ID["EPSG",4530]],AXIS["Northing (X)",north],AXIS["Easting (Y)",east],LENGTHUNIT["metre",1,ID["EPSG",9001]],ID["EPSG",31257]]'); 145 | const root = parser.parse(); 146 | const projjson = PROJJSONBuilder.build(root); 147 | console.log(JSON.stringify(projjson, null, 2)); -------------------------------------------------------------------------------- /wkt2_tokenizer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tokenizer for WKT2 strings. 3 | */ 4 | class Tokenizer { 5 | /** 6 | * @param {string} input 7 | */ 8 | constructor(input) { 9 | this.input = input; 10 | this.length = input.length; 11 | this.pos = 0; 12 | } 13 | 14 | /** @returns {Token|null} */ 15 | nextToken() { 16 | this._skipWhitespace(); 17 | 18 | if (this.pos >= this.length) return null; 19 | 20 | const char = this.input[this.pos]; 21 | 22 | // Punctuation 23 | if (char === '[' || char === ']' || char === ',') { 24 | this.pos++; 25 | return { 26 | type: 'punctuation', 27 | value: char, 28 | position: this.pos - 1, 29 | }; 30 | } 31 | 32 | // Quoted string 33 | if (char === '"') { 34 | const start = this.pos++; 35 | let str = ''; 36 | while (this.pos < this.length && this.input[this.pos] !== '"') { 37 | str += this.input[this.pos++]; 38 | } 39 | if (this.input[this.pos] !== '"') { 40 | throw new WKTParsingError('Unterminated string', start); 41 | } 42 | this.pos++; // skip closing quote 43 | return { 44 | type: 'string', 45 | value: str, 46 | position: start, 47 | }; 48 | } 49 | 50 | // Number (int or float) 51 | if (char.match(/[0-9\.\-]/)) { 52 | const start = this.pos; 53 | let num = ''; 54 | while (this.pos < this.length && this.input[this.pos].match(/[0-9eE\.\+\-]/)) { 55 | num += this.input[this.pos++]; 56 | } 57 | return { 58 | type: 'number', 59 | value: num, 60 | position: start, 61 | }; 62 | } 63 | 64 | // Keyword (identifiers) 65 | if (char.match(/[A-Z_]/i)) { 66 | const start = this.pos; 67 | let ident = ''; 68 | while (this.pos < this.length && this.input[this.pos].match(/[A-Z0-9_]/i)) { 69 | ident += this.input[this.pos++]; 70 | } 71 | return { 72 | type: 'keyword', 73 | value: ident, 74 | position: start, 75 | }; 76 | } 77 | 78 | throw new WKTParsingError(`Unexpected character '${char}'`, this.pos); 79 | } 80 | 81 | /** @returns {Token|null} */ 82 | peekToken() { 83 | const savedPos = this.pos; 84 | try { 85 | return this.nextToken(); 86 | } finally { 87 | this.pos = savedPos; 88 | } 89 | } 90 | 91 | _skipWhitespace() { 92 | while (this.pos < this.length && this.input[this.pos].match(/\s/)) { 93 | this.pos++; 94 | } 95 | } 96 | } 97 | 98 | export default Tokenizer; 99 | 100 | // example usage 101 | // const tokenizer = new Tokenizer(`GEODCRS["WGS 84", DATUM["World Geodetic System 1984"]]`); 102 | // let token; 103 | // while ((token = tokenizer.nextToken())) { 104 | // console.log(token); 105 | // } -------------------------------------------------------------------------------- /wkt_node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a WKT node in the parsed tree. 3 | */ 4 | class WKTNode { 5 | /** 6 | * @param {string} keyword 7 | * @param {string} [value] 8 | */ 9 | constructor(keyword, value) { 10 | this.keyword = keyword; 11 | this.value = value; 12 | this.children = []; 13 | } 14 | 15 | /** 16 | * @param {WKTNode} node 17 | */ 18 | addChild(node) { 19 | this.children.push(node); 20 | } 21 | 22 | /** 23 | * Finds the first child with the specified keyword. 24 | * @param {string} keyword 25 | * @returns {WKTNode | undefined} 26 | */ 27 | findChild(keyword) { 28 | return this.children.find( 29 | (c) => c.keyword && c.keyword.toUpperCase() === keyword.toUpperCase() 30 | ); 31 | } 32 | 33 | /** 34 | * Finds all children with the specified keyword. 35 | * @param {string} keyword 36 | * @returns {WKTNode[]} 37 | */ 38 | findChildren(keyword) { 39 | return this.children.filter( 40 | (c) => c.keyword && c.keyword.toUpperCase() === keyword.toUpperCase() 41 | ); 42 | } 43 | 44 | /** 45 | * Gets the value or literal content of a child node matching the keyword. 46 | * @param {string} keyword 47 | * @returns {string | undefined} 48 | */ 49 | getValue(keyword) { 50 | const child = this.findChild(keyword); 51 | return child ? (child.value !== undefined ? child.value : child.literal) : undefined; 52 | } 53 | } 54 | 55 | export default WKTNode; --------------------------------------------------------------------------------