[GRASS-SVN] r45873 - grass/trunk/vector/v.buffer
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Apr 8 04:33:38 EDT 2011
Author: mmetz
Date: 2011-04-08 01:33:37 -0700 (Fri, 08 Apr 2011)
New Revision: 45873
Modified:
grass/trunk/vector/v.buffer/main.c
Log:
v.buffer update (backport from devbr)
Modified: grass/trunk/vector/v.buffer/main.c
===================================================================
--- grass/trunk/vector/v.buffer/main.c 2011-04-08 07:25:46 UTC (rev 45872)
+++ grass/trunk/vector/v.buffer/main.c 2011-04-08 08:33:37 UTC (rev 45873)
@@ -76,19 +76,32 @@
struct line_pnts **iPoints;
};
-int point_in_buffer(struct buf_contours *arr_bc, int buffers_count,
+int point_in_buffer(struct buf_contours *arr_bc, struct spatial_index *si,
double x, double y)
{
int i, j, ret, flag;
+ struct bound_box bbox;
+ static struct ilist *List = NULL;
- for (i = 0; i < buffers_count; i++) {
- ret = Vect_point_in_poly(x, y, arr_bc[i].oPoints);
+ if (List == NULL)
+ List = Vect_new_list();
+
+ /* 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;
+
+ Vect_spatial_index_select(si, &bbox, List);
+
+ for (i = 0; i < List->n_values; i++) {
+ ret = Vect_point_in_poly(x, y, arr_bc[List->value[i]].oPoints);
if (ret == 0)
continue;
flag = 1;
- for (j = 0; j < arr_bc[i].inner_count; j++) {
- ret = Vect_point_in_poly(x, y, arr_bc[i].iPoints[j]);
+ for (j = 0; j < arr_bc[List->value[i]].inner_count; j++) {
+ ret = Vect_point_in_poly(x, y, arr_bc[List->value[i]].iPoints[j]);
if (ret != 0) { /* inside inner contour */
flag = 0;
break;
@@ -104,6 +117,47 @@
return 0;
}
+int get_line_box(const struct line_pnts *Points, struct bound_box *Box)
+{
+ int i;
+
+ 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;
+ }
+
+ 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];
+
+ 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];
+
+ if (Points->y[i] > Box->N)
+ Box->N = Points->y[i];
+ else if (Points->y[i] < Box->S)
+ Box->S = Points->y[i];
+
+ if (Points->z[i] > Box->T)
+ Box->T = Points->z[i];
+ else if (Points->z[i] < Box->B)
+ Box->B = Points->z[i];
+ }
+
+ return 1;
+}
+
int main(int argc, char *argv[])
{
struct Map_info In, Out;
@@ -123,6 +177,8 @@
int field;
struct buf_contours *arr_bc;
int buffers_count;
+ struct spatial_index si;
+ struct bound_box bbox;
/* Attributes if sizecol is used */
int nrec, ctype;
@@ -328,18 +384,29 @@
/* Create buffers' boundaries */
- nlines = Vect_get_num_lines(&In);
- nareas = Vect_get_num_areas(&In);
- /* TODO: don't allocate so much space */
- buffers_count = 0;
- arr_bc = G_malloc((nlines + nareas) * sizeof(struct buf_contours));
+ nlines = nareas = 0;
+ if ((type & GV_POINTS) || (type & GV_LINES))
+ nlines += Vect_get_num_primitives(&In, type);
+ if (type & GV_AREA)
+ nareas = Vect_get_num_areas(&In);
+
+ if (nlines + nareas == 0) {
+ G_warning(_("No features available for buffering. "
+ "Check type option and features available in the input vector."));
+ exit(EXIT_SUCCESS);
+ }
+ buffers_count = 1;
+ arr_bc = G_malloc((nlines + nareas + 1) * sizeof(struct buf_contours));
+
+ Vect_spatial_index_init(&si, 0);
+
/* Lines (and Points) */
if ((type & GV_POINTS) || (type & GV_LINES)) {
int ltype;
if (nlines > 0)
- G_message(_("Buffering features..."));
+ G_message(_("Buffering lines..."));
for (line = 1; line <= nlines; line++) {
int cat;
@@ -382,7 +449,8 @@
G_debug(2, _("The tolerance in map units: %g"),
unit_tolerance);
}
-
+
+ Vect_line_prune(Points);
if (ltype & GV_POINTS || Points->n_points == 1) {
Vect_point_buffer2(Points->x[0], Points->y[0], da, db, dalpha,
!(straight_flag->answer), unit_tolerance,
@@ -465,9 +533,13 @@
/* write all buffer contours */
G_message(_("Writting buffers..."));
- for (i = 0; i < buffers_count; i++) {
+ for (i = 1; i < buffers_count; i++) {
G_percent(i, buffers_count, 2);
Vect_write_line(&Out, GV_BOUNDARY, arr_bc[i].oPoints, BCats);
+
+ get_line_box(arr_bc[i].oPoints, &bbox);
+ Vect_spatial_index_add_item(&si, i, &bbox);
+
for (j = 0; j < arr_bc[i].inner_count; j++)
Vect_write_line(&Out, GV_BOUNDARY, arr_bc[i].iPoints[j], BCats);
}
@@ -490,20 +562,27 @@
G_message(_("Removing duplicates..."));
Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL);
- G_message(_("Breaking boundaries..."));
- Vect_break_lines(&Out, GV_BOUNDARY, NULL);
+ do {
+ G_message(_("Breaking boundaries..."));
+ Vect_break_lines(&Out, GV_BOUNDARY, NULL);
- G_message(_("Removing duplicates..."));
- Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL);
+ G_message(_("Removing duplicates..."));
+ Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL);
+ G_message(_("Cleaning boundaries at nodes"));
+
+ } while (Vect_clean_small_angles_at_nodes(&Out, GV_BOUNDARY, NULL) > 0);
+
/* Dangles and bridges don't seem to be necessary if snapping is small enough. */
+ /* Still needed for larger buffer distances ? */
+
/*
- G_message ( "Removing dangles..." );
- Vect_remove_dangles ( &Out, GV_BOUNDARY, -1, NULL, stderr );
+ G_message(_("Removing dangles..."));
+ Vect_remove_dangles(&Out, GV_BOUNDARY, -1, NULL);
- G_message ( "Removing bridges..." );
- Vect_remove_bridges ( &Out, NULL, stderr );
- */
+ G_message (_("Removing bridges..."));
+ Vect_remove_bridges(&Out, NULL);
+ */
G_message(_("Attaching islands..."));
Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES);
@@ -529,7 +608,7 @@
continue;
}
- ret = point_in_buffer(arr_bc, buffers_count, x, y);
+ ret = point_in_buffer(arr_bc, &si, x, y);
if (ret) {
G_debug(3, " -> in buffer");
@@ -578,10 +657,23 @@
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];
+
+ Vect_get_line_areas(&Out, line, &side[0], &side[1]);
+
+ if (!side[0] && !side[1])
+ Vect_delete_line(&Out, line);
+ }
}
G_free(Lines);
@@ -608,7 +700,7 @@
continue;
}
- ret = point_in_buffer(arr_bc, buffers_count, x, y);
+ ret = point_in_buffer(arr_bc, &si, x, y);
if (ret) {
Vect_reset_line(Points);
@@ -626,6 +718,7 @@
G_free(arr_bc[i].iPoints);
} */
+ Vect_spatial_index_destroy(&si);
G_set_verbose(verbose);
Vect_close(&In);
More information about the grass-commit
mailing list