proj4 2.20.2 → 2.20.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proj4",
3
- "version": "2.20.2",
3
+ "version": "2.20.3",
4
4
  "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
5
5
  "homepage": "https://github.com/proj4js/proj4js",
6
6
  "main": "dist/proj4.js",
package/component.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proj4",
3
- "version": "2.20.2",
3
+ "version": "2.20.3",
4
4
  "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
5
5
  "repo": "proj4js/proj4js",
6
6
  "keywords": [
package/dist/proj4-src.js CHANGED
@@ -259,7 +259,7 @@
259
259
 
260
260
  class PROJJSONBuilderBase {
261
261
  static getId(node) {
262
- const idNode = node.find((child) => Array.isArray(child) && child[0] === "ID");
262
+ const idNode = node.find((child) => Array.isArray(child) && child[0] === 'ID');
263
263
  if (idNode && idNode.length >= 3) {
264
264
  return {
265
265
  authority: idNode[1],
@@ -269,20 +269,20 @@
269
269
  return null;
270
270
  }
271
271
 
272
- static convertUnit(node, type = "unit") {
272
+ static convertUnit(node, type = 'unit') {
273
273
  if (!node || node.length < 3) {
274
- return { type, name: "unknown", conversion_factor: null };
274
+ return { type, name: 'unknown', conversion_factor: null };
275
275
  }
276
276
 
277
277
  const name = node[1];
278
278
  const conversionFactor = parseFloat(node[2]) || null;
279
279
 
280
- const idNode = node.find((child) => Array.isArray(child) && child[0] === "ID");
280
+ const idNode = node.find((child) => Array.isArray(child) && child[0] === 'ID');
281
281
  const id = idNode
282
282
  ? {
283
- authority: idNode[1],
284
- code: parseInt(idNode[2], 10),
285
- }
283
+ authority: idNode[1],
284
+ code: parseInt(idNode[2], 10),
285
+ }
286
286
  : null;
287
287
 
288
288
  return {
@@ -294,7 +294,7 @@
294
294
  }
295
295
 
296
296
  static convertAxis(node) {
297
- const name = node[1] || "Unknown";
297
+ const name = node[1] || 'Unknown';
298
298
 
299
299
  // Determine the direction
300
300
  let direction;
@@ -308,16 +308,16 @@
308
308
  else throw new Error(`Unknown axis abbreviation: ${abbreviation}`);
309
309
  } else {
310
310
  // Use the explicit direction provided in the AXIS node
311
- direction = node[2]?.toLowerCase() || "unknown";
311
+ direction = node[2] ? node[2].toLowerCase() : 'unknown';
312
312
  }
313
313
 
314
- const orderNode = node.find((child) => Array.isArray(child) && child[0] === "ORDER");
314
+ const orderNode = node.find((child) => Array.isArray(child) && child[0] === 'ORDER');
315
315
  const order = orderNode ? parseInt(orderNode[1], 10) : null;
316
316
 
317
317
  const unitNode = node.find(
318
318
  (child) =>
319
319
  Array.isArray(child) &&
320
- (child[0] === "LENGTHUNIT" || child[0] === "ANGLEUNIT" || child[0] === "SCALEUNIT")
320
+ (child[0] === 'LENGTHUNIT' || child[0] === 'ANGLEUNIT' || child[0] === 'SCALEUNIT')
321
321
  );
322
322
  const unit = this.convertUnit(unitNode);
323
323
 
@@ -331,7 +331,7 @@
331
331
 
332
332
  static extractAxes(node) {
333
333
  return node
334
- .filter((child) => Array.isArray(child) && child[0] === "AXIS")
334
+ .filter((child) => Array.isArray(child) && child[0] === 'AXIS')
335
335
  .map((axis) => this.convertAxis(axis))
336
336
  .sort((a, b) => (a.order || 0) - (b.order || 0)); // Sort by the "order" property
337
337
  }
@@ -339,17 +339,17 @@
339
339
  static convert(node, result = {}) {
340
340
 
341
341
  switch (node[0]) {
342
- case "PROJCRS":
343
- result.type = "ProjectedCRS";
342
+ case 'PROJCRS':
343
+ result.type = 'ProjectedCRS';
344
344
  result.name = node[1];
345
- result.base_crs = node.find((child) => Array.isArray(child) && child[0] === "BASEGEOGCRS")
346
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "BASEGEOGCRS"))
345
+ result.base_crs = node.find((child) => Array.isArray(child) && child[0] === 'BASEGEOGCRS')
346
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'BASEGEOGCRS'))
347
347
  : null;
348
- result.conversion = node.find((child) => Array.isArray(child) && child[0] === "CONVERSION")
349
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "CONVERSION"))
348
+ result.conversion = node.find((child) => Array.isArray(child) && child[0] === 'CONVERSION')
349
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'CONVERSION'))
350
350
  : null;
