1
1
/* <<<< Cartographic projection filter program >>>> */
2
2
#include " proj.h"
3
3
#include " emess.h"
4
+ #include " proj_experimental.h"
4
5
#include " proj_internal.h"
5
6
#include " utils.h"
6
7
#include < ctype.h>
9
10
#include < stdlib.h>
10
11
#include < string.h>
11
12
13
+ #include < proj/crs.hpp>
14
+
12
15
#include < vector>
13
16
14
17
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__)
22
25
#define MAX_LINE 1000
23
26
#define PJ_INVERSE (P ) (P->inv ? 1 : 0 )
24
27
25
- static PJ *Proj;
28
+ static PJ *Proj = nullptr ;
29
+ static PJ *ProjForFactors = nullptr ;
30
+ static bool swapAxisCrs = false ;
26
31
static union {
27
32
PJ_XY (*fwd)(PJ_LP, PJ *);
28
33
PJ_LP (*inv)(PJ_XY, PJ *);
@@ -115,16 +120,16 @@ static void process(FILE *fid) {
115
120
data.uv .v *= fscale;
116
121
}
117
122
if (dofactors && !inverse) {
118
- facs = proj_factors (Proj , coord);
119
- facs_bad = proj_errno (Proj );
123
+ facs = proj_factors (ProjForFactors , coord);
124
+ facs_bad = proj_errno (ProjForFactors );
120
125
}
121
126
122
127
const auto xy = (*proj.fwd )(data.lp , Proj);
123
128
data.xy = xy;
124
129
125
130
if (dofactors && inverse) {
126
- facs = proj_factors (Proj , coord);
127
- facs_bad = proj_errno (Proj );
131
+ facs = proj_factors (ProjForFactors , coord);
132
+ facs_bad = proj_errno (ProjForFactors );
128
133
}
129
134
130
135
if (postscale && data.uv .u != HUGE_VAL) {
@@ -281,8 +286,8 @@ static void vprocess(FILE *fid) {
281
286
if (!*s && (s > line))
282
287
--s; /* assumed we gobbled \n */
283
288
coord.lp = dat_ll;
284
- facs = proj_factors (Proj , coord);
285
- if (proj_errno (Proj )) {
289
+ facs = proj_factors (ProjForFactors , coord);
290
+ if (proj_errno (ProjForFactors )) {
286
291
emess (-1 , " failed to compute factors\n\n " );
287
292
continue ;
288
293
}
@@ -298,10 +303,12 @@ static void vprocess(FILE *fid) {
298
303
(void )fputs (proj_rtodms2 (pline, sizeof (pline), dat_ll.phi , ' N' , ' S' ),
299
304
stdout);
300
305
(void )printf (" [ %.11g ]\n " , dat_ll.phi * RAD_TO_DEG);
301
- (void )fputs (" Easting (x): " , stdout);
306
+ (void )fputs (swapAxisCrs ? " Northing (y): " : " Easting (x): " ,
307
+ stdout);
302
308
(void )printf (oform, dat_xy.x );
303
309
putchar (' \n ' );
304
- (void )fputs (" Northing (y): " , stdout);
310
+ (void )fputs (swapAxisCrs ? " Easting (x): " : " Northing (y): " ,
311
+ stdout);
305
312
(void )printf (oform, dat_xy.y );
306
313
putchar (' \n ' );
307
314
(void )printf (" Meridian scale (h) : %.8f ( %.4g %% error )\n " ,
@@ -507,8 +514,6 @@ int main(int argc, char **argv) {
507
514
} else /* assumed to be input file name(s) */
508
515
eargv[eargc++] = *argv;
509
516
}
510
- if (eargc == 0 ) /* if no specific files force sysin */
511
- eargv[eargc++] = const_cast <char *>(" -" );
512
517
513
518
if (oform) {
514
519
if (!validate_form_string_for_numbers (oform)) {
@@ -525,14 +530,80 @@ int main(int argc, char **argv) {
525
530
}
526
531
proj_context_use_proj4_init_rules (nullptr , true );
527
532
533
+ if (argvVector.empty () && eargc >= 1 ) {
534
+ // Consider the next arg as a CRS, not a file.
535
+ std::string ocrs = eargv[0 ];
536
+ eargv++;
537
+ eargc--;
538
+ // logic copied from proj_factors function
539
+ if (PJ *P = proj_create (nullptr , ocrs.c_str ())) {
540
+ const auto type = proj_get_type (P);
541
+ if (type == PJ_TYPE_PROJECTED_CRS) {
542
+ try {
543
+ using namespace osgeo ::proj;
544
+ auto crs = dynamic_cast <const crs::ProjectedCRS *>(
545
+ P->iso_obj .get ());
546
+ auto dir =
547
+ crs->coordinateSystem ()->axisList ()[0 ]->direction ();
548
+ swapAxisCrs = dir == cs::AxisDirection::NORTH ||
549
+ dir == cs::AxisDirection::SOUTH;
550
+ } catch (...) {
551
+ }
552
+ auto ctx = P->ctx ;
553
+ auto geodetic_crs = proj_get_source_crs (ctx, P);
554
+ assert (geodetic_crs);
555
+ auto datum = proj_crs_get_datum (ctx, geodetic_crs);
556
+ auto datum_ensemble =
557
+ proj_crs_get_datum_ensemble (ctx, geodetic_crs);
558
+ auto cs = proj_create_ellipsoidal_2D_cs (
559
+ ctx, PJ_ELLPS2D_LONGITUDE_LATITUDE, " Radian" , 1.0 );
560
+ auto geogCRSNormalized = proj_create_geographic_crs_from_datum (
561
+ ctx, " unnamed crs" , datum ? datum : datum_ensemble, cs);
562
+ proj_destroy (datum);
563
+ proj_destroy (datum_ensemble);
564
+ proj_destroy (cs);
565
+ Proj = proj_create_crs_to_crs_from_pj (ctx, geogCRSNormalized, P,
566
+ nullptr , nullptr );
567
+
568
+ auto conversion = proj_crs_get_coordoperation (ctx, P);
569
+ auto projCS = proj_create_cartesian_2D_cs (
570
+ ctx, PJ_CART2D_EASTING_NORTHING, " metre" , 1.0 );
571
+ auto projCRSNormalized = proj_create_projected_crs (
572
+ ctx, nullptr , geodetic_crs, conversion, projCS);
573
+ assert (projCRSNormalized);
574
+ proj_destroy (geodetic_crs);
575
+ proj_destroy (conversion);
576
+ proj_destroy (projCS);
577
+ ProjForFactors = proj_create_crs_to_crs_from_pj (
578
+ ctx, geogCRSNormalized, projCRSNormalized, nullptr ,
579
+ nullptr );
580
+
581
+ proj_destroy (geogCRSNormalized);
582
+ proj_destroy (projCRSNormalized);
583
+ } else {
584
+ emess (3 , " CRS must be projected" );
585
+ }
586
+ proj_destroy (P);
587
+ } else {
588
+ emess (3 , " CRS is not parseable" );
589
+ }
590
+ }
591
+ if (eargc == 0 ) /* if no specific files force sysin */
592
+ eargv[eargc++] = const_cast <char *>(" -" );
593
+
528
594
// proj historically ignores any datum shift specifier, like nadgrids,
529
595
// towgs84, etc
530
596
argvVector.push_back (const_cast <char *>(" break_cs2cs_recursion" ));
531
597
532
- if (!(Proj = proj_create_argv (nullptr , static_cast <int >(argvVector.size ()),
533
- argvVector.data ())))
534
- emess (3 , " projection initialization failure\n cause: %s" ,
535
- proj_errno_string (proj_context_errno (nullptr )));
598
+ if (!Proj) {
599
+ if (!(Proj =
600
+ proj_create_argv (nullptr , static_cast <int >(argvVector.size ()),
601
+ argvVector.data ())))
602
+ emess (3 , " projection initialization failure\n cause: %s" ,
603
+ proj_errno_string (proj_context_errno (nullptr )));
604
+
605
+ ProjForFactors = Proj;
606
+ }
536
607
537
608
if (!proj_angular_input (Proj, PJ_FWD)) {
538
609
emess (3 , " can't initialize operations that take non-angular input "
@@ -616,6 +687,8 @@ int main(int argc, char **argv) {
616
687
emess_dat.File_name = nullptr ;
617
688
}
618
689
690
+ if (ProjForFactors && ProjForFactors != Proj)
691
+ proj_destroy (ProjForFactors);
619
692
if (Proj)
620
693
proj_destroy (Proj);
621
694
0 commit comments