[GRASS-SVN] r51563 - grass/trunk/vector/v.buffer
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Apr 28 13:19:37 EDT 2012
Author: mmetz
Date: 2012-04-28 10:19:36 -0700 (Sat, 28 Apr 2012)
New Revision: 51563
Added:
grass/trunk/vector/v.buffer/geos.c
Modified:
grass/trunk/vector/v.buffer/main.c
Log:
v.buffer: use GEOS
Added: grass/trunk/vector/v.buffer/geos.c
===================================================================
--- grass/trunk/vector/v.buffer/geos.c (rev 0)
+++ grass/trunk/vector/v.buffer/geos.c 2012-04-28 17:19:36 UTC (rev 51563)
@@ -0,0 +1,128 @@
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+#ifdef HAVE_GEOS
+
+static int ring2pts(const GEOSGeometry *geom, struct line_pnts *Points)
+{
+ int i, ncoords;
+ double x, y, z;
+ const GEOSCoordSequence *seq = NULL;
+
+ G_debug(3, "ring2pts()");
+
+ z = 0.0;
+ ncoords = GEOSGetNumCoordinates(geom);
+ if (!ncoords)
+ G_warning(_("No coordinates in GEOS geometry!"));
+ seq = GEOSGeom_getCoordSeq(geom);
+ for (i = 0; i < ncoords; i++) {
+ GEOSCoordSeq_getX(seq, i, &x);
+ GEOSCoordSeq_getY(seq, i, &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)
+{
+ int i, nrings, ngeoms, count;
+ const GEOSGeometry *geom2;
+ struct line_pnts *Points, **arrPoints = *iPoints;
+
+ 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;
+ }
+ }
+ 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;
+ }
+
+ nrings = GEOSGetNumInteriorRings(geom);
+
+ if (nrings > 0) {
+
+ count = *inner_count + nrings;
+ arrPoints = G_realloc(arrPoints, count * sizeof(struct line_pnts *));
+
+ for (i = 0; i < nrings; i++) {
+ geom2 = GEOSGetInteriorRingN(geom, i);
+ arrPoints[*inner_count + i] = Vect_new_line_struct();
+ ring2pts(geom2, arrPoints[*inner_count + i]);
+ }
+ *inner_count = count;
+ *iPoints = arrPoints;
+ }
+ }
+ else if (GEOSGeomTypeId(geom) == GEOS_MULTILINESTRING ||
+ GEOSGeomTypeId(geom) == GEOS_MULTIPOLYGON ||
+ GEOSGeomTypeId(geom) == GEOS_GEOMETRYCOLLECTION) {
+
+ ngeoms = GEOSGetNumGeometries(geom);
+ for (i = 0; i < ngeoms; i++) {
+ geom2 = GEOSGetGeometryN(geom, i);
+ geom2ring((GEOSGeometry *)geom2, oPoints, iPoints, inner_count);
+ }
+ }
+ else
+ G_fatal_error(_("Unknown GEOS geometry type"));
+
+ 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)
+{
+ GEOSGeometry *IGeom = NULL;
+ GEOSGeometry *OGeom = NULL;
+
+ *oPoints = Vect_new_line_struct();
+ *iPoints = NULL;
+ *inner_count = 0;
+
+ if (type == GV_AREA)
+ IGeom = Vect_read_area_geos(In, id);
+ else
+ IGeom = Vect_read_line_geos(In, id, &type);
+
+ OGeom = GEOSBufferWithParams(IGeom, buffer_params, da);
+
+ if (!OGeom)
+ G_warning(_("Buffering failed"));
+
+ geom2ring(OGeom, oPoints, iPoints, inner_count);
+
+ if (IGeom)
+ GEOSGeom_destroy(IGeom);
+ if (OGeom)
+ GEOSGeom_destroy(OGeom);
+
+ return 1;
+}
+
+#endif /* HAVE_GEOS */
Property changes on: grass/trunk/vector/v.buffer/geos.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Modified: grass/trunk/vector/v.buffer/main.c
===================================================================
--- grass/trunk/vector/v.buffer/main.c 2012-04-27 15:24:25 UTC (rev 51562)
+++ grass/trunk/vector/v.buffer/main.c 2012-04-28 17:19:36 UTC (rev 51563)
@@ -34,6 +34,11 @@
#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)
@@ -200,12 +205,16 @@
/* Attributes if sizecol is used */
int nrec, ctype;
- struct field_info *Fi;
+ struct field_info *Fi = NULL;
dbDriver *Driver;
dbCatValArray cvarr;
double size_val, scale;
+#ifdef HAVE_GEOS
+ GEOSBufferParams *buffer_params = NULL;
+#endif
+
module = G_define_module();
G_add_keyword(_("vector"));
G_add_keyword(_("geometry"));
@@ -323,7 +332,7 @@
if (scale <= 0.0)
G_fatal_error("Illegal scale value");
- da = db = dalpha = 0;
+ da = db = dalpha = unit_tolerance = 0;
if (dista_opt->answer) {
da = atof(dista_opt->answer);
@@ -409,7 +418,7 @@
/* Create buffers' boundaries */
nlines = nareas = 0;
if ((type & GV_POINTS) || (type & GV_LINES))
- nlines += Vect_get_num_primitives(&In, type);
+ nlines = Vect_get_num_primitives(&In, type);
if (type & GV_AREA)
nareas = Vect_get_num_areas(&In);
@@ -424,12 +433,20 @@
Vect_spatial_index_init(&si, 0);
+#ifdef HAVE_GEOS
+ initGEOS(G_message, G_fatal_error);
+ buffer_params = GEOSBufferParams_create();
+ GEOSBufferParams_setEndCapStyle(buffer_params, GEOSBUF_CAP_ROUND);
+ GEOSBufferParams_setJoinStyle(buffer_params, GEOSBUF_JOIN_ROUND);
+#endif
+
/* Lines (and Points) */
- if ((type & GV_POINTS) || (type & GV_LINES)) {
+ if (nlines > 0) {
int ltype;
- if (nlines > 0)
- G_message(_("Buffering lines..."));
+ G_message(_("Buffering lines..."));
+
+ nlines = Vect_get_num_lines(&In);
for (line = 1; line <= nlines; line++) {
int cat;
@@ -492,12 +509,19 @@
}
else {
+
+#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));
+#else
Vect_line_buffer2(Points, da, db, dalpha,
!(straight_flag->answer),
!(nocaps_flag->answer), unit_tolerance,
&(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);
@@ -527,11 +551,10 @@
}
/* Areas */
- if (type & GV_AREA) {
+ if (nareas > 0) {
int centroid;
- if (nareas > 0)
- G_message(_("Buffering areas..."));
+ G_message(_("Buffering areas..."));
for (area = 1; area <= nareas; area++) {
int cat;
@@ -575,12 +598,19 @@
unit_tolerance);
}
+#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));
+#else
Vect_area_buffer2(&In, area, da, db, dalpha,
!(straight_flag->answer),
!(nocaps_flag->answer), unit_tolerance,
&(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);
@@ -608,6 +638,11 @@
}
}
+#ifdef HAVE_GEOS
+ GEOSBufferParams_destroy(buffer_params);
+ finishGEOS();
+#endif
+
verbose = G_verbose();
G_message(_("Cleaning buffers..."));
More information about the grass-commit
mailing list