|
@@ -37,18 +37,25 @@ int main(int argc, char **argv)
|
|
|
struct Option *map, *output, *method_opt;
|
|
|
struct Option *afield_opt, *nfield_opt, *afcol, *abcol, *ncol, *type_opt,
|
|
|
*term_opt, *tfield_opt, *tucfield_opt;
|
|
|
- struct Flag *geo_f, *turntable_f;
|
|
|
+ struct Flag *geo_f, *turntable_f, *ucat_f;
|
|
|
struct GModule *module;
|
|
|
struct Map_info Map, Out;
|
|
|
struct cat_list *catlist;
|
|
|
CENTER *Centers = NULL;
|
|
|
int acenters = 0, ncenters = 0;
|
|
|
NODE *Nodes;
|
|
|
- struct line_cats *Cats;
|
|
|
+ struct line_cats *Cats, *ICats, *OCats;
|
|
|
struct line_pnts *Points, *SPoints;
|
|
|
int graph_version;
|
|
|
int from_centers;
|
|
|
|
|
|
+ /* Attribute table */
|
|
|
+ int unique_cats, ucat, ocat, n;
|
|
|
+ char buf[2000];
|
|
|
+ dbString sql;
|
|
|
+ dbDriver *driver;
|
|
|
+ struct field_info *Fi;
|
|
|
+
|
|
|
/* initialize GIS environment */
|
|
|
G_gisinit(argv[0]); /* reads grass env, stores program name to G_program_name() */
|
|
|
|
|
@@ -150,12 +157,20 @@ int main(int argc, char **argv)
|
|
|
geo_f->description =
|
|
|
_("Use geodesic calculation for longitude-latitude locations");
|
|
|
|
|
|
+ ucat_f = G_define_flag();
|
|
|
+ ucat_f->key = 'u';
|
|
|
+ ucat_f->label =
|
|
|
+ _("Create unique categories and attribute table");
|
|
|
+ ucat_f->description =
|
|
|
+ _("Default: same category like nearest center");
|
|
|
+
|
|
|
if (G_parser(argc, argv))
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
Vect_check_input_output_name(map->answer, output->answer, G_FATAL_EXIT);
|
|
|
|
|
|
Cats = Vect_new_cats_struct();
|
|
|
+ OCats = Vect_new_cats_struct();
|
|
|
Points = Vect_new_line_struct();
|
|
|
SPoints = Vect_new_line_struct();
|
|
|
|
|
@@ -164,6 +179,8 @@ int main(int argc, char **argv)
|
|
|
catlist = Vect_new_cat_list();
|
|
|
Vect_str_to_cat_list(term_opt->answer, catlist);
|
|
|
|
|
|
+ unique_cats = ucat_f->answer;
|
|
|
+
|
|
|
if (geo_f->answer)
|
|
|
geo = 1;
|
|
|
else
|
|
@@ -274,13 +291,63 @@ int main(int argc, char **argv)
|
|
|
|
|
|
Vect_hist_command(&Out);
|
|
|
|
|
|
+ Fi = NULL;
|
|
|
+ driver = NULL;
|
|
|
+ if (unique_cats) {
|
|
|
+ /* create attribute table:
|
|
|
+ * cat: new category
|
|
|
+ * ocat: original category in afield
|
|
|
+ * centre: nearest centre
|
|
|
+ */
|
|
|
+ Fi = Vect_default_field_info(&Out, 1, NULL, GV_MTABLE);
|
|
|
+ Vect_map_add_dblink(&Out, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
|
|
|
+ Fi->driver);
|
|
|
+
|
|
|
+ driver = db_start_driver_open_database(Fi->driver, Fi->database);
|
|
|
+ if (driver == NULL)
|
|
|
+ G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
|
|
|
+ Fi->database, Fi->driver);
|
|
|
+ db_set_error_handler_driver(driver);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "create table %s ( %s integer, ocat integer, center integer )",
|
|
|
+ Fi->table, GV_KEY_COLUMN);
|
|
|
+
|
|
|
+ db_init_string(&sql);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(2, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
|
|
|
+ G_warning(_("Cannot create index"));
|
|
|
+
|
|
|
+ if (db_grant_on_table
|
|
|
+ (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
|
|
|
+ G_fatal_error(_("Cannot grant privileges on table <%s>"), Fi->table);
|
|
|
+
|
|
|
+ db_begin_transaction(driver);
|
|
|
+ }
|
|
|
+
|
|
|
nlines = Vect_get_num_lines(&Map);
|
|
|
+ ucat = 1;
|
|
|
for (line = 1; line <= nlines; line++) {
|
|
|
- ltype = Vect_read_line(&Map, Points, NULL, line);
|
|
|
+ ltype = Vect_read_line(&Map, Points, ICats, line);
|
|
|
if (!(ltype & type)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_reset_cats(OCats);
|
|
|
+ for (n = 0; n < ICats->n_cats; n++) {
|
|
|
+ if (ICats->field[n] == afield) {
|
|
|
+ Vect_cat_set(OCats, 2, ICats->cat[n]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (turntable_f->answer) {
|
|
|
center1 = Nodes[line * 2].center;
|
|
|
center2 = Nodes[line * 2 + 1].center;
|
|
@@ -331,7 +398,30 @@ int main(int argc, char **argv)
|
|
|
cat = Centers[center1].cat; /* line reachable */
|
|
|
else
|
|
|
cat = Centers[center2].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
}
|
|
|
else { /* each node in different area */
|
|
@@ -340,7 +430,30 @@ int main(int argc, char **argv)
|
|
|
G_debug(3,
|
|
|
" -> arc is not reachable from 1. node -> alloc to 2. node");
|
|
|
cat = Centers[center2].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
continue;
|
|
|
}
|
|
@@ -348,7 +461,30 @@ int main(int argc, char **argv)
|
|
|
G_debug(3,
|
|
|
" -> arc is not reachable from 2. node -> alloc to 1. node");
|
|
|
cat = Centers[center1].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
continue;
|
|
|
}
|
|
@@ -362,12 +498,59 @@ int main(int argc, char **argv)
|
|
|
* Note this check also possibility of (e1cost + e2cost) = 0 */
|
|
|
if (s1cost + e1cost <= s2cost) { /* whole arc reachable from node1 */
|
|
|
cat = Centers[center1].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ Vect_reset_cats(Cats);
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
}
|
|
|
else if (s2cost + e2cost <= s1cost) { /* whole arc reachable from node2 */
|
|
|
cat = Centers[center2].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
}
|
|
|
else { /* split */
|
|
@@ -395,7 +578,30 @@ int main(int argc, char **argv)
|
|
|
}
|
|
|
else {
|
|
|
cat = Centers[center1].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, SPoints, Cats);
|
|
|
}
|
|
|
|
|
@@ -408,7 +614,30 @@ int main(int argc, char **argv)
|
|
|
else {
|
|
|
Vect_reset_cats(Cats);
|
|
|
cat = Centers[center2].cat;
|
|
|
- Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d')",
|
|
|
+ Fi->table, ucat, ocat, cat);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ Vect_cat_set(Cats, 1, cat);
|
|
|
+
|
|
|
Vect_write_line(&Out, ltype, SPoints, Cats);
|
|
|
}
|
|
|
}
|
|
@@ -417,10 +646,37 @@ int main(int argc, char **argv)
|
|
|
else {
|
|
|
/* arc is not reachable */
|
|
|
G_debug(3, " -> arc is not reachable");
|
|
|
+ if (unique_cats) {
|
|
|
+ Vect_cat_set(Cats, 1, ucat);
|
|
|
+ for (n = 0; n < OCats->n_cats; n++) {
|
|
|
+ Vect_cat_set(Cats, 2, OCats->cat[n]);
|
|
|
+ }
|
|
|
+ ocat = -1;
|
|
|
+ Vect_cat_get(ICats, afield, &ocat);
|
|
|
+
|
|
|
+ sprintf(buf,
|
|
|
+ "insert into %s values ( %d, %d, %d)",
|
|
|
+ Fi->table, ucat, ocat, -1);
|
|
|
+ db_set_string(&sql, buf);
|
|
|
+ G_debug(3, "%s", db_get_string(&sql));
|
|
|
+
|
|
|
+ if (db_execute_immediate(driver, &sql) != DB_OK) {
|
|
|
+ G_fatal_error(_("Cannot insert new record: %s"),
|
|
|
+ db_get_string(&sql));
|
|
|
+ }
|
|
|
+ ucat++;
|
|
|
+ }
|
|
|
Vect_write_line(&Out, ltype, Points, Cats);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (unique_cats) {
|
|
|
+ db_commit_transaction(driver);
|
|
|
+ db_close_database_shutdown_driver(driver);
|
|
|
+
|
|
|
+ Vect_copy_table(&Map, &Out, afield, 2, NULL, GV_MTABLE);
|
|
|
+ }
|
|
|
+
|
|
|
Vect_build(&Out);
|
|
|
|
|
|
/* Free, ... */
|