source: grass/trunk/vector/v.to.points/main.c

Last change on this file was 74283, checked in by martinl, 5 years ago

v.to.points: new option use=start/end [news]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 9.7 KB
Line 
1
2/***************************************************************
3 *
4 * MODULE: v.to.points
5 *
6 * AUTHOR(S): Radim Blazek
7 * OGR support by Martin Landa <landa.martin gmail.com>
8 *
9 * PURPOSE: Create points along lines
10 *
11 * COPYRIGHT: (C) 2002-2019 by the GRASS Development Team
12 *
13 * This program is free software under the GNU General
14 * Public License (>=v2). Read the file COPYING that
15 * comes with GRASS for details.
16 *
17 **************************************************************/
18#include <stdlib.h>
19#include <string.h>
20#include <math.h>
21#include <grass/gis.h>
22#include <grass/vector.h>
23#include <grass/dbmi.h>
24#include <grass/glocale.h>
25
26#include "local_proto.h"
27
28int main(int argc, char **argv)
29{
30 int field, type, vertex_type;
31 double dmax;
32 char buf[DB_SQL_MAX];
33
34 struct {
35 struct Option *input, *output, *type, *dmax, *lfield, *use;
36 } opt;
37 struct {
38 struct Flag *table, *inter, *percent, *reverse;
39 } flag;
40 struct GModule *module;
41 struct Map_info In, Out;
42 struct line_cats *LCats;
43 struct line_pnts *LPoints;
44
45 dbDriver *driver;
46 struct field_info *Fi;
47
48 dbString stmt;
49
50 G_gisinit(argv[0]);
51
52 module = G_define_module();
53 G_add_keyword(_("vector"));
54 G_add_keyword(_("geometry"));
55 G_add_keyword("3D");
56 G_add_keyword(_("line"));
57 G_add_keyword(_("node"));
58 G_add_keyword(_("vertex"));
59 G_add_keyword(_("point"));
60 module->description =
61 _("Creates points along input lines in new vector map with 2 layers.");
62
63 opt.input = G_define_standard_option(G_OPT_V_INPUT);
64
65 opt.lfield = G_define_standard_option(G_OPT_V_FIELD);
66 opt.lfield->label = "Line layer number or name";
67 opt.lfield->guisection = _("Selection");
68
69 opt.type = G_define_standard_option(G_OPT_V3_TYPE);
70 opt.type->answer = "point,line,boundary,centroid,face";
71 opt.type->guisection = _("Selection");
72
73 opt.output = G_define_standard_option(G_OPT_V_OUTPUT);
74
75 opt.use = G_define_option();
76 opt.use->key = "use";
77 opt.use->type = TYPE_STRING;
78 opt.use->required = NO;
79 opt.use->description = _("Use line nodes (start/end) or vertices only");
80 opt.use->options = "node,start,end,vertex";
81
82 opt.dmax = G_define_option();
83 opt.dmax->key = "dmax";
84 opt.dmax->type = TYPE_DOUBLE;
85 opt.dmax->required = NO;
86 opt.dmax->answer = "100";
87 opt.dmax->description = _("Maximum distance between points in map units or percentage with -p");
88
89 flag.inter = G_define_flag();
90 flag.inter->key = 'i';
91 flag.inter->description = _("Interpolate points between line vertices (only for use=vertex)");
92
93 flag.percent = G_define_flag();
94 flag.percent->key = 'p';
95 flag.percent->description = _("Use dmax as percentage of line length");
96
97 flag.reverse = G_define_flag();
98 flag.reverse->key = 'r';
99 flag.reverse->description = _("Start from the end node");
100
101 flag.table = G_define_standard_flag(G_FLG_V_TABLE);
102
103 if (G_parser(argc, argv))
104 exit(EXIT_FAILURE);
105
106 LCats = Vect_new_cats_struct();
107 LPoints = Vect_new_line_struct();
108 db_init_string(&stmt);
109
110 type = Vect_option_to_types(opt.type);
111 dmax = atof(opt.dmax->answer);
112 if (dmax <= 0)
113 G_fatal_error(_("Option %s must be positive"), opt.dmax->key);
114
115 vertex_type = 0;
116 if (opt.use->answer) {
117 switch (opt.use->answer[0]) {
118 case 'n':
119 vertex_type = GV_NODE;
120 break;
121 case 's':
122 vertex_type = GV_START;
123 break;
124 case 'e':
125 vertex_type = GV_END;
126 break;
127 default:
128 vertex_type = GV_VERTEX;
129 break;
130 }
131 }
132
133 if (flag.inter->answer && vertex_type != GV_VERTEX) {
134 G_warning(_("Flag -%c ignored (requires %s=%s)"), flag.inter->key,
135 opt.use->key, "vertex");
136 flag.inter->answer = FALSE;
137 }
138 if (flag.reverse->answer && (vertex_type == GV_START || vertex_type == GV_END)) {
139 G_warning(_("Flag -%c ignored (reason %s=%s)"), flag.reverse->key,
140 opt.use->key, opt.use->answer);
141 flag.reverse->answer = FALSE;
142 }
143 Vect_check_input_output_name(opt.input->answer, opt.output->answer,
144 G_FATAL_EXIT);
145
146 /* Open input lines */
147 Vect_set_open_level(2);
148
149 if (Vect_open_old2(&In, opt.input->answer, "", opt.lfield->answer) < 0)
150 G_fatal_error(_("Unable to open vector map <%s>"), opt.input->answer);
151
152 Vect_set_error_handler_io(&In, &Out);
153
154 field = Vect_get_field_number(&In, opt.lfield->answer);
155
156 /* Open output segments */
157 if (Vect_open_new(&Out, opt.output->answer, Vect_is_3d(&In)) < 0)
158 G_fatal_error(_("Unable to create vector map <%s>"),
159 opt.output->answer);
160
161 Vect_copy_head_data(&In, &Out);
162 Vect_hist_copy(&In, &Out);
163 Vect_hist_command(&Out);
164
165 /* Table */
166 driver = NULL;
167 Fi = NULL;
168 if (!flag.table->answer) {
169 struct field_info *Fin;
170
171 /* copy input table */
172 Fin = Vect_get_field(&In, field);
173 if (Fin) { /* table defined */
174 int ret;
175
176 Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE);
177 Vect_map_add_dblink(&Out, 1, NULL, Fi->table, Fin->key,
178 Fi->database, Fi->driver);
179
180 ret = db_copy_table(Fin->driver, Fin->database, Fin->table,
181 Fi->driver, Vect_subst_var(Fi->database,
182 &Out), Fi->table);
183
184 if (ret == DB_FAILED) {
185 G_fatal_error(_("Unable to copy table <%s>"),
186 Fin->table);
187 }
188 }
189
190 Fi = Vect_default_field_info(&Out, 2, NULL, GV_MTABLE);
191 Vect_map_add_dblink(&Out, 2, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
192 Fi->driver);
193
194 /* Open driver */
195 driver = db_start_driver_open_database(Fi->driver, Fi->database);
196 if (driver == NULL)
197 G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
198 Fi->database, Fi->driver);
199 db_set_error_handler_driver(driver);
200
201 if (field == -1)
202 sprintf(buf,
203 "create table %s ( cat int, along double precision )",
204 Fi->table);
205 else
206 sprintf(buf,
207 "create table %s ( cat int, lcat int, along double precision )",
208 Fi->table);
209 db_append_string(&stmt, buf);
210
211 if (db_execute_immediate(driver, &stmt) != DB_OK) {
212 G_fatal_error(_("Unable to create table: '%s'"),
213 db_get_string(&stmt));
214 }
215
216 if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
217 G_warning(_("Unable to create index for table <%s>, key <%s>"),
218 Fi->table, GV_KEY_COLUMN);
219
220 if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT,
221 DB_GROUP | DB_PUBLIC) != DB_OK)
222 G_fatal_error(_("Unable to grant privileges on table <%s>"),
223 Fi->table);
224
225 db_begin_transaction(driver);
226 }
227
228 if (type & (GV_POINTS | GV_LINES | GV_FACE)) {
229 int line, nlines, nskipped;
230
231 nskipped = 0;
232 nlines = Vect_get_num_lines(&In);
233 for (line = 1; line <= nlines; line++) {
234 int ltype, cat;
235
236 G_debug(3, "line = %d", line);
237 G_percent(line, nlines, 2);
238
239 ltype = Vect_read_line(&In, LPoints, LCats, line);
240 if (!(ltype & type))
241 continue;
242 if (!Vect_cat_get(LCats, field, &cat) && field != -1) {
243 nskipped++;
244 continue;
245 }
246
247 /* Assign CAT for layer 0 objects (i.e. boundaries) */
248 if (field == -1)
249 cat = -1;
250
251 if (LPoints->n_points <= 1) {
252 write_point(&Out, LPoints->x[0], LPoints->y[0], LPoints->z[0],
253 cat, 0.0, driver, Fi);
254 }
255 else if (flag.percent->answer) { /* lines */
256 double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
257 write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
258 flag.reverse->answer, dmaxlen, driver, Fi);
259 } else {
260 write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
261 flag.reverse->answer, dmax, driver, Fi);
262 }
263 }
264
265 if (nskipped > 0)
266 G_warning(_("%d features without category in layer <%d> skipped. "
267 "Note that features without category (usually boundaries) are not "
268 "skipped when '%s=-1' is given."),
269 nskipped, field, opt.lfield->key);
270 }
271
272 if (type == GV_AREA) {
273 int area, nareas, centroid, cat;
274
275 nareas = Vect_get_num_areas(&In);
276 for (area = 1; area <= nareas; area++) {
277 int i, isle, nisles;
278
279 G_percent(area, nareas, 2);
280
281 centroid = Vect_get_area_centroid(&In, area);
282 cat = -1;
283 if (centroid > 0) {
284 Vect_read_line(&In, NULL, LCats, centroid);
285 if (!Vect_cat_get(LCats, field, &cat))
286 continue;
287 }
288
289 Vect_get_area_points(&In, area, LPoints);
290
291 if (flag.percent->answer) {
292 double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
293 write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
294 flag.reverse->answer, dmaxlen, driver, Fi);
295 } else {
296 write_line(&Out, LPoints, cat, vertex_type, flag.inter->answer,
297 flag.reverse->answer, dmax, driver, Fi);
298 }
299
300 nisles = Vect_get_area_num_isles(&In, area);
301
302 for (i = 0; i < nisles; i++) {
303 isle = Vect_get_area_isle(&In, area, i);
304 Vect_get_isle_points(&In, isle, LPoints);
305
306 if (flag.percent->answer) {
307 double dmaxlen = Vect_line_length(LPoints) * dmax / 100.0;
308 write_line(&Out, LPoints, cat, vertex_type,
309 flag.inter->answer, flag.reverse->answer,
310 dmaxlen, driver, Fi);
311 } else {
312 write_line(&Out, LPoints, cat, vertex_type,
313 flag.inter->answer, flag.reverse->answer, dmax,
314 driver, Fi);
315 }
316 }
317 }
318 }
319
320 if (!flag.table->answer) {
321 db_commit_transaction(driver);
322 db_close_database_shutdown_driver(driver);
323 }
324
325 Vect_build(&Out);
326
327 /* Free, close ... */
328 Vect_close(&In);
329
330 G_done_msg(_("%d points written to output vector map."),
331 Vect_get_num_primitives(&Out, GV_POINT));
332
333 Vect_close(&Out);
334
335 exit(EXIT_SUCCESS);
336}
Note: See TracBrowser for help on using the repository browser.