PostGIS  3.4.0dev-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  /* use gdal polygonize */
437  gv = rt_raster_gdal_polygonize(raster, nband, 1, &gvcount);
438  /* no polygons returned */
439  if (gvcount < 1) {
440  RASTER_DEBUG(3, "All pixels of band are NODATA. Returning NULL");
441  if (gv != NULL) rtdealloc(gv);
442  return ES_NONE;
443  }
444  /* more than 1 polygon */
445  else if (gvcount > 1) {
446  /* convert LWPOLY to GEOSGeometry */
447  geomscount = gvcount;
448  geoms = rtalloc(sizeof(GEOSGeometry *) * geomscount);
449  if (geoms == NULL) {
450  rterror("rt_raster_surface: Could not allocate memory for pixel polygons as GEOSGeometry");
451  for (i = 0; i < gvcount; i++) lwpoly_free(gv[i].geom);
452  rtdealloc(gv);
453  return ES_ERROR;
454  }
455  for (i = 0; i < gvcount; i++) {
456 #if POSTGIS_DEBUG_LEVEL > 3
457  {
458  char *wkt = lwgeom_to_wkt(lwpoly_as_lwgeom(gv[i].geom), WKT_ISO, DBL_DIG, NULL);
459  RASTER_DEBUGF(4, "geom %d = %s", i, wkt);
460  rtdealloc(wkt);
461  }
462 #endif
463 
464  geoms[i] = LWGEOM2GEOS(lwpoly_as_lwgeom(gv[i].geom), 0);
465  lwpoly_free(gv[i].geom);
466  }
467  rtdealloc(gv);
468 
469  /* create geometry collection */
470  gc = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, geomscount);
471 
472  if (gc == NULL) {
473  rterror("rt_raster_surface: Could not create GEOS GEOMETRYCOLLECTION from set of pixel polygons");
474 
475  for (i = 0; i < geomscount; i++)
476  GEOSGeom_destroy(geoms[i]);
477  rtdealloc(geoms);
478  return ES_ERROR;
479  }
480 
481  /* run the union */
482  gunion = GEOSUnaryUnion(gc);
483 
484  GEOSGeom_destroy(gc);
485  rtdealloc(geoms);
486 
487  if (gunion == NULL) {
488  rterror("rt_raster_surface: Could not union the pixel polygons using GEOSUnaryUnion()");
489  return ES_ERROR;
490  }
491 
492  /* convert union result from GEOSGeometry to LWGEOM */
493  mpoly = GEOS2LWGEOM(gunion, 0);
494 
495  /*
496  is geometry valid?
497  if not, try to make valid
498  */
499  do {
500  LWGEOM *mpolyValid = NULL;
501 
502  if (GEOSisValid(gunion))
503  break;
504 
505  /* make geometry valid */
506  mpolyValid = lwgeom_make_valid(mpoly);
507  if (mpolyValid == NULL) {
508  rtwarn("Cannot fix invalid geometry");
509  break;
510  }
511 
512  lwgeom_free(mpoly);
513  mpoly = mpolyValid;
514  }
515  while (0);
516 
517  GEOSGeom_destroy(gunion);
518  }
519  else {
520  mpoly = lwpoly_as_lwgeom(gv[0].geom);
521  rtdealloc(gv);
522 
523 #if POSTGIS_DEBUG_LEVEL > 3
524  {
525  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
526  RASTER_DEBUGF(4, "geom 0 = %s", wkt);
527  rtdealloc(wkt);
528  }
529 #endif
530  }
531 
532  /* specify SRID */
534 
535  if (mpoly != NULL) {
536  /* convert to multi */
537  if (!lwgeom_is_collection(mpoly)) {
538  tmp = mpoly;
539 
540 #if POSTGIS_DEBUG_LEVEL > 3
541  {
542  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
543  RASTER_DEBUGF(4, "before multi = %s", wkt);
544  rtdealloc(wkt);
545  }
546 #endif
547 
548  RASTER_DEBUGF(4, "mpoly @ %p", mpoly);
549 
550  /*
551  lwgeom_as_multi() only does a shallow clone internally
552  so input and output geometries may share memory
553  hence the deep clone of the output geometry for returning
554  is the only way to guarentee the memory isn't shared
555  */
556  mpoly = lwgeom_as_multi(tmp);
557  clone = lwgeom_clone_deep(mpoly);
558  lwgeom_free(tmp);
559  lwgeom_free(mpoly);
560  mpoly = clone;
561 
562  RASTER_DEBUGF(4, "mpoly @ %p", mpoly);
563 
564 #if POSTGIS_DEBUG_LEVEL > 3
565  {
566  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
567  RASTER_DEBUGF(4, "after multi = %s", wkt);
568  rtdealloc(wkt);
569  }
570 #endif
571  }
572 
573 #if POSTGIS_DEBUG_LEVEL > 3
574  {
575  char *wkt = lwgeom_to_wkt(mpoly, WKT_ISO, DBL_DIG, NULL);
576  RASTER_DEBUGF(4, "returning geometry = %s", wkt);
577  rtdealloc(wkt);
578  }
579 #endif
580 
581  *surface = lwgeom_as_lwmpoly(mpoly);
582  return ES_NONE;
583  }
584 
585  return ES_NONE;
586 }
587 
588 /******************************************************************************
589 * rt_raster_pixel_as_polygon()
590 ******************************************************************************/
591 
606 LWPOLY*
608 {
609  double scale_x, scale_y;
610  double skew_x, skew_y;
611  double ul_x, ul_y;
612  int32_t srid;
613  POINTARRAY **points;
614  POINT4D p, p0;
615  LWPOLY *poly;
616 
617  assert(rast != NULL);
618 
619  scale_x = rt_raster_get_x_scale(rast);
620  scale_y = rt_raster_get_y_scale(rast);
621  skew_x = rt_raster_get_x_skew(rast);
622  skew_y = rt_raster_get_y_skew(rast);
625  srid = rt_raster_get_srid(rast);
626 
627  points = rtalloc(sizeof(POINTARRAY *)*1);
628  points[0] = ptarray_construct(0, 0, 5);
629 
630  p0.x = scale_x * x + skew_x * y + ul_x;
631  p0.y = scale_y * y + skew_y * x + ul_y;
632  ptarray_set_point4d(points[0], 0, &p0);
633 
634  p.x = p0.x + scale_x;
635  p.y = p0.y + skew_y;
636  ptarray_set_point4d(points[0], 1, &p);
637 
638  p.x = p0.x + scale_x + skew_x;
639  p.y = p0.y + scale_y + skew_y;
640  ptarray_set_point4d(points[0], 2, &p);
641 
642  p.x = p0.x + skew_x;
643  p.y = p0.y + scale_y;
644  ptarray_set_point4d(points[0], 3, &p);
645 
646  /* close it */
647  ptarray_set_point4d(points[0], 4, &p0);
648 
649  poly = lwpoly_construct(srid, NULL, 1, points);
650 
651  return poly;
652 }
653 
654 /******************************************************************************
655 * rt_raster_pixel_as_centroid_point()
656 ******************************************************************************/
657 
667 LWPOINT*
669 {
670  double scale_x, scale_y;
671  double skew_x, skew_y;
672  double ul_x, ul_y;
673  int32_t srid;
674  double center_x, center_y;
675  LWPOINT* point;
676 
677  scale_x = rt_raster_get_x_scale(rast);
678  scale_y = rt_raster_get_y_scale(rast);
679  skew_x = rt_raster_get_x_skew(rast);
680  skew_y = rt_raster_get_y_skew(rast);
683  srid = rt_raster_get_srid(rast);
684 
685  center_x = scale_x * x + skew_x * y + ul_x + (scale_x + skew_x) * 0.5;
686  center_y = scale_y * y + skew_y * x + ul_y + (scale_y + skew_y) * 0.5;
687  point = lwpoint_make2d(srid, center_x, center_y);
688 
689  return point;
690 }
691 
692 /******************************************************************************
693 * rt_raster_get_envelope_geom()
694 ******************************************************************************/
695 
706  double gt[6] = {0.0};
707  int32_t srid = SRID_UNKNOWN;
708 
709  POINTARRAY *pts = NULL;
710  POINT4D p4d;
711 
712  assert(env != NULL);
713  *env = NULL;
714 
715  /* raster is NULL, envelope is NULL */
716  if (raster == NULL)
717  return ES_NONE;
718 
719  /* raster metadata */
720  srid = rt_raster_get_srid(raster);
722 
724  3,
725  "rt_raster_get_envelope: raster is %dx%d",
726  raster->width,
727  raster->height
728  );
729 
730  /* return point or line since at least one of the two dimensions is 0 */
731  if ((!raster->width) || (!raster->height)) {
732  p4d.x = gt[0];
733  p4d.y = gt[3];
734 
735  /* return point */
736  if (!raster->width && !raster->height) {
737  LWPOINT *point = lwpoint_make2d(srid, p4d.x, p4d.y);
738  *env = lwpoint_as_lwgeom(point);
739  }
740  /* return linestring */
741  else {
742  LWLINE *line = NULL;
743  pts = ptarray_construct_empty(0, 0, 2);
744 
745  /* first point of line */
746  ptarray_append_point(pts, &p4d, LW_TRUE);
747 
748  /* second point of line */
750  raster,
752  &p4d.x, &p4d.y,
753  gt
754  ) != ES_NONE) {
755  rterror("rt_raster_get_envelope: Could not get second point for linestring");
756  return ES_ERROR;
757  }
758  ptarray_append_point(pts, &p4d, LW_TRUE);
759  line = lwline_construct(srid, NULL, pts);
760 
761  *env = lwline_as_lwgeom(line);
762  }
763 
764  return ES_NONE;
765  }
766  else {
767  rt_envelope rtenv;
768  int err = ES_NONE;
769  POINTARRAY **rings = NULL;
770  LWPOLY* poly = NULL;
771 
772  /* only one ring */
773  rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
774  if (!rings) {
775  rterror("rt_raster_get_envelope_geom: Could not allocate memory for polygon ring");
776  return ES_ERROR;
777  }
778  rings[0] = ptarray_construct(0, 0, 5);
779  if (!rings[0]) {
780  rterror("rt_raster_get_envelope_geom: Could not construct point array");
781  return ES_ERROR;
782  }
783  pts = rings[0];
784 
785  err = rt_raster_get_envelope(raster, &rtenv);
786  if (err != ES_NONE) {
787  rterror("rt_raster_get_envelope_geom: Could not get raster envelope");
788  return err;
789  }
790 
791  /* build ring */
792 
793  /* minx, maxy */
794  p4d.x = rtenv.MinX;
795  p4d.y = rtenv.MaxY;
796  ptarray_set_point4d(pts, 0, &p4d);
797  ptarray_set_point4d(pts, 4, &p4d);
798 
799  /* maxx, maxy */
800  p4d.x = rtenv.MaxX;
801  p4d.y = rtenv.MaxY;
802  ptarray_set_point4d(pts, 1, &p4d);
803 
804  /* maxx, miny */
805  p4d.x = rtenv.MaxX;
806  p4d.y = rtenv.MinY;
807  ptarray_set_point4d(pts, 2, &p4d);
808 
809  /* minx, miny */
810  p4d.x = rtenv.MinX;
811  p4d.y = rtenv.MinY;
812  ptarray_set_point4d(pts, 3, &p4d);
813 
814  poly = lwpoly_construct(srid, 0, 1, rings);
815  *env = lwpoly_as_lwgeom(poly);
816  }
817 
818  return ES_NONE;
819 }
820 
821 /******************************************************************************
822 * rt_raster_get_convex_hull()
823 ******************************************************************************/
824 
839  double gt[6] = {0.0};
840  int32_t srid = SRID_UNKNOWN;
841 
842  POINTARRAY *pts = NULL;
843  POINT4D p4d;
844 
845  assert(hull != NULL);
846  *hull = NULL;
847 
848  /* raster is NULL, convex hull is NULL */
849  if (raster == NULL)
850  return ES_NONE;
851 
852  /* raster metadata */
853  srid = rt_raster_get_srid(raster);
855 
856  RASTER_DEBUGF(3, "rt_raster_get_convex_hull: raster is %dx%d", raster->width, raster->height);
857 
858  /* return point or line since at least one of the two dimensions is 0 */
859  if ((!raster->width) || (!raster->height)) {
860  p4d.x = gt[0];
861  p4d.y = gt[3];
862 
863  /* return point */
864  if (!raster->width && !raster->height) {
865  LWPOINT *point = lwpoint_make2d(srid, p4d.x, p4d.y);
866  *hull = lwpoint_as_lwgeom(point);
867  }
868  /* return linestring */
869  else {
870  LWLINE *line = NULL;
871  pts = ptarray_construct_empty(0, 0, 2);
872 
873  /* first point of line */
874  ptarray_append_point(pts, &p4d, LW_TRUE);
875 
876  /* second point of line */
878  raster,
880  &p4d.x, &p4d.y,
881  gt
882  ) != ES_NONE) {
883  rterror("rt_raster_get_convex_hull: Could not get second point for linestring");
884  return ES_ERROR;
885  }
886  ptarray_append_point(pts, &p4d, LW_TRUE);
887  line = lwline_construct(srid, NULL, pts);
888 
889  *hull = lwline_as_lwgeom(line);
890  }
891 
892  return ES_NONE;
893  }
894  else {
895  POINTARRAY **rings = NULL;
896  LWPOLY* poly = NULL;
897 
898  /* only one ring */
899  rings = (POINTARRAY **) rtalloc(sizeof (POINTARRAY*));
900  if (!rings) {
901  rterror("rt_raster_get_convex_hull: Could not allocate memory for polygon ring");
902  return ES_ERROR;
903  }
904  rings[0] = ptarray_construct(0, 0, 5);
905  /* TODO: handle error on ptarray construction */
906  /* XXX jorgearevalo: the error conditions aren't managed in ptarray_construct */
907  if (!rings[0]) {
908  rterror("rt_raster_get_convex_hull: Could not construct point array");
909  return ES_ERROR;
910  }
911  pts = rings[0];
912 
913  /* Upper-left corner (first and last points) */
914  p4d.x = gt[0];
915  p4d.y = gt[3];
916  ptarray_set_point4d(pts, 0, &p4d);
917  ptarray_set_point4d(pts, 4, &p4d);
918 
919  /* Upper-right corner (we go clockwise) */
921  raster,
922  raster->width, 0,
923  &p4d.x, &p4d.y,
924  gt
925  );
926  ptarray_set_point4d(pts, 1, &p4d);
927 
928  /* Lower-right corner */
930  raster,
931  raster->width, raster->height,
932  &p4d.x, &p4d.y,
933  gt
934  );
935  ptarray_set_point4d(pts, 2, &p4d);
936 
937  /* Lower-left corner */
939  raster,
940  0, raster->height,
941  &p4d.x, &p4d.y,
942  gt
943  );
944  ptarray_set_point4d(pts, 3, &p4d);
945 
946  poly = lwpoly_construct(srid, 0, 1, rings);
947  *hull = lwpoly_as_lwgeom(poly);
948  }
949 
950  return ES_NONE;
951 }
952 
953 /******************************************************************************
954 * rt_raster_gdal_polygonize()
955 ******************************************************************************/
956 
976  rt_raster raster, int nband,
977  int exclude_nodata_value,
978  int *pnElements
979 ) {
980  CPLErr cplerr = CE_None;
981  char *pszQuery;
982  long j;
983  OGRSFDriverH ogr_drv = NULL;
984  GDALDriverH gdal_drv = NULL;
985  int destroy_gdal_drv = 0;
986  GDALDatasetH memdataset = NULL;
987  GDALRasterBandH gdal_band = NULL;
988  OGRDataSourceH memdatasource = NULL;
989  rt_geomval pols = NULL;
990  OGRLayerH hLayer = NULL;
991  OGRFeatureH hFeature = NULL;
992  OGRGeometryH hGeom = NULL;
993  OGRFieldDefnH hFldDfn = NULL;
994  unsigned char *wkb = NULL;
995  int wkbsize = 0;
996  LWGEOM *lwgeom = NULL;
997  int nFeatureCount = 0;
998  rt_band band = NULL;
999  int iPixVal = -1;
1000  double dValue = 0.0;
1001  int iBandHasNodataValue = FALSE;
1002  double dBandNoData = 0.0;
1003 
1004  uint32_t bandNums[1] = {nband};
1005  int excludeNodataValues[1] = {exclude_nodata_value};
1006 
1007  /* checks */
1008  assert(NULL != raster);
1009  assert(NULL != pnElements);
1010 
1011  RASTER_DEBUG(2, "In rt_raster_gdal_polygonize");
1012 
1013  *pnElements = 0;
1014 
1015  /*******************************
1016  * Get band
1017  *******************************/
1019  if (NULL == band) {
1020  rterror("rt_raster_gdal_polygonize: Error getting band %d from raster", nband);
1021  return NULL;
1022  }
1023 
1024  if (exclude_nodata_value) {
1025 
1026  /* band is NODATA */
1028  RASTER_DEBUG(3, "Band is NODATA. Returning null");
1029  *pnElements = 0;
1030  return NULL;
1031  }
1032 
1033  iBandHasNodataValue = rt_band_get_hasnodata_flag(band);
1034  if (iBandHasNodataValue)
1035  rt_band_get_nodata(band, &dBandNoData);
1036  else
1037  exclude_nodata_value = FALSE;
1038  }
1039 
1040  /*****************************************************
1041  * Convert raster to GDAL MEM dataset
1042  *****************************************************/
1043  memdataset = rt_raster_to_gdal_mem(raster, NULL, bandNums, excludeNodataValues, 1, &gdal_drv, &destroy_gdal_drv);
1044  if (NULL == memdataset) {
1045  rterror("rt_raster_gdal_polygonize: Couldn't convert raster to GDAL MEM dataset");
1046  return NULL;
1047  }
1048 
1049  /*****************************
1050  * Register ogr mem driver
1051  *****************************/
1052 #ifdef GDAL_DCAP_RASTER
1053  /* in GDAL 2.0, OGRRegisterAll() is an alias to GDALAllRegister() */
1055 #else
1056  OGRRegisterAll();
1057 #endif
1058 
1059  RASTER_DEBUG(3, "creating OGR MEM vector");
1060 
1061  /*****************************************************
1062  * Create an OGR in-memory vector for layers
1063  *****************************************************/
1064  ogr_drv = OGRGetDriverByName("Memory");
1065  memdatasource = OGR_Dr_CreateDataSource(ogr_drv, "", NULL);
1066  if (NULL == memdatasource) {
1067  rterror("rt_raster_gdal_polygonize: Couldn't create a OGR Datasource to store pols");
1068  GDALClose(memdataset);
1069  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1070  return NULL;
1071  }
1072 
1073  /* Can MEM driver create new layers? */
1074  if (!OGR_DS_TestCapability(memdatasource, ODsCCreateLayer)) {
1075  rterror("rt_raster_gdal_polygonize: MEM driver can't create new layers, aborting");
1076 
1077  /* xxx jorgearevalo: what should we do now? */
1078  GDALClose(memdataset);
1079  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1080  OGRReleaseDataSource(memdatasource);
1081 
1082  return NULL;
1083  }
1084 
1085  RASTER_DEBUG(3, "polygonizying GDAL MEM raster band");
1086 
1087  /*****************************
1088  * Polygonize the raster band
1089  *****************************/
1090 
1096  hLayer = OGR_DS_CreateLayer(memdatasource, "PolygonizedLayer", NULL, wkbPolygon, NULL);
1097 
1098  if (NULL == hLayer) {
1099  rterror("rt_raster_gdal_polygonize: Couldn't create layer to store polygons");
1100 
1101  GDALClose(memdataset);
1102  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1103  OGRReleaseDataSource(memdatasource);
1104 
1105  return NULL;
1106  }
1107 
1112  /* First, create a field definition to create the field */
1113  hFldDfn = OGR_Fld_Create("PixelValue", OFTReal);
1114 
1115  /* Second, create the field */
1116  if (OGR_L_CreateField(hLayer, hFldDfn, TRUE) != OGRERR_NONE) {
1117  rtwarn("Couldn't create a field in OGR Layer. The polygons generated won't be able to store the pixel value");
1118  iPixVal = -1;
1119  }
1120  else {
1121  /* Index to the new field created in the layer */
1122  iPixVal = 0;
1123  }
1124 
1125  /* Get GDAL raster band */
1126  gdal_band = GDALGetRasterBand(memdataset, 1);
1127  if (NULL == gdal_band) {
1128  rterror("rt_raster_gdal_polygonize: Couldn't get GDAL band to polygonize");
1129 
1130  GDALClose(memdataset);
1131  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1132  OGR_Fld_Destroy(hFldDfn);
1133  OGR_DS_DeleteLayer(memdatasource, 0);
1134  OGRReleaseDataSource(memdatasource);
1135 
1136  return NULL;
1137  }
1138 
1139  /* We don't need a raster mask band. Each band has a nodata value. */
1140  cplerr = GDALFPolygonize(gdal_band, NULL, hLayer, iPixVal, NULL, NULL, NULL);
1141 
1142  if (cplerr != CE_None) {
1143  rterror("rt_raster_gdal_polygonize: Could not polygonize GDAL band");
1144 
1145  GDALClose(memdataset);
1146  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1147  OGR_Fld_Destroy(hFldDfn);
1148  OGR_DS_DeleteLayer(memdatasource, 0);
1149  OGRReleaseDataSource(memdatasource);
1150 
1151  return NULL;
1152  }
1153 
1160  if (iBandHasNodataValue) {
1161  size_t sz = 50 * sizeof (char);
1162  pszQuery = (char *) rtalloc(sz);
1163  snprintf(pszQuery, sz, "PixelValue != %f", dBandNoData );
1164  OGRErr e = OGR_L_SetAttributeFilter(hLayer, pszQuery);
1165  if (e != OGRERR_NONE) {
1166  rtwarn("Error filtering NODATA values for band. All values will be treated as data values");
1167  }
1168  }
1169  else {
1170  pszQuery = NULL;
1171  }
1172 
1173  /*********************************************************************
1174  * Transform OGR layers to WKB polygons
1175  * XXX jorgearevalo: GDALPolygonize does not set the coordinate system
1176  * on the output layer. Application code should do this when the layer
1177  * is created, presumably matching the raster coordinate system.
1178  *********************************************************************/
1179  nFeatureCount = OGR_L_GetFeatureCount(hLayer, TRUE);
1180 
1181  /* Allocate memory for pols */
1182  pols = (rt_geomval) rtalloc(nFeatureCount * sizeof(struct rt_geomval_t));
1183 
1184  if (NULL == pols) {
1185  rterror("rt_raster_gdal_polygonize: Could not allocate memory for geomval set");
1186 
1187  GDALClose(memdataset);
1188  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1189  OGR_Fld_Destroy(hFldDfn);
1190  OGR_DS_DeleteLayer(memdatasource, 0);
1191  if (NULL != pszQuery)
1192  rtdealloc(pszQuery);
1193  OGRReleaseDataSource(memdatasource);
1194 
1195  return NULL;
1196  }
1197 
1198  /* initialize GEOS */
1199  initGEOS(rtinfo, lwgeom_geos_error);
1200 
1201  RASTER_DEBUGF(3, "storing polygons (%d)", nFeatureCount);
1202 
1203  /* Reset feature reading to start in the first feature */
1204  OGR_L_ResetReading(hLayer);
1205 
1206  for (j = 0; j < nFeatureCount; j++) {
1207  hFeature = OGR_L_GetNextFeature(hLayer);
1208  dValue = OGR_F_GetFieldAsDouble(hFeature, iPixVal);
1209 
1210  hGeom = OGR_F_GetGeometryRef(hFeature);
1211  wkbsize = OGR_G_WkbSize(hGeom);
1212 
1213  /* allocate wkb buffer */
1214  wkb = rtalloc(sizeof(unsigned char) * wkbsize);
1215  if (wkb == NULL) {
1216  rterror("rt_raster_gdal_polygonize: Could not allocate memory for WKB buffer");
1217 
1218  OGR_F_Destroy(hFeature);
1219  GDALClose(memdataset);
1220  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1221  OGR_Fld_Destroy(hFldDfn);
1222  OGR_DS_DeleteLayer(memdatasource, 0);
1223  if (NULL != pszQuery)
1224  rtdealloc(pszQuery);
1225  OGRReleaseDataSource(memdatasource);
1226 
1227  return NULL;
1228  }
1229 
1230  /* export WKB with LSB byte order */
1231  OGR_G_ExportToWkb(hGeom, wkbNDR, wkb);
1232 
1233  /* convert WKB to LWGEOM */
1234  lwgeom = lwgeom_from_wkb(wkb, wkbsize, LW_PARSER_CHECK_NONE);
1235 
1236 #if POSTGIS_DEBUG_LEVEL > 3
1237  {
1238  char *wkt = NULL;
1239  OGR_G_ExportToWkt(hGeom, &wkt);
1240  RASTER_DEBUGF(4, "GDAL wkt = %s", wkt);
1241  CPLFree(wkt);
1242 
1243  d_print_binary_hex("GDAL wkb", wkb, wkbsize);
1244  }
1245 #endif
1246 
1247  /* cleanup unnecessary stuff */
1248  rtdealloc(wkb);
1249  wkb = NULL;
1250  wkbsize = 0;
1251 
1252  OGR_F_Destroy(hFeature);
1253 
1254  /* specify SRID */
1256 
1257  /* save lwgeom */
1258  pols[j].geom = lwgeom_as_lwpoly(lwgeom);
1259 
1260 #if POSTGIS_DEBUG_LEVEL > 3
1261  {
1262  char *wkt = lwgeom_to_wkt(lwgeom, WKT_ISO, DBL_DIG, NULL);
1263  RASTER_DEBUGF(4, "LWGEOM wkt = %s", wkt);
1264  rtdealloc(wkt);
1265 
1266  lwvarlena_t *lwwkb = lwgeom_to_wkb_varlena(lwgeom, WKB_ISO | WKB_NDR);
1267  size_t lwwkbsize = LWSIZE_GET(lwwkb->size) - LWVARHDRSZ;
1268  if (lwwkbsize) {
1269  d_print_binary_hex("LWGEOM wkb", (const uint8_t *)lwwkb->data, lwwkbsize);
1270  rtdealloc(lwwkb);
1271  }
1272  }
1273 #endif
1274 
1275  /* set pixel value */
1276  pols[j].val = dValue;
1277  }
1278 
1279  *pnElements = nFeatureCount;
1280 
1281  RASTER_DEBUG(3, "destroying GDAL MEM raster");
1282  GDALClose(memdataset);
1283  if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1284 
1285  RASTER_DEBUG(3, "destroying OGR MEM vector");
1286  OGR_Fld_Destroy(hFldDfn);
1287  OGR_DS_DeleteLayer(memdatasource, 0);
1288  if (NULL != pszQuery) rtdealloc(pszQuery);
1289  OGRReleaseDataSource(memdatasource);
1290 
1291  return pols;
1292 }
1293 
#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:339
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition: lwpoint.c:163
#define WKB_ISO
Definition: liblwgeom.h:2175
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:1547
#define LWVARHDRSZ
Definition: liblwgeom.h:311
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2114
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition: lwgeom.c:380
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
Definition: liblwgeom.h:324
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:329
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition: lwgeom.c:529
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:260
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:344
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1097
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:2184
#define WKB_NDR
Definition: liblwgeom.h:2178
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:708
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:93
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:215
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
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:369
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:342
#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:668
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:975
LWPOLY * rt_raster_pixel_as_polygon(rt_raster rast, int x, int y)
Get a raster pixel as a polygon.
Definition: rt_geometry.c:607
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
Definition: rt_geometry.c:838
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:705
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:414
double y
Definition: liblwgeom.h:414
uint32_t size
Definition: liblwgeom.h:307
char data[]
Definition: liblwgeom.h:308
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:2507
LWPOLY * geom
Definition: librtcore.h:2506