@@ -55,13 +55,16 @@ struct PROJECT_CTRL { /* All control options for this program (except common arg
55
55
bool active ;
56
56
char col [PROJECT_N_FARGS ]; /* Character codes for desired output in the right order */
57
57
} F ;
58
- struct PROJECT_G { /* -G<inc>[/<colat>][+h ] */
58
+ struct PROJECT_G { /* -G<inc>[<unit>[ /<colat>][+c|h][+n ] */
59
59
bool active ;
60
60
bool header ;
61
+ bool number ;
61
62
bool through_C ;
62
63
unsigned int mode ;
63
64
double inc ;
64
65
double colat ;
66
+ char unit ;
67
+ int d_mode ; /* Could be negative */
65
68
} G ;
66
69
struct PROJECT_L { /* -L[w][<l_min>/<l_max>] */
67
70
bool active ;
@@ -323,8 +326,8 @@ static void Free_Ctrl (struct GMT_CTRL *GMT, struct PROJECT_CTRL *C) { /* Deallo
323
326
static int usage (struct GMTAPI_CTRL * API , int level ) {
324
327
const char * name = gmt_show_name_and_purpose (API , THIS_MODULE_LIB , THIS_MODULE_CLASSIC_NAME , THIS_MODULE_PURPOSE );
325
328
if (level == GMT_MODULE_PURPOSE ) return (GMT_NOERROR );
326
- GMT_Usage (API , 0 , "usage: %s [<table>] -C<ox>/<oy> [-A<azimuth>] [-E<bx>/<by>] [-F<flags>] [-G<dist>[/<colat>][+c|h ]] "
327
- "[-L[w|<l_min>/<l_max>]] [-N] [-Q] [-S] [-T<px>/<py>] [%s] [-W<w_min>/<w_max>] [-Z<major>[unit][/<minor>/<azimuth>][+e|n ]] "
329
+ GMT_Usage (API , 0 , "usage: %s [<table>] -C<ox>/<oy> [-A<azimuth>] [-E<bx>/<by>] [-F<flags>] [-G<dist>[unit][ /<colat>][+c][+h][+n ]] "
330
+ "[-L[w|<l_min>/<l_max>]] [-N] [-Q] [-S] [-T<px>/<py>] [%s] [-W<w_min>/<w_max>] [-Z<major>[unit][/<minor>/<azimuth>][+e]] "
328
331
"[%s] [%s] [%s] [%s] [%s] [%s] [%s] [%s] [%s] [%s] [%s] [%s]\n" ,
329
332
name , GMT_V_OPT , GMT_b_OPT , GMT_d_OPT , GMT_e_OPT , GMT_f_OPT , GMT_g_OPT , GMT_h_OPT , GMT_i_OPT , GMT_o_OPT ,
330
333
GMT_q_OPT , GMT_s_OPT , GMT_colon_OPT , GMT_PAR_OPT );
@@ -361,12 +364,15 @@ static int usage (struct GMTAPI_CTRL *API, int level) {
361
364
"Note 2: z refers to all input data columns beyond the required x,y. "
362
365
"Note 3: If -G is set, -F is not available and output defaults to rsp "
363
366
"[Default is all fields, i.e., -Fxyzpqrs]." );
364
- GMT_Usage (API , 1 , "\n-G<dist>[/<colat>][+c|h]" );
367
+ GMT_Usage (API , 1 , "\n-G<dist>[<unit>][ /<colat>][+c|h]" );
365
368
GMT_Usage (API , -2 , "Generate (r,s,p) points along profile every <dist> units. (No input data used.) "
366
369
"If E given, will generate from C to E; else must give -L<l_min>/<l_max> for length. "
367
370
"Optionally, append /<colat> for a small circle path through C and E (requires -C -E). Some modifiers:" );
368
371
GMT_Usage (API , 3 , "+c If given -T and -C, compute and use <colat> of C [90]." );
369
372
GMT_Usage (API , 3 , "+h Place information about the pole in a segment header [no header]." );
373
+ GMT_Usage (API , 3 , "+n Increment specifies the number of points instead (requires -C -E or -Z)." );
374
+ GMT_Usage (API , -2 , "For geographic profile, append e (meter), f (foot), k (km), M (mile), n (nautical mile), u (survey foot), d (arc degree), "
375
+ "m (arc minute), or s (arc second) to <inc> [k]. " );
370
376
GMT_Usage (API , 1 , "\n-L[w|<l_min>/<l_max>]" );
371
377
GMT_Usage (API , -2 , "Check the Length along the projected track and use only certain points:n" );
372
378
GMT_Usage (API , 3 , "%s Append w to only use those points Within the span from C to E (Must have set -E)." , GMT_LINE_BULLET );
@@ -387,7 +393,6 @@ static int usage (struct GMTAPI_CTRL *API, int level) {
387
393
GMT_Usage (API , 1 , "\n-Z<major>[unit][/<minor>/<azimuth>][+e|n]" );
388
394
GMT_Usage (API , -2 , "With -G and -C, generate an ellipse of given major and minor axes and the azimuth of the major axis." );
389
395
GMT_Usage (API , 3 , "+e Adjust increment to fix perimeter exactly [use increment as given in -G]." );
390
- GMT_Usage (API , 3 , "+n Indicate that increment in -G specifies the number of unique perimeter points instead." );
391
396
GMT_Usage (API , -2 , "For a degenerate ellipse, i.e., circle, you may just give <major> only as the <diameter>. "
392
397
"Append e (meter), f (foot), k (km), M (mile), n (nautical mile), u (survey foot), d (arc degree), "
393
398
"m (arc minute), or s (arc second) to <major> [k]; we assume -G is in the same units (unless +n is used). "
@@ -411,7 +416,14 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
411
416
struct GMT_OPTION * opt = NULL ;
412
417
struct GMTAPI_CTRL * API = GMT -> parent ;
413
418
414
- for (opt = options ; opt ; opt = opt -> next ) if (opt -> option == 'N' ) Ctrl -> N .active = true; /* Must find -N first, if given */
419
+ for (opt = options ; opt ; opt = opt -> next ) {
420
+ if (opt -> option == 'N' ) /* Must find -N first, if given */
421
+ Ctrl -> N .active = true;
422
+ else if (opt -> option == 'Q' ) { /* Geographic coordinates */
423
+ gmt_set_geographic (GMT , GMT_IN );
424
+ gmt_set_geographic (GMT , GMT_OUT );
425
+ }
426
+ }
415
427
416
428
for (opt = options ; opt ; opt = opt -> next ) {
417
429
switch (opt -> option ) {
@@ -488,24 +500,33 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
488
500
opt -> arg [len ] = 0 ; /* Temporarily remove the trailing + sign */
489
501
ch = & opt -> arg [len ];
490
502
}
491
- if ((c = gmt_first_modifier (GMT , opt -> arg , "ch " ))) { /* Process any modifiers */
503
+ if ((c = gmt_first_modifier (GMT , opt -> arg , "chn " ))) { /* Process any modifiers */
492
504
pos = 0 ; /* Reset to start of new word */
493
- while (gmt_getmodopt (GMT , 'G' , c , "ch " , & pos , p , & n_errors ) && n_errors == 0 ) {
505
+ while (gmt_getmodopt (GMT , 'G' , c , "chn " , & pos , p , & n_errors ) && n_errors == 0 ) {
494
506
switch (p [0 ]) {
495
- case 'c' : Ctrl -> G .through_C = true; break ; /* Compute required colatitude for small ircle to go through C */
507
+ case 'c' : Ctrl -> G .through_C = true; break ; /* Compute required colatitude for small circle to go through C */
496
508
case 'h' : Ctrl -> G .header = true; break ; /* Output segment header */
509
+ case 'n' : Ctrl -> G .number = true; break ; /* Gave number of points rather than increment */
497
510
default : break ; /* These are caught in gmt_getmodopt so break is just for Coverity */
498
511
}
499
512
}
500
513
c [0 ] = '\0' ; /* Hide modifiers */
501
514
}
502
515
if (sscanf (opt -> arg , "%[^/]/%s" , txt_a , txt_b ) == 2 ) { /* Got dist/colat */
503
516
Ctrl -> G .mode = 1 ;
504
- Ctrl -> G .inc = atof (txt_a );
505
517
n_errors += gmt_verify_expectations (GMT , gmt_M_type (GMT , GMT_IN , GMT_Y ), gmt_scanf_arg (GMT , txt_b , gmt_M_type (GMT , GMT_IN , GMT_Y ), false, & Ctrl -> G .colat ), txt_b );
506
518
}
507
519
else
508
- Ctrl -> G .inc = atof (opt -> arg );
520
+ strcpy (txt_a , opt -> arg );
521
+ if (Ctrl -> G .number ) {
522
+ Ctrl -> Z .number = true; /* Since -Z +n needs backwards compatibility support */
523
+ Ctrl -> G .inc = atof (txt_a );
524
+ }
525
+ else {
526
+ if (gmt_M_is_geographic (GMT , GMT_IN ) && strchr (GMT_LEN_UNITS , txt_a [strlen (txt_a )- 1 ]) == NULL ) /* No unit given, append k for default km */
527
+ strcat (txt_a , "k" );
528
+ Ctrl -> G .d_mode = gmt_get_distance (GMT , txt_a , & (Ctrl -> G .inc ), & (Ctrl -> G .unit ));
529
+ }
509
530
if (ch ) ch [0 ] = '+' ; /* Restore the obsolete plus-sign */
510
531
if (c ) c [0 ] = '+' ; /* Restore modifier */
511
532
break ;
@@ -568,6 +589,8 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
568
589
Ctrl -> Z .minor = atof (txt_b );
569
590
}
570
591
else { /* Watch out for units and convert to km */
592
+ if (gmt_M_is_geographic (GMT , GMT_IN ) && strchr (GMT_LEN_UNITS , txt_a [strlen (txt_a )- 1 ]) == NULL ) /* No unit given, append k for default km */
593
+ strcat (txt_a , "k" );
571
594
Ctrl -> Z .mode = gmt_get_distance (GMT , txt_a , & (Ctrl -> Z .major ), & (Ctrl -> Z .unit ));
572
595
(void ) gmt_get_distance (GMT , txt_b , & (Ctrl -> Z .minor ), & dummy );
573
596
}
@@ -588,6 +611,9 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
588
611
if (Ctrl -> N .active )
589
612
Ctrl -> Z .minor = Ctrl -> Z .major = atof (opt -> arg );
590
613
else {
614
+ strcpy (txt_a , opt -> arg );
615
+ if (gmt_M_is_geographic (GMT , GMT_IN ) && strchr (GMT_LEN_UNITS , txt_a [strlen (txt_a )- 1 ]) == NULL ) /* No unit given, append k for default km */
616
+ strcat (txt_a , "k" );
591
617
Ctrl -> Z .mode = gmt_get_distance (GMT , opt -> arg , & (Ctrl -> Z .minor ), & (Ctrl -> Z .unit ));
592
618
Ctrl -> Z .major = Ctrl -> Z .minor ;
593
619
}
@@ -611,6 +637,8 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
611
637
n_errors ++ ;
612
638
}
613
639
640
+ n_errors += gmt_M_check_condition (GMT , Ctrl -> G .number && !(Ctrl -> C .active && Ctrl -> E .active ),
641
+ "Option -G: Can only use +n if both -C and -E are specified\n" );
614
642
n_errors += gmt_M_check_condition (GMT , Ctrl -> L .active && !Ctrl -> L .constrain && Ctrl -> L .min >= Ctrl -> L .max ,
615
643
"Option -L: w_min must be < w_max\n" );
616
644
n_errors += gmt_M_check_condition (GMT , Ctrl -> W .active && Ctrl -> W .min >= Ctrl -> W .max ,
@@ -635,6 +663,8 @@ static int parse (struct GMT_CTRL *GMT, struct PROJECT_CTRL *Ctrl, struct GMT_OP
635
663
"Option -N: Cannot be used with -G<dist>/<colat>\n" );
636
664
n_errors += gmt_M_check_condition (GMT , Ctrl -> G .through_C && !Ctrl -> C .active ,
637
665
"Option -G: Modifier +c requires both -C and -T\n" );
666
+ n_errors += gmt_M_check_condition (GMT , Ctrl -> Z .active && !Ctrl -> G .active ,
667
+ "Option -Z: Requires option -G as well\n" );
638
668
n_errors += gmt_M_check_condition (GMT , Ctrl -> G .through_C && !Ctrl -> T .active ,
639
669
"Option -G: Modifier +c requires both -C and -T\n" );
640
670
n_errors += gmt_check_binary_io (GMT , 2 );
@@ -761,12 +791,10 @@ EXTERN_MSC int GMT_project (void *V_API, int mode, void *args) {
761
791
if (GMT -> current .map .dist [GMT_MAP_DIST ].arc ) { /* Got angular measures, convert to km */
762
792
Ctrl -> Z .minor *= (GMT -> current .proj .KM_PR_DEG / GMT -> current .map .dist [GMT_MAP_DIST ].scale ); /* Now in km */
763
793
Ctrl -> Z .major *= (GMT -> current .proj .KM_PR_DEG / GMT -> current .map .dist [GMT_MAP_DIST ].scale ); /* Now in km */
764
- if (!Ctrl -> Z .number ) Ctrl -> G .inc *= (GMT -> current .proj .KM_PR_DEG / GMT -> current .map .dist [GMT_MAP_DIST ].scale ); /* Now in km */
765
794
}
766
795
else {
767
796
Ctrl -> Z .minor /= (GMT -> current .map .dist [GMT_MAP_DIST ].scale * METERS_IN_A_KM ); /* Now in km */
768
797
Ctrl -> Z .major /= (GMT -> current .map .dist [GMT_MAP_DIST ].scale * METERS_IN_A_KM ); /* Now in km */
769
- if (!Ctrl -> Z .number ) Ctrl -> G .inc /= (GMT -> current .map .dist [GMT_MAP_DIST ].scale * METERS_IN_A_KM ); /* Now in km */
770
798
}
771
799
}
772
800
}
@@ -813,10 +841,24 @@ EXTERN_MSC int GMT_project (void *V_API, int mode, void *args) {
813
841
P .find_new_point = true;
814
842
}
815
843
if (Ctrl -> G .active ) { /* Hardwire 3 output columns and set their types */
844
+ if (gmt_M_is_geographic (GMT , GMT_IN ) && Ctrl -> G .d_mode ) {
845
+ if (gmt_init_distaz (GMT , Ctrl -> G .unit , Ctrl -> G .d_mode , GMT_MAP_DIST ) == GMT_NOT_A_VALID_TYPE )
846
+ Return (GMT_NOT_A_VALID_TYPE );
847
+ }
816
848
P .n_outputs = 3 ;
817
849
gmt_set_column_type (GMT , GMT_OUT , GMT_X , (Ctrl -> N .active ) ? GMT_IS_FLOAT : GMT_IS_LON );
818
850
gmt_set_column_type (GMT , GMT_OUT , GMT_Y , (Ctrl -> N .active ) ? GMT_IS_FLOAT : GMT_IS_LAT );
819
851
gmt_set_column_type (GMT , GMT_OUT , GMT_Z , GMT_IS_FLOAT );
852
+ if (Ctrl -> G .number ) { /* Must compute great circle separation and divide to get increment */
853
+ double L ;
854
+ if (gmt_M_is_geographic (GMT , GMT_IN ))
855
+ L = 0.001 * gmt_great_circle_dist_meter (GMT , Ctrl -> C .x , Ctrl -> C .y , Ctrl -> E .x , Ctrl -> E .y );
856
+ else
857
+ L = hypot (Ctrl -> C .x - Ctrl -> E .x , Ctrl -> C .y - Ctrl -> E .y );
858
+ Ctrl -> G .inc = L / (Ctrl -> G .inc - 1.0 );
859
+ }
860
+ else if (Ctrl -> Q .active && Ctrl -> G .unit != 'k' )
861
+ Ctrl -> G .inc *= 0.001 / GMT -> current .map .dist [GMT_MAP_DIST ].scale ; /* Now in km */
820
862
}
821
863
else if (!Ctrl -> N .active ) { /* Decode and set the various output column types in the geographic case */
822
864
for (col = 0 ; col < P .n_outputs ; col ++ ) {
@@ -937,6 +979,7 @@ EXTERN_MSC int GMT_project (void *V_API, int mode, void *args) {
937
979
double h = pow (Ctrl -> Z .major - Ctrl -> Z .minor , 2.0 ) / pow (Ctrl -> Z .major + Ctrl -> Z .minor , 2.0 );
938
980
Ctrl -> L .min = 0.0 ;
939
981
Ctrl -> L .max = M_PI * (Ctrl -> Z .major + Ctrl -> Z .minor ) * (1.0 + (3.0 * h )/(10.0 + sqrt (4.0 - 3.0 * h ))); /* Ramanujan approximation of ellipse circumference */
982
+ if (gmt_M_is_geographic (GMT , GMT_IN )) Ctrl -> L .max /= GMT -> current .proj .DIST_KM_PR_DEG ;
940
983
if (Ctrl -> Z .number ) /* Want a specific number of points */
941
984
Ctrl -> G .inc = Ctrl -> L .max / rint (Ctrl -> G .inc );
942
985
else if (Ctrl -> Z .exact ) { /* Adjust inc to fit the ellipse perimeter exactly */
0 commit comments