[GRASS-SVN] r51582 - grass/trunk/vector/v.buffer
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue May 1 04:34:25 EDT 2012
Author: mmetz
Date: 2012-05-01 01:34:25 -0700 (Tue, 01 May 2012)
New Revision: 51582
Modified:
grass/trunk/vector/v.buffer/Makefile
grass/trunk/vector/v.buffer/geos.c
grass/trunk/vector/v.buffer/local_proto.h
grass/trunk/vector/v.buffer/main.c
grass/trunk/vector/v.buffer/v.buffer.html
Log:
v.buffer: add flag to transfer categories
Modified: grass/trunk/vector/v.buffer/Makefile
===================================================================
--- grass/trunk/vector/v.buffer/Makefile 2012-04-30 15:05:33 UTC (rev 51581)
+++ grass/trunk/vector/v.buffer/Makefile 2012-05-01 08:34:25 UTC (rev 51582)
@@ -2,7 +2,7 @@
PGM = v.buffer
-LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(MATHLIB) $(GEOSLIBS)
+LIBES = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(MATHLIB)
DEPENDENCIES = $(VECTORDEP) $(DBMIDEP) $(GISDEP)
EXTRA_INC = $(VECT_INC)
EXTRA_CFLAGS = $(VECT_CFLAGS)
Modified: grass/trunk/vector/v.buffer/geos.c
===================================================================
--- grass/trunk/vector/v.buffer/geos.c 2012-04-30 15:05:33 UTC (rev 51581)
+++ grass/trunk/vector/v.buffer/geos.c 2012-05-01 08:34:25 UTC (rev 51582)
@@ -42,7 +42,7 @@
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 line_cats *Cats,
struct buf_contours **arr_bc,
int *buffers_count, int *arr_bc_alloc)
{
@@ -50,12 +50,15 @@
const GEOSGeometry *geom2;
struct bound_box bbox;
static struct line_pnts *Points = NULL;
+ static struct line_cats *BCats = NULL;
struct buf_contours *p = *arr_bc;
G_debug(3, "geom2ring(): GEOS %s", GEOSGeomType(geom));
if (!Points)
Points = Vect_new_line_struct();
+ if (!BCats)
+ BCats = Vect_new_cats_struct();
if (GEOSGeomTypeId(geom) == GEOS_LINESTRING ||
GEOSGeomTypeId(geom) == GEOS_LINEARRING) {
@@ -104,7 +107,7 @@
G_fatal_error(_("Corrupt GEOS geometry"));
}
Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
- line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
+ line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, BCats);
p[*buffers_count].inner[i] = line_id;
}
}
@@ -124,7 +127,7 @@
ngeoms = GEOSGetNumGeometries(geom);
for (i = 0; i < ngeoms; i++) {
geom2 = GEOSGetGeometryN(geom, i);
- geom2ring((GEOSGeometry *)geom2, Out, Buf, si, Cats, BCats,
+ geom2ring((GEOSGeometry *)geom2, Out, Buf, si, Cats,
arr_bc, buffers_count, arr_bc_alloc);
}
}
@@ -138,7 +141,7 @@
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 line_cats *Cats,
struct buf_contours **arr_bc,
int *buffers_count, int *arr_bc_alloc)
{
@@ -157,7 +160,7 @@
if (!OGeom)
G_warning(_("Buffering failed"));
- geom2ring(OGeom, Out, Buf, si, Cats, BCats, arr_bc, buffers_count, arr_bc_alloc);
+ geom2ring(OGeom, Out, Buf, si, Cats, arr_bc, buffers_count, arr_bc_alloc);
if (IGeom)
GEOSGeom_destroy(IGeom);
Modified: grass/trunk/vector/v.buffer/local_proto.h
===================================================================
--- grass/trunk/vector/v.buffer/local_proto.h 2012-04-30 15:05:33 UTC (rev 51581)
+++ grass/trunk/vector/v.buffer/local_proto.h 2012-05-01 08:34:25 UTC (rev 51582)
@@ -18,7 +18,7 @@
struct Map_info *, int, int, double,
GEOSBufferParams *,
struct spatial_index *,
- struct line_cats *, struct line_cats *,
+ struct line_cats *,
struct buf_contours **,
int *, int *);
#endif
Modified: grass/trunk/vector/v.buffer/main.c
===================================================================
--- grass/trunk/vector/v.buffer/main.c 2012-04-30 15:05:33 UTC (rev 51581)
+++ grass/trunk/vector/v.buffer/main.c 2012-05-01 08:34:25 UTC (rev 51582)
@@ -78,11 +78,14 @@
struct bound_box bbox;
static struct ilist *List = NULL;
static struct line_pnts *Points = NULL;
+ static struct line_cats *BCats = NULL;
if (List == NULL)
List = Vect_new_list();
if (Points == NULL)
Points = Vect_new_line_struct();
+ if (BCats == NULL)
+ BCats = Vect_new_cats_struct();
/* select outer contours overlapping with centroid (x, y) */
bbox.W = bbox.E = x;
@@ -91,9 +94,9 @@
bbox.B = -PORT_DOUBLE_MAX;
Vect_spatial_index_select(si, &bbox, List);
-
+
for (i = 0; i < List->n_values; i++) {
- Vect_read_line(Buf, Points, NULL, arr_bc[List->value[i]].outer);
+ Vect_read_line(Buf, Points, BCats, arr_bc[List->value[i]].outer);
ret = Vect_point_in_poly(x, y, Points);
if (ret == 0)
continue;
@@ -120,57 +123,73 @@
return 0;
}
-int get_line_box(const struct line_pnts *Points, struct bound_box *Box)
+int buffer_cats(struct buf_contours *arr_bc, struct spatial_index *si,
+ struct Map_info *Buf, double x, double y, struct line_cats *Cats)
{
- int i;
+ int i, j, ret, flag, inside;
+ struct bound_box bbox;
+ static struct ilist *List = NULL;
+ static struct line_pnts *Points = NULL;
+ static struct line_cats *BCats = NULL;
- if (Points->n_points <= 0) {
- Box->N = 0;
- Box->S = 0;
- Box->E = 0;
- Box->W = 0;
- Box->T = 0;
- Box->B = 0;
- return 0;
- }
+ if (List == NULL)
+ List = Vect_new_list();
+ if (Points == NULL)
+ Points = Vect_new_line_struct();
+ if (BCats == NULL)
+ BCats = Vect_new_cats_struct();
- Box->E = Points->x[0];
- Box->W = Points->x[0];
- Box->N = Points->y[0];
- Box->S = Points->y[0];
- Box->T = Points->z[0];
- Box->B = Points->z[0];
+ /* select outer contours overlapping with centroid (x, y) */
+ bbox.W = bbox.E = x;
+ bbox.N = bbox.S = y;
+ bbox.T = PORT_DOUBLE_MAX;
+ bbox.B = -PORT_DOUBLE_MAX;
- for (i = 1; i < Points->n_points; i++) {
- if (Points->x[i] > Box->E)
- Box->E = Points->x[i];
- else if (Points->x[i] < Box->W)
- Box->W = Points->x[i];
+ Vect_spatial_index_select(si, &bbox, List);
+
+ Vect_reset_cats(Cats);
+
+ inside = 0;
+ for (i = 0; i < List->n_values; i++) {
+ Vect_read_line(Buf, Points, BCats, arr_bc[List->value[i]].outer);
+ ret = Vect_point_in_poly(x, y, Points);
+ if (ret == 0)
+ continue;
- if (Points->y[i] > Box->N)
- Box->N = Points->y[i];
- else if (Points->y[i] < Box->S)
- Box->S = Points->y[i];
+ flag = 1;
+ for (j = 0; j < arr_bc[List->value[i]].inner_count; j++) {
+ if (arr_bc[List->value[i]].inner[j] < 1)
+ continue;
- if (Points->z[i] > Box->T)
- Box->T = Points->z[i];
- else if (Points->z[i] < Box->B)
- Box->B = Points->z[i];
+ Vect_read_line(Buf, Points, NULL, arr_bc[List->value[i]].inner[j]);
+ ret = Vect_point_in_poly(x, y, Points);
+ if (ret != 0) { /* inside inner contour */
+ flag = 0;
+ break;
+ }
+ }
+
+ if (flag) {
+ /* (x,y) is inside outer contour and outside inner contours of arr_bc[i] */
+ inside = 1;
+ for (j = 0; j < BCats->n_cats; j++)
+ Vect_cat_set(Cats, BCats->field[j], BCats->cat[j]);
+ }
}
- return 1;
+ return inside;
}
int main(int argc, char *argv[])
{
struct Map_info In, Out, Buf;
struct line_pnts *Points;
- struct line_cats *Cats, *BCats;
+ struct line_cats *Cats, *BCats, *CCats;
char bufname[GNAME_MAX];
struct GModule *module;
struct Option *in_opt, *out_opt, *type_opt, *dista_opt, *distb_opt,
*angle_opt;
- struct Flag *straight_flag, *nocaps_flag;
+ struct Flag *straight_flag, *nocaps_flag, *cats_flag;
struct Option *tol_opt, *bufcol_opt, *scale_opt, *field_opt;
int verbose;
@@ -271,6 +290,10 @@
nocaps_flag->key = 'c';
nocaps_flag->description = _("Don't make caps at the ends of polylines");
+ cats_flag = G_define_flag();
+ cats_flag->key = 't';
+ cats_flag->description = _("Transfer categories and attributes");
+
G_gisinit(argv[0]);
if (G_parser(argc, argv))
@@ -283,12 +306,6 @@
G_fatal_error(_("Select a buffer distance/minordistance/angle "
"or column, but not both."));
- if (bufcol_opt->answer)
- G_warning(_("The bufcol option may contain bugs during the cleaning "
- "step. If you encounter problems, use the debug "
- "option or clean manually with v.clean tool=break; "
- "v.category step=0; v.extract -d type=area"));
-
Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT);
Vect_set_open_level(2); /* topology required */
@@ -337,6 +354,7 @@
Points = Vect_new_line_struct();
Cats = Vect_new_cats_struct();
BCats = Vect_new_cats_struct();
+ CCats = Vect_new_cats_struct();
/* open tmp vector for buffers, needed for cleaning */
sprintf(bufname, "%s_tmp_%d", out_opt->answer, getpid());
@@ -422,6 +440,13 @@
buffer_params = GEOSBufferParams_create();
GEOSBufferParams_setEndCapStyle(buffer_params, GEOSBUF_CAP_ROUND);
GEOSBufferParams_setJoinStyle(buffer_params, GEOSBUF_JOIN_ROUND);
+#else
+ if (da < 0. || db < 0.) {
+ G_warning(_("Negative distances for internal buffers are not supported "
+ "and converted to positive values."));
+ da = fabs(da);
+ db = fabs(db);
+ }
#endif
/* Lines (and Points) */
@@ -453,6 +478,13 @@
if (field > 0 && !Vect_cat_get(Cats, field, &cat))
continue;
+ Vect_reset_cats(CCats);
+ for (i = 0; i < Cats->n_cats; i++) {
+ if (field < 0 || Cats->field[i] == field) {
+ Vect_cat_set(CCats, Cats->field[i], Cats->cat[i]);
+ }
+ }
+
if (bufcol_opt->answer) {
ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val);
if (ret != DB_OK) {
@@ -491,7 +523,7 @@
&(arr_bc_pts.oPoints));
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats);
- line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats);
+ line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, CCats);
Vect_destroy_line_struct(arr_bc_pts.oPoints);
/* add buffer to spatial index */
Vect_get_line_box(&Buf, line_id, &bbox);
@@ -507,7 +539,7 @@
#ifdef HAVE_GEOS
GEOSBufferParams_setMitreLimit(buffer_params, unit_tolerance);
geos_buffer(&In, &Out, &Buf, line, type, da, buffer_params,
- &si, Cats, BCats, &arr_bc, &buffers_count, &arr_bc_alloc);
+ &si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc);
#else
Vect_line_buffer2(Points, da, db, dalpha,
!(straight_flag->answer),
@@ -517,7 +549,7 @@
&(arr_bc_pts.inner_count));
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats);
- line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats);
+ line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, CCats);
Vect_destroy_line_struct(arr_bc_pts.oPoints);
/* add buffer to spatial index */
Vect_get_line_box(&Buf, line_id, &bbox);
@@ -529,7 +561,7 @@
arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int));
for (i = 0; i < arr_bc_pts.inner_count; i++) {
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);
+ line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats);
Vect_destroy_line_struct(arr_bc_pts.iPoints[i]);
arr_bc[buffers_count].inner[i] = line_id;
}
@@ -562,6 +594,13 @@
if (field > 0 && !Vect_cat_get(Cats, field, &cat))
continue;
+ Vect_reset_cats(CCats);
+ for (i = 0; i < Cats->n_cats; i++) {
+ if (field < 0 || Cats->field[i] == field) {
+ Vect_cat_set(CCats, Cats->field[i], Cats->cat[i]);
+ }
+ }
+
if (bufcol_opt->answer) {
ret = db_CatValArray_get_value_di(&cvarr, cat, &size_val);
if (ret != DB_OK) {
@@ -591,10 +630,16 @@
#ifdef HAVE_GEOS
GEOSBufferParams_setSingleSided(buffer_params, 1);
- GEOSBufferParams_setMitreLimit(buffer_params, unit_tolerance);
+ GEOSBufferParams_setMitreLimit(buffer_params, fabs(unit_tolerance));
geos_buffer(&In, &Out, &Buf, area, GV_AREA, da, buffer_params,
- &si, Cats, BCats, &arr_bc, &buffers_count, &arr_bc_alloc);
+ &si, CCats, &arr_bc, &buffers_count, &arr_bc_alloc);
#else
+ if (da < 0. || db < 0.) {
+ G_warning(_("Negative distances for internal buffers are not supported "
+ "and converted to positive values."));
+ da = fabs(da);
+ db = fabs(db);
+ }
Vect_area_buffer2(&In, area, da, db, dalpha,
!(straight_flag->answer),
!(nocaps_flag->answer), unit_tolerance,
@@ -603,7 +648,7 @@
&(arr_bc_pts.inner_count));
Vect_write_line(&Out, GV_BOUNDARY, arr_bc_pts.oPoints, BCats);
- line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, Cats);
+ line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.oPoints, CCats);
Vect_destroy_line_struct(arr_bc_pts.oPoints);
/* add buffer to spatial index */
Vect_get_line_box(&Buf, line_id, &bbox);
@@ -615,7 +660,7 @@
arr_bc[buffers_count].inner = G_malloc(arr_bc_pts.inner_count * sizeof(int));
for (i = 0; i < arr_bc_pts.inner_count; i++) {
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);
+ line_id = Vect_write_line(&Buf, GV_BOUNDARY, arr_bc_pts.iPoints[i], BCats);
Vect_destroy_line_struct(arr_bc_pts.iPoints[i]);
arr_bc[buffers_count].inner[i] = line_id;
}
@@ -631,22 +676,6 @@
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..."));
@@ -655,6 +684,17 @@
G_message(_("Building parts of topology..."));
Vect_build_partial(&Out, GV_BUILD_BASE);
+ /* Warning: snapping must be done, otherwise colinear boundaries are not broken and
+ * topology cannot be built (the same angle). But snapping distance must be very, very
+ * small, otherwise counterclockwise boundaries can appear in areas outside the buffer.
+ * I have done some tests on real data (projected) and threshold 1e-8 was not enough,
+ * Snapping threshold 1e-7 seems to work. Don't increase until we find example
+ * where it is not sufficient. RB */
+
+ /* TODO: look at snapping threshold better, calculate some theoretical value to avoid
+ * the same angles of lines at nodes, don't forget about LongLat data, probably
+ * calculate different threshold for each map, depending on map's bounding box
+ * and/or distance and tolerance */
G_message(_("Snapping boundaries..."));
Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL);
@@ -689,97 +729,99 @@
G_message(_("Attaching islands..."));
Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES);
- /* Calculate new centroids for all areas */
- nareas = Vect_get_num_areas(&Out);
- Areas = (char *)G_calloc(nareas + 1, sizeof(char));
- G_message(_("Calculating centroids for areas..."));
- G_percent(0, nareas, 2);
- for (area = 1; area <= nareas; area++) {
- double x, y;
+ if (!cats_flag->answer) {
+ /* Calculate new centroids for all areas */
+ nareas = Vect_get_num_areas(&Out);
+ Areas = (char *)G_calloc(nareas + 1, sizeof(char));
+ G_message(_("Calculating centroids for all areas..."));
+ G_percent(0, nareas, 2);
+ for (area = 1; area <= nareas; area++) {
+ double x, y;
- G_percent(area, nareas, 2);
+ G_percent(area, nareas, 2);
- G_debug(3, "area = %d", area);
+ G_debug(3, "area = %d", area);
- if (!Vect_area_alive(&Out, area))
- continue;
+ if (!Vect_area_alive(&Out, area))
+ continue;
- ret = Vect_get_point_in_area(&Out, area, &x, &y);
- if (ret < 0) {
- G_warning(_("Cannot calculate area centroid"));
- continue;
- }
+ ret = Vect_get_point_in_area(&Out, area, &x, &y);
+ if (ret < 0) {
+ G_warning(_("Cannot calculate area centroid"));
+ continue;
+ }
- ret = point_in_buffer(arr_bc, &si, &Buf, x, y);
+ ret = point_in_buffer(arr_bc, &si, &Buf, x, y);
- if (ret) {
- G_debug(3, " -> in buffer");
- Areas[area] = 1;
+ if (ret) {
+ G_debug(3, " -> in buffer");
+ Areas[area] = 1;
+ }
}
- }
- /* Make a list of boundaries to be deleted (both sides inside) */
- nlines = Vect_get_num_lines(&Out);
- G_debug(3, "nlines = %d", nlines);
- Lines = (char *)G_calloc(nlines + 1, sizeof(char));
+ /* Make a list of boundaries to be deleted (both sides inside) */
+ nlines = Vect_get_num_lines(&Out);
+ G_debug(3, "nlines = %d", nlines);
+ Lines = (char *)G_calloc(nlines + 1, sizeof(char));
- G_message(_("Generating list of boundaries to be deleted..."));
- for (line = 1; line <= nlines; line++) {
- int j, side[2], areas[2];
+ G_message(_("Generating list of boundaries to be deleted..."));
+ for (line = 1; line <= nlines; line++) {
+ int j, side[2], areas[2];
- G_percent(line, nlines, 2);
+ G_percent(line, nlines, 2);
- G_debug(3, "line = %d", line);
+ G_debug(3, "line = %d", line);
- if (!Vect_line_alive(&Out, line))
- continue;
+ if (!Vect_line_alive(&Out, line))
+ continue;
- Vect_get_line_areas(&Out, line, &side[0], &side[1]);
+ Vect_get_line_areas(&Out, line, &side[0], &side[1]);
- for (j = 0; j < 2; j++) {
- if (side[j] == 0) { /* area/isle not build */
- areas[j] = 0;
+ for (j = 0; j < 2; j++) {
+ if (side[j] == 0) { /* area/isle not build */
+ areas[j] = 0;
+ }
+ else if (side[j] > 0) { /* area */
+ areas[j] = side[j];
+ }
+ else { /* < 0 -> island */
+ areas[j] = Vect_get_isle_area(&Out, abs(side[j]));
+ }
}
- else if (side[j] > 0) { /* area */
- areas[j] = side[j];
- }
- else { /* < 0 -> island */
- areas[j] = Vect_get_isle_area(&Out, abs(side[j]));
- }
+
+ G_debug(3, " areas = %d , %d -> Areas = %d, %d", areas[0], areas[1],
+ Areas[areas[0]], Areas[areas[1]]);
+ if (Areas[areas[0]] && Areas[areas[1]])
+ Lines[line] = 1;
}
+ G_free(Areas);
- G_debug(3, " areas = %d , %d -> Areas = %d, %d", areas[0], areas[1],
- Areas[areas[0]], Areas[areas[1]]);
- if (Areas[areas[0]] && Areas[areas[1]])
- Lines[line] = 1;
- }
- G_free(Areas);
+ /* Delete boundaries */
+ G_message(_("Deleting boundaries..."));
+ for (line = 1; line <= nlines; line++) {
+ G_percent(line, nlines, 2);
+
+ if (!Vect_line_alive(&Out, line))
+ continue;
- /* Delete boundaries */
- G_message(_("Deleting boundaries..."));
- for (line = 1; line <= nlines; line++) {
- G_percent(line, nlines, 2);
-
- if (!Vect_line_alive(&Out, line))
- continue;
+ if (Lines[line]) {
+ G_debug(3, " delete line %d", line);
+ Vect_delete_line(&Out, line);
+ }
+ else {
+ /* delete incorrect boundaries */
+ int side[2];
- if (Lines[line]) {
- G_debug(3, " delete line %d", line);
- Vect_delete_line(&Out, line);
+ Vect_get_line_areas(&Out, line, &side[0], &side[1]);
+
+ if (!side[0] && !side[1])
+ Vect_delete_line(&Out, line);
+ }
}
- else {
- /* delete incorrect boundaries */
- int side[2];
- Vect_get_line_areas(&Out, line, &side[0], &side[1]);
-
- if (!side[0] && !side[1])
- Vect_delete_line(&Out, line);
- }
+ G_free(Lines);
}
- G_free(Lines);
-
/* Create new centroids */
Vect_reset_cats(Cats);
Vect_cat_set(Cats, 1, 1);
@@ -802,7 +844,10 @@
continue;
}
- ret = point_in_buffer(arr_bc, &si, &Buf, x, y);
+ if (cats_flag->answer)
+ ret = buffer_cats(arr_bc, &si, &Buf, x, y, Cats);
+ else
+ ret = point_in_buffer(arr_bc, &si, &Buf, x, y);
if (ret) {
Vect_reset_line(Points);
@@ -811,21 +856,15 @@
}
}
- /* free arr_bc[] */
- /* will only slow down the module
- for (i = 0; i < buffers_count; i++) {
- Vect_destroy_line_struct(arr_bc[i].oPoints);
- for (j = 0; j < arr_bc[i].inner_count; j++)
- Vect_destroy_line_struct(arr_bc[i].iPoints[j]);
- G_free(arr_bc[i].iPoints);
- } */
-
Vect_spatial_index_destroy(&si);
Vect_close(&Buf);
Vect_delete(bufname);
G_set_verbose(verbose);
+ if (cats_flag->answer)
+ Vect_copy_tables(&In, &Out, field);
+
Vect_close(&In);
Vect_build_partial(&Out, GV_BUILD_NONE);
Modified: grass/trunk/vector/v.buffer/v.buffer.html
===================================================================
--- grass/trunk/vector/v.buffer/v.buffer.html 2012-04-30 15:05:33 UTC (rev 51581)
+++ grass/trunk/vector/v.buffer/v.buffer.html 2012-05-01 08:34:25 UTC (rev 51582)
@@ -1,44 +1,47 @@
<h2>DESCRIPTION</h2>
-<em>v.buffer</em> creates a buffer around features of given <b>type</b>, which
-have a category in the given <b>layer</b>. The <b>tolerance</b> controls
-the number of vector segments being generated (the smaller the value, the more
-vector segments are generated).
+<em>v.buffer</em> creates a buffer around features of given <b>type
+</b>, which have a category in the given <b>layer</b>. The <b>
+tolerance</b> controls the number of vector segments being generated
+(the smaller the value, the more vector segments are generated).
-
<h2>NOTES</h2>
-Attributes are not transferred due to potential buffer overlap, which
-cannot be resolved automatically.
+Internal buffers for areas can be generated with negative distiance
+values (GRASS must be compiled with GEOS).
+<p>
+Categories and attributes can be transferred with the <em>t</em> flag.
+The resulting buffer areas can have multiple categories, and multiple
+buffer areas can have the same category. The buffer for the input
+feature with category X can thus be retrieved by selecting all buffer
+areas with category X (see example below).
<h2>EXAMPLES</h2>
+All examples are based on the North Carolina sample dataset.
+
<h3>Buffer around input lines</h3>
<div class="code"><pre>
-v.buffer input=map output=buffer type=line distance=100
+v.buffer input=roadsmajor output=roadsmajor_buffer type=line distance=100
</pre></div>
<h3>Circles around input points</h3>
<div class="code"><pre>
-v.buffer input=pointsmap output=circles type=point distance=1000
+v.buffer input=hospitals output=hospitals_circled type=point distance=1000
</pre></div>
-<h3>Non-overlapping circles around input points with attribute transfer</h3>
+<h3>Circles around input points with attribute transfer</h3>
<div class="code"><pre>
-v.buffer input=archsites output=circles type=point distance=200
-# change original points to centroids:
-v.type in=archsites out=archcentroids type=point,centroid
-# patch circles and centroids:
-v.patch in=archcentroids,circles out=circles_db
-# attach attributes, either use
-# db.copy ...
-# or link to the original table:
-v.db.connect map=circles_db table=archsites field=1 key=cat driver=dbf \
-database='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf'
+v.buffer input=hospitals output=hospitals_circled type=point distance=1000 -t
+# display buffer around hospital with category 36,
+# this buffer is composed of several areas:
+d.vect map=hospitals_circled type=area layer=1 cats=36
+# extract this buffer, dissolving boundaries
+v.extract in=hospitals_circled out=hospital_36_circled layer=1 cats=36 -d
</pre></div>
@@ -57,5 +60,6 @@
Radim Blazek<br>
Rewritten by Rosen Matev (with support through the
- Google Summer of Code program 2008)
+ Google Summer of Code program 2008)<br>
+Rewritten by Markus Metz (2011, 2012)
<p><i>Last changed: $Date$</i>
More information about the grass-commit
mailing list