Pārlūkot izejas kodu

v.to.points: Add -p (percentage) and -r (reverse) flags

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@70595 15284696-431f-4ddb-bdfa-cd5b030d7da7
Huidae Cho 8 gadi atpakaļ
vecāks
revīzija
59bac7334a

+ 1 - 1
vector/v.to.points/local_proto.h

@@ -5,5 +5,5 @@
 void write_point(struct Map_info *, double, double, double,
 void write_point(struct Map_info *, double, double, double,
 		 int, double, dbDriver *, struct field_info *);
 		 int, double, dbDriver *, struct field_info *);
 void write_line(struct Map_info *, struct line_pnts *, int,
 void write_line(struct Map_info *, struct line_pnts *, int,
-		int, int, double, dbDriver *, struct field_info *);
+		int, int, int, double, dbDriver *, struct field_info *);
 #endif
 #endif

+ 39 - 11
vector/v.to.points/main.c

@@ -8,7 +8,7 @@
  *               
  *               
  * PURPOSE:      Create points along lines 
  * PURPOSE:      Create points along lines 
  *               
  *               
- * COPYRIGHT:    (C) 2002-2014 by the GRASS Development Team
+ * COPYRIGHT:    (C) 2002-2017 by the GRASS Development Team
  *
  *
  *               This program is free software under the GNU General
  *               This program is free software under the GNU General
  *               Public License (>=v2).  Read the file COPYING that
  *               Public License (>=v2).  Read the file COPYING that
@@ -35,7 +35,7 @@ int main(int argc, char **argv)
         struct Option *input, *output, *type, *dmax, *lfield, *use;
         struct Option *input, *output, *type, *dmax, *lfield, *use;
     } opt;
     } opt;
     struct {
     struct {
-        struct Flag *table, *inter;
+        struct Flag *table, *inter, *percent, *reverse;
     } flag;
     } flag;
     struct GModule *module;
     struct GModule *module;
     struct Map_info In, Out;
     struct Map_info In, Out;
@@ -84,12 +84,19 @@ int main(int argc, char **argv)
     opt.dmax->type = TYPE_DOUBLE;
     opt.dmax->type = TYPE_DOUBLE;
     opt.dmax->required = NO;
     opt.dmax->required = NO;
     opt.dmax->answer = "100";
     opt.dmax->answer = "100";
-    opt.dmax->description = _("Maximum distance between points in map units");
+    opt.dmax->description = _("Maximum distance between points in map units or percentage with -p");
 
 
     flag.inter = G_define_flag();
     flag.inter = G_define_flag();
     flag.inter->key = 'i';
     flag.inter->key = 'i';
     flag.inter->description = _("Interpolate points between line vertices (only for use=vertex)");
     flag.inter->description = _("Interpolate points between line vertices (only for use=vertex)");
-    
+
+    flag.percent = G_define_flag();
+    flag.percent->key = 'p';
+    flag.percent->description = _("Use dmax as percentage of line length");
+
+    flag.reverse = G_define_flag();
+    flag.reverse->key = 'r';
+    flag.reverse->description = _("Start from the end node");
 
 
     flag.table = G_define_standard_flag(G_FLG_V_TABLE);
     flag.table = G_define_standard_flag(G_FLG_V_TABLE);
 
 
@@ -102,6 +109,8 @@ int main(int argc, char **argv)
 
 
     type = Vect_option_to_types(opt.type);
     type = Vect_option_to_types(opt.type);
     dmax = atof(opt.dmax->answer);
     dmax = atof(opt.dmax->answer);
