Skip to content

Commit a4fca92

Browse files
Handle matrix via reference for grid input (#3829) (#3838)
* Handle matrix vai reference for grid input Testing is done via testapi_matrix_360_ref.c Seems to work but raises an issue related to memory freeing. Since the matrix data is only pointed to by the grid, I set the grid alloc_mode to external. However, that also means that the x and y arrays that are created when creating the grid is left unfreed at the end. We could just ignore this rare memory leak or do something about it. One way is to add info to the struct HIDDEN so that we free those arrays even those the matrix is left untouched. * Add PS orig * Update gmt_api.c * Update gmt_grdio.c * Fix output ij * Handle a switch from reference to duplicate * make sure we set min/max when needed and not reset it * use lessons learned from MATRIX/DUPLICATE to GRID/DUPLICATE Lots of errors there as well and probalby never accessed. * Use duplcate for 360 adn ref for 360_ref Also fix the region assignment * Apply same logic for finding min/max as for duplicate * handle non-projection in grdimage when a referenced global grid Co-authored-by: Paul Wessel <[email protected]>
1 parent 262f739 commit a4fca92

File tree

6 files changed

+95
-59
lines changed

6 files changed

+95
-59
lines changed

src/gmt_api.c

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5193,6 +5193,15 @@ GMT_LOCAL int gmtapi_export_image (struct GMTAPI_CTRL *API, int object_ID, unsig
51935193
return (GMT_NOERROR);
51945194
}
51955195

5196+
unsigned int gmt_whole_earth (struct GMT_CTRL *GMT, double we_in[], double we_out[]) {
5197+
/* Determines if this is a global geographic grid and we want the whole world, regardless of central longitude */
5198+
if (!gmt_M_is_geographic (GMT, GMT_IN)) return 0;
5199+
if (!gmt_M_360_range (we_in[XLO], we_in[XHI])) return 0;
5200+
if (!gmt_M_360_range (we_out[XLO], we_out[XHI])) return 0;
5201+
if (doubleAlmostEqualZero (we_in[XLO], we_out[XLO])) return 2; /* Both regions are the same */
5202+
return 1; /* Different central meridians */
5203+
}
5204+
51965205
/*! . */
51975206
GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int object_ID, unsigned int mode, struct GMT_GRID *grid) {
51985207
/* Handles the reading of a 2-D grid given in one of several ways.
@@ -5207,10 +5216,10 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
52075216

52085217
int item, new_item, new_ID;
52095218
bool done = true, new = false, row_by_row;
5210-
uint64_t row, col, kol, i0, i1, j0, j1, ij, ij_orig;
5219+
uint64_t row, col, kol, row_out, i0, i1, j0, j1, ij, ij_orig;
52115220
size_t size;
52125221
unsigned int both_set = (GMT_CONTAINER_ONLY | GMT_DATA_ONLY);
5213-
unsigned int method;
5222+
unsigned int method, start_over_method = 0;
52145223
double dx, dy, d;
52155224
p_func_uint64_t GMT_2D_to_index = NULL;
52165225
struct GMT_GRID *G_obj = NULL, *G_orig = NULL;
@@ -5243,6 +5252,9 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
52435252
if (grid->header->wesn[XLO] == S_obj->wesn[XLO] && grid->header->wesn[XHI] == S_obj->wesn[XHI] && grid->header->wesn[YLO] == S_obj->wesn[YLO] && grid->header->wesn[YHI] == S_obj->wesn[YHI]) S_obj->region = false;
52445253
}
52455254
method = gmtapi_set_method (S_obj); /* Get the actual method to use since may be MATRIX or VECTOR masquerading as GRID */
5255+
5256+
start_over_import_grid: /* We may get here if we cannot honor a GMT_IS_REFERENCE from below */
5257+
52465258
switch (method) {
52475259
/* Status: This case is fully tested and operational */
52485260
case GMT_IS_FILE: /* Name of a grid file on disk */
@@ -5332,26 +5344,32 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
53325344
GH->alloc_mode = GMT_ALLOC_INTERNALLY;
53335345
if (!S_obj->region && gmt_grd_pad_status (GMT, G_obj->header, GMT->current.io.pad)) { /* Want an exact copy with no subset and same padding */
53345346
gmt_M_memcpy (G_obj->data, G_orig->data, G_orig->header->size, gmt_grdfloat);
5347+
gmt_BC_init (GMT, G_obj->header); /* Initialize grid interpolation and boundary condition parameters */
5348+
if (gmt_M_err_pass (GMT, gmt_grd_BC_set (GMT, G_obj, GMT_IN), "Grid memory"))
5349+
return_null (API, GMT_GRID_BC_ERROR); /* Set boundary conditions */
53355350
break; /* Done with this grid */
53365351
}
53375352
/* Here we need to do more work: Either extract subset or add/change padding, or both. */
53385353
/* Get start/stop row/cols for subset (or the entire domain) */
53395354
/* dx,dy are needed when the grid is pixel-registered as the w/e/s/n bounds are off by 0.5 {dx,dy} relative to node coordinates */
53405355
dx = G_obj->header->inc[GMT_X] * G_obj->header->xy_off; dy = G_obj->header->inc[GMT_Y] * G_obj->header->xy_off;
5341-
j1 = (unsigned int)gmt_M_grd_y_to_row (GMT, G_obj->header->wesn[YLO]+dy, G_orig->header);
5342-
j0 = (unsigned int)gmt_M_grd_y_to_row (GMT, G_obj->header->wesn[YHI]-dy, G_orig->header);
5343-
i0 = (unsigned int)gmt_M_grd_x_to_col (GMT, G_obj->header->wesn[XLO]+dx, G_orig->header);
5344-
i1 = (unsigned int)gmt_M_grd_x_to_col (GMT, G_obj->header->wesn[XHI]-dx, G_orig->header);
5356+
j1 = (unsigned int)gmt_M_grd_y_to_row (GMT, S_obj->wesn[YLO]+dy, G_orig->header);
5357+
j0 = (unsigned int)gmt_M_grd_y_to_row (GMT, S_obj->wesn[YHI]-dy, G_orig->header);
5358+
i0 = (unsigned int)gmt_M_grd_x_to_col (GMT, S_obj->wesn[XLO]+dx, G_orig->header);
5359+
i1 = (unsigned int)gmt_M_grd_x_to_col (GMT, S_obj->wesn[XHI]-dx, G_orig->header);
53455360
gmt_M_memcpy (G_obj->header->pad, GMT->current.io.pad, 4, int); /* Set desired padding */
5361+
gmt_M_memcpy (G_obj->header->wesn, S_obj->wesn, 4U, double); /* Update the grid header region to match subset request */
5362+
gmt_set_grddim (GMT, G_obj->header); /* Adjust all dimensions accordingly before accessing the grid for output */
53465363
/* get stats */
53475364
HH = gmt_get_H_hidden (G_obj->header);
53485365
G_obj->header->z_min = DBL_MAX;
53495366
G_obj->header->z_max = -DBL_MAX;
53505367
HH->has_NaNs = GMT_GRID_NO_NANS; /* We are about to check for NaNs and if none are found we retain 1, else 2 */
5351-
for (row = j0; row <= j1; row++) {
5368+
for (row = j0, row_out = 0; row <= j1; row++, row_out++) {
5369+
ij = gmt_M_ijp (G_obj->header, row_out, 0); /* Position in output grid at start of current row */
53525370
for (col = i0; col <= i1; col++, ij++) {
5353-
ij_orig = gmt_M_ijp (G_orig->header, row, col); /* Position of this (row,col) in original grid organization */
5354-
ij = gmt_M_ijp (G_obj->header, row, col); /* Position of this (row,col) in output grid organization */
5371+
kol = col % G_orig->header->n_columns;
5372+
ij_orig = gmt_M_ijp (G_orig->header, row, kol); /* Position of this (row,col) in original grid organization */
53555373
G_obj->data[ij] = G_orig->data[ij_orig];
53565374
if (gmt_M_is_fnan (G_obj->data[ij]))
53575375
HH->has_NaNs = GMT_GRID_HAS_NANS;
@@ -5419,34 +5437,38 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
54195437
GMT_2D_to_index = gmtapi_get_2d_to_index (API, M_obj->shape, GMT_GRID_IS_REAL);
54205438
if ((api_get_val = gmtapi_select_get_function (API, M_obj->type)) == NULL)
54215439
return_null (API, GMT_NOT_A_VALID_TYPE);
5422-
G_obj->header->z_min = +DBL_MAX;
5423-
G_obj->header->z_max = -DBL_MAX;
54245440
HH = gmt_get_H_hidden (G_obj->header);
5425-
HH->has_NaNs = GMT_GRID_NO_NANS; /* We are about to check for NaNs and if none are found we retain 1, else 2 */
54265441

54275442
if (! (mode & GMT_DATA_ONLY)) { /* Must first init header and copy the header information from the matrix header */
54285443
gmtapi_matrixinfo_to_grdheader (GMT, G_obj->header, M_obj); /* Populate a GRD header structure */
5429-
if (mode & GMT_CONTAINER_ONLY) { /* Just needed the header */
5430-
/* Must get the full zmin/max range since not provided by the matrix header */
5444+
/* Must get the full zmin/max range since not provided by the matrix header */
5445+
G_obj->header->z_min = +DBL_MAX;
5446+
G_obj->header->z_max = -DBL_MAX;
5447+
HH->has_NaNs = GMT_GRID_NO_NANS; /* We are about to check for NaNs and if none are found we retain 1, else 2 */
54315448
gmt_M_grd_loop (GMT, G_obj, row, col, ij) {
5432-
ij_orig = GMT_2D_to_index (row, col, M_obj->dim);
5433-
api_get_val (&(M_obj->data), ij_orig, &d);
5434-
if (gmt_M_is_dnan (d))
5435-
HH->has_NaNs = GMT_GRID_HAS_NANS;
5436-
else {
5437-
G_obj->header->z_min = MIN (G_obj->header->z_min, (gmt_grdfloat)d);
5438-
G_obj->header->z_max = MAX (G_obj->header->z_max, (gmt_grdfloat)d);
5439-
}
5449+
ij_orig = GMT_2D_to_index (row, col, M_obj->dim);
5450+
api_get_val (&(M_obj->data), ij_orig, &d);
5451+
if (gmt_M_is_dnan (d))
5452+
HH->has_NaNs = GMT_GRID_HAS_NANS;
5453+
else {
5454+
G_obj->header->z_min = MIN (G_obj->header->z_min, (gmt_grdfloat)d);
5455+
G_obj->header->z_max = MAX (G_obj->header->z_max, (gmt_grdfloat)d);
54405456
}
5441-
break; /* Done for now */
54425457
}
5458+
if (mode & GMT_CONTAINER_ONLY) /* Just needed the header */
5459+
break; /* Done for now */
54435460
}
54445461

54455462
GMT_Report (API, GMT_MSG_INFORMATION, "Importing grid data from user matrix memory location\n");
54465463

54475464
/* Get start/stop row/cols for subset (or the entire domain) */
54485465
/* dx,dy are needed when the grid is pixel-registered as the w/e/s/n bounds are off by 0.5 {dx,dy} relative to node coordinates */
5449-
if (S_obj->region) { /* Want a subset */
5466+
if (!S_obj->region || gmt_whole_earth (GMT, M_obj->range, S_obj->wesn)) { /* Easy, get the whole enchilada */
5467+
j0 = i0 = 0;
5468+
j1 = G_obj->header->n_rows - 1; /* Minus 1 since we loop up to and including below */
5469+
i1 = G_obj->header->n_columns - 1;
5470+
}
5471+
else { /* Want a subset */
54505472
dx = G_obj->header->inc[GMT_X] * G_obj->header->xy_off; dy = G_obj->header->inc[GMT_Y] * G_obj->header->xy_off;
54515473
j1 = (unsigned int)gmt_M_grd_y_to_row (GMT, S_obj->wesn[YLO]+dy, G_obj->header);
54525474
j0 = (unsigned int)gmt_M_grd_y_to_row (GMT, S_obj->wesn[YHI]-dy, G_obj->header);
@@ -5455,23 +5477,18 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
54555477
gmt_M_memcpy (G_obj->header->wesn, S_obj->wesn, 4U, double); /* Update the grid header region to match subset request */
54565478
gmt_set_grddim (GMT, G_obj->header); /* Adjust all dimensions accordingly before allocating space */
54575479
}
5458-
else { /* Easy, get the whole enchilada */
5459-
j0 = i0 = 0;
5460-
j1 = G_obj->header->n_rows - 1; /* Minus 1 since we loop up to and including below */
5461-
i1 = G_obj->header->n_columns - 1;
5462-
}
54635480
if (G_obj->data) { /* This is an error - there cannot be a data pointer yet */
54645481
GMT_Report (API, GMT_MSG_ERROR, "G->data is not NULL when memory allocation is about to happen\n");
54655482
return_null (API, GMT_PTR_IS_NULL);
54665483
}
54675484
else
54685485
G_obj->data = gmt_M_memory_aligned (GMT, NULL, G_obj->header->size, gmt_grdfloat);
54695486

5470-
for (row = j0; row <= j1; row++) {
5487+
for (row = j0, row_out = 0; row <= j1; row++, row_out++) {
5488+
ij = gmt_M_ijp (G_obj->header, row_out, 0); /* Position in output grid at start of current row */
54715489
for (col = i0; col <= i1; col++, ij++) {
54725490
kol = col % M_obj->n_columns;
54735491
ij_orig = GMT_2D_to_index (row, kol, M_obj->dim); /* Position of this (row,col) in input matrix organization */
5474-
ij = gmt_M_ijp (G_obj->header, row, kol); /* Position of this (row,col) in output grid organization */
54755492
api_get_val (&(M_obj->data), ij_orig, &d); /* Get the next item from the matrix */
54765493
G_obj->data[ij] = (gmt_grdfloat)d;
54775494
if (gmt_M_is_dnan (d))
@@ -5482,7 +5499,7 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
54825499
}
54835500
}
54845501
}
5485-
if (gmt_M_is_geographic (GMT, GMT_IN) && gmt_M_360_range (M_obj->range[XLO], M_obj->range[XHI]) && gmt_M_360_range (G_obj->header->wesn[XLO], G_obj->header->wesn[XHI])) {
5502+
if (gmt_whole_earth (GMT, M_obj->range, S_obj->wesn)) {
54865503
/* Global grids passed via matrix are not rotated to fit the desired global region, so we need to correct the wesn for this grid to match the matrix */
54875504
gmt_M_memcpy (G_obj->header->wesn, M_obj->range, 4U, double);
54885505
}
@@ -5491,13 +5508,25 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
54915508
return_null (API, GMT_GRID_BC_ERROR); /* Set boundary conditions */
54925509
API->object[new_item]->status = GMT_IS_USED; /* Mark as read */
54935510
API->object[new_item]->actual_family = GMT_IS_GRID; /* Done reading from matrix */
5511+
if (start_over_method) API->object[new_item]->method = start_over_method; /* We changed our mind from reference to duplicate due to region */
54945512
GH->alloc_level = API->object[new_item]->alloc_level; /* Since allocated here */
54955513
break;
54965514

54975515
case GMT_IS_REFERENCE|GMT_VIA_MATRIX: /* The user's 2-D grid array of some sort, + info in the args [NOT YET FULLY TESTED] */
54985516
/* Getting a matrix info S_obj->resource. Create grid header and then pass the grid pointer via the matrix pointer */
54995517
if ((M_obj = S_obj->resource) == NULL) return_null (API, GMT_PTR_IS_NULL);
5500-
//if (S_obj->region) return_null (API, GMT_SUBSET_NOT_ALLOWED);
5518+
/* Determine if it is possible to use the matrix given the region selected and the fact we chose GMT_IS_REFERENCE. This test will
5519+
* only kick in after we allocate the G_obj and come back the second time (after getting header) since otherwise S_obj->wesn is not set yet */
5520+
if (!(!S_obj->region ||
5521+
(S_obj->wesn[XLO] >= M_obj->range[XLO] && S_obj->wesn[XHI] <= M_obj->range[XHI] && S_obj->wesn[YLO] >= M_obj->range[YLO] && S_obj->wesn[YHI] <= M_obj->range[YHI]) ||
5522+
gmt_whole_earth (GMT, M_obj->range, S_obj->wesn))) { /* Cannot do this by reference, switch to duplication */
5523+
method -= GMT_IS_REFERENCE;
5524+
method += GMT_IS_DUPLICATE;
5525+
start_over_method = GMT_IS_DUPLICATE;
5526+
GMT_Report (API, GMT_MSG_DEBUG, "Subset selection requires GMT_IS_DUPLICATION instead of GMT_IS_REFERENCE - method has been switched\n");
5527+
goto start_over_import_grid;
5528+
}
5529+
55015530
/* This method requires the input data to be a GMT_GRD_FORMAT matrix - otherwise we should be DUPLICATING */
55025531
MH = gmt_get_M_hidden (M_obj);
55035532
if (!(M_obj->shape == GMT_IS_ROW_FORMAT && M_obj->type == GMT_GRDFLOAT && (mode & GMT_GRID_IS_COMPLEX_MASK) == 0))
@@ -5514,27 +5543,26 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
55145543
done = (mode & GMT_CONTAINER_ONLY) ? false : true; /* Not done until we read grid */
55155544
if (! (mode & GMT_DATA_ONLY)) {
55165545
gmtapi_matrixinfo_to_grdheader (GMT, G_obj->header, M_obj); /* Populate a GRD header structure */
5517-
if (mode & GMT_CONTAINER_ONLY) { /* Just needed the header but need to set zmin/zmax first */
5518-
/* Temporarily set data pointer for convenience; removed later */
5546+
/* Temporarily set data pointer for convenience; removed later */
55195547
#ifdef DOUBLE_PRECISION_GRID
5520-
G_obj->data = M_obj->data.f8;
5548+
G_obj->data = M_obj->data.f8;
55215549
#else
5522-
G_obj->data = M_obj->data.f4;
5550+
G_obj->data = M_obj->data.f4;
55235551
#endif
5524-
G_obj->header->z_min = +DBL_MAX;
5525-
G_obj->header->z_max = -DBL_MAX;
5526-
HH->has_NaNs = GMT_GRID_NO_NANS; /* We are about to check for NaNs and if none are found we retain 1, else 2 */
5527-
gmt_M_grd_loop (GMT, G_obj, row, col, ij) {
5528-
if (gmt_M_is_fnan (G_obj->data[ij]))
5529-
HH->has_NaNs = GMT_GRID_HAS_NANS;
5530-
else {
5531-
G_obj->header->z_min = MIN (G_obj->header->z_min, G_obj->data[ij]);
5532-
G_obj->header->z_max = MAX (G_obj->header->z_max, G_obj->data[ij]);
5533-
}
5552+
G_obj->header->z_min = +DBL_MAX;
5553+
G_obj->header->z_max = -DBL_MAX;
5554+
HH->has_NaNs = GMT_GRID_NO_NANS; /* We are about to check for NaNs and if none are found we retain 1, else 2 */
5555+
gmt_M_grd_loop (GMT, G_obj, row, col, ij) {
5556+
if (gmt_M_is_fnan (G_obj->data[ij]))
5557+
HH->has_NaNs = GMT_GRID_HAS_NANS;
5558+
else {
5559+
G_obj->header->z_min = MIN (G_obj->header->z_min, G_obj->data[ij]);
5560+
G_obj->header->z_max = MAX (G_obj->header->z_max, G_obj->data[ij]);
55345561
}
5535-
G_obj->data = NULL; /* Since data are not requested yet */
5536-
break;
55375562
}
5563+
G_obj->data = NULL; /* Since data are not requested yet */
5564+
if (mode & GMT_CONTAINER_ONLY) /* Just needed the header but had to set zmin/zmax first */
5565+
break;
55385566
}
55395567
if ((new_ID = gmtapi_get_object (API, GMT_IS_GRID, G_obj)) == GMT_NOTSET)
55405568
return_null (API, GMT_OBJECT_NOT_FOUND);
@@ -5548,11 +5576,15 @@ GMT_LOCAL struct GMT_GRID * gmtapi_import_grid (struct GMTAPI_CTRL *API, int obj
55485576
#endif
55495577
GH = gmt_get_G_hidden (G_obj);
55505578
S_obj->alloc_mode = MH->alloc_mode; /* Pass on alloc_mode of matrix */
5551-
GH->alloc_mode = MH->alloc_mode;
5579+
GH->alloc_mode = GMT_ALLOC_EXTERNALLY; /* Since we cannot have both M and G try to free */
55525580
API->object[new_item]->resource = G_obj;
55535581
API->object[new_item]->status = GMT_IS_USED; /* Mark as read */
55545582
GH->alloc_level = API->object[new_item]->alloc_level; /* Since allocated here */
5555-
if (S_obj->region) { /* Possibly adjust the pad so inner region matches wesn */
5583+
if (gmt_whole_earth (GMT, M_obj->range, S_obj->wesn)) {
5584+
/* Global grids passed via matrix are not rotated to fit the desired global region, so we need to correct the wesn for this grid to match the matrix */
5585+
gmt_M_memcpy (G_obj->header->wesn, M_obj->range, 4U, double);
5586+
}
5587+
else if (S_obj->region) { /* Possibly adjust the pad so inner region matches wesn */
55565588
if (S_obj->reset_pad) { /* First undo a prior sub-region used with this memory grid */
55575589
gmtlib_contract_headerpad (GMT, G_obj->header, S_obj->orig_pad, S_obj->orig_wesn);
55585590
S_obj->reset_pad = 0;

src/gmt_grdio.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,6 +2660,7 @@ struct GMT_GRID *gmt_duplicate_grid (struct GMT_CTRL *GMT, struct GMT_GRID *G, u
26602660
gmt_copy_gridheader (GMT, Gnew->header, G->header);
26612661

26622662
if ((mode & GMT_DUPLICATE_DATA) || (mode & GMT_DUPLICATE_ALLOC)) { /* Also allocate and possibly duplicate data array */
2663+
struct GMT_GRID_HIDDEN *GH = gmt_get_G_hidden (Gnew);
26632664
if ((mode & GMT_DUPLICATE_RESET) && !gmt_grd_pad_status (GMT, G->header, GMT->current.io.pad)) {
26642665
/* Pads differ and we requested resetting the pad */
26652666
gmt_M_grd_setpad (GMT, Gnew->header, GMT->current.io.pad); /* Set default pad size */
@@ -2682,6 +2683,7 @@ struct GMT_GRID *gmt_duplicate_grid (struct GMT_CTRL *GMT, struct GMT_GRID *G, u
26822683

26832684
Gnew->x = gmt_grd_coord (GMT, Gnew->header, GMT_X); /* Get array of x coordinates */
26842685
Gnew->y = gmt_grd_coord (GMT, Gnew->header, GMT_Y); /* Get array of y coordinates */
2686+
GH->xy_alloc_mode[GMT_X] = GH->xy_alloc_mode[GMT_Y] = GMT_ALLOC_INTERNALLY;
26852687
}
26862688
return (Gnew);
26872689
}
@@ -2712,13 +2714,11 @@ unsigned int gmtlib_free_grid_ptr (struct GMT_CTRL *GMT, struct GMT_GRID *G, boo
27122714
if (GH->alloc_mode == GMT_ALLOC_INTERNALLY) gmt_M_free_aligned (GMT, G->data);
27132715
G->data = NULL; /* This will remove reference to external memory since gmt_M_free_aligned would not have been called */
27142716
}
2715-
if (G->x && G->y && free_grid) {
2716-
if (GH->xy_alloc_mode[GMT_X] == GMT_ALLOC_INTERNALLY)
2717-
gmt_M_free (GMT, G->x);
2718-
if (GH->xy_alloc_mode[GMT_Y] == GMT_ALLOC_INTERNALLY)
2719-
gmt_M_free (GMT, G->y);
2720-
G->x = G->y = NULL; /* This will remove reference to external memory since gmt_M_free would not have been called */
2721-
}
2717+
if (G->x && GH->xy_alloc_mode[GMT_X] == GMT_ALLOC_INTERNALLY)
2718+
gmt_M_free (GMT, G->x);
2719+
if (G->y && GH->xy_alloc_mode[GMT_Y] == GMT_ALLOC_INTERNALLY)
2720+
gmt_M_free (GMT, G->y);
2721+
G->x = G->y = NULL; /* This will remove reference to external memory since gmt_M_free would not have been called */
27222722
if (GH->extra) gmtlib_close_grd (GMT, G); /* Close input file used for row-by-row i/o */
27232723
alloc_mode = GH->alloc_mode;
27242724
gmt_M_free (GMT, G->hidden);

src/gmt_prototypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ EXTERN_MSC void gmt_polar_to_cart (struct GMT_CTRL *GMT, double r, double theta,
680680
EXTERN_MSC void gmt_cart_to_polar (struct GMT_CTRL *GMT, double *r, double *theta, double *a, bool degrees);
681681

682682
/* From gmt_api.c */
683+
EXTERN_MSC unsigned int gmt_whole_earth (struct GMT_CTRL *GMT, double we_in[], double we_out[]);
683684
EXTERN_MSC int gmt_copy (struct GMTAPI_CTRL *API, enum GMT_enum_family family, unsigned int direction, char *ifile, char *ofile);
684685
EXTERN_MSC struct GMTAPI_CTRL * gmt_get_api_ptr (struct GMTAPI_CTRL *ptr);
685686
EXTERN_MSC const char * gmt_show_name_and_purpose (void *API, const char *name, const char *component, const char *purpose);

src/grdimage.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,9 @@ EXTERN_MSC int GMT_grdimage (void *V_API, int mode, void *args) {
969969

970970
}
971971

972+
if (n_grids && (gmt_whole_earth (GMT, Grid_orig[0]->header->wesn, wesn) == 1))
973+
need_to_project = true; /* This can only happen if reading a global geographic memory grid */
974+
972975
if (need_to_project) { /* Need to resample the grd file using the specified map projection */
973976
int nx_proj = 0, ny_proj = 0;
974977
double inc[2] = {0.0, 0.0};

src/testapi_matrix_360.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ int main () {
1919
M->inc[0] = M->inc[1] = 1.0;
2020
M->registration = 1;
2121
/* Create a virtual file to pass as a grid */
22-
GMT_Open_VirtualFile (API, GMT_IS_GRID|GMT_VIA_MATRIX, GMT_IS_SURFACE, GMT_IN|GMT_IS_REFERENCE, M, input);
22+
GMT_Open_VirtualFile (API, GMT_IS_GRID|GMT_VIA_MATRIX, GMT_IS_SURFACE, GMT_IN, M, input);
2323
/* Call grdimage with central longitude 0, which is the center of the grid */
2424
sprintf (args, "%s -Rg -JH0/6i -Bg30 -K -Cgeo -P", input);
2525
GMT_Call_Module (API, "grdimage", GMT_MODULE_CMD, args);

test/api/apimat_360_ref.ps

426 KB
Binary file not shown.

0 commit comments

Comments
 (0)