#include #include #include #include #include #include "local_proto.h" static int srch(const void *, const void *); /*! \brief transform 3d vector features to 2d (z-coordinate is omitted) \param In input vector \param Out output vector \param type feature type to be transformed \param field layer number \param zcolumn attribute column where to store height */ void trans3d(struct Map_info *In, struct Map_info *Out, int type, const char *field_name, const char *zcolumn) { int ltype, line; int ctype; int field; struct line_pnts *Points; struct line_cats *Cats; struct field_info *Fi; dbDriver *driver; dbString stmt; char buf[2000]; int ncats, *cats, cat, *cex; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); db_init_string(&stmt); field = Vect_get_field_number(In, field_name); if (zcolumn) { if (field == -1) { G_warning(_("Invalid layer number %d, assuming 1"), field); field = 1; } Fi = Vect_get_field(Out, field); if (!Fi) { G_fatal_error(_("Database connection not defined for layer <%s>"), field_name); } driver = db_start_driver_open_database(Fi->driver, Fi->database); if (!driver) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); } db_set_error_handler_driver(driver); /* column type must numeric */ ctype = db_column_Ctype(driver, Fi->table, zcolumn); if (ctype == -1) { G_fatal_error(_("Column <%s> not found in table <%s>"), zcolumn, Fi->table); } if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE) { G_fatal_error(_("Column must be numeric")); } db_begin_transaction(driver); /* select existing categories (layer) to array (array is sorted) */ G_message(_("Reading categories...")); ncats = db_select_int(driver, Fi->table, Fi->key, NULL, &cats); G_debug(3, "Existing categories: %d", ncats); } G_message(_("Transforming features...")); line = 1; while (1) { ltype = Vect_read_next_line(In, Points, Cats); if (ltype == -1) { G_fatal_error(_("Unable to read vector map")); } if (ltype == -2) { /* EOF */ break; } G_progress(line, 1000); if (!(ltype & type)) continue; if (field != -1 && !Vect_cat_get(Cats, field, &cat)) continue; /* get first cat */ if (cat == -1) { G_warning(_("Feature id %d has no category - skipping"), line); } else if (Cats->n_cats > 1) { G_warning(_("Feature id %d has more categories. " "Using category %d."), line, cat); } if (zcolumn && ltype & (GV_POINT | GV_LINE) && cat > -1) { /* category exist in table ? */ cex = (int *)bsearch((void *)&cat, cats, ncats, sizeof(int), srch); /* store height to the attribute table */ if (ctype == DB_C_TYPE_INT) sprintf(buf, "update %s set %s = %d where cat = %d", Fi->table, zcolumn, (int)Points->z[0], cat); else /* double */ sprintf(buf, "update %s set %s = %.8f where cat = %d", Fi->table, zcolumn, Points->z[0], cat); G_debug(3, "SQL: %s", buf); db_set_string(&stmt, buf); if (cex) { if (db_execute_immediate(driver, &stmt) == DB_OK) { /* TODO */ } } else { /* cat does not exist in table */ G_warning(_("Record (cat %d) does not exist (not updated)"), cat); } } Vect_write_line(Out, ltype, Points, Cats); line++; } G_progress(1, 1); if (zcolumn) { db_commit_transaction(driver); G_free(cats); db_close_database_shutdown_driver(driver); db_free_string(&stmt); } Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); } int srch(const void *pa, const void *pb) { int *p1 = (int *)pa; int *p2 = (int *)pb; if (*p1 < *p2) return -1; if (*p1 > *p2) return 1; return 0; }