+    if (dmax <= 0)
+	G_fatal_error(_("Option %s must be positive"), opt.dmax->key);
 
 
     vertex_type = 0;
     vertex_type = 0;
     if (opt.use->answer) {
     if (opt.use->answer) {
@@ -134,6 +143,7 @@ int main(int argc, char **argv)
     Vect_hist_command(&Out);
     Vect_hist_command(&Out);
 
 
     /* Table */
     /* Table */
+    driver = NULL;
     Fi = NULL;
     Fi = NULL;
     if (!flag.table->answer) {
     if (!flag.table->answer) {
 	struct field_info *Fin;
 	struct field_info *Fin;
@@ -222,9 +232,13 @@ int main(int argc, char **argv)
 		write_point(&Out, LPoints->x[0], LPoints->y[0], LPoints->z[0],
 		write_point(&Out, LPoints->x[0], LPoints->y[0], LPoints->z[0],
 			    cat, 0.0, driver, Fi);
 			    cat, 0.0, driver, Fi);
 	    }
 	    }
-	    else {		/* lines */
-		write_line(&Out, LPoints, cat, vertex_type,
-			   flag.inter->answer, dmax, driver, Fi);
+	    else if (flag.percent->answer) {		/* lines */
+		double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
+		write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
+			   flag.reverse->answer, dmaxlen, driver, Fi);
+	    } else {
+		write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
+			   flag.reverse->answer, dmax, driver, Fi);
 	    }
 	    }
 	}
 	}
 
 
@@ -254,8 +268,14 @@ int main(int argc, char **argv)
 
 
 	    Vect_get_area_points(&In, area, LPoints);
 	    Vect_get_area_points(&In, area, LPoints);
 
 
-	    write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
-		       dmax, driver, Fi);
+	    if (flag.percent->answer) {
+		double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
+		write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
+			   flag.reverse->answer, dmaxlen, driver, Fi);
+	    } else {
+		write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
+			   flag.reverse->answer, dmax, driver, Fi);
+	    }
 
 
 	    nisles = Vect_get_area_num_isles(&In, area);
 	    nisles = Vect_get_area_num_isles(&In, area);
 
 
@@ -263,8 +283,16 @@ int main(int argc, char **argv)
 		isle = Vect_get_area_isle(&In, area, i);
 		isle = Vect_get_area_isle(&In, area, i);
 		Vect_get_isle_points(&In, isle, LPoints);
 		Vect_get_isle_points(&In, isle, LPoints);
 
 
-		write_line(&Out, LPoints, cat, vertex_type,
-			   flag.inter->answer, dmax, driver, Fi);
+		if (flag.percent->answer) {
+		    double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
+		    write_line(&Out, LPoints, cat, vertex_type,
+			       flag.inter->answer, flag.reverse->answer,
+			       dmaxlen, driver, Fi);
+		} else {
+		    write_line(&Out, LPoints, cat, vertex_type,
+			       flag.inter->answer, flag.reverse->answer, dmax,
+			       driver, Fi);
+		}
 	    }
 	    }
 	}
 	}
     }
     }

+ 8 - 5
vector/v.to.points/v.to.points.html

@@ -70,24 +70,27 @@ this case. Similarly to <b>use=node</b> when only line's node are
 used.
 used.
 
 
 <p>
 <p>
-If the <b>-i</b> flag is used in conjunction with
-the <b>use=vertex</b> option,
+If the <b>-i</b> flag is used in conjunction with the <b>use=vertex</b> option,
 <em>v.to.points</em> will digitize points on the line vertices, as
 <em>v.to.points</em> will digitize points on the line vertices, as
 well as interpolate points between line vertices using <b>dmax</b> as
 well as interpolate points between line vertices using <b>dmax</b> as
 the maximum allowable spacing.
 the maximum allowable spacing.
 
 
 <p>
 <p>
-To get points created for the beginning, middle and end only, use
-the <b>-i</b> flag and set <b>dmax</b> so that:
+Use the <b>-p</b> flag to treat <b>dmax</b> as a percentage of each line
+length.  For example, to get points created for the beginning, middle and end
+only, use the <b>-p</b> flag and set <b>dmax</b> so that:
 
 
 <div class="code"><pre>
 <div class="code"><pre>