351
351
 
352
- const csNode = node.find((child) => Array.isArray(child) && child[0] === "CS");
352
+ const csNode = node.find((child) => Array.isArray(child) && child[0] === 'CS');
353
353
  if (csNode) {
354
354
  result.coordinate_system = {
355
355
  type: csNode[1],
@@ -357,7 +357,7 @@
357
357
  };
358
358
  }
359
359
 
360
- const lengthUnitNode = node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT");
360
+ const lengthUnitNode = node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT');
361
361
  if (lengthUnitNode) {
362
362
  const unit = this.convertUnit(lengthUnitNode);
363
363
  result.coordinate_system.unit = unit; // Add unit to coordinate_system
@@ -366,23 +366,23 @@
366
366
  result.id = this.getId(node);
367
367
  break;
368
368
 
369
- case "BASEGEOGCRS":
370
- case "GEOGCRS":
371
- result.type = "GeographicCRS";
369
+ case 'BASEGEOGCRS':
370
+ case 'GEOGCRS':
371
+ result.type = 'GeographicCRS';
372
372
  result.name = node[1];
373
373
 
374
374
  // Handle DATUM or ENSEMBLE
375
375
  const datumOrEnsembleNode = node.find(
376
- (child) => Array.isArray(child) && (child[0] === "DATUM" || child[0] === "ENSEMBLE")
376
+ (child) => Array.isArray(child) && (child[0] === 'DATUM' || child[0] === 'ENSEMBLE')
377
377
  );
378
378
  if (datumOrEnsembleNode) {
379
379
  const datumOrEnsemble = this.convert(datumOrEnsembleNode);
380
- if (datumOrEnsembleNode[0] === "ENSEMBLE") {
380
+ if (datumOrEnsembleNode[0] === 'ENSEMBLE') {
381
381
  result.datum_ensemble = datumOrEnsemble;
382
382
  } else {
383
383
  result.datum = datumOrEnsemble;
384
384
  }
385
- const primem = node.find((child) => Array.isArray(child) && child[0] === "PRIMEM");
385
+ const primem = node.find((child) => Array.isArray(child) && child[0] === 'PRIMEM');
386
386
  if (primem && primem[1] !== 'Greenwich') {
387
387
  datumOrEnsemble.prime_meridian = {
388
388
  name: primem[1],
@@ -392,42 +392,42 @@
392
392
  }
393
393
 
394
394
  result.coordinate_system = {
395
- type: "ellipsoidal",
395
+ type: 'ellipsoidal',
396
396
  axis: this.extractAxes(node),
397
397
  };
398
398
 
399
399
  result.id = this.getId(node);
400
400
  break;
401
401
 
402
- case "DATUM":
403
- result.type = "GeodeticReferenceFrame";
402
+ case 'DATUM':
403
+ result.type = 'GeodeticReferenceFrame';
404
404
  result.name = node[1];
405
- result.ellipsoid = node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID")
406
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID"))
405
+ result.ellipsoid = node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID')
406
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID'))
407
407
  : null;
408
408
  break;
409
409
 
410
- case "ENSEMBLE":
411
- result.type = "DatumEnsemble";
410
+ case 'ENSEMBLE':
411
+ result.type = 'DatumEnsemble';
412
412
  result.name = node[1];
413
413
 
414
414
  // Extract ensemble members
415
415
  result.members = node
416
- .filter((child) => Array.isArray(child) && child[0] === "MEMBER")
416
+ .filter((child) => Array.isArray(child) && child[0] === 'MEMBER')
417
417
  .map((member) => ({
418
- type: "DatumEnsembleMember",
418
+ type: 'DatumEnsembleMember',
419
419
  name: member[1],
420
420
  id: this.getId(member), // Extract ID as { authority, code }
421
421
  }));
422
422
 
423
423
  // Extract accuracy
424
- const accuracyNode = node.find((child) => Array.isArray(child) && child[0] === "ENSEMBLEACCURACY");
424
+ const accuracyNode = node.find((child) => Array.isArray(child) && child[0] === 'ENSEMBLEACCURACY');
425
425
  if (accuracyNode) {
426
426
  result.accuracy = parseFloat(accuracyNode[1]);
427
427
  }
428
428
 
429
429
  // Extract ellipsoid
430
- const ellipsoidNode = node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID");
430
+ const ellipsoidNode = node.find((child) => Array.isArray(child) && child[0] === 'ELLIPSOID');
431
431
  if (ellipsoidNode) {
432
432
  result.ellipsoid = this.convert(ellipsoidNode); // Convert the ellipsoid node
433
433
  }
@@ -436,66 +436,66 @@
436
436
  result.id = this.getId(node);
437
437
  break;
438
438
 
439
- case "ELLIPSOID":
440
- result.type = "Ellipsoid";
439
+ case 'ELLIPSOID':
440
+ result.type = 'Ellipsoid';
441
441
  result.name = node[1];
442
442
  result.semi_major_axis = parseFloat(node[2]);
443
443
  result.inverse_flattening = parseFloat(node[3]);
444
- node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT")
445
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT"), result)
444
+ node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT')
445
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'LENGTHUNIT'), result)
446
446
  : null;
447
447
  break;
448
448
 
449
- case "CONVERSION":
450
- result.type = "Conversion";
449
+ case 'CONVERSION':
450
+ result.type = 'Conversion';
451
451
  result.name = node[1];
452
- result.method = node.find((child) => Array.isArray(child) && child[0] === "METHOD")
453
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "METHOD"))
452
+ result.method = node.find((child) => Array.isArray(child) && child[0] === 'METHOD')
453
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'METHOD'))
454
454
  : null;
