[GRASS-SVN] r50087 - grass/trunk/vector/v.clean

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Jan 7 08:51:55 EST 2012


Author: mmetz
Date: 2012-01-07 05:51:55 -0800 (Sat, 07 Jan 2012)
New Revision: 50087

Added:
   grass/trunk/vector/v.clean/split.c
Log:
v.clean: new helper tool for tool=break

Added: grass/trunk/vector/v.clean/split.c
===================================================================
--- grass/trunk/vector/v.clean/split.c	                        (rev 0)
+++ grass/trunk/vector/v.clean/split.c	2012-01-07 13:51:55 UTC (rev 50087)
@@ -0,0 +1,141 @@
+/****************************************************************
+ *
+ * MODULE:       v.clean
+ * 
+ * AUTHOR(S):    Markus Metz
+ *               
+ * PURPOSE:      Split lines - helper tool for breaking lines
+ *               
+ * COPYRIGHT:    (C) 2012 by the GRASS Development Team
+ *
+ *               This program is free software under the 
+ *               GNU General Public License (>=v2). 
+ *               Read the file COPYING that comes with GRASS
+ *               for details.
+ *
+ ***************************************************************/
+#include <stdlib.h>
+#include <math.h>
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/glocale.h>
+
+int split_line(struct Map_info *Map, int otype, struct line_pnts *Points,
+	       struct line_cats *Cats, struct Map_info *Err, double split_distance);
+
+/* split lines
+ * threshold is determined automatically
+ * returns number of split points */
+int split_lines(struct Map_info *Map, int otype, struct Map_info *Err)
+{
+    int line, nlines, n_split_lines, n_splits_total, type;
+    struct line_pnts *Points;
+    struct line_cats *Cats;
+    double area_size, split_distance;
+    struct bound_box box;
+    
+    nlines = Vect_get_num_lines(Map);
+    n_split_lines = 0;
+    for (line = 1; line <= nlines; line++) {
+	type = Vect_get_line_type(Map, line);
+	if ((type & otype) && (type & GV_LINES))
+	    n_split_lines++;
+    }
+
+    if (n_split_lines < 50)
+	return 0;
+
+    Vect_get_map_box(Map, &box);
+    area_size = sqrt((box.E - box.W) * (box.N - box.S));
+
+    split_distance = area_size / log(n_split_lines);
+    /* divisor is the handle: increase divisor to decrease split_distance */
+    split_distance = split_distance / 10.;
+    G_debug(1, "area size: %f", area_size);
+    G_debug(1, "split distance: %f", split_distance);
+
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+    n_splits_total = 0;
+    for (line = 1; line <= nlines; line++) {
+	int n_splits;
+
+	type = Vect_get_line_type(Map, line);
+	if (!((type & otype) && (type & GV_LINES)))
+	    continue;
+	    
+	Vect_read_line(Map, Points, Cats, line);
+	
+	/* can't split boundaries with only 2 vertices */
+	if (Points->n_points < 3)
+	    continue;
+
+	n_splits = split_line(Map, type, Points, Cats, Err, split_distance);
+	
+	if (n_splits)
+	    Vect_delete_line(Map, line);
+	
+	n_splits_total += n_splits;
+    }
+    
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_cats_struct(Cats);
+
+    G_verbose_message(_("Line splits: %d"), n_splits_total);
+
+    return n_splits_total;    
+}
+
+/* split a line using split_distance
+ * returns number of split points */
+int split_line(struct Map_info *Map, int otype, struct line_pnts *Points,
+	       struct line_cats *Cats, struct Map_info *Err, double split_distance)
+{
+    int i, n_segs = 0;
+    double dist = 0., seg_dist, dx, dy;
+    struct line_pnts *OutPoints;
+
+    /* don't write zero length boundaries */
+    Vect_line_prune(Points);
+    if (Points->n_points < 2)
+	return 0;
+
+    /* can't split boundaries with only 2 vertices */
+    if (Points->n_points == 2) {
+	Vect_write_line(Map, otype, Points, Cats);
+	return 0;
+    }
+
+    OutPoints = Vect_new_line_struct();
+    Vect_append_point(OutPoints, Points->x[0], Points->y[0], Points->z[0]);
+    Vect_append_point(OutPoints, Points->x[1], Points->y[1], Points->z[1]);
+    dx = Points->x[1] - Points->x[0];
+    dy = Points->y[1] - Points->y[0];
+    dist = sqrt(dx * dx + dy * dy);
+
+    /* trying to keep line length smaller than split_distance
+     * alternative, less code: write line as soon as split_distance is exceeded */
+    for (i = 2; i < Points->n_points; i++) {
+	dx = Points->x[i] - Points->x[i - 1];
+	dy = Points->y[i] - Points->y[i - 1];
+	seg_dist = sqrt(dx * dx + dy * dy);
+	dist += seg_dist;
+	if (dist > split_distance) {
+	    Vect_write_line(Map, otype, OutPoints, Cats);
+	    Vect_reset_line(OutPoints);
+	    dist = seg_dist;
+	    Vect_append_point(OutPoints, Points->x[i - 1], Points->y[i - 1],
+			      Points->z[i - 1]);
+	    n_segs++;
+	}
+	Vect_append_point(OutPoints, Points->x[i], Points->y[i],
+			  Points->z[i]);
+    }
+    /* write out remaining line points only when original line was split */
+    if (n_segs)
+	Vect_write_line(Map, otype, OutPoints, Cats);
+
+    Vect_destroy_line_struct(OutPoints);
+
+    return n_segs;
+}


Property changes on: grass/trunk/vector/v.clean/split.c
___________________________________________________________________
Added: svn:mime-type
   + text/x-csrc
Added: svn:eol-style
   + native



More information about the grass-commit mailing list