[GRASS-SVN] r44899 - grass/trunk/vector/v.generalize
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Jan 6 13:15:46 EST 2011
Author: mmetz
Date: 2011-01-06 10:15:45 -0800 (Thu, 06 Jan 2011)
New Revision: 44899
Modified:
grass/trunk/vector/v.generalize/displacement.c
grass/trunk/vector/v.generalize/main.c
grass/trunk/vector/v.generalize/misc.c
grass/trunk/vector/v.generalize/misc.h
grass/trunk/vector/v.generalize/network.c
grass/trunk/vector/v.generalize/operators.h
grass/trunk/vector/v.generalize/v.generalize.html
Log:
do not delete areas, do not mix up area attributes
Modified: grass/trunk/vector/v.generalize/displacement.c
===================================================================
--- grass/trunk/vector/v.generalize/displacement.c 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/displacement.c 2011-01-06 18:15:45 UTC (rev 44899)
@@ -26,7 +26,7 @@
#include "matrix.h"
/* snakes method modified for displacement.
- * Function returns somthing. This function affects only the
+ * Function returns something. This function affects only the
* lines specified in varray (or all lines if varray is null).
Other lines are copied */
int snakes_displacement(struct Map_info *In, struct Map_info *Out,
@@ -111,7 +111,7 @@
}
threshold2 = threshold * threshold;
- /*select only the points which need to be displace */
+ /*select only the points which need to be displaced */
for (i = 0; i < index; i++) {
if (need[point_index[i]])
continue;
Modified: grass/trunk/vector/v.generalize/main.c
===================================================================
--- grass/trunk/vector/v.generalize/main.c 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/main.c 2011-01-06 18:15:45 UTC (rev 44899)
@@ -5,10 +5,11 @@
*
* AUTHOR(S): Daniel Bundala
* OGR support by Martin Landa <landa.martin gmail.com> (2009)
+ * Markus Metz: preserve areas and area attributes
*
* PURPOSE: Module for line simplification and smoothing
*
- * COPYRIGHT: (C) 2007-2009 by the GRASS Development Team
+ * COPYRIGHT: (C) 2007-2010 by the GRASS Development Team
*
* This program is free software under the GNU General
* Public License (>=v2). Read the file COPYING that
@@ -36,14 +37,13 @@
#define SNAKES 8
#define DOUGLAS_REDUCTION 9
#define SLIDING_AVERAGING 10
-#define REMOVE_SMALL 11
#define NETWORK 100
#define DISPLACEMENT 101
int main(int argc, char *argv[])
{
struct Map_info In, Out;
- static struct line_pnts *Points;
+ struct line_pnts *Points;
struct line_cats *Cats;
int i, type, iter;
struct GModule *module; /* GRASS module for parsing arguments */
@@ -54,7 +54,7 @@
struct Option *angle_thresh_opt, *degree_thresh_opt,
*closeness_thresh_opt;
struct Option *betweeness_thresh_opt;
- struct Flag *ca_flag, *rs_flag;
+ struct Flag *ca_flag;
int with_z;
int total_input, total_output; /* Number of points in the input/output map respectively */
double thresh, alpha, beta, reduction, slide, angle_thresh;
@@ -62,13 +62,11 @@
int method;
int look_ahead, iterations;
int chcat;
- int ret, layer;
- int n_areas, n_orig_areas, n_lines;
- double x, y;
+ int layer;
+ int n_lines;
int simplification, mask_type;
struct varray *varray;
char *s;
- int left, right;
/* initialize GIS environment */
G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
@@ -89,8 +87,8 @@
field_opt = G_define_standard_option(G_OPT_V_FIELD_ALL);
type_opt = G_define_standard_option(G_OPT_V_TYPE);
- type_opt->options = "line,boundary,area";
- type_opt->answer = "line,boundary,area";
+ type_opt->options = "line,boundary";
+ type_opt->answer = "line,boundary";
map_out = G_define_standard_option(G_OPT_V_OUTPUT);
@@ -101,14 +99,13 @@
method_opt->required = YES;
method_opt->multiple = NO;
method_opt->options =
- "douglas,douglas_reduction,lang,reduction,reumann,remove_small,boyle,sliding_averaging,distance_weighting,chaiken,hermite,snakes,network,displacement";
+ "douglas,douglas_reduction,lang,reduction,reumann,boyle,sliding_averaging,distance_weighting,chaiken,hermite,snakes,network,displacement";
method_opt->answer = "douglas";
method_opt->descriptions = _("douglas;Douglas-Peucker Algorithm;"
"douglas_reduction;Douglas-Peucker Algorithm with reduction parameter;"
"lang;Lang Simplification Algorithm;"
"reduction;Vertex Reduction Algorithm eliminates points close to each other;"
"reumann;Reumann-Witkam Algorithm;"
- "remove_small;Removes lines shorter than threshold and areas of area less than threshold;"
"boyle;Boyle's Forward-Looking Algorithm;"
"sliding_averaging;McMaster's Sliding Averaging Algorithm;"
"distance_weighting;McMaster's Distance-Weighting Algorithm;"
@@ -211,15 +208,10 @@
cat_opt = G_define_standard_option(G_OPT_V_CATS);
where_opt = G_define_standard_option(G_OPT_DB_WHERE);
-
ca_flag = G_define_flag();
ca_flag->key = 'c';
ca_flag->description = _("Copy attributes");
- rs_flag = G_define_flag();
- rs_flag->key = 'r';
- rs_flag->description = _("Remove lines and areas smaller than threshold");
-
/* options and flags parser */
if (G_parser(argc, argv))
exit(EXIT_FAILURE);
@@ -270,11 +262,6 @@
/* we can displace only the lines */
mask_type = GV_LINE;
}
- else if (strcmp(s, "remove_small") == 0) {
- method = REMOVE_SMALL;
- /* switch -r flag on */
- rs_flag->answer = 1;
- }
else {
G_fatal_error(_("Unknown method"));
exit(EXIT_FAILURE);
@@ -288,7 +275,6 @@
case LANG:
case VERTEX_REDUCTION:
case REUMANN:
- case REMOVE_SMALL:
simplification = 1;
break;
default:
@@ -316,212 +302,195 @@
}
- /* parse filter option and select appropriate lines */
- layer = Vect_get_field_number(&In, field_opt->answer);
- if (where_opt->answer) {
- if (layer < 1)
- G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
- if (cat_opt->answer)
- G_warning(_("'where' and 'cats' parameters were supplied, cat will be ignored"));
- chcat = 1;
- varray = Vect_new_varray(Vect_get_num_lines(&In));
- if (Vect_set_varray_from_db
- (&In, layer, where_opt->answer, mask_type, 1, varray) == -1) {
- G_warning(_("Unable to load data from database"));
- }
- }
- else if (cat_opt->answer) {
- if (layer < 1)
- G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
- varray = Vect_new_varray(Vect_get_num_lines(&In));
- chcat = 1;
- if (Vect_set_varray_from_cat_string
- (&In, layer, cat_opt->answer, mask_type, 1, varray) == -1) {
- G_warning(_("Problem loading category values"));
- }
- }
- else {
- chcat = 0;
- varray = NULL;
- }
-
Vect_copy_head_data(&In, &Out);
Vect_hist_copy(&In, &Out);
Vect_hist_command(&Out);
-
+
total_input = total_output = 0;
+ chcat = 0;
+ varray = NULL;
+ layer = Vect_get_field_number(&In, field_opt->answer);
+ /* parse filter option and select appropriate lines */
+ if (method == DISPLACEMENT || method == NETWORK)
+ varray = parse_filter_options(&In, layer, mask_type,
+ where_opt->answer, cat_opt->answer, &chcat);
+
if (method == DISPLACEMENT) {
+ /* modifies only lines, all other features including boundaries are preserved */
+ G_message(_("Displacement..."));
snakes_displacement(&In, &Out, thresh, alpha, beta, 1.0, 10.0,
iterations, varray);
}
/* TODO: rearrange code below. It's really messy */
if (method == NETWORK) {
+ /* extracts lines of selected type, all other features are discarded */
+ G_message(_("Network generalization..."));
total_output =
- graph_generalization(&In, &Out, degree_thresh, closeness_thresh,
- betweeness_thresh);
+ graph_generalization(&In, &Out, mask_type, degree_thresh,
+ closeness_thresh, betweeness_thresh);
}
- else {
- G_message(_("Generalization (%s)..."), method_opt->answer);
- G_percent_reset();
+
+ /* copy tables here because method == NETWORK is complete and
+ * tables for Out may be needed for parse_filter_options() below */
+ if (ca_flag->answer) {
+ if (method == NETWORK)
+ copy_tables_by_cats(&In, &Out);
+ else
+ Vect_copy_tables(&In, &Out, -1);
}
- i = 0;
- n_lines = Vect_get_num_lines(&In);
- while (method < NETWORK &&
- (type = Vect_read_next_line(&In, Points, Cats)) > 0) {
- i++;
- G_percent(i, n_lines, 1);
- if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
- continue;
-
- if (type == GV_CENTROID && (mask_type & GV_BOUNDARY))
- continue; /* skip old centroids,
- * we calculate new if we generalize boundarie */
- total_input += Points->n_points;
+ /* smoothing/simplification */
+ if (method < NETWORK) {
+ /* modifies only lines of selected type, all other features are preserved */
+ int not_modified_boundaries = 0, n_oversimplified = 0;
+ struct line_pnts *APoints; /* original Points */
- if ((type & mask_type) && (!chcat || varray->c[i])) {
- int after = 0;
+ Vect_copy_map_lines(&In, &Out);
+ Vect_build_partial(&Out, GV_BUILD_CENTROIDS);
+ /* varray needs to be retrieved from Out vector and not from In vector
+ * because identical lines can have different ids
+ * if dead lines are still registered in topo of In */
+ varray = parse_filter_options(&Out, layer, mask_type,
+ where_opt->answer, cat_opt->answer, &chcat);
- for (iter = 0; iter < iterations; iter++) {
- switch (method) {
- case DOUGLAS:
- douglas_peucker(Points, thresh, with_z);
- break;
- case DOUGLAS_REDUCTION:
- douglas_peucker_reduction(Points, thresh, reduction,
- with_z);
- break;
- case LANG:
- lang(Points, thresh, look_ahead, with_z);
- break;
- case VERTEX_REDUCTION:
- vertex_reduction(Points, thresh, with_z);
- break;
- case REUMANN:
- reumann_witkam(Points, thresh, with_z);
- break;
- case BOYLE:
- boyle(Points, look_ahead, with_z);
- break;
- case SLIDING_AVERAGING:
- sliding_averaging(Points, slide, look_ahead, with_z);
- break;
- case DISTANCE_WEIGHTING:
- distance_weighting(Points, slide, look_ahead, with_z);
- break;
- case CHAIKEN:
- chaiken(Points, thresh, with_z);
- break;
- case HERMITE:
- hermite(Points, thresh, angle_thresh, with_z);
- break;
- case SNAKES:
- snakes(Points, alpha, beta, with_z);
- break;
- }
- }
+ G_message("-----------------------------------------------------");
+ G_message(_("Generalization (%s)..."), method_opt->answer);
+ G_percent_reset();
+ APoints = Vect_new_line_struct();
- /* remove "oversimplified" lines */
- if (rs_flag->answer && simplification && type == GV_LINE &&
- Vect_line_length(Points) < thresh)
- continue;
-
- after = Points->n_points;
- total_output += after;
- Vect_write_line(&Out, type, Points, Cats);
- }
- else {
- total_output += Points->n_points;
- Vect_write_line(&Out, type, Points, Cats);
- }
- }
-
- /* remove incorrect boundaries
- * they may occur only if they were generalized */
- if (mask_type & GV_BOUNDARY) {
- int n_del = 0;
- Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES);
n_lines = Vect_get_num_lines(&Out);
for (i = 1; i <= n_lines; i++) {
- type = Vect_read_line(&Out, Points, Cats, i);
+ G_percent(i, n_lines, 1);
+
+ type = Vect_read_line(&Out, APoints, Cats, i);
+
+ if (layer != -1 && !Vect_cat_get(Cats, layer, NULL))
+ continue;
- if (layer > 0 && !Vect_cat_get(Cats, layer, NULL))
+ if (!(type & GV_LINES) || !(mask_type & type))
continue;
+
+ Vect_line_prune(APoints);
- if (type != GV_BOUNDARY)
+ if (APoints->n_points < 2)
+ /* Line of length zero */
continue;
- Vect_get_line_areas(&Out, i, &left, &right);
- if (left == 0 || right == 0) {
- Vect_delete_line(&Out, i);
- total_output -= Points->n_points;
- n_del++;
- }
- }
- if (n_del)
- G_warning(_("%d boundaries were deleted, input areas are not preserved"), n_del);
- /* make sure that clean topo is built at the end */
- Vect_build_partial(&Out, GV_BUILD_NONE);
- }
+ total_input += APoints->n_points;
+ if ((type & mask_type) && (!chcat || varray->c[i])) {
+ int after = 0;
- /* calculate new centroids
- * We need to calculate them only if the boundaries
- * were generalized
- */
- if ((mask_type & GV_BOUNDARY) && method != DISPLACEMENT) {
- Vect_build_partial(&Out, GV_BUILD_ATTACH_ISLES);
- n_areas = Vect_get_num_areas(&Out);
- for (i = 1; i <= n_areas; i++) {
- /* skip dead area */
- if (!Vect_area_alive(&Out, i))
- continue;
+ /* copy points */
+ Vect_reset_line(Points);
+ Vect_append_points(Points, APoints, GV_FORWARD);
+
+ for (iter = 0; iter < iterations; iter++) {
+ switch (method) {
+ case DOUGLAS:
+ douglas_peucker(Points, thresh, with_z);
+ break;
+ case DOUGLAS_REDUCTION:
+ douglas_peucker_reduction(Points, thresh, reduction,
+ with_z);
+ break;
+ case LANG:
+ lang(Points, thresh, look_ahead, with_z);
+ break;
+ case VERTEX_REDUCTION:
+ vertex_reduction(Points, thresh, with_z);
+ break;
+ case REUMANN:
+ reumann_witkam(Points, thresh, with_z);
+ break;
+ case BOYLE:
+ boyle(Points, look_ahead, with_z);
+ break;
+ case SLIDING_AVERAGING:
+ sliding_averaging(Points, slide, look_ahead, with_z);
+ break;
+ case DISTANCE_WEIGHTING:
+ distance_weighting(Points, slide, look_ahead, with_z);
+ break;
+ case CHAIKEN:
+ chaiken(Points, thresh, with_z);
+ break;
+ case HERMITE:
+ hermite(Points, thresh, angle_thresh, with_z);
+ break;
+ case SNAKES:
+ snakes(Points, alpha, beta, with_z);
+ break;
+ }
+ }
+
+ /* safety check, BUG in method if not passed */
+ if (APoints->x[0] != Points->x[0] ||
+ APoints->y[0] != Points->y[0] ||
+ APoints->z[0] != Points->z[0])
+ G_fatal_error(_("Method '%s' did not preserve first point"), method_opt->answer);
+
+ if (APoints->x[APoints->n_points - 1] != Points->x[Points->n_points - 1] ||
+ APoints->y[APoints->n_points - 1] != Points->y[Points->n_points - 1] ||
+ APoints->z[APoints->n_points - 1] != Points->z[Points->n_points - 1])
+ G_fatal_error(_("Method '%s' did not preserve last point"), method_opt->answer);
- /* area i in Out is not necessarily equal to area i in In! */
- Vect_get_area_cats(&In, i, Cats);
- ret = Vect_get_point_in_area(&Out, i, &x, &y);
- if (ret < 0) {
- G_warning(_("Unable to calculate centroid for area %d"), i);
- continue;
+ Vect_line_prune(Points);
+
+ /* oversimplified line */
+ if (Points->n_points < 2) {
+ after = APoints->n_points;
+ n_oversimplified++;
+ }
+ /* check for topology corruption */
+ else if (type == GV_BOUNDARY) {
+ if (!check_topo(&Out, i, APoints, Points, Cats)) {
+ after = APoints->n_points;
+ not_modified_boundaries++;
+ }
+ else
+ after = Points->n_points;
+ }
+ else {
+ /* type == GV_LINE */
+ Vect_rewrite_line(&Out, i, type, Points, Cats);
+ after = Points->n_points;
+ }
+
+ total_output += after;
}
- Vect_reset_line(Points);
- Vect_append_point(Points, x, y, 0.0);
- Vect_write_line(&Out, GV_CENTROID, Points, Cats);
+ else {
+ total_output += APoints->n_points;
+ }
}
- G_warning(_("New centroids were calculated, attribute attachment may be changed"));
- }
+ if (not_modified_boundaries > 0)
+ G_message(_("%d boundaries were not modified because modification would damage topology"),
+ not_modified_boundaries);
+ if (n_oversimplified > 0)
+ G_message(_("%d lines/boundaries were not modified due to over-simplification"),
+ n_oversimplified);
+ G_message("-----------------------------------------------------");
- /* remove small areas */
- if (rs_flag->answer && simplification && (mask_type & GV_AREA)) {
- Vect_build_partial(&Out, GV_BUILD_CENTROIDS);
- Vect_remove_small_areas(&Out, thresh, NULL, &slide);
-
/* make sure that clean topo is built at the end */
Vect_build_partial(&Out, GV_BUILD_NONE);
}
Vect_build(&Out);
- /* finally copy tables */
- if (ca_flag->answer)
- copy_tables_by_cats(&In, &Out);
+ Vect_close(&In);
+ Vect_close(&Out);
- /* warning about area corruption */
- if (mask_type & GV_BOUNDARY && (n_orig_areas = Vect_get_num_areas(&In)) > 0) {
- G_warning(_("Areas may have disappeared and/or area attribute attachment may have changed"));
- G_warning(_("Try v.clean tool=prune thresh=%f"), thresh);
- }
-
- if (total_input != 0)
- G_done_msg(_("Number of vertices reduced from %d to %d (%d%%)."),
+ G_message("-----------------------------------------------------");
+ if (total_input != 0 && total_input != total_output)
+ G_done_msg(_("Number of vertices %s from %d to %d (%d%%)."),
+ simplification ? _("reduced") : _("changed"),
total_input, total_output,
(total_output * 100) / total_input);
+ else
+ G_done_msg(" ");
- Vect_close(&In);
- Vect_close(&Out);
-
exit(EXIT_SUCCESS);
}
Modified: grass/trunk/vector/v.generalize/misc.c
===================================================================
--- grass/trunk/vector/v.generalize/misc.c 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/misc.c 2011-01-06 18:15:45 UTC (rev 44899)
@@ -3,7 +3,7 @@
*
* MODULE: v.generalize
*
- * AUTHOR(S): Daniel Bundala
+ * AUTHOR(S): Daniel Bundala, Markus Metz
*
* PURPOSE: miscellaneous functions of v.generalize
*
@@ -74,7 +74,7 @@
}
/* TODO: The collection of categories is horrible in current version!
- * Rverything repeats many times. We need some data structure
+ * Everything repeats many times. We need some data structure
* implementing set! */
int copy_tables_by_cats(struct Map_info *In, struct Map_info *Out)
{
@@ -186,3 +186,139 @@
G_free(fields);
return 1;
}
+
+/* parse filter option and select appropriate lines */
+/* return array with selected lines or NULL */
+struct varray *parse_filter_options(struct Map_info *Map, int layer,
+ int mask_type, char *where, char *cats, int *chcat)
+{
+ struct varray *varray;
+
+ if (where) {
+ if (layer < 1)
+ G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "where");
+ if (cats)
+ G_warning(_("'where' and 'cats' parameters were supplied, cat will be ignored"));
+ *chcat = 1;
+ varray = Vect_new_varray(Vect_get_num_lines(Map));
+ if (Vect_set_varray_from_db
+ (Map, layer, where, mask_type, 1, varray) == -1) {
+ G_warning(_("Unable to load data from database"));
+ }
+ }
+ else if (cats) {
+ if (layer < 1)
+ G_fatal_error(_("'%s' must be > 0 for '%s'"), "layer", "cat");
+ varray = Vect_new_varray(Vect_get_num_lines(Map));
+ *chcat = 1;
+ if (Vect_set_varray_from_cat_string
+ (Map, layer, cats, mask_type, 1, varray) == -1) {
+ G_warning(_("Problem loading category values"));
+ }
+ }
+ else
+ return NULL;
+
+ return varray;
+}
+
+/* check topology corruption by boundary modification
+ * return 0 on corruption, 1 if modification is ok */
+int check_topo(struct Map_info *Out, int line, struct line_pnts *APoints,
+ struct line_pnts *Points, struct line_cats *Cats)
+{
+ int i, intersect, newline, left_old, right_old,
+ left_new, right_new;
+ struct bound_box box;
+ static struct line_pnts *BPoints = NULL;
+ static struct ilist *List = NULL;
+
+ if (!BPoints)
+ BPoints = Vect_new_line_struct();
+ if (!List)
+ List = Vect_new_list();
+
+ /* Check intersection of the modified boundary with other boundaries */
+ Vect_line_box(Points, &box);
+ Vect_select_lines_by_box(Out, &box, GV_BOUNDARY, List);
+
+ intersect = 0;
+ for (i = 0; i < List->n_values; i++) {
+ int j, bline;
+ struct line_pnts **AXLines, **BXLines;
+ int naxlines, nbxlines;
+
+ bline = List->value[i];
+ if (bline == line)
+ continue;
+
+ Vect_read_line(Out, BPoints, NULL, bline);
+
+ /* Vect_line_intersection is quite slow, hopefully not so bad because only few
+ * intersections should be found if any */
+
+ Vect_line_intersection(Points, BPoints, &AXLines, &BXLines,
+ &naxlines, &nbxlines, 0);
+
+ G_debug(4,
+ "bline = %d intersect = %d naxlines = %d nbxlines = %d",
+ bline, intersect, naxlines, nbxlines);
+
+ /* Free */
+ if (naxlines > 0) {
+ for (j = 0; j < naxlines; j++) {
+ Vect_destroy_line_struct(AXLines[j]);
+ }
+ G_free(AXLines);
+ }
+ if (nbxlines > 0) {
+ for (j = 0; j < nbxlines; j++) {
+ Vect_destroy_line_struct(BXLines[j]);
+ }
+ G_free(BXLines);
+ }
+
+ if (naxlines > 1 || nbxlines > 1) {
+ intersect = 1;
+ break;
+ }
+ }
+
+ /* modified boundary intersects another boundary */
+ if (intersect)
+ return 0;
+
+ /* Get centroids on the left and right side */
+ Vect_get_line_areas(Out, line, &left_old, &right_old);
+ if (left_old < 0)
+ left_old = Vect_get_isle_area(Out, abs(left_old));
+ if (left_old > 0)
+ left_old = Vect_get_area_centroid(Out, left_old);
+ if (right_old < 0)
+ right_old = Vect_get_isle_area(Out, abs(right_old));
+ if (right_old > 0)
+ right_old = Vect_get_area_centroid(Out, right_old);
+
+ /* OK, rewrite modified boundary */
+ newline = Vect_rewrite_line(Out, line, GV_BOUNDARY, Points, Cats);
+
+ /* Check position of centroids */
+ Vect_get_line_areas(Out, newline, &left_new, &right_new);
+ if (left_new < 0)
+ left_new = Vect_get_isle_area(Out, abs(left_new));
+ if (left_new > 0)
+ left_new = Vect_get_area_centroid(Out, left_new);
+ if (right_new < 0)
+ right_new = Vect_get_isle_area(Out, abs(right_new));
+ if (right_new > 0)
+ right_new = Vect_get_area_centroid(Out, right_new);
+
+ if (left_new != left_old || right_new != right_old) {
+ G_debug(3,
+ "The modified boundary changes attachement of centroid -> not modified");
+ Vect_rewrite_line(Out, newline, GV_BOUNDARY, APoints, Cats);
+ return 0;
+ }
+
+ return 1;
+}
Modified: grass/trunk/vector/v.generalize/misc.h
===================================================================
--- grass/trunk/vector/v.generalize/misc.h 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/misc.h 2011-01-06 18:15:45 UTC (rev 44899)
@@ -19,4 +19,14 @@
/* returns 1 on success, 0 on failure */
extern int copy_tables_by_cats(struct Map_info *In, struct Map_info *Out);
+/* parse filter option and select appropriate lines */
+/* return array with selected lines or NULL */
+struct varray *parse_filter_options(struct Map_info *Map, int layer,
+ int mask_type, char *where, char *cats, int *chcat);
+
+/* check topology corruption by boundary modification
+ * return 0 on corruption, 1 if modification is ok */
+int check_topo(struct Map_info *, int, struct line_pnts *,
+ struct line_pnts *, struct line_cats *);
+
#endif
Modified: grass/trunk/vector/v.generalize/network.c
===================================================================
--- grass/trunk/vector/v.generalize/network.c 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/network.c 2011-01-06 18:15:45 UTC (rev 44899)
@@ -65,12 +65,12 @@
/* writes the most important part of the In network to Out network
* according to the thresholds, output is bigger for smaller
* thresholds. Function returns the number of points written
- TODO: rewrite ilist by somthing more space and time efficient
+ TODO: rewrite ilist by something more space and time efficient
or at least, implement append which does not check whether
the value is already in the list*/
int graph_generalization(struct Map_info *In, struct Map_info *Out,
- double degree_thresh, double closeness_thresh,
- double betweeness_thresh)
+ int mask_type, double degree_thresh,
+ double closeness_thresh, double betweeness_thresh)
{
int i;
@@ -85,7 +85,7 @@
double *betw, *betweeness;
struct ilist **prev;
- Vect_net_build_graph(In, GV_LINE | GV_BOUNDARY, 0, 0, NULL, NULL, NULL, 0,
+ Vect_net_build_graph(In, mask_type, 0, 0, NULL, NULL, NULL, 0,
0);
gr = &(In->graph);
/* build own graph by edge<->vertex */
@@ -207,7 +207,7 @@
}
}
}
- /*finally run another BFS from the leaves in the BFS DAG
+ /* finally run another BFS from the leaves in the BFS DAG
* and calculate betweeness centrality measure */
front = 0;
back = 0;
@@ -245,8 +245,10 @@
(comp[i] - 1.0) / closeness[i] >= closeness_thresh &&
betweeness[i] >= betweeness_thresh)) {
type = Vect_read_line(In, Points, Cats, i);
- output += Points->n_points;
- Vect_write_line(Out, type, Points, Cats);
+ if (type & mask_type) {
+ output += Points->n_points;
+ Vect_write_line(Out, type, Points, Cats);
+ }
}
}
Modified: grass/trunk/vector/v.generalize/operators.h
===================================================================
--- grass/trunk/vector/v.generalize/operators.h 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/operators.h 2011-01-06 18:15:45 UTC (rev 44899)
@@ -21,9 +21,9 @@
int snakes(struct line_pnts *Points, double alpha, double beta, int with_z);
/* network.c */
-int graph_generalization(struct Map_info *In, struct Map_info *Out,
- double degree_thresh, double closeness_thresh,
- double betweeness_thresh);
+int graph_generalization(struct Map_info *In, struct Map_info *Out,
+ int type, double degree_thresh,
+ double closeness_thresh, double betweeness_thresh);
/* displacement.c */
int snakes_displacement(struct Map_info *In, struct Map_info *Out,
Modified: grass/trunk/vector/v.generalize/v.generalize.html
===================================================================
--- grass/trunk/vector/v.generalize/v.generalize.html 2011-01-06 11:04:57 UTC (rev 44898)
+++ grass/trunk/vector/v.generalize/v.generalize.html 2011-01-06 18:15:45 UTC (rev 44899)
@@ -1,6 +1,6 @@
<h2>DESCRIPTION</h2>
-<em>v.generalise</em>
+<em>v.generalize</em>
is a module for the generalization of GRASS vector maps. This module
consists of algorithms for line simplification, line smoothing,
network generalization and displacement (new methods may be added later).
@@ -8,177 +8,207 @@
<em><a href="http://users.ox.ac.uk/~orie1848/tutorial.html">tutorial</a><br></em>
<h2>NOTES</h2>
-(Line) simplification is a process of reducing the complexity of vector features.
-The module transforms a line into another line consisting of fewer vertices, that
-still approximate the original line. Most of the algorithms described below
-select a subset of points on the original line.
+(Line) simplification is a process of reducing the complexity of vector
+features. The module transforms a line into another line consisting of
+fewer vertices, that still approximate the original line. Most of the
+algorithms described below select a subset of points on the original line.
<p>
(Line) smoothing is a "reverse" process which takes as input a line and
-produces a smoother approximate of the original.
-In some cases, this is achieved by inserting new vertices into the original line, and can
-total up to 4000% of the number of vertices in the original. In such an instance,
+produces a smoother approximate of the original. In some cases, this is
+achieved by inserting new vertices into the original line, and can total
+up to 4000% of the number of vertices in the original. In such an instance,
it is always a good idea to simplify the line after smoothing.
<p>
-Smoothing and simplification algorithms implemented in this module work line by
-line, i.e. simplification/smoothing of one line does not affect the other lines;
-they are treated separately. Also, the first and the last point of each line is
-never translated and/or deleted.
+Smoothing and simplification algorithms implemented in this module work
+line by line, i.e. simplification/smoothing of one line does not affect
+the other lines; they are treated separately. Also, the first and the
+last point of each line is never translated and/or deleted.
<h3>SIMPLIFICATION</h3>
-<em>v.generalise</em> contains following line simplification algorithms:
+<em>v.generalize</em> contains following line simplification algorithms:
<ul>
<li>Douglas-Peucker Algorithm</li>
-<li>"Douglas-Peucker Reduction Algorithm"</li>
+<li>Douglas-Peucker Reduction Algorithm</li>
<li>Lang Algorithm</li>
<li>Vertex Reduction</li>
<li>Reumann-Witkam Algorithm</li>
<li>Remove Small Lines/Areas</li>
</ul>
-Different algorithms require different parameters, but all the algorithms have
-one parameter in common: the <b>threshold</b> parameter. In general, the degree
-of simplification increases with the increasing value of <b>threshold</b>.<br>
+Different algorithms require different parameters, but all the algorithms
+have one parameter in common: the <b>threshold</b> parameter. In general,
+the degree of simplification increases with the increasing value of
+<b>threshold</b>.<br>
-If the <b>-r</b> flag is passed, simplified lines that become shorter becomes shorter than the
-<b>threshold</b> value are removed. Additionally, if the <b>type</b> parameter contains <b>area</b>
-and a simplification algorithm is selected, then areas less than <b>threshold</b> are also removed.
-
<h4>ALGORITHM DESCRIPTIONS</h4>
<ul>
-<li> <i>Douglas-Peucker</i> - "Quicksort" of line simplification, the most widely used
- algorithm. Input parameters: <b>input</b>, <b>threshold</b>. For more
- information, please see: <A href="http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm">http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm</a>.</li>
-<li> <i>Douglas-Peucker Reduction Algorithm</i> is essentially the same algorithm as the
- algorithm above, the difference being that it takes additional <b>reduction</b> parameter
- which denotes the percentage of the number of points on the new line with respect
- to the number of points on the original line. Input parameters: <b>input</b>,
+<li> <i>Douglas-Peucker</i> - "Quicksort" of line simplification, the
+ most widely used algorithm. Input parameters: <b>input</b>,
+ <b>threshold</b>. For more information, see: <br>
+ <A href="http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm">http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm</a>.</li>
+<li> <i>Douglas-Peucker Reduction Algorithm</i> is essentially the same
+ algorithm as the algorithm above, the difference being that it takes
+ an additional <b>reduction</b> parameter which denotes the percentage
+ of the number of points on the new line with respect to the number
+ of points on the original line. Input parameters: <b>input</b>,
<b>threshold</b>, <b>reduction</b>.</li>
-<li> <i>Lang</i> - Another standard algorithm. Input parameters: <b>input</b>, <b>threshold</b>, <b>look_ahead</b>.
- For an excellent description, see: <A href="http://www.sli.unimelb.edu.au/gisweb/LGmodule/LGLangVisualisation.htm">http://www.sli.unimelb.edu.au/gisweb/LGmodule/LGLangVisualisation.htm</a>.</li>
-<li> <i>Vertex Reduction</i> - Simplest among the algorithms. Input parameters: <b>input</b>, <b>threshold</b>.
- Given a line, this algorithm removes the points of this line which are closer to each other than <b>threshold</b>.
- More precisely, if p1 and p2 are two consecutive points, and the distance between p2 and p1 is less
- than <b>threshold</b>, it removes p2 and repeats the same process on the remaining points.</li>
-<li> <i>Reuman-Witkam</i> - Input parameters: <b>input</b>, <b>threshold</b>. This algorithm quite
- reasonably preserves the global characteristics of the lines. For more information
- see <A href="http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/GIS1/Lernmodule/Lg/LG_de_6.html">http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/GIS1/Lernmodule/Lg/LG_de_6.html</a>(german)</li>
-<li> <i>Remove Small Lines/Areas</i> - removes the lines (strictly) shorter than threshold and areas (strictly) less than threshold.
- Other lines/areas/boundaries are left unchanged. Input parameters: <b>input</b>, <b>threshold</b>
+<li> <i>Lang</i> - Another standard algorithm. Input parameters:
+ <b>input</b>, <b>threshold</b>, <b>look_ahead</b>.
+ For an excellent description, see: <br>
+ <A href="http://www.sli.unimelb.edu.au/gisweb/LGmodule/LGLangVisualisation.htm">http://www.sli.unimelb.edu.au/gisweb/LGmodule/LGLangVisualisation.htm</a>.</li>
+<li> <i>Vertex Reduction</i> - Simplest among the algorithms. Input
+ parameters: <b>input</b>, <b>threshold</b>.
+ Given a line, this algorithm removes the points of this line which
+ are closer to each other than <b>threshold</b>. More precisely, if
+ p1 and p2 are two consecutive points, and the distance between p2
+ and p1 is less than <b>threshold</b>, it removes p2 and repeats the
+ same process on the remaining points.</li>
+<li> <i>Reuman-Witkam</i> - Input parameters: <b>input</b>,
+ <b>threshold</b>.
+ This algorithm quite reasonably preserves the global characteristics
+ of the lines. For more information, see: <br>
+ <A href="http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/GIS1/Lernmodule/Lg/LG_de_6.html">http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/GIS1/Lernmodule/Lg/LG_de_6.html</a> (german).</li>
</ul>
-<i>Douglas-Peucker</i> and <i>Douglas-Peucker Reduction Algorithm</i> use the same method
-to simplify the lines. Note that
+<i>Douglas-Peucker</i> and <i>Douglas-Peucker Reduction Algorithm</i>
+use the same method to simplify the lines. Note that
<div class="code"><pre>
-v.generalise input=in output=out method=douglas threshold=eps
+v.generalize input=in output=out method=douglas threshold=eps
</pre></div>
is equivalent to
<div class="code"><pre>
-v.generalise input=in output=out method=douglas_reduction threshold=eps reduction=100
+v.generalize input=in output=out method=douglas_reduction threshold=eps reduction=100
</pre></div>
However, in this case, the first method is faster. Also observe that
-<i>douglas_reduction</i> never outputs more vertices than <i>douglas</i>. And that,
-in general, <i>douglas</i> is more efficient than <i>douglas_reduction</i>.
-More importantly, the effect of
+<i>douglas_reduction</i> never outputs more vertices than <i>douglas</i>,
+and that, in general, <i>douglas</i> is more efficient than
+<i>douglas_reduction</i>. More importantly, the effect of
<div class="code"><pre>
-v.generalise input=in output=out method=douglas_reduction threshold=0 reduction=X
+v.generalize input=in output=out method=douglas_reduction threshold=0 reduction=X
</pre></div>
-
is that 'out' contains approximately only X% of points of 'in'.
<h3>SMOOTHING</h3>
-The following smoothing algorithms are implemented in <em>v.generalise</em>
+The following smoothing algorithms are implemented in <em>v.generalize</em>
<ul>
-<li><i>Boyle's Forward-Looking Algorithm</i> - The position of each point depends on the
- position of the previous points and the point <b>look_ahead</b> ahead.
- <b>look_ahead</b> consecutive points. Input parameters: <b>input</b>, <b>look_ahead</b>.</li>
-<li><i>McMaster's Sliding Averaging Algorithm</i> - Input Parameters: <b>input</b>, <b>slide</b>, <b>look_ahead</b>.
- The new position of each point is the average of the <b>look_ahead</b> points around. Parameter <b>slide</b>
- is used for linear interpolation between old and new position (see below).</li>
-<li><i>McMaster's Distance-Weighting Algorithm</i> - Works by taking the weighted average of <b>look_ahead</b> consecutive points
- where the weight is the reciprocal of the distance from the point to the currently smoothed point. And parameter <b>slide</b> is used
- for linear interpolation between the original position of the point and newly computed position where value 0 means the original position.
+<li><i>Boyle's Forward-Looking Algorithm</i> - The position of each point
+ depends on the position of the previous points and the point
+ <b>look_ahead</b> ahead. <b>look_ahead</b> consecutive points. Input
+ parameters: <b>input</b>, <b>look_ahead</b>.</li>
+<li><i>McMaster's Sliding Averaging Algorithm</i> - Input Parameters:
+ <b>input</b>, <b>slide</b>, <b>look_ahead</b>.
+ The new position of each point is the average of the <b>look_ahead</b>
+ points around. Parameter <b>slide</b> is used for linear interpolation
+ between old and new position (see below).</li>
+<li><i>McMaster's Distance-Weighting Algorithm</i> - Takes the weighted
+ average of <b>look_ahead</b> consecutive points where the weight is
+ the reciprocal of the distance from the point to the currently
+ smoothed point. The parameter <b>slide</b> is used for linear
+ interpolation between the original position of the point and newly
+ computed position where value 0 means the original position.
Input parameters: <b>input</b>, <b>slide</b>, <b>look_ahead</b>.
</li>
-<li><i>Chaiken's Algorithm</i> - "Inscribes" a line touching the original line such that the points on this new line
- are at least <i>threshold</i> apart. Input parameters: <b>input</b>, <b>threshold</b>. This algorithm
- approximates the given line very well.</li>
-<li> <i>Hermite Interpolation</i> - This algorithm takes the points of the given line as the control
- points of hermite cubic spline and approximates this spline by the points approximately <b>threshold</b> apart.
- This method has excellent results for the small values of <b>threshold</b>, but in this case it produces
- a huge number of new points and some simplification is usually needed. Input parameters: <b>input</b>, <b>threshold</b>, <b>angle_thresh</b>.
- <b>Angle_thresh</b> is used for reducing the number of the outputed points. It denotes the minimal
- angle (in degrees) between two consecutive segments of line.</li>
-<li> <i>Snakes</i> is the method of minimisation of the "energy" of the line. This method preserves the
- general characteristics of the lines but smooths the "sharp corners" of the line. Input parameters <b>input</b>, <b>alpha</b>, <b>beta</b>.
- This algorithm works very well for small values of <b>alpha</b> and <b>beta</b> (between 0 and 5). These
- parameters affects the "sharpness" and the curvature of the computed line.</li>
+<li><i>Chaiken's Algorithm</i> - "Inscribes" a line touching the original
+ line such that the points on this new line are at least
+ <i>threshold</i> apart. Input parameters: <b>input</b>,
+ <b>threshold</b>. This algorithm approximates the given line very
+ well.</li>
+<li> <i>Hermite Interpolation</i> - This algorithm takes the points of
+ the given line as the control points of hermite cubic spline and
+ approximates this spline by the points approximately
+ <b>threshold</b> apart. This method has excellent results for small
+ values of <b>threshold</b>, but in this case it produces a huge
+ number of new points and some simplification is usually needed.
+ Input parameters: <b>input</b>, <b>threshold</b>, <b>angle_thresh</b>.
+ <b>Angle_thresh</b> is used for reducing the number of the points.
+ It denotes the minimal angle (in degrees) between two consecutive
+ segments of a line.</li>
+<li> <i>Snakes</i> is the method of minimisation of the "energy" of a
+ line. This method preserves the general characteristics of the lines
+ but smooths the "sharp corners" of a line. Input parameters
+ <b>input</b>, <b>alpha</b>, <b>beta</b>.
+ This algorithm works very well for small values of <b>alpha</b> and
+ <b>beta</b> (between 0 and 5). These parameters affect the
+ "sharpness" and the curvature of the computed line.</li>
</ul>
-One of the key advantages of <i>Hermite Interpolation</i> is the fact that the computed line
-always passes through the points of the original line, whereas the lines produced by the
-remaining algorithms never pass through these points. In some sense, this algorithm outputs
-a line which "circumscribes" the input line.
+One of the key advantages of <i>Hermite Interpolation</i> is the fact
+that the computed line always passes through the points of the original
+line, whereas the lines produced by the remaining algorithms never pass
+through these points. In some sense, this algorithm outputs a line which
+"circumscribes" the input line.
<p>
-On the other hand, <i>Chaiken's Algorithm</i> outputs a line which "inscribes" a given line.
-The output line always touches/intersects the centre of the input line segment between two
-consecutive points. For more iterations, the property above does not hold, but the computed
-lines are very similar to the Bezier Splines. The disadvantage of the two algorithms given above is that
-they increase the number of points. However, <i>Hermite Interpolation</i> can be used as another
-simplification algorithm. To achieve this, it is necessary to set <i>angle_thresh</i> to higher values (15 or so).
+On the other hand, <i>Chaiken's Algorithm</i> outputs a line which
+"inscribes" a given line. The output line always touches/intersects the
+centre of the input line segment between two consecutive points. For
+more iterations, the property above does not hold, but the computed
+lines are very similar to the Bezier Splines. The disadvantage of the
+two algorithms given above is that they increase the number of points.
+However, <i>Hermite Interpolation</i> can be used as another
+simplification algorithm. To achieve this, it is necessary to set
+<i>angle_thresh</i> to higher values (15 or so).
<p>
-One restriction on both McMasters' Algorithms is that <i>look_ahead</i> parameter must be odd. Also
-note that these algorithms have no effect if <i>look_ahead = 1</i>.
+One restriction on both McMasters' Algorithms is that <i>look_ahead</i>
+parameter must be odd. Also note that these algorithms have no effect if
+<i>look_ahead = 1</i>.
<p>
-Note that <i>Boyle's</i>, <i>McMasters'</i> and <i>Snakes</i> algorithm are sometimes used in the signal processing to smooth the signals.
-More importantly, these algorithms never change the number of points on the lines; they only
-translate the points, and do not insert any new points.
+Note that <i>Boyle's</i>, <i>McMasters'</i> and <i>Snakes</i> algorithm
+are sometimes used in the signal processing to smooth the signals.
+More importantly, these algorithms never change the number of points on
+the lines; they only translate the points, and do not insert any new points.
<p>
-<i>Snakes</i> Algorithm is (asymptotically) the slowest among the algorithms presented above. Also,
-it requires quite a lot of memory. This means that it is not very efficient for maps with the lines
+<i>Snakes</i> Algorithm is (asymptotically) the slowest among the
+algorithms presented above. Also, it requires quite a lot of memory.
+This means that it is not very efficient for maps with the lines
consisting of many segments.
<h3>DISPLACEMENT</h3>
-The displacement is used when the lines overlap and/or are close to each other at the current
-level of detail. In general, displacement methods moves the conflicting features apart so
-that they do not interact and can be distinguished.
+The displacement is used when the lines overlap and/or are close to each
+other at the current level of detail. In general, displacement methods
+move the conflicting features apart so that they do not interact and can
+be distinguished.
<p>
-This module implements algorithm for displacement of linear features based on
-the <i>Snakes</i> approach. This method generally yields very good results; however, it
-requires a lot of memory and is not very efficient.
+This module implements an algorithm for displacement of linear features
+based on the <i>Snakes</i> approach. This method generally yields very
+good results; however, it requires a lot of memory and is not very efficient.
<p>
-Displacement is selected by <b>method=displacement</b>. It uses following parameters:
+Displacement is selected by <b>method=displacement</b>. It uses the
+following parameters:
<ul>
<li>
-<b>threshold</b> - specifies critical distance. Two features interact if they are
-closer than <b>threshold</b> apart.
+<b>threshold</b> - specifies critical distance. Two features interact if
+they are closer than <b>threshold</b> apart.
</li>
<li>
-<b>alpha</b>, <b>beta</b> - These parameters define the rigidity of lines. For greater
-values of <b>alpha</b>, <b>beta</b> (>=1), the algorithm does a better job at retaining the original
-shape of the lines, possibly at the expense of displacement distance. If the values of <b>alpha</b>,
-<b>beta</b> are too small (<=0.001), then the lines are moved sufficiently, but the geometry and topology of lines can
-be destroyed. Most likely the best way to find the good values of <b>alpha</b>, <b>beta</b>
+<b>alpha</b>, <b>beta</b> - These parameters define the rigidity of lines.
+For larger values of <b>alpha</b>, <b>beta</b> (>=1), the algorithm
+does a better job at retaining the original shape of the lines, possibly
+at the expense of displacement distance. If the values of <b>alpha</b>,
+<b>beta</b> are too small (<=0.001), then the lines are moved
+sufficiently, but the geometry and topology of lines can be destroyed.
+Most likely the best way to find the good values of <b>alpha</b>, <b>beta</b>
is by trial and error.
</li>
<li>
-<b>iterations</b> - denotes the number of iterations the interactions between
-the lines are resolved. Good starting points for values of <b>iterations</b> are between 10 and 100.
+<b>iterations</b> - denotes the number of iterations the interactions
+between the lines are resolved. Good starting points for values of
+<b>iterations</b> are between 10 and 100.
</li>
</ul>
@@ -202,28 +232,30 @@
with at least <b>degree_thresh</b> different lines.
</li>
<li>
-<b>closeness_thresh</b> - is always in the range (0, 1]. Only the lines with
-the closeness centrality value at least <b>closeness_thresh</b> apart are selected.
-The lines in the centre of a network have greater values of this measure than
-the lines near the border of a network. This means that this parameter can be used
-for selecting the centre(s) of a network. Note that if closeness_thresh=0 then everything is selected.
+<b>closeness_thresh</b> - is always in the range (0, 1]. Only the lines
+with the closeness centrality value at least <b>closeness_thresh</b> apart
+are selected. The lines in the centre of a network have greater values of
+this measure than the lines near the border of a network. This means that
+this parameter can be used for selecting the centre(s) of a network. Note
+that if closeness_thresh=0 then everything is selected.
</li>
<li>
-<b>betweeness_thresh</b> - Again, only the lines with a betweeness centrality
-measure at least <b>betweeness_thresh</b> are selected. This value is always
-positive and is larger for large networks. It denotes to what extent a line
-is in between the other lines in the network. This value is great for the lines
-which lie between other lines and lie on the paths between two parts of a network.
-In the terminology of the road networks, these are highways, bypasses, main roads/streets, etc.
+<b>betweeness_thresh</b> - Again, only the lines with a betweeness
+centrality measure at least <b>betweeness_thresh</b> are selected. This
+value is always positive and is larger for large networks. It denotes to
+what extent a line is in between the other lines in the network. This
+value is large for the lines which lie between other lines and lie on
+the paths between two parts of a network. In the terminology of road
+networks, these are highways, bypasses, main roads/streets, etc.
</li>
</ul>
-All three parameters above can be presented at the same time. In that case,
-the algorithm selects only the lines which meet each criterion.
+All three parameters above can be presented at the same time. In that
+case, the algorithm selects only the lines which meet each criterion.
<p>
-Also, the outputed network may not be connected if the value of <b>betweeness_thresh</b>
-is too large.
+Also, the outputed network may not be connected if the value of
+<b>betweeness_thresh</b> is too large.
<!-- TODO: example(s) -->
More information about the grass-commit
mailing list