455
455
  result.parameters = node
456
- .filter((child) => Array.isArray(child) && child[0] === "PARAMETER")
456
+ .filter((child) => Array.isArray(child) && child[0] === 'PARAMETER')
457
457
  .map((param) => this.convert(param));
458
458
  break;
459
459
 
460
- case "METHOD":
461
- result.type = "Method";
460
+ case 'METHOD':
461
+ result.type = 'Method';
462
462
  result.name = node[1];
463
463
  result.id = this.getId(node);
464
464
  break;
465
465
 
466
- case "PARAMETER":
467
- result.type = "Parameter";
466
+ case 'PARAMETER':
467
+ result.type = 'Parameter';
468
468
  result.name = node[1];
469
469
  result.value = parseFloat(node[2]);
470
470
  result.unit = this.convertUnit(
471
471
  node.find(
472
472
  (child) =>
473
473
  Array.isArray(child) &&
474
- (child[0] === "LENGTHUNIT" || child[0] === "ANGLEUNIT" || child[0] === "SCALEUNIT")
474
+ (child[0] === 'LENGTHUNIT' || child[0] === 'ANGLEUNIT' || child[0] === 'SCALEUNIT')
475
475
  )
476
476
  );
477
477
  result.id = this.getId(node);
478
478
  break;
479
479
 
480
- case "BOUNDCRS":
481
- result.type = "BoundCRS";
480
+ case 'BOUNDCRS':
481
+ result.type = 'BoundCRS';
482
482
 
483
483
  // Process SOURCECRS
484
- const sourceCrsNode = node.find((child) => Array.isArray(child) && child[0] === "SOURCECRS");
484
+ const sourceCrsNode = node.find((child) => Array.isArray(child) && child[0] === 'SOURCECRS');
485
485
  if (sourceCrsNode) {
486
486
  const sourceCrsContent = sourceCrsNode.find((child) => Array.isArray(child));
487
487
  result.source_crs = sourceCrsContent ? this.convert(sourceCrsContent) : null;
488
488
  }
489
489
 
490
490
  // Process TARGETCRS
