22
22
* Version: 6 API
23
23
*
24
24
* Brief synopsis: gmtselect is a general-purpose spatial filter. Data pass
25
- * or fail basedon one or more conditions. Seven conditions may be set:
25
+ * or fail based on one or more conditions. Seven conditions may be set:
26
26
*
27
27
* 1. Only data inside a rectangular area may pass
28
28
* 2. Only data within a certain distance from given points may pass
@@ -87,8 +87,10 @@ struct GMTSELECT_CTRL { /* All control options for this program (except common a
87
87
} A ;
88
88
struct GMTSELECT_C { /* [-C[-|=|+]<dist>/<ptfile>] */
89
89
bool active ;
90
+ bool point ; /* True if we got a single point */
90
91
int mode ; /* Form of distance calculation (can be negative) */
91
92
double dist ; /* Radius of influence for each point */
93
+ double lon , lat ; /* Coordinates give for a single point */
92
94
char unit ; /* Unit name */
93
95
char * file ; /* Name of file with points */
94
96
} C ;
@@ -179,7 +181,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) {
179
181
const char * name = gmt_show_name_and_purpose (API , THIS_MODULE_LIB , THIS_MODULE_CLASSIC_NAME , THIS_MODULE_PURPOSE );
180
182
if (level == GMT_MODULE_PURPOSE ) return (GMT_NOERROR );
181
183
GMT_Message (API , GMT_TIME_NONE , "usage: %s [<table>] [%s]\n" , name , GMT_A_OPT );
182
- GMT_Message (API , GMT_TIME_NONE , "\t[-C<ptfile>+d%s] [-D<resolution>][+f] [-E[f][n]] [-F<polygon>] [-G<gridmask>] [%s]\n" ,
184
+ GMT_Message (API , GMT_TIME_NONE , "\t[-C<ptfile|lon/lat >+d%s] [-D<resolution>][+f] [-E[f][n]] [-F<polygon>] [-G<gridmask>] [%s]\n" ,
183
185
GMT_DIST_OPT , GMT_J_OPT );
184
186
GMT_Message (API , GMT_TIME_NONE , "\t[-I[cfglrsz] [-L<lfile>+d%s[+p]] [-N<info>] [%s]\n\t[%s] [-Z<min>[/<max>][+c<col>][+a][+i]] [%s] "
185
187
"[%s]\n\t[%s] [%s] [%s] [%s]\n\t[%s] [%s]\n\t[%s] [%s] [%s] [%s] [%s]\n\n" ,
@@ -194,6 +196,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) {
194
196
GMT_Message (API , GMT_TIME_NONE , "\t (ignored unless -N is set).\n" );
195
197
gmt_dist_syntax (API -> GMT , 'C' , "Pass locations that are within <dist> of any point in the ASCII <ptfile>." );
196
198
GMT_Message (API , GMT_TIME_NONE , "\t Give distance as 0 if 3rd column of <ptfile> has individual distances.\n" );
199
+ GMT_Message (API , GMT_TIME_NONE , "\t For a single point you can instead specify <lon>/<lat>+d[unit].\n" );
197
200
GMT_Message (API , GMT_TIME_NONE , "\t Use -R -J to compute mapped Cartesian distances in cm, inch, m, or points [%s].\n" ,
198
201
API -> GMT -> session .unit_name [API -> GMT -> current .setting .proj_length_unit ]);
199
202
GMT_Message (API , GMT_TIME_NONE , "\t-D Choose one of the following resolutions: (Ignored unless -N is set).\n" );
@@ -336,7 +339,7 @@ static int parse (struct GMT_CTRL *GMT, struct GMTSELECT_CTRL *Ctrl, struct GMT_
336
339
Ctrl -> A .active = true;
337
340
n_errors += gmt_set_levels (GMT , opt -> arg , & Ctrl -> A .info );
338
341
break ;
339
- case 'C' : /* Near a point test Syntax -C<pfile>+d<distance> */
342
+ case 'C' : /* Near a point test Syntax -C<pfile>+d<distance> or -C<lon/lat>+d<distance> */
340
343
Ctrl -> C .active = true;
341
344
if ((c = strstr (opt -> arg , "+d" )) == NULL ) { /* Must be old syntax or error */
342
345
n_errors += gmtselect_old_C_parser (API , opt -> arg , Ctrl );
@@ -347,8 +350,16 @@ static int parse (struct GMT_CTRL *GMT, struct GMTSELECT_CTRL *Ctrl, struct GMT_
347
350
GMT_Report (API , GMT_MSG_ERROR , "Option -C: No file given\n" );
348
351
n_errors ++ ;
349
352
}
350
- else
353
+ else {
351
354
Ctrl -> C .file = gmt_get_filename (API , opt -> arg , "d" );
355
+ if (gmt_count_char (GMT , Ctrl -> C .file , '/' ) == 1 && gmt_access (GMT , Ctrl -> C .file , R_OK )) { /* Check if we got a lon/lat point */
356
+ if ((j = sscanf (Ctrl -> C .file , "%[^/]/%s" , za , zb )) != 2 ) continue ; /* No, strange... */
357
+ n_errors += gmt_verify_expectations (GMT , gmt_M_type (GMT , GMT_IN , GMT_X ), gmt_scanf_arg (GMT , za , gmt_M_type (GMT , GMT_IN , GMT_X ), false, & Ctrl -> C .lon ), za );
358
+ n_errors += gmt_verify_expectations (GMT , gmt_M_type (GMT , GMT_IN , GMT_Y ), gmt_scanf_arg (GMT , zb , gmt_M_type (GMT , GMT_IN , GMT_Y ), false, & Ctrl -> C .lat ), zb );
359
+ if (n_errors == 0 )
360
+ Ctrl -> C .point = true;
361
+ }
362
+ }
352
363
Ctrl -> C .mode = gmt_get_distance (GMT , & c [2 ], & (Ctrl -> C .dist ), & (Ctrl -> C .unit ));
353
364
break ;
354
365
case 'D' : /* Set GSHHS resolution */
@@ -507,7 +518,7 @@ static int parse (struct GMT_CTRL *GMT, struct GMTSELECT_CTRL *Ctrl, struct GMT_
507
518
n_errors += gmt_M_check_condition (GMT , Ctrl -> C .mode == -1 , "Option -C: Unrecognized distance unit\n" );
508
519
n_errors += gmt_M_check_condition (GMT , Ctrl -> C .mode == -2 , "Option -C: Unable to decode distance\n" );
509
520
n_errors += gmt_M_check_condition (GMT , Ctrl -> C .mode == -3 , "Option -C: Distance is negative\n" );
510
- n_errors += gmt_M_check_condition (GMT , Ctrl -> C .active && gmt_access (GMT , Ctrl -> C .file , R_OK ),
521
+ n_errors += gmt_M_check_condition (GMT , Ctrl -> C .active && ! Ctrl -> C . point && gmt_access (GMT , Ctrl -> C .file , R_OK ),
511
522
"Option -C: Cannot read file %s!\n" , Ctrl -> C .file );
512
523
n_errors += gmt_M_check_condition (GMT , Ctrl -> F .active && gmt_access (GMT , Ctrl -> F .file , R_OK ),
513
524
"Option -F: Cannot read file %s!\n" , Ctrl -> F .file );
@@ -640,17 +651,28 @@ EXTERN_MSC int GMT_gmtselect (void *V_API, int mode, void *args) {
640
651
641
652
gmt_disable_bghi_opts (GMT ); /* Do not want any -b -g -h -i to affect the reading from -C,-F,-L files */
642
653
643
- if (Ctrl -> C .active ) { /* Initialize point structure used in test for proximity to points [use Ctrl->C.dist ]*/
644
- if ((Cin = GMT_Read_Data (API , GMT_IS_DATASET , GMT_IS_FILE , GMT_IS_POINT , GMT_IO_ASCII , NULL , Ctrl -> C .file , NULL )) == NULL ) {
645
- Return (API -> error );
646
- }
647
- if (Cin -> n_columns < 2 ) { /* Trouble */
648
- GMT_Report (API , GMT_MSG_ERROR , "Option -C: %s does not have at least 2 columns with coordinates\n" , Ctrl -> C .file );
649
- Return (GMT_RUNTIME_ERROR );
654
+ if (Ctrl -> C .active ) { /* Initialize point structure used in test for proximity to points [use Ctrl->C.dist] */
655
+ if (Ctrl -> C .point ) {
656
+ uint64_t dim [4 ] = {1 , 1 , 1 , 2 };
657
+ if ((Cin = GMT_Create_Data (API , GMT_IS_DATASET , GMT_IS_POINT , 0 , dim , NULL , NULL , 0 , 0 , NULL )) == NULL ) {
658
+ Return (API -> error );
659
+ }
660
+ /* Place the given point in the array */
661
+ Cin -> table [0 ]-> segment [0 ]-> data [GMT_X ][0 ] = Ctrl -> C .lon ;
662
+ Cin -> table [0 ]-> segment [0 ]-> data [GMT_Y ][0 ] = Ctrl -> C .lat ;
650
663
}
651
- if (Ctrl -> C .dist == 0.0 && Cin -> n_columns <= 2 ) { /* Trouble */
652
- GMT_Report (API , GMT_MSG_ERROR , "Option -C: %s does not have a 3rd column with distances, yet -C0/<file> was given\n" , Ctrl -> C .file );
653
- Return (GMT_RUNTIME_ERROR );
664
+ else { /* Read from file */
665
+ if ((Cin = GMT_Read_Data (API , GMT_IS_DATASET , GMT_IS_FILE , GMT_IS_POINT , GMT_IO_ASCII , NULL , Ctrl -> C .file , NULL )) == NULL ) {
666
+ Return (API -> error );
667
+ }
668
+ if (Cin -> n_columns < 2 ) { /* Trouble */
669
+ GMT_Report (API , GMT_MSG_ERROR , "Option -C: %s does not have at least 2 columns with coordinates\n" , Ctrl -> C .file );
670
+ Return (GMT_RUNTIME_ERROR );
671
+ }
672
+ if (Ctrl -> C .dist == 0.0 && Cin -> n_columns <= 2 ) { /* Trouble */
673
+ GMT_Report (API , GMT_MSG_ERROR , "Option -C: %s does not have a 3rd column with distances, yet -C0/<file> was given\n" , Ctrl -> C .file );
674
+ Return (GMT_RUNTIME_ERROR );
675
+ }
654
676
}
655
677
point = Cin -> table [0 ]; /* Can only be one table since we read a single file */
656
678
for (seg = 0 ; seg < point -> n_segments ; seg ++ ) {
0 commit comments