PostGIS  3.2.2dev-r@@SVN_REVISION@@
rt_geometry.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2011-2013 Regents of the University of California
7  * <bkpark@ucdavis.edu>
8  * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9  * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10  * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11  * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12  * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  *
28  */
29 
30 #include "librtcore.h"
31 #include "librtcore_internal.h"
32 #include "rt_serialize.h"
33 
34 /******************************************************************************
35 * rt_raster_perimeter()
36 ******************************************************************************/
37 
38 static rt_errorstate
40  uint16_t width = 0;
41  uint16_t height = 0;
42  int x = 0;
43  int y = 0;
44  int offset = 0;
45  int done[4] = {0};
46  double value = 0;
47  int nodata = 0;
48 
49  assert(band != NULL);
50  assert(band->raster != NULL);
51  assert(trim != NULL);
52 
53  memset(trim, 0, sizeof(uint16_t) * 4);
54 
55  width = rt_band_get_width(band);
56  height = rt_band_get_height(band);
57 
58  /* top */
59  for (y = 0; y < height; y++) {
60  for (offset = 0; offset < 3; offset++) {
61  /* every third pixel */
62  for (x = offset; x < width; x += 3) {
63  if (rt_band_get_pixel(band, x, y, &value, &nodata) != ES_NONE) {
64  rterror("_rti_raster_get_band_perimeter: Could not get band pixel");
65  return ES_ERROR;
66  }
67 
68  RASTER_DEBUGF(4, "top (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
69  if (!nodata) {
70  trim[0] = y;
71  done[0] = 1;
72  break;
73  }
74  }
75 
76  if (done[0])
77  break;
78  }
79 
80  if (done[0])
81  break;
82  }
83 
84  /* right */
85  for (x = width - 1; x >= 0; x--) {
86  for (offset = 0; offset < 3; offset++) {
87  /* every third pixel */
88  for (y = offset; y < height; y += 3) {
89  if (rt_band_get_pixel(band, x, y, &value, &nodata) != ES_NONE) {
90  rterror("_rti_raster_get_band_perimeter: Could not get band pixel");
91  return ES_ERROR;
92  }
93 
94  RASTER_DEBUGF(4, "right (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
95  if (!nodata) {
96  trim[1] = width - (x + 1);
97  done[1] = 1;
98  break;
99  }
100  }
101 
102  if (done[1])
103  break;
104  }
105 
106  if (done[1])
107  break;
108  }
109 
110  /* bottom */
111  for (y = height - 1; y >= 0; y--) {
112  for (offset = 0; offset < 3; offset++) {
113  /* every third pixel */
114  for (x = offset; x < width; x += 3) {
115  if (rt_band_get_pixel(band, x, y, &value, &nodata) != ES_NONE) {
116  rterror("_rti_raster_get_band_perimeter: Could not get band pixel");
117  return ES_ERROR;
118  }
119 
120  RASTER_DEBUGF(4, "bottom (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
121  if (!nodata) {
122  trim[2] = height - (y + 1);
123  done[2] = 1;
124  break;
125  }
126  }
127 
128  if (done[2])
129  break;
130  }
131 
132  if (done[2])
133  break;
134  }
135 
136  /* left */
137  for (x = 0; x < width; x++) {
138  for (offset = 0; offset < 3; offset++) {
139  /* every third pixel */
140  for (y = offset; y < height; y += 3) {
141  if (rt_band_get_pixel(band, x, y, &value, &nodata) != ES_NONE) {
142  rterror("_rti_raster_get_band_perimeter: Could not get band pixel");
143  return ES_ERROR;
144  }
145 
146  RASTER_DEBUGF(4, "left (x, , value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
147  if (!nodata) {
148  trim[3] = x;
149  done[3] = 1;
150  break;
151  }
152  }
153 
154  if (done[3])
155  break;
156  }
157 
158  if (done[3])
159  break;
160  }
161 
162  RASTER_DEBUGF(4, "trim = (%d, %d, %d, %d)",
163  trim[0], trim[1], trim[2], trim[3]);
164 
165  return ES_NONE;
166 }
167 
183  rt_raster raster, int nband,
184  LWGEOM **perimeter
185 ) {
186  rt_band band = NULL;
187  int numband = 0;
188  uint16_t *_nband = NULL;
189  int i = 0;
190  int j = 0;
191  uint16_t _trim[4] = {0};
192  uint16_t trim[4] = {0}; /* top, right, bottom, left */
193  int isset[4] = {0};
194  double gt[6] = {0.0};
195  int32_t srid = SRID_UNKNOWN;
196 
197  POINTARRAY *pts = NULL;
198  POINT4D p4d;
199  POINTARRAY **rings = NULL;
200  LWPOLY* poly = NULL;
201 
202  assert(perimeter != NULL);
203 
204  *perimeter = NULL;
205 
206  /* empty raster, no perimeter */
208  return ES_NONE;
209 
210  /* raster metadata */
211  srid = rt_raster_get_srid(raster);
213  numband = rt_raster_get_num_bands(raster);
214 
215  RASTER_DEBUGF(3, "rt_raster_get_perimeter: raster is %dx%d", raster->width, raster->height);
216 
217  /* nband < 0 means all bands */
218  if (nband >= 0) {
219  if (nband >= numband) {
220  rterror("rt_raster_get_boundary: Band %d not found for raster", nband);
221  return ES_ERROR;
222  }
223 
224  numband = 1;
225  }
226  else
227  nband = -1;
228 
229  RASTER_DEBUGF(3, "rt_raster_get_perimeter: nband, numband = %d, %d", nband, numband);
230 
231  _nband = rtalloc(sizeof(uint16_t) * numband);
232  if (_nband == NULL) {
233  rterror("rt_raster_get_boundary: Could not allocate memory for band indices");
234  return ES_ERROR;
235  }
236 
237  if (nband < 0) {
238  for (i = 0; i < numband; i++)
239  _nband[i] = i;
240  }
241  else
242  _nband[0] = nband;
243 
244  for (i = 0; i < numband; i++) {
245  band = rt_raster_get_band(raster, _nband[i]);
246  if (band == NULL) {
247  rterror("rt_raster_get_boundary: Could not get band at index %d", _nband[i]);
248  rtdealloc(_nband);
249  return ES_ERROR;
250  }
251 
252  /* band is nodata */
254  continue;
255 
257  rterror("rt_raster_get_boundary: Could not get band perimeter");
258  rtdealloc(_nband);
259  return ES_ERROR;
260  }
261 
262  for (j = 0; j < 4; j++) {
263  if (!isset[j] || trim[j] < _trim[j]) {
264  _trim[j] = trim[j];
265  isset[j] = 1;
266  }
267  }
268  }
269 
270  /* no longer needed */
271  rtdealloc(_nband);
272 
273  /* check isset, just need to check one element */
274  if (!isset[0]) {
275  /* return NULL as bands are empty */
276  return ES_NONE;
277  }
278 
279  RASTER_DEBUGF(4, "trim = (%d, %d, %d, %d)",
280  trim[0], trim[1], trim[2], trim[3]);
281 
282  /* only one ring */
283  rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
284  if (!rings) {
285  rterror("rt_raster_get_perimeter: Could not allocate memory for polygon ring");
286  return ES_ERROR;
287  }
288  rings[0] = ptarray_construct(0, 0, 5);
289  if (!rings[0]) {
290  rterror("rt_raster_get_perimeter: Could not construct point array");
291  return ES_ERROR;
292  }
293  pts = rings[0];
294 
295  /* Upper-left corner (first and last points) */
297  raster,
298  _trim[3], _trim[0],
299  &p4d.x, &p4d.y,
300  gt
301  );
302  ptarray_set_point4d(pts, 0, &p4d);
303  ptarray_set_point4d(pts, 4, &p4d);
304 
305  /* Upper-right corner (we go clockwise) */
307  raster,
308  raster->width - _trim[1], _trim[0],
309  &p4d.x, &p4d.y,
310  gt
311  );
312  ptarray_set_point4d(pts, 1, &p4d);
313 
314  /* Lower-right corner */
316  raster,
317  raster->width - _trim[1], raster->height - _trim[2],
318  &p4d.x, &p4d.y,
319  gt
320  );
321  ptarray_set_point4d(pts, 2, &p4d);
322 
323  /* Lower-left corner */
325  raster,
326  _trim[3], raster->height - _trim[2],
327  &p4d.x, &p4d.y,
328  gt
329  );
330  ptarray_set_point4d(pts, 3, &p4d);
331 
332  poly = lwpoly_construct(srid, 0, 1, rings);
333  *perimeter = lwpoly_as_lwgeom(poly);
334 
335  return ES_NONE;
336 }
337 
338 /******************************************************************************
339 * rt_raster_surface()
340 ******************************************************************************/
341 
356  rt_band band = NULL;
357  LWGEOM *mpoly = NULL;
358  LWGEOM *tmp = NULL;
359  LWGEOM *clone = NULL;
360  rt_geomval gv = NULL;
361  int gvcount = 0;
362  GEOSGeometry *gc = NULL;
363  GEOSGeometry *gunion = NULL;
364  GEOSGeometry **geoms = NULL;
365  int geomscount = 0;
366  int i = 0;
367 
368  assert(surface != NULL);
369 
370  /* init *surface to NULL */
371  *surface = NULL;
372 
373  /* raster is empty, surface = NULL */
375  return ES_NONE;
376 
377  /* if nband < 0, return the convex hull as a multipolygon */
378  if (nband < 0) {
379  /*
380  lwgeom_as_multi() only does a shallow clone internally
381  so input and output geometries may share memory
382  hence the deep clone of the output geometry for returning
383  is the only way to guarentee the memory isn't shared
384  */
385  if (rt_raster_get_convex_hull(raster, &tmp) != ES_NONE) {
386  rterror("rt_raster_surface: Could not get convex hull of raster");
387  return ES_ERROR;
388  }
389  mpoly = lwgeom_as_multi(tmp);
390  clone = lwgeom_clone_deep(mpoly);
391  lwgeom_free(tmp);
392  lwgeom_free(mpoly);
393 
394  *surface = lwgeom_as_lwmpoly(clone);
395  return ES_NONE;
396  }
397  /* check that nband is valid */
398  else if (nband >= rt_raster_get_num_bands(raster)) {
399  rterror("rt_raster_surface: The band index %d is invalid", nband);
400  return ES_ERROR;
401  }
402 
403  /* get band */
405  if (band == NULL) {
406  rterror("rt_raster_surface: Error getting band %d from raster", nband);
407  return ES_ERROR;
408  }
409 
410  /* band does not have a NODATA flag, return convex hull */
412  /*
413  lwgeom_as_multi() only does a shallow clone internally
414  so input and output geometries may share memory
415  hence the deep clone of the output geometry for returning
416  is the only way to guarentee the memory isn't shared
417  */
418  if (rt_raster_get_convex_hull(raster, &tmp) != ES_NONE) {
419  rterror("rt_raster_surface: Could not get convex hull of raster");
420  return ES_ERROR;
421  }
422  mpoly = lwgeom_as_multi(tmp);
423  clone = lwgeom_clone_deep(mpoly);
424  lwgeom_free(tmp);
425  lwgeom_free(mpoly);
426 
427  *surface = lwgeom_as_lwmpoly(clone);
428  return ES_NONE;
429  }
430  /* band is NODATA, return NULL */
431  else if (rt_band_get_isnodata_flag(band)) {
432  RASTER_DEBUG(3, "Band is NODATA. Returning NULL");
433  return ES_NONE;
434  }
435 
436  /* initialize GEOS */
437  initGEOS(rtinfo, lwgeom_geos_error);
438 
439  /* use gdal polygonize */
440  gv = rt_raster_gdal_polygonize(raster, nband, 1, &gvcount);
441  /* no polygons returned */
442  if (gvcount < 1) {
443  RASTER_DEBUG(3, "All pixels of band are NODATA. Returning NULL");
444  if (gv != NULL) rtdealloc(gv);
445  return ES_NONE;
446  }
447  /* more than 1 polygon */
448  else if (gvcount > 1) {
449  /* convert LWPOLY to GEOSGeometry */
450  geomscount = gvcount;
451  geoms = rtalloc(sizeof(GEOSGeometry *) * geomscount);
452  if (geoms == NULL) {
453  rterror("rt_raster_surface: Could not allocate memory for pixel polygons as GEOSGeometry");
454  for (i = 0; i < gvcount; i++) lwpoly_free(gv[i].geom);
455  rtdealloc(gv);
456  return ES_ERROR;
457  }
458  for (i = 0; i < gvcount; i++) {
459 #if POSTGIS_DEBUG_LEVEL > 3
460  {
461  char *wkt = lwgeom_to_wkt(lwpoly_as_lwgeom(gv[i].geom), WKT_ISO, DBL_DIG, NULL);
462  RASTER_DEBUGF(4, "geom %d = %s", i, wkt);
463  rtdealloc(wkt);
464  }
465 #endif
466 
467  geoms[i] = LWGEOM2GEOS(lwpoly_as_lwgeom(gv[i].geom), 0);
468  lwpoly_free(gv[i].geom);
469  }
470  rtdealloc(gv);
471 
472  /* create geometry collection */
473  gc = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, geomscount);
474 
475  if (gc == NULL) {
476  rterror("rt_raster_surface: Could not create GEOS GEOMETRYCOLLECTION from set of pixel polygons");
477 
478  for (i = 0; i < geomscount; i++)
479  GEOSGeom_destroy(geoms[i]);
480  rtdealloc(geoms);
481  return ES_ERROR;
482  }
483 
484  /* run the union */
485  gunion = GEOSUnaryUnion(gc);
486 
487  GEOSGeom_destroy(gc);
488  rtdealloc(geoms);
489 
490  if (gunion == NULL) {
491  rterror("rt_raster_surface: Could not union the pixel polygons using GEOSUnaryUnion()");
492  return ES_ERROR;
493  }
494 
495  /* convert union result from GEOSGeometry to LWGEOM */
496  mpoly = GEOS2LWGEOM(gunion, 0);
497 
498  /*
499  is geometry valid?
500  if not, try to make valid
501  */
502  do {
503  LWGEOM *mpolyValid = NULL;
504 
505  if (GEOSisValid(gunion))
506  break;
507 
508  /* make geometry valid */
509  mpolyValid = lwgeom_make_valid(mpoly);
510  if (mpolyValid == NULL) {
511  rtwarn("Cannot fix invalid geometry");
512  break;
513  }
514 
515  lwgeom_free(mpoly);
516  mpoly = mpolyValid;
517  }
518  while (0);
519 
520  GEOSGeom_destroy(gunion);
521  }
522  else {
523  mpoly = lwpoly_as_lwgeom(gv[0].geom);
524  rtdealloc(gv);
525 
526 #if POSTGIS_DEBUG_LEVEL > 3
527  {
528  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
529  RASTER_DEBUGF(4, "geom 0 = %s", wkt);
530  rtdealloc(wkt);
531  }
532 #endif
533  }
534 
535  /* specify SRID */
537 
538  if (mpoly != NULL) {
539  /* convert to multi */
540  if (!lwgeom_is_collection(mpoly)) {
541  tmp = mpoly;
542 
543 #if POSTGIS_DEBUG_LEVEL > 3
544  {
545  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
546  RASTER_DEBUGF(4, "before multi = %s", wkt);
547  rtdealloc(wkt);
548  }
549 #endif
550 
551  RASTER_DEBUGF(4, "mpoly @ %p", mpoly);
552 
553  /*
554  lwgeom_as_multi() only does a shallow clone internally
555  so input and output geometries may share memory
556  hence the deep clone of the output geometry for returning
557  is the only way to guarentee the memory isn't shared
558  */
559  mpoly = lwgeom_as_multi(tmp);
560  clone = lwgeom_clone_deep(mpoly);
561  lwgeom_free(tmp);
562  lwgeom_free(mpoly);
563  mpoly = clone;
564 
565  RASTER_DEBUGF(4, "mpoly @ %p", mpoly);
566 
567 #if POSTGIS_DEBUG_LEVEL > 3
568  {
569  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
570  RASTER_DEBUGF(4, "after multi = %s", wkt);
571  rtdealloc(wkt);
572  }
573 #endif
574  }
575 
576 #if POSTGIS_DEBUG_LEVEL > 3
577  {
578  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
579  RASTER_DEBUGF(4, "returning geometry = %s", wkt);
580  rtdealloc(wkt);
581  }
582 #endif
583 
584  *surface = lwgeom_as_lwmpoly(mpoly);
585  return ES_NONE;
586  }
587 
588  return ES_NONE;
589 }
590 
591 /******************************************************************************
592 * rt_raster_pixel_as_polygon()
593 ******************************************************************************/
594 
609 LWPOLY*
611 {
612  double scale_x, scale_y;
613  double skew_x, skew_y;
614  double ul_x, ul_y;
615  int32_t srid;
616  POINTARRAY **points;
617  POINT4D p, p0;
618  LWPOLY *poly;
619 
620  assert(rast != NULL);
621 
622  scale_x = rt_raster_get_x_scale(rast);
623  scale_y = rt_raster_get_y_scale(rast);
624  skew_x = rt_raster_get_x_skew(rast);
625  skew_y = rt_raster_get_y_skew(rast);
628  srid = rt_raster_get_srid(rast);
629 
630  points = rtalloc(sizeof(POINTARRAY *)*1);
631  points[0] = ptarray_construct(0, 0, 5);
632 
633  p0.x = scale_x * x + skew_x * y + ul_x;
634  p0.y = scale_y * y + skew_y * x + ul_y;
635  ptarray_set_point4d(points[0], 0, &p0);
636 
637  p.x = p0.x + scale_x;
638  p.y = p0.y + skew_y;
639  ptarray_set_point4d(points[0], 1, &p);
640 
641  p.x = p0.x + scale_x + skew_x;
642  p.y = p0.y + scale_y + skew_y;
643  ptarray_set_point4d(points[0], 2, &p);
644 
645  p.x = p0.x + skew_x;
646  p.y = p0.y + scale_y;
647  ptarray_set_point4d(points[0], 3, &p);
648 
649  /* close it */
650  ptarray_set_point4d(points[0], 4, &p0);
651 
652  poly = lwpoly_construct(srid, NULL, 1, points);
653 
654  return poly;
655 }
656 
657 /******************************************************************************
658 * rt_raster_pixel_as_centroid_point()
659 ******************************************************************************/
660 
670 LWPOINT*
672 {
673  double scale_x, scale_y;
674  double skew_x, skew_y;
675  double ul_x, ul_y;
676  int32_t srid;
677  double center_x, center_y;
678  LWPOINT* point;
679 
680  scale_x = rt_raster_get_x_scale(rast);
681  scale_y = rt_raster_get_y_scale(rast);
682  skew_x = rt_raster_get_x_skew(rast);
683  skew_y = rt_raster_get_y_skew(rast);
686  srid = rt_raster_get_srid(rast);
687 
688  center_x = scale_x * x + skew_x * y + ul_x + (scale_x + skew_x) * 0.5;
689  center_y = scale_y * y + skew_y * x + ul_y + (scale_y + skew_y) * 0.5;
690  point = lwpoint_make2d(srid, center_x, center_y);
691 
692  return point;
693 }
694 
695 /******************************************************************************
696 * rt_raster_get_envelope_geom()
697 ******************************************************************************/
698 
709  double gt[6] = {0.0};
710  int32_t srid = SRID_UNKNOWN;
711 
712  POINTARRAY *pts = NULL;
713  POINT4D p4d;
714 
715  assert(env != NULL);
716  *env = NULL;
717 
718  /* raster is NULL, envelope is NULL */
719  if (raster == NULL)
720  return ES_NONE;
721 
722  /* raster metadata */
723  srid = rt_raster_get_srid(raster);
725 
727  3,
728  "rt_raster_get_envelope: raster is %dx%d",
729  raster->width,
730  raster->height
731  );
732 
733  /* return point or line since at least one of the two dimensions is 0 */
734  if ((!raster->width) || (!raster->height)) {
735  p4d.x = gt[0];
736  p4d.y = gt[3];
737 
738  /* return point */
739  if (!raster->width && !raster->height) {
740  LWPOINT *point = lwpoint_make2d(srid, p4d.x, p4d.y);
741  *env = lwpoint_as_lwgeom(point);
742  }
743  /* return linestring */
744  else {
745  LWLINE *line = NULL;
746  pts = ptarray_construct_empty(0, 0, 2);
747 
748  /* first point of line */
749  ptarray_append_point(pts, &p4d, LW_TRUE);
750 
751  /* second point of line */
753  raster,
755  &p4d.x, &p4d.y,
756  gt
757  ) != ES_NONE) {
758  rterror("rt_raster_get_envelope: Could not get second point for linestring");
759  return ES_ERROR;
760  }
761  ptarray_append_point(pts, &p4d, LW_TRUE);
762  line = lwline_construct(srid, NULL, pts);
763 
764  *env = lwline_as_lwgeom(line);
765  }
766 
767  return ES_NONE;
768  }
769  else {
770  rt_envelope rtenv;
771  int err = ES_NONE;
772  POINTARRAY **rings = NULL;
773  LWPOLY* poly = NULL;
774 
775  /* only one ring */
776  rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
777  if (!rings) {
778  rterror("rt_raster_get_envelope_geom: Could not allocate memory for polygon ring");
779  return ES_ERROR;
780  }
781  rings[0] = ptarray_construct(0, 0, 5);
782  if (!rings[0]) {
783  rterror("rt_raster_get_envelope_geom: Could not construct point array");
784  return ES_ERROR;
785  }
786  pts = rings[0];
787 
788  err = rt_raster_get_envelope(raster, &rtenv);
789  if (err != ES_NONE) {
790  rterror("rt_raster_get_envelope_geom: Could not get raster envelope");
791  return err;
792  }
793 
794  /* build ring */
795 
796  /* minx, maxy */
797  p4d.x = rtenv.MinX;
798  p4d.y = rtenv.MaxY;
799  ptarray_set_point4d(pts, 0, &p4d);
800  ptarray_set_point4d(pts, 4, &p4d);
801 
802  /* maxx, maxy */
803  p4d.x = rtenv.MaxX;
804  p4d.y = rtenv.MaxY;
805  ptarray_set_point4d(pts, 1, &p4d);
806 
807  /* maxx, miny */
808  p4d.x = rtenv.MaxX;
809  p4d.y = rtenv.MinY;
810  ptarray_set_point4d(pts, 2, &p4d);
811 
812  /* minx, miny */
813  p4d.x = rtenv.MinX;
814  p4d.y = rtenv.MinY;
815  ptarray_set_point4d(pts, 3, &p4d);
816 
817  poly = lwpoly_construct(srid, 0, 1, rings);
818  *env = lwpoly_as_lwgeom(poly);
819  }
820 
821  return ES_NONE;
822 }
823 
824 /******************************************************************************
825 * rt_raster_get_convex_hull()
826 ******************************************************************************/
827 
842  double gt[6] = {0.0};
843  int32_t srid = SRID_UNKNOWN;
844 
845  POINTARRAY *pts = NULL;
846  POINT4D p4d;
847 
848  assert(hull != NULL);
849  *hull = NULL;
850 
851  /* raster is NULL, convex hull is NULL */
852  if (raster == NULL)
853  return ES_NONE;
854 
855  /* raster metadata */
856  srid = rt_raster_get_srid(raster);
858 
859  RASTER_DEBUGF(3, "rt_raster_get_convex_hull: raster is %dx%d", raster->width, raster->height);
860 
861  /* return point or line since at least one of the two dimensions is 0 */
862  if ((!raster->width) || (!raster->height)) {
863  p4d.x = gt[0];
864  p4d.y = gt[3];
865 
866  /* return point */
867  if (!raster->width && !raster->height) {
868  LWPOINT *point = lwpoint_make2d(srid, p4d.x, p4d.y);
869  *hull = lwpoint_as_lwgeom(point);
870  }
871  /* return linestring */
872  else {
873  LWLINE *line = NULL;
874  pts = ptarray_construct_empty(0, 0, 2);
875 
876  /* first point of line */
877  ptarray_append_point(pts, &p4d, LW_TRUE);
878 
879  /* second point of line */
881  raster,
883  &p4d.x, &p4d.y,
884  gt
885  ) != ES_NONE) {
886  rterror("rt_raster_get_convex_hull: Could not get second point for linestring");
887  return ES_ERROR;
888  }
889  ptarray_append_point(pts, &p4d, LW_TRUE);
890  line = lwline_construct(srid, NULL, pts);
891 
892  *hull = lwline_as_lwgeom(line);
893  }
894 
895  return ES_NONE;
896  }
897  else {
898  POINTARRAY **rings = NULL;
899  LWPOLY* poly = NULL;
900 
901  /* only one ring */
902  rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
903  if (!rings) {
904  rterror("rt_raster_get_convex_hull: Could not allocate memory for polygon ring");
905  return ES_ERROR;
906  }
907  rings[0] = ptarray_construct(0, 0, 5);
908  /* TODO: handle error on ptarray construction */
909  /* XXX jorgearevalo: the error conditions aren't managed in ptarray_construct */
910  if (!rings[0]) {
911  rterror("rt_raster_get_convex_hull: Could not construct point array");
912  return ES_ERROR;
913  }
914  pts = rings[0];
915 
916  /* Upper-left corner (first and last points) */
917  p4d.x = gt[0];
918  p4d.y = gt[3];
919  ptarray_set_point4d(pts, 0, &p4d);
920  ptarray_set_point4d(pts, 4, &p4d);
921 
922  /* Upper-right corner (we go clockwise) */
924  raster,
925  raster->width, 0,
926  &p4d.x, &p4d.y,
927  gt
928  );
929  ptarray_set_point4d(pts, 1, &p4d);
930 
931  /* Lower-right corner */
933  raster,
934  raster->width, raster->height,
935  &p4d.x, &p4d.y,
936  gt
937  );
938  ptarray_set_point4d(pts, 2, &p4d);
939 
940  /* Lower-left corner */
942  raster,
943  0, raster->height,
944  &p4d.x, &p4d.y,
945  gt
946  );
947  ptarray_set_point4d(pts, 3, &p4d);
948 
949  poly = lwpoly_construct(srid, 0, 1, rings);
950  *hull = lwpoly_as_lwgeom(poly);
951  }
952 
953  return ES_NONE;
954 }
955 
956 /******************************************************************************
957 * rt_raster_gdal_polygonize()
958 ******************************************************************************/
959 
979  rt_raster raster, int nband,
980  int exclude_nodata_value,
981  int *pnElements
982 ) {
983  CPLErr cplerr = CE_None;
984  char *pszQuery;
985  long j;
986  OGRSFDriverH ogr_drv = NULL;
987  GDALDriverH gdal_drv = NULL;
988  int destroy_gdal_drv = 0;
989  GDALDatasetH memdataset = NULL;
990  GDALRasterBandH gdal_band = NULL;
991  OGRDataSourceH memdatasource = NULL;
992  rt_geomval pols = NULL;
993  OGRLayerH hLayer = NULL;
994  OGRFeatureH hFeature = NULL;
995  OGRGeometryH hGeom = NULL;
996  OGRFieldDefnH hFldDfn = NULL;
997  unsigned char *wkb = NULL;
998  int wkbsize = 0;
999  LWGEOM *lwgeom = NULL;
1000  int nFeatureCount = 0;
1001  rt_band band = NULL;
1002  int iPixVal = -1;
1003  double dValue = 0.0;
1004  int iBandHasNodataValue = FALSE;
1005  double dBandNoData = 0.0;
1006 
1007  /* for checking that a geometry is valid */
1008  GEOSGeometry *ggeom = NULL;
1009  int isValid;
1010  LWGEOM *lwgeomValid = NULL;
1011 
1012  uint32_t bandNums[1] = {nband};
1013  int excludeNodataValues[1] = {exclude_nodata_value};
1014 
1015  /* checks */
1016  assert(NULL != raster);
1017  assert(NULL != pnElements);
1018 
1019  RASTER_DEBUG(2, "In rt_raster_gdal_polygonize");
1020 
1021  *pnElements = 0;
1022 
1023  /*******************************
1024  * Get band
1025  *******************************/
1027  if (NULL == band) {
1028  rterror("rt_raster_gdal_polygonize: Error getting band %d from raster", nband);
1029  return NULL;
1030  }
1031 
1032  if (exclude_nodata_value) {
1033 
1034  /* band is NODATA */
1036  RASTER_DEBUG(3, "Band is NODATA. Returning null");
1037  *pnElements = 0;
1038  return NULL;
1039  }
1040 
1041  iBandHasNodataValue = rt_band_get_hasnodata_flag(band);
1042  if (iBandHasNodataValue)
1043  rt_band_get_nodata(band, &dBandNoData);
1044  else
1045  exclude_nodata_value = FALSE;
1046  }
1047 
1048  /*****************************************************
1049  * Convert raster to GDAL MEM dataset
1050  *****************************************************/
1051  memdataset = rt_raster_to_gdal_mem(raster, NULL, bandNums, excludeNodataValues, 1, &gdal_drv, &destroy_gdal_drv);
1052  if (NULL == memdataset) {
1053  rterror("rt_raster_gdal_polygonize: Couldn't convert raster to GDAL MEM dataset");
1054  return NULL;
1055  }
1056 
1057  /*****************************
1058  * Register ogr mem driver
1059  *****************************/
1060 #ifdef GDAL_DCAP_RASTER
1061  /* in GDAL 2.0, OGRRegisterAll() is an alias to GDALAllRegister() */
1063 #else
1064  OGRRegisterAll();
1065 #endif
1066 
1067  RASTER_DEBUG(3, "creating OGR MEM vector");
1068 
1069  /*****************************************************
1070  * Create an OGR in-memory vector for layers
1071  *****************************************************/
1072  ogr_drv = OGRGetDriverByName("Memory");
1073  memdatasource = OGR_Dr_CreateDataSource(ogr_drv, "", NULL);
1074  if (NULL == memdatasource) {
1075  rterror("rt_raster_gdal_polygonize: Couldn't create a OGR Datasource to store pols");
1076  GDALClose(memdataset);
1077  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1078  return NULL;
1079  }
1080 
1081  /* Can MEM driver create new layers? */
1082  if (!OGR_DS_TestCapability(memdatasource, ODsCCreateLayer)) {
1083  rterror("rt_raster_gdal_polygonize: MEM driver can't create new layers, aborting");
1084 
1085  /* xxx jorgearevalo: what should we do now? */
1086  GDALClose(memdataset);
1087  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1088  OGRReleaseDataSource(memdatasource);
1089 
1090  return NULL;
1091  }
1092 
1093  RASTER_DEBUG(3, "polygonizying GDAL MEM raster band");
1094 
1095  /*****************************
1096  * Polygonize the raster band
1097  *****************************/
1098 
1104  hLayer = OGR_DS_CreateLayer(memdatasource, "PolygonizedLayer", NULL, wkbPolygon, NULL);
1105 
1106  if (NULL == hLayer) {
1107  rterror("rt_raster_gdal_polygonize: Couldn't create layer to store polygons");
1108 
1109  GDALClose(memdataset);
1110  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1111  OGRReleaseDataSource(memdatasource);
1112 
1113  return NULL;
1114  }
1115 
1120  /* First, create a field definition to create the field */
1121  hFldDfn = OGR_Fld_Create("PixelValue", OFTReal);
1122 
1123  /* Second, create the field */
1124  if (OGR_L_CreateField(hLayer, hFldDfn, TRUE) != OGRERR_NONE) {
1125  rtwarn("Couldn't create a field in OGR Layer. The polygons generated won't be able to store the pixel value");
1126  iPixVal = -1;
1127  }
1128  else {
1129  /* Index to the new field created in the layer */
1130  iPixVal = 0;
1131  }
1132 
1133  /* Get GDAL raster band */
1134  gdal_band = GDALGetRasterBand(memdataset, 1);
1135  if (NULL == gdal_band) {
1136  rterror("rt_raster_gdal_polygonize: Couldn't get GDAL band to polygonize");
1137 
1138  GDALClose(memdataset);
1139  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1140  OGR_Fld_Destroy(hFldDfn);
1141  OGR_DS_DeleteLayer(memdatasource, 0);
1142  OGRReleaseDataSource(memdatasource);
1143 
1144  return NULL;
1145  }
1146 
1147  /* We don't need a raster mask band. Each band has a nodata value. */
1148  cplerr = GDALFPolygonize(gdal_band, NULL, hLayer, iPixVal, NULL, NULL, NULL);
1149 
1150  if (cplerr != CE_None) {
1151  rterror("rt_raster_gdal_polygonize: Could not polygonize GDAL band");
1152 
1153  GDALClose(memdataset);
1154  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1155  OGR_Fld_Destroy(hFldDfn);
1156  OGR_DS_DeleteLayer(memdatasource, 0);
1157  OGRReleaseDataSource(memdatasource);
1158 
1159  return NULL;
1160  }
1161 
1168  if (iBandHasNodataValue) {
1169  size_t sz = 50 * sizeof (char);
1170  pszQuery = (char *) rtalloc(sz);
1171  snprintf(pszQuery, sz, "PixelValue != %f", dBandNoData );
1172  OGRErr e = OGR_L_SetAttributeFilter(hLayer, pszQuery);
1173  if (e != OGRERR_NONE) {
1174  rtwarn("Error filtering NODATA values for band. All values will be treated as data values");
1175  }
1176  }
1177  else {
1178  pszQuery = NULL;
1179  }
1180 
1181  /*********************************************************************
1182  * Transform OGR layers to WKB polygons
1183  * XXX jorgearevalo: GDALPolygonize does not set the coordinate system
1184  * on the output layer. Application code should do this when the layer
1185  * is created, presumably matching the raster coordinate system.
1186  *********************************************************************/
1187  nFeatureCount = OGR_L_GetFeatureCount(hLayer, TRUE);
1188 
1189  /* Allocate memory for pols */
1190  pols = (rt_geomval) rtalloc(nFeatureCount * sizeof(struct rt_geomval_t));
1191 
1192  if (NULL == pols) {
1193  rterror("rt_raster_gdal_polygonize: Could not allocate memory for geomval set");
1194 
1195  GDALClose(memdataset);
1196  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1197  OGR_Fld_Destroy(hFldDfn);
1198  OGR_DS_DeleteLayer(memdatasource, 0);
1199  if (NULL != pszQuery)
1200  rtdealloc(pszQuery);
1201  OGRReleaseDataSource(memdatasource);
1202 
1203  return NULL;
1204  }
1205 
1206  /* initialize GEOS */
1207  initGEOS(rtinfo, lwgeom_geos_error);
1208 
1209  RASTER_DEBUGF(3, "storing polygons (%d)", nFeatureCount);
1210 
1211  /* Reset feature reading to start in the first feature */
1212  OGR_L_ResetReading(hLayer);
1213 
1214  for (j = 0; j < nFeatureCount; j++) {
1215  hFeature = OGR_L_GetNextFeature(hLayer);
1216  dValue = OGR_F_GetFieldAsDouble(hFeature, iPixVal);
1217 
1218  hGeom = OGR_F_GetGeometryRef(hFeature);
1219  wkbsize = OGR_G_WkbSize(hGeom);
1220 
1221  /* allocate wkb buffer */
1222  wkb = rtalloc(sizeof(unsigned char) * wkbsize);
1223  if (wkb == NULL) {
1224  rterror("rt_raster_gdal_polygonize: Could not allocate memory for WKB buffer");
1225 
1226  OGR_F_Destroy(hFeature);
1227  GDALClose(memdataset);
1228  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1229  OGR_Fld_Destroy(hFldDfn);
1230  OGR_DS_DeleteLayer(memdatasource, 0);
1231  if (NULL != pszQuery)
1232  rtdealloc(pszQuery);
1233  OGRReleaseDataSource(memdatasource);
1234 
1235  return NULL;
1236  }
1237 
1238  /* export WKB with LSB byte order */
1239  OGR_G_ExportToWkb(hGeom, wkbNDR, wkb);
1240 
1241  /* convert WKB to LWGEOM */
1242  lwgeom = lwgeom_from_wkb(wkb, wkbsize, LW_PARSER_CHECK_NONE);
1243  if (!lwgeom) rterror("%s: invalid wkb", __func__);
1244 
1245 #if POSTGIS_DEBUG_LEVEL > 3
1246  {
1247  char *wkt = NULL;
1248  OGR_G_ExportToWkt(hGeom, &wkt);
1249  RASTER_DEBUGF(4, "GDAL wkt = %s", wkt);
1250  CPLFree(wkt);
1251 
1252  d_print_binary_hex("GDAL wkb", wkb, wkbsize);
1253  }
1254 #endif
1255 
1256  /* cleanup unnecessary stuff */
1257  rtdealloc(wkb);
1258  wkb = NULL;
1259  wkbsize = 0;
1260 
1261  OGR_F_Destroy(hFeature);
1262 
1263  /* specify SRID */
1265 
1266  /*
1267  is geometry valid?
1268  if not, try to make valid
1269  */
1270  do {
1271  ggeom = (GEOSGeometry *) LWGEOM2GEOS(lwgeom, 0);
1272  if (ggeom == NULL) {
1273  rtwarn("Cannot test geometry for validity");
1274  break;
1275  }
1276 
1277  isValid = GEOSisValid(ggeom);
1278 
1279  GEOSGeom_destroy(ggeom);
1280  ggeom = NULL;
1281 
1282  /* geometry is valid */
1283  if (isValid)
1284  break;
1285 
1286  RASTER_DEBUG(3, "fixing invalid geometry");
1287 
1288  /* make geometry valid */
1289  lwgeomValid = lwgeom_make_valid(lwgeom);
1290  if (lwgeomValid == NULL) {
1291  rtwarn("Cannot fix invalid geometry");
1292  break;
1293  }
1294 
1295  lwgeom_free(lwgeom);
1296  lwgeom = lwgeomValid;
1297  }
1298  while (0);
1299 
1300  /* save lwgeom */
1301  pols[j].geom = lwgeom_as_lwpoly(lwgeom);
1302 
1303 #if POSTGIS_DEBUG_LEVEL > 3
1304  {
1305  char *wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, DBL_DIG, NULL);
1306  RASTER_DEBUGF(4, "LWGEOM wkt = %s", wkt);
1307  rtdealloc(wkt);
1308 
1309  lwvarlena_t *lwwkb = lwgeom_to_wkb_varlena(lwgeom, WKB_ISO | WKB_NDR);
1310  size_t lwwkbsize = LWSIZE_GET(lwwkb->size) - LWVARHDRSZ;
1311  if (lwwkbsize) {
1312  d_print_binary_hex("LWGEOM wkb", (const uint8_t *)lwwkb->data, lwwkbsize);
1313  rtdealloc(lwwkb);
1314  }
1315  }
1316 #endif
1317 
1318  /* set pixel value */
1319  pols[j].val = dValue;
1320  }
1321 
1322  *pnElements = nFeatureCount;
1323 
1324  RASTER_DEBUG(3, "destroying GDAL MEM raster");
1325  GDALClose(memdataset);
1326  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1327 
1328  RASTER_DEBUG(3, "destroying OGR MEM vector");
1329  OGR_Fld_Destroy(hFldDfn);
1330  OGR_DS_DeleteLayer(memdatasource, 0);
1331  if (NULL != pszQuery) rtdealloc(pszQuery);
1332  OGRReleaseDataSource(memdatasource);
1333 
1334  return pols;
1335 }
1336 
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
void lwgeom_geos_error(const char *fmt,...)
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:322
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition: lwpoint.c:163
#define WKB_ISO
Definition: liblwgeom.h:2156
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
Definition: lwgeom.c:1530
#define LWVARHDRSZ
Definition: liblwgeom.h:325
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2095
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition: lwgeom.c:363
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
Definition: liblwgeom.h:338
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:312
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:512
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:243
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:51
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:327
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1080
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
#define WKT_ISO
Definition: liblwgeom.h:2165
#define WKB_NDR
Definition: liblwgeom.h:2159
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:704
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:147
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:198
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:229
LWGEOM * lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_wkb.c:834
lwvarlena_t * lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant)
Definition: lwout_wkb.c:851
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition: lwgeom_api.c:370
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:219
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:191
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
Definition: rt_band.c:640
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:302
rt_errorstate rt_raster_cell_to_geopoint(rt_raster raster, double xr, double yr, double *xw, double *yw, double *gt)
Convert an xr, yr raster point to an xw, yw point on map.
Definition: rt_raster.c:759
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition: rt_raster.c:360
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:339
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:306
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:185
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_raster.c:217
void rtinfo(const char *fmt,...)
Definition: rt_context.c:231
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1376
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_band.c:714
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_raster.c:154
void rtwarn(const char *fmt,...)
Definition: rt_context.c:244
rt_errorstate
Enum definitions.
Definition: librtcore.h:181
@ ES_NONE
Definition: librtcore.h:182
@ ES_ERROR
Definition: librtcore.h:183
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:376
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:133
struct rt_geomval_t * rt_geomval
Definition: librtcore.h:151
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1887
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:125
void rtdealloc(void *mem)
Definition: rt_context.c:206
GDALDatasetH rt_raster_to_gdal_mem(rt_raster raster, const char *srs, uint32_t *bandNums, int *excludeNodataValues, int count, GDALDriverH *rtn_drv, int *destroy_rtn_drv)
Return GDAL dataset using GDAL MEM driver from raster.
Definition: rt_raster.c:1935
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_raster.c:163
rt_errorstate rt_raster_get_envelope(rt_raster raster, rt_envelope *env)
Get raster's envelope.
Definition: rt_raster.c:904
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:194
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:710
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
Definition: rt_band.c:649
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition: rt_raster.c:226
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1362
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:385
This library is the generic raster handling section of PostGIS.
int value
Definition: genraster.py:62
band
Definition: ovdump.py:58
nband
Definition: pixval.py:53
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
gt
Definition: window.py:78
static char * trim(const char *input)
Definition: raster2pgsql.c:265
LWPOINT * rt_raster_pixel_as_centroid_point(rt_raster rast, int x, int y)
Get a raster pixel centroid point.
Definition: rt_geometry.c:671
rt_errorstate rt_raster_surface(rt_raster raster, int nband, LWMPOLY **surface)
Get a raster as a surface (multipolygon).
Definition: rt_geometry.c:355
rt_geomval rt_raster_gdal_polygonize(rt_raster raster, int nband, int exclude_nodata_value, int *pnElements)
Returns a set of "geomval" value, one for each group of pixel sharing the same value for the provided...
Definition: rt_geometry.c:978
LWPOLY * rt_raster_pixel_as_polygon(rt_raster rast, int x, int y)
Get a raster pixel as a polygon.
Definition: rt_geometry.c:610
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
Definition: rt_geometry.c:841
static rt_errorstate _rti_raster_get_band_perimeter(rt_band band, uint16_t *trim)
Definition: rt_geometry.c:39
rt_errorstate rt_raster_get_envelope_geom(rt_raster raster, LWGEOM **env)
Get raster's envelope as a geometry.
Definition: rt_geometry.c:708
rt_errorstate rt_raster_get_perimeter(rt_raster raster, int nband, LWGEOM **perimeter)
Get raster perimeter.
Definition: rt_geometry.c:182
double x
Definition: liblwgeom.h:428
double y
Definition: liblwgeom.h:428
uint32_t size
Definition: liblwgeom.h:321
char data[]
Definition: liblwgeom.h:322
double MinX
Definition: librtcore.h:167
double MaxX
Definition: librtcore.h:168
double MinY
Definition: librtcore.h:169
double MaxY
Definition: librtcore.h:170
double val
Definition: librtcore.h:2500
LWPOLY * geom
Definition: librtcore.h:2499