491
- const targetCrsNode = node.find((child) => Array.isArray(child) && child[0] === "TARGETCRS");
491
+ const targetCrsNode = node.find((child) => Array.isArray(child) && child[0] === 'TARGETCRS');
492
492
  if (targetCrsNode) {
493
493
  const targetCrsContent = targetCrsNode.find((child) => Array.isArray(child));
494
494
  result.target_crs = targetCrsContent ? this.convert(targetCrsContent) : null;
495
495
  }
496
496
 
497
497
  // Process ABRIDGEDTRANSFORMATION
498
- const transformationNode = node.find((child) => Array.isArray(child) && child[0] === "ABRIDGEDTRANSFORMATION");
498
+ const transformationNode = node.find((child) => Array.isArray(child) && child[0] === 'ABRIDGEDTRANSFORMATION');
499
499
  if (transformationNode) {
500
500
  result.transformation = this.convert(transformationNode);
501
501
  } else {
@@ -503,25 +503,25 @@
503
503
  }
504
504
  break;
505
505
 
506
- case "ABRIDGEDTRANSFORMATION":
507
- result.type = "Transformation";
506
+ case 'ABRIDGEDTRANSFORMATION':
507
+ result.type = 'Transformation';
508
508
  result.name = node[1];
509
- result.method = node.find((child) => Array.isArray(child) && child[0] === "METHOD")
510
- ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "METHOD"))
509
+ result.method = node.find((child) => Array.isArray(child) && child[0] === 'METHOD')
510
+ ? this.convert(node.find((child) => Array.isArray(child) && child[0] === 'METHOD'))
511
511
  : null;
512
512
 
513
513
  result.parameters = node