- (length of input line / 2) &lt;= <em>dmax</em> &lt;= length of input line
+ 50 &lt; <em>dmax</em> &lt;= 100
 </pre></div>
 </pre></div>
 
 
 Hence, if <b>dmax</b> is between 0.5x and 1.0x the line length, you will
 Hence, if <b>dmax</b> is between 0.5x and 1.0x the line length, you will
 always get points created at exactly the beginning, middle and end of
 always get points created at exactly the beginning, middle and end of
 the input line.
 the input line.
 
 
+<p>
+Use the <b>-r</b> flag to create points starting from the end node.
+
 <h2>EXAMPLE</h2>
 <h2>EXAMPLE</h2>
 
 
 In this example, the 'railroads' vector lines map of the North Carolina
 In this example, the 'railroads' vector lines map of the North Carolina

+ 114 - 3
vector/v.to.points/write.c

@@ -9,6 +9,11 @@ static struct line_cats *PCats;
 static struct line_pnts *PPoints;
 static struct line_pnts *PPoints;
 static int point_cat = 1;
 static int point_cat = 1;
 
 
+static void write_line_forward(struct Map_info *, struct line_pnts *, int, int,
+			       int, double, dbDriver *, struct field_info *);
+static void write_line_backward(struct Map_info *, struct line_pnts *, int, int,
+				int, double, dbDriver *, struct field_info *);
+
 void write_point(struct Map_info *Out, double x, double y, double z,
 void write_point(struct Map_info *Out, double x, double y, double z,
 		 int line_cat, double along, dbDriver *driver, struct field_info *Fi)
 		 int line_cat, double along, dbDriver *driver, struct field_info *Fi)
 {
 {
@@ -57,8 +62,21 @@ void write_point(struct Map_info *Out, double x, double y, double z,
 }
 }
 
 
 void write_line(struct Map_info *Out, struct line_pnts *LPoints, int cat,
 void write_line(struct Map_info *Out, struct line_pnts *LPoints, int cat,
-		int vertex, int interpolate, double dmax,
-                dbDriver *driver, struct field_info *Fi)
+		int vertex, int interpolate, int reverse, double dmax,
+		dbDriver *driver, struct field_info *Fi)
+{
+    if (reverse == 0)
+	write_line_forward(Out, LPoints, cat, vertex, interpolate, dmax,
+			   driver, Fi);
+    else
+	write_line_backward(Out, LPoints, cat, vertex, interpolate, dmax,
+			    driver, Fi);
+}
+
+static void write_line_forward(struct Map_info *Out, struct line_pnts *LPoints,
+			       int cat, int vertex, int interpolate,
+			       double dmax, dbDriver *driver,
+			       struct field_info *Fi)
 {
 {
     if (vertex == GV_VERTEX || vertex == GV_NODE) {	/* use line vertices */
     if (vertex == GV_VERTEX || vertex == GV_NODE) {	/* use line vertices */
 	double along;
 	double along;
@@ -71,6 +89,8 @@ void write_line(struct Map_info *Out, struct line_pnts *LPoints, int cat,
 	    if (vertex == GV_VERTEX ||
 	    if (vertex == GV_VERTEX ||
 		(vertex == GV_NODE &&
 		(vertex == GV_NODE &&
 		 (vert == 0 || vert == LPoints->n_points - 1))) {
 		 (vert == 0 || vert == LPoints->n_points - 1))) {
+		if (vert == LPoints->n_points - 1)
+		    along = Vect_line_length(LPoints);
 		write_point(Out, LPoints->x[vert], LPoints->y[vert],
 		write_point(Out, LPoints->x[vert], LPoints->y[vert],
 			    LPoints->z[vert], cat, along, driver, Fi);
 			    LPoints->z[vert], cat, along, driver, Fi);
 	    }
 	    }
@@ -84,7 +104,7 @@ void write_line(struct Map_info *Out, struct line_pnts *LPoints, int cat,
 		len = hypot(hypot(dx, dy), dz);
 		len = hypot(hypot(dx, dy), dz);
 
 
 		/* interpolate segment */
 		/* interpolate segment */
-		if (vertex == GV_VERTEX && interpolate) {
+		if (interpolate && vertex == GV_VERTEX) {
 		    int i, n;
 		    int i, n;
 		    double x, y, z, dlen;
 		    double x, y, z, dlen;
 
 
@@ -143,3 +163,94 @@ void write_line(struct Map_info *Out, struct line_pnts *LPoints, int cat,
 	}
 	}
     }
     }
 }
 }
+
+static void write_line_backward(struct Map_info *Out, struct line_pnts *LPoints,
+				int cat, int vertex, int interpolate,
+				double dmax, dbDriver *driver,
+				struct field_info *Fi)
+{
+    if (vertex == GV_VERTEX || vertex == GV_NODE) {	/* use line vertices */
+	double along;
+	int vert;
+
+	along = Vect_line_length(LPoints);
+	for (vert = LPoints->n_points - 1; vert >= 0; vert--) {
+	    G_debug(3, "vert = %d", vert);
+
+	    if (vertex == GV_VERTEX ||
+		(vertex == GV_NODE &&
+		 (vert == 0 || vert == LPoints->n_points - 1))) {
+		if (vert == 0)
+		    along = 0;
+		write_point(Out, LPoints->x[vert], LPoints->y[vert],
+			    LPoints->z[vert], cat, along, driver, Fi);
+	    }
+
+	    if (vert > 0) {
+		double dx, dy, dz, len;
+
+		dx = LPoints->x[vert - 1] - LPoints->x[vert];
+		dy = LPoints->y[vert - 1] - LPoints->y[vert];
+		dz = LPoints->z[vert - 1] - LPoints->z[vert];
+		len = hypot(hypot(dx, dy), dz);
+
+		/* interpolate segment */
+		if (interpolate && vertex == GV_VERTEX) {
+		    int i, n;
+		    double x, y, z, dlen;
+
+		    if (len > dmax) {
+			n = len / dmax + 1;	/* number of segments */
+			dx /= n;
+			dy /= n;
+			dz /= n;
+			dlen = len / n;
+
+			for (i = 1; i < n; i++) {
+			    x = LPoints->x[vert] + i * dx;
+			    y = LPoints->y[vert] + i * dy;
+			    z = LPoints->z[vert] + i * dz;
+
+			    write_point(Out, x, y, z, cat, along - i * dlen,
+					driver, Fi);
+			}
+		    }
+		}
+		along -= len;
+	    }
+	}
+    }
+    else {			/* do not use vertices */
+	int i, n;
+	double len, dlen, along, x, y, z;
+
+	len = Vect_line_length(LPoints);
+	n = len / dmax + 1;	/* number of segments */
+	dlen = len / n;		/* length of segment */
+
+	G_debug(3, "n = %d len = %f dlen = %f", n, len, dlen);
+
+	for (i = 0; i <= n; i++) {
+	    if (i > 0 && i < n) {
+		along = len - i * dlen;
+		Vect_point_on_line(LPoints, along, &x, &y, &z, NULL, NULL);
+	    }
+	    else {		/* first and last vertex */
+		if (i == 0) {
+		    along = len;
+		    x = LPoints->x[LPoints->n_points - 1];
+		    y = LPoints->y[LPoints->n_points - 1];
+		    z = LPoints->z[LPoints->n_points - 1];
+		}
+		else {		/* last */
+		    along = 0;
+		    x = LPoints->x[0];
+		    y = LPoints->y[0];
+		    z = LPoints->z[0];
+		}
+	    }
+	    G_debug(3, "  i = %d along = %f", i, along);
+	    write_point(Out, x, y, z, cat, along, driver, Fi);
+	}
+    }
+}