[GRASS-SVN] r51579 - grass/trunk/vector/v.buffer
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Apr 30 10:46:43 EDT 2012
Author: mmetz
Date: 2012-04-30 07:46:43 -0700 (Mon, 30 Apr 2012)
New Revision: 51579
Modified:
grass/trunk/vector/v.buffer/geos.c
grass/trunk/vector/v.buffer/main.c
Log:
v.buffer: full support for negative distances
Modified: grass/trunk/vector/v.buffer/geos.c
===================================================================
--- grass/trunk/vector/v.buffer/geos.c 2012-04-30 11:08:37 UTC (rev 51578)
+++ grass/trunk/vector/v.buffer/geos.c 2012-04-30 14:46:43 UTC (rev 51579)
@@ -1,6 +1,8 @@
+#include <float.h>
#include <grass/gis.h>
#include <grass/vector.h>
#include <grass/glocale.h>
+#include "local_proto.h"
#ifdef HAVE_GEOS
@@ -12,80 +14,118 @@
G_debug(3, "ring2pts()");
+ Vect_reset_line(Points);
+ if (!geom) {
+ G_warning(_("Invalid GEOS geometry!"));
+ return 0;
+ }
z = 0.0;
ncoords = GEOSGetNumCoordinates(geom);
- if (!ncoords)
- G_warning(_("No coordinates in GEOS geometry!"));
+ if (!ncoords) {
+ G_warning(_("No coordinates in GEOS geometry (can be ok for negative distance)!"));
+ return 0;
+ }
seq = GEOSGeom_getCoordSeq(geom);
for (i = 0; i < ncoords; i++) {
GEOSCoordSeq_getX(seq, i, &x);
GEOSCoordSeq_getY(seq, i, &y);
+ if (x != x || x > DBL_MAX || x < -DBL_MAX)
+ G_fatal_error(_("Invalid x coordinate %f"), x);
+ if (y != y || y > DBL_MAX || y < -DBL_MAX)
+ G_fatal_error(_("Invalid y coordinate %f"), y);
Vect_append_point(Points, x, y, z);
}
return 1;
}
-static int geom2ring(GEOSGeometry *geom, struct line_pnts **oPoints,
- struct line_pnts ***iPoints, int *inner_count)
+static int geom2ring(GEOSGeometry *geom, struct Map_info *Out,
+ struct Map_info *Buf,
+ struct spatial_index *si,
+ struct line_cats *Cats, struct line_cats *BCats,
+ struct buf_contours **arr_bc,
+ int *buffers_count, int *arr_bc_alloc)
{
- int i, nrings, ngeoms, count;
+ int i, nrings, ngeoms, line_id;
const GEOSGeometry *geom2;
- struct line_pnts *Points, **arrPoints = *iPoints;
+ struct bound_box bbox;
+ static struct line_pnts *Points = NULL;
+ struct buf_contours *p = *arr_bc;
+ G_debug(3, "geom2ring(): GEOS %s", GEOSGeomType(geom));
+
+ if (!Points)
+ Points = Vect_new_line_struct();
+
if (GEOSGeomTypeId(geom) == GEOS_LINESTRING ||
GEOSGeomTypeId(geom) == GEOS_LINEARRING) {
- Points = *oPoints;
- if (Points->n_points == 0)
- ring2pts(geom, Points);
- else {
- count = *inner_count + 1;
- arrPoints = G_realloc(arrPoints, count * sizeof(struct line_pnts *));
- arrPoints[*inner_count] = Vect_new_line_struct();
- ring2pts(geom, arrPoints[*inner_count]);
- *inner_count = count;
- *iPoints = arrPoints;
+ if (!ring2pts(geom, Points))
+ return 0;
+
+ Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
+ line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
+ /* add buffer to spatial index */
+ Vect_get_line_box(Buf, line_id, &bbox);
+ Vect_spatial_index_add_item(si, *buffers_count, &bbox);
+ p[*buffers_count].outer = line_id;
+
+ p[*buffers_count].inner_count = 0;
+ *buffers_count += 1;
+ if (*buffers_count >= *arr_bc_alloc) {
+ *arr_bc_alloc += 100;
+ p = G_realloc(p, *arr_bc_alloc * sizeof(struct buf_contours));
+ *arr_bc = p;
}
}
else if (GEOSGeomTypeId(geom) == GEOS_POLYGON) {
geom2 = GEOSGetExteriorRing(geom);
- Points = *oPoints;
- if (Points->n_points == 0)
- ring2pts(geom2, Points);
- else {
- count = *inner_count + 1;
- arrPoints = G_realloc(arrPoints, count * sizeof(struct line_pnts *));
- arrPoints[*inner_count] = Vect_new_line_struct();
- ring2pts(geom2, arrPoints[*inner_count]);
- *inner_count = count;
- *iPoints = arrPoints;
- }
+ if (!ring2pts(geom2, Points))
+ return 0;
+ Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
+ line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
+ /* add buffer to spatial index */
+ Vect_get_line_box(Buf, line_id, &bbox);
+ Vect_spatial_index_add_item(si, *buffers_count, &bbox);
+ p[*buffers_count].outer = line_id;
+ p[*buffers_count].inner_count = 0;
+
nrings = GEOSGetNumInteriorRings(geom);
if (nrings > 0) {
- count = *inner_count + nrings;
- arrPoints = G_realloc(arrPoints, count * sizeof(struct line_pnts *));
+ p[*buffers_count].inner_count = nrings;
+ p[*buffers_count].inner = G_malloc(nrings * sizeof(int));
for (i = 0; i < nrings; i++) {
geom2 = GEOSGetInteriorRingN(geom, i);
- arrPoints[*inner_count + i] = Vect_new_line_struct();
- ring2pts(geom2, arrPoints[*inner_count + i]);
+ if (!ring2pts(geom2, Points)) {
+ G_fatal_error(_("Corrupt GEOS geometry"));
+ }
+ Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
+ line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
+ p[*buffers_count].inner[i] = line_id;
}
- *inner_count = count;
- *iPoints = arrPoints;
}
+ *buffers_count += 1;
+ if (*buffers_count >= *arr_bc_alloc) {
+ *arr_bc_alloc += 100;
+ p = G_realloc(p, *arr_bc_alloc * sizeof(struct buf_contours));
+ *arr_bc = p;
+ }
}
else if (GEOSGeomTypeId(geom) == GEOS_MULTILINESTRING ||
GEOSGeomTypeId(geom) == GEOS_MULTIPOLYGON ||
GEOSGeomTypeId(geom) == GEOS_GEOMETRYCOLLECTION) {
+ G_debug(3, "GEOS %s", GEOSGeomType(geom));
+
ngeoms = GEOSGetNumGeometries(geom);
for (i = 0; i < ngeoms; i++) {
geom2 = GEOSGetGeometryN(geom, i);
- geom2ring((GEOSGeometry *)geom2, oPoints, iPoints, inner_count);
+ geom2ring((GEOSGeometry *)geom2, Out, Buf, si, Cats, BCats,
+ arr_bc, buffers_count, arr_bc_alloc);
}
}
else
@@ -94,16 +134,18 @@
return 1;
}
-int geos_buffer(struct Map_info *In, int id, int type, double da,
- GEOSBufferParams *buffer_params, struct line_pnts **oPoints,
- struct line_pnts ***iPoints, int *inner_count)
+int geos_buffer(struct Map_info *In, struct Map_info *Out,
+ struct Map_info *Buf, int id, int type, double da,
+ GEOSBufferParams *buffer_params,
+ struct spatial_index *si,
+ struct line_cats *Cats, struct line_cats *BCats,
+ struct buf_contours **arr_bc,
+ int *buffers_count, int *arr_bc_alloc)
{
GEOSGeometry *IGeom = NULL;
GEOSGeometry *OGeom = NULL;
- *oPoints = Vect_new_line_struct();
- *iPoints = NULL;
- *inner_count = 0;
+ G_debug(3, "geos_buffer()");
if (type == GV_AREA)
IGeom = Vect_read_area_geos(In, id);
@@ -115,7 +157,7 @@
if (!OGeom)
G_warning(_("Buffering failed"));
- geom2ring(OGeom, oPoints, iPoints, inner_count);
+ geom2ring(OGeom, Out, Buf, si, Cats, BCats, arr_bc, buffers_count, arr_bc_alloc);
if (IGeom)
GEOSGeom_destroy(IGeom);
Modified: grass/trunk/vector/v.buffer/main.c
===================================================================
--- grass/trunk/vector/v.buffer/main.c 2012-04-30 11:08:37 UTC (rev 51578)
+++ grass/trunk/vector/v.buffer/main.c 2012-04-30 14:46:43 UTC (rev 51579)
@@ -26,6 +26,7 @@
#include <grass/vector.h>
#include <grass/dbmi.h>
#include <grass/glocale.h>
+#include "local_proto.h"
#define PI M_PI
#ifndef MIN
@@ -35,12 +36,6 @@
#define MAX(X,Y) ((X>Y)?X:Y)
#endif
-#ifdef HAVE_GEOS
-int geos_buffer(struct Map_info *, int, int, double,
- GEOSBufferParams *, struct line_pnts **,
- struct line_pnts ***, int *);
-#endif
-
/* returns 1 if unit_tolerance is adjusted, 0 otherwise */
int adjust_tolerance(double *tolerance)
{
@@ -76,20 +71,6 @@
return DB_FAILED;
}
-struct buf_contours
-{
- int inner_count;
- int outer;
- int *inner;
-};
-
-struct buf_contours_pts
-{
- int inner_count;
- struct line_pnts *oPoints;
- struct line_pnts **iPoints;
-};
-
int point_in_buffer(struct buf_contours *arr_bc, struct spatial_index *si,
struct Map_info *Buf, double x, double y)
{
@@ -199,8 +180,9 @@
char *Areas, *Lines;
int field;
struct buf_contours *arr_bc;
+ int arr_bc_alloc;
struct buf_contours_pts arr_bc_pts;
- int buffers_count = 0, line_id;
+ int line_id, buffers_count = 0;
struct spatial_index si;
struct bound_box bbox;
@@ -215,7 +197,6 @@
GEOSBufferParams *buffer_params = NULL;
#endif
-
module = G_define_module();
G_add_keyword(_("vector"));
G_add_keyword(_("geometry"));
@@ -429,8 +410,10 @@
exit(EXIT_SUCCESS);
}
+ /* init arr_bc */
buffers_count = 1;
- arr_bc = G_malloc((nlines + nareas + 1) * sizeof(struct buf_contours));
+ arr_bc_alloc = nlines + nareas + 1;
+ arr_bc = G_calloc(arr_bc_alloc, sizeof(struct buf_contours));
Vect_spatial_index_init(&si, 0);
@@ -523,8 +506,8 @@
#ifdef HAVE_GEOS
GEOSBufferParams_setMitreLimit(buffer_params, unit_tolerance);
- geos_buffer(&In, line, type, da, buffer_params, &(arr_bc_pts.oPoints),
- &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count));
+ geos_buffer(&In, &Out, &Buf, line, type, da, buffer_params,
+ &si, Cats, BCats, &arr_bc, &buffers_count, &arr_bc_alloc);
#else
Vect_line_buffer2(Points, da, db, dalpha,
!(straight_flag->answer),
@@ -532,7 +515,6 @@
&(arr_bc_pts.oPoints),
&(arr_bc_pts.iPoints),
&(arr_bc_pts.inner_count));
-#endif
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats);
line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats);
@@ -549,14 +531,12 @@
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats);
line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats);
Vect_destroy_line_struct(arr_bc_pts.iPoints[i]);
- /* add buffer to spatial index */
- Vect_get_line_box(&Buf, line_id, &bbox);
- Vect_spatial_index_add_item(&si, buffers_count, &bbox);
arr_bc[buffers_count].inner[i] = line_id;
}
G_free(arr_bc_pts.iPoints);
}
buffers_count++;
+#endif
}
}
}
@@ -612,8 +592,8 @@
#ifdef HAVE_GEOS
GEOSBufferParams_setSingleSided(buffer_params, 1);
GEOSBufferParams_setMitreLimit(buffer_params, unit_tolerance);
- geos_buffer(&In, area, GV_AREA, da, buffer_params, &(arr_bc_pts.oPoints),
- &(arr_bc_pts.iPoints), &(arr_bc_pts.inner_count));
+ geos_buffer(&In, &Out, &Buf, area, GV_AREA, da, buffer_params,
+ &si, Cats, BCats, &arr_bc, &buffers_count, &arr_bc_alloc);
#else
Vect_area_buffer2(&In, area, da, db, dalpha,
!(straight_flag->answer),
@@ -621,7 +601,6 @@
&(arr_bc_pts.oPoints),
&(arr_bc_pts.iPoints),
&(arr_bc_pts.inner_count));
-#endif
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats);
line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats);
@@ -638,14 +617,12 @@
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats);
line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], Cats);
Vect_destroy_line_struct(arr_bc_pts.iPoints[i]);
- /* add buffer to spatial index */
- Vect_get_line_box(&Buf, line_id, &bbox);
- Vect_spatial_index_add_item(&si, buffers_count, &bbox);
arr_bc[buffers_count].inner[i] = line_id;
}
G_free(arr_bc_pts.iPoints);
}
buffers_count++;
+#endif
}
}
@@ -654,6 +631,22 @@
finishGEOS();
#endif
+#if 0
+ Vect_spatial_index_destroy(&si);
+ Vect_close(&Buf);
+ Vect_delete(bufname);
+
+ G_set_verbose(verbose);
+
+ Vect_close(&In);
+
+ Vect_build_partial(&Out, GV_BUILD_NONE);
+ Vect_build(&Out);
+ Vect_close(&Out);
+
+ exit(EXIT_SUCCESS);
+#endif
+
verbose = G_verbose();
G_message(_("Cleaning buffers..."));
More information about the grass-commit
mailing list