514
- .filter((child) => Array.isArray(child) && (child[0] === "PARAMETER" || child[0] === "PARAMETERFILE"))
514
+ .filter((child) => Array.isArray(child) && (child[0] === 'PARAMETER' || child[0] === 'PARAMETERFILE'))
515
515
  .map((param) => {
516
- if (param[0] === "PARAMETER") {
516
+ if (param[0] === 'PARAMETER') {
517
517
  return this.convert(param);
518
- } else if (param[0] === "PARAMETERFILE") {
518
+ } else if (param[0] === 'PARAMETERFILE') {
519
519
  return {
520
520
  name: param[1],
521
521
  value: param[2],
522
522
  id: {
523
- "authority": "EPSG",
524
- "code": 8656
523
+ 'authority': 'EPSG',
524
+ 'code': 8656
525
525
  }
526
526
  };
527
527
  }
@@ -530,7 +530,7 @@
530
530
  // Adjust the Scale difference parameter if present
531
531
  if (result.parameters.length === 7) {
532
532
  const scaleDifference = result.parameters[6];
533
- if (scaleDifference.name === "Scale difference") {
533
+ if (scaleDifference.name === 'Scale difference') {
534
534
  scaleDifference.value = Math.round((scaleDifference.value - 1) * 1e12) / 1e6;
535
535
  }
536
536
  }
@@ -538,14 +538,14 @@
538
538
  result.id = this.getId(node);
539
539
  break;
540
540
 
541
- case "AXIS":
541
+ case 'AXIS':
542
542
  if (!result.coordinate_system) {
543
- result.coordinate_system = { type: "unspecified", axis: [] };
543
+ result.coordinate_system = { type: 'unspecified', axis: [] };
544
544
  }
545
545
  result.coordinate_system.axis.push(this.convertAxis(node));
546
546
  break;
547
547
 
548
- case "LENGTHUNIT":
548
+ case 'LENGTHUNIT':
549
549
  const unit = this.convertUnit(node, 'LinearUnit');
550
550
  if (result.coordinate_system && result.coordinate_system.axis) {
551
551
  result.coordinate_system.axis.forEach((axis) => {
@@ -578,7 +578,7 @@
578
578
  super.convert(node, result);
579
579
 
580
580
  // Skip `CS` and `USAGE` nodes for WKT2-2015
581
- if (result.coordinate_system?.subtype === "Cartesian") {
581
+ if (result.coordinate_system && result.coordinate_system.subtype === 'Cartesian') {
582
582
  delete result.coordinate_system;
583
583
  }
584
584
  if (result.usage) {
@@ -594,7 +594,7 @@
594
594
  super.convert(node, result);
595
595
 
596
596
  // Handle `CS` node for WKT2-2019
597
- const csNode = node.find((child) => Array.isArray(child) && child[0] === "CS");
597
+ const csNode = node.find((child) => Array.isArray(child) && child[0] === 'CS');
598
598
  if (csNode) {
599
599
  result.coordinate_system = {
600
600
  subtype: csNode[1],
@@ -603,13 +603,21 @@
603
603
  }
604
604
 
605
605
  // Handle `USAGE` node for WKT2-2019
606
- const usageNode = node.find((child) => Array.isArray(child) && child[0] === "USAGE");
606
+ const usageNode = node.find((child) => Array.isArray(child) && child[0] === 'USAGE');
607
607
  if (usageNode) {
608
- result.usage = {
609
- scope: usageNode.find((child) => Array.isArray(child) && child[0] === "SCOPE")?.[1],
610
- area: usageNode.find((child) => Array.isArray(child) && child[0] === "AREA")?.[1],
611
- bbox: usageNode.find((child) => Array.isArray(child) && child[0] === "BBOX")?.slice(1),
612
- };
608
+ const scope = usageNode.find((child) => Array.isArray(child) && child[0] === 'SCOPE');
609
+ const area = usageNode.find((child) => Array.isArray(child) && child[0] === 'AREA');
610
+ const bbox = usageNode.find((child) => Array.isArray(child) && child[0] === 'BBOX');
611
+ result.usage = {};
612
+ if (scope) {
613
+ result.usage.scope = scope[1];
614
+ }
615
+ if (area) {
616
+ result.usage.area = area[1];
617
+ }
618
+ if (bbox) {
619
+ result.usage.bbox = bbox.slice(1);
620
+ }
613
621
  }
614
622
 
615
623
  return result;
@@ -623,21 +631,21 @@
623
631
  */
624
632
  function detectWKT2Version(root) {
625
633
  // Check for WKT2-2019-specific nodes
626
- if (root.find((child) => Array.isArray(child) && child[0] === "USAGE")) {
627
- return "2019"; // `USAGE` is specific to WKT2-2019
634
+ if (root.find((child) => Array.isArray(child) && child[0] === 'USAGE')) {
635
+ return '2019'; // `USAGE` is specific to WKT2-2019
628
636
  }
629
637
 
630
638
  // Check for WKT2-2015-specific nodes
631
- if (root.find((child) => Array.isArray(child) && child[0] === "CS")) {
632
- return "2015"; // `CS` is valid in both, but default to 2015 unless `USAGE` is present
639
+ if (root.find((child) => Array.isArray(child) && child[0] === 'CS')) {
640
+ return '2015'; // `CS` is valid in both, but default to 2015 unless `USAGE` is present
633
641
  }
634
642
 
635
- if (root[0] === "BOUNDCRS" || root[0] === "PROJCRS" || root[0] === "GEOGCRS") {
636
- return "2015"; // These are valid in both, but default to 2015
643
+ if (root[0] === 'BOUNDCRS' || root[0] === 'PROJCRS' || root[0] === 'GEOGCRS') {
644
+ return '2015'; // These are valid in both, but default to 2015
637
645
  }
638
646
 
639
647
  // Default to WKT2-2015 if no specific indicators are found
640
- return "2015";
648
+ return '2015';
641
649
  }
642
650
 
643
651
  /**
@@ -647,7 +655,7 @@
647
655
  */
648
656
  function buildPROJJSON(root) {
649
657
  const version = detectWKT2Version(root);
650
- const builder = version === "2019" ? PROJJSONBuilder2019 : PROJJSONBuilder2015;
658
+ const builder = version === '2019' ? PROJJSONBuilder2019 : PROJJSONBuilder2015;
651
659
  return builder.convert(root);
652
660
  }
653
661
 
@@ -662,30 +670,30 @@
662
670
 
663
671
  // Check for WKT2-specific keywords
664
672
  if (
665
- normalizedWKT.includes("PROJCRS") ||
666
- normalizedWKT.includes("GEOGCRS") ||
667
- normalizedWKT.includes("BOUNDCRS") ||
668
- normalizedWKT.includes("VERTCRS") ||
669
- normalizedWKT.includes("LENGTHUNIT") ||
670
- normalizedWKT.includes("ANGLEUNIT") ||
671
- normalizedWKT.includes("SCALEUNIT")
673
+ normalizedWKT.includes('PROJCRS') ||
674
+ normalizedWKT.includes('GEOGCRS') ||
675
+ normalizedWKT.includes('BOUNDCRS') ||
676
+ normalizedWKT.includes('VERTCRS') ||
677
+ normalizedWKT.includes('LENGTHUNIT') ||
678
+ normalizedWKT.includes('ANGLEUNIT') ||
679
+ normalizedWKT.includes('SCALEUNIT')
672
680
  ) {
673
- return "WKT2";
681
+ return 'WKT2';
674
682
  }
675
683
 
676
684
  // Check for WKT1-specific keywords
677
685
  if (
678
- normalizedWKT.includes("PROJCS") ||
679
- normalizedWKT.includes("GEOGCS") ||
680
- normalizedWKT.includes("LOCAL_CS") ||
681
- normalizedWKT.includes("VERT_CS") ||
682
- normalizedWKT.includes("UNIT")
686
+ normalizedWKT.includes('PROJCS') ||
687
+ normalizedWKT.includes('GEOGCS') ||
688
+ normalizedWKT.includes('LOCAL_CS') ||
689
+ normalizedWKT.includes('VERT_CS') ||
690
+ normalizedWKT.includes('UNIT')
683
691
  ) {
684
- return "WKT1";
692
+ return 'WKT1';
685
693
  }
686
694
 
687
695
  // Default to WKT1 if no specific indicators are found
688
- return "WKT1";
696
+ return 'WKT1';
689
697
  }
690
698
 
691
699
  var NEUTRAL = 1;
@@ -1010,7 +1018,7 @@
1010
1018
  if (result.units === 'meter') {
1011
1019
  result.to_meter = 1; // Only set to_meter if units are 'meter'
1012
1020
  }
1013
- } else if (unit?.name) {
1021
+ } else if (unit && unit.name) {
1014
1022
  result.units = unit.name.toLowerCase();
1015
1023
  if (result.units === 'metre') {
1016
1024
  result.units = 'meter'; // Normalize 'metre' to 'meter'
@@ -1051,7 +1059,7 @@
1051
1059
  transformPROJJSON(projjson.source_crs, result);
1052
1060
 
1053
1061
  if (projjson.transformation) {
1054
- if (projjson.transformation.method?.name === 'NTv2') {
1062
+ if (projjson.transformation.method && projjson.transformation.method.name === 'NTv2') {
1055
1063
  // Set nadgrids to the filename from the parameterfile
1056
1064
  result.nadgrids = projjson.transformation.parameters[0].value;
1057
1065
  } else {
@@ -1081,8 +1089,8 @@
1081
1089
  case 'type':
1082
1090
  if (value === 'GeographicCRS') {
1083
1091
  result.projName = 'longlat';
1084
- } else if (value === 'ProjectedCRS') {
1085
- result.projName = projjson.conversion?.method?.name; // Retain original capitalization
1092
+ } else if (value === 'ProjectedCRS' && projjson.conversion && projjson.conversion.method) {
1093
+ result.projName = projjson.conversion.method.name; // Retain original capitalization
1086
1094
  }
1087
1095
  break;
1088
1096
 
@@ -1124,7 +1132,7 @@
1124
1132
  const { units, to_meter } = processUnit(value.unit);
1125
1133
  result.units = units;
1126
1134
  result.to_meter = to_meter;
1127
- } else if (value.axis[0]?.unit) {
1135
+ } else if (value.axis[0] && value.axis[0].unit) {
1128
1136
  const { units, to_meter } = processUnit(value.axis[0].unit);
1129
1137
  result.units = units;
1130
1138
  result.to_meter = to_meter;
@@ -1590,6 +1598,9 @@
1590
1598
  }
1591
1599
  var codes = ['3857', '900913', '3785', '102113'];
1592
1600
  function checkMercator(item) {
1601
+ if (item.title) {
1602
+ return item.title.toLowerCase().indexOf('epsg:') === 0 && codes.indexOf(item.title.substr(5)) > -1;
1603
+ }
1593
1604
  var auth = match(item, 'authority');
1594
1605
  if (!auth) {
1595
1606
  return;
@@ -8910,8 +8921,8 @@
8910
8921
 
8911
8922
  /* Place parameters in static storage for common use
8912
8923
  ------------------------------------------------- */
8913
- this.sin_p14 = Math.sin(this.lat0);
8914
- this.cos_p14 = Math.cos(this.lat0);
8924
+ this.sin_p14 = Math.sin(this.lat0 || 0);
8925
+ this.cos_p14 = Math.cos(this.lat0 || 0);
8915
8926
  }
8916
8927
 
8917
8928
  /* Orthographic forward equations--mapping lat,long to x,y
@@ -8926,7 +8937,7 @@
8926
8937
  var lat = p.y;
8927
8938
  /* Forward equations
8928
8939
  ----------------- */
8929
- dlon = adjust_lon(lon - this.long0, this.over);
8940
+ dlon = adjust_lon(lon - (this.long0 || 0), this.over);
8930
8941
 
8931
8942
  sinphi = Math.sin(lat);
8932
8943
  cosphi = Math.cos(lat);
@@ -8936,7 +8947,7 @@
8936
8947
  ksp = 1;
8937
8948
  if ((g > 0) || (Math.abs(g) <= EPSLN)) {
8938
8949
  x = this.a * ksp * cosphi * Math.sin(dlon);
8939
- y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
8950
+ y = (this.y0 || 0) + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
8940
8951
  }
8941
8952
  p.x = x;
8942
8953
  p.y = y;
@@ -8949,36 +8960,39 @@
8949
8960
  var sinz, cosz; /* sin of z and cos of z */
8950
8961
  var con;
8951
8962
  var lon, lat;
8963
+ var long0, lat0;
8952
8964
  /* Inverse equations
8953
8965
  ----------------- */
8954
- p.x -= this.x0;
8955
- p.y -= this.y0;
8966
+ p.x -= this.x0 || 0;
8967
+ p.y -= this.y0 || 0;
8956
8968
  rh = Math.sqrt(p.x * p.x + p.y * p.y);
8957
8969
  z = asinz(rh / this.a);
8958
8970
 
8959
8971
  sinz = Math.sin(z);
8960
8972
  cosz = Math.cos(z);
8961
8973
 
8962
- lon = this.long0;
8974
+ long0 = this.long0 || 0;
8975
+ lat0 = this.lat0 || 0;
8976
+ lon = long0;
8963
8977
  if (Math.abs(rh) <= EPSLN) {
8964
- lat = this.lat0;
8978
+ lat = lat0;
8965
8979
  p.x = lon;
8966
8980
  p.y = lat;
8967
8981
  return p;
8968
8982
  }
8969
8983
  lat = asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14) / rh);
8970
- con = Math.abs(this.lat0) - HALF_PI;
8984
+ con = Math.abs(lat0) - HALF_PI;
8971
8985
  if (Math.abs(con) <= EPSLN) {
8972
- if (this.lat0 >= 0) {
8973
- lon = adjust_lon(this.long0 + Math.atan2(p.x, -p.y), this.over);
8986
+ if (lat0 >= 0) {
8987
+ lon = adjust_lon(long0 + Math.atan2(p.x, -p.y), this.over);
8974
8988
  } else {
8975
- lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y), this.over);
8989
+ lon = adjust_lon(long0 - Math.atan2(-p.x, p.y), this.over);
8976
8990
  }
8977
8991
  p.x = lon;
8978
8992
  p.y = lat;
8979
8993
  return p;
8980
8994
  }
8981
- lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz), rh * this.cos_p14 * cosz - p.y * this.sin_p14 * sinz), this.over);
8995
+ lon = adjust_lon(long0 + Math.atan2((p.x * sinz), rh * this.cos_p14 * cosz - p.y * this.sin_p14 * sinz), this.over);
8982
8996
  p.x = lon;
8983
8997
  p.y = lat;
8984
8998
  return p;
@@ -10552,7 +10566,7 @@
10552
10566
  nadgrid,
10553
10567
  transform,
10554
10568
  mgrs,
10555
- version: '2.20.2'
10569
+ version: '2.20.3'
10556
10570
  });
10557
10571
  includedProjections(proj4);
10558
10572