/*! \brief Write (dump) category index in text form to file \param Map pointer to Map_info structure \param[out] out output file \return 1 on success \return 0 on error */ int Vect_cidx_dump(const struct Map_info *Map, FILE * out) { int i, field, nfields, ntypes; G_debug(2, "Vect_cidx_dump()"); check_status(Map); nfields = Vect_cidx_get_num_fields(Map); fprintf(out, "---------- CATEGORY INDEX DUMP: Number of layers: %d " "--------------------------------------\n", nfields); for (i = 0; i < nfields; i++) { int j, nucats, ncats; field = Vect_cidx_get_field_number(Map, i); nucats = Vect_cidx_get_num_unique_cats_by_index(Map, i); ncats = Vect_cidx_get_num_cats_by_index(Map, i); ntypes = Vect_cidx_get_num_types_by_index(Map, i); fprintf(out, "Layer %6d number of unique cats: %7d number of " "cats: %7d number of types: %d\n", field, nucats, ncats, ntypes); fprintf(out, SEP); fprintf(out, " type | count\n"); for (j = 0; j < ntypes; j++) { int type, count; Vect_cidx_get_type_count_by_index(Map, i, j, &type, &count); fprintf(out, " %5d | %9d\n", type, count); } fprintf(out, " category | type | line/area\n"); for (j = 0; j < ncats; j++) { int cat, type, id; Vect_cidx_get_cat_by_index(Map, i, j, &cat, &type, &id); fprintf(out, "%9d | %4d | %9d\n", cat, type, id); } fprintf(out, SEP); } return 1; }
// Slot called when the "Add GRASS vector layer" menu item is triggered void QgsGrassPlugin::addVector() { // QgsDebugMsg("entered."); QString uri; QgsGrassSelect *sel = new QgsGrassSelect( qGisInterface->mainWindow(), QgsGrassSelect::VECTOR ); if ( sel->exec() ) { uri = sel->gisdbase + "/" + sel->location + "/" + sel->mapset + "/" + sel->map + "/" + sel->layer; } // QgsDebugMsg(QString("plugin URI: %1").arg(uri)); if ( uri.length() == 0 ) { // QgsDebugMsg("Nothing was selected"); return; } else { // QgsDebugMsg("Add new vector layer"); // create vector name: vector layer QString name = sel->map; QString field; QString type; if ( !sel->layer.startsWith( "topo_" ) ) { QRegExp rx( "(\\d+)_(.+)" ); if ( rx.indexIn( sel->layer ) != -1 ) { field = rx.cap( 1 ); type = rx.cap( 2 ); } } // Set location QgsGrass::setLocation( sel->gisdbase, sel->location ); /* Open vector */ try { //Vect_set_open_level( 2 ); struct Map_info map; int level = Vect_open_old_head( &map, sel->map.toUtf8().data(), sel->mapset.toUtf8().data() ); if ( level == 1 ) { QgsDebugMsg( "Cannot open vector on level 2" ); QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open vector %1 in mapset %2 on level 2 (topology not available, try to rebuild topology using v.build module)." ).arg( sel->map ).arg( sel->mapset ) ); Vect_close( &map ); return; } else if ( level < 1 ) { QgsDebugMsg( "Cannot open vector" ); QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open vector %1 in mapset %2" ).arg( sel->map ).arg( sel->mapset ) ); return; } if ( level >= 2 ) { if ( !sel->layer.startsWith( "topo_" ) ) { // Count layers int cnt = 0; int ncidx = Vect_cidx_get_num_fields( &map ); for ( int i = 0; i < ncidx; i++ ) { int field = Vect_cidx_get_field_number( &map, i ); if ( Vect_cidx_get_type_count( &map, field, GV_POINT | GV_LINE | GV_AREA ) > 0 || ( field > 1 && Vect_cidx_get_type_count( &map, field, GV_BOUNDARY ) ) ) { cnt++; } } if ( cnt > 1 ) { name.append( " " + field ); // No need to ad type, the type is obvious from the legend } } else { name.append( " " + sel->layer ); } } Vect_close( &map ); } catch ( QgsGrass::Exception &e ) { QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open GRASS vector:\n %1" ).arg( e.what() ) ); } qGisInterface->addVectorLayer( uri, name, "grass" ); } }
QStringList QgsGrassSelect::vectorLayers( QString gisdbase, QString location, QString mapset, QString mapName ) { QStringList list; // Set location QgsGrass::setLocation( gisdbase, location ); /* Open vector */ QgsGrass::resetError(); //Vect_set_open_level( 2 ); struct Map_info map; int level = -1; try { level = Vect_open_old_head( &map, ( char * ) mapName.toUtf8().data(), ( char * ) mapset.toUtf8().data() ); } catch ( QgsGrass::Exception &e ) { Q_UNUSED( e ); QgsDebugMsg( QString( "Cannot open GRASS vector: %1" ).arg( e.what() ) ); return list; } if ( level == 1 ) { QgsDebugMsg( "Cannot open vector on level 2" ); QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open vector %1 in mapset %2 on level 2 (topology not available, try to rebuild topology using v.build module)." ).arg( mapName ).arg( mapset ) ); // Vect_close here is correct, it should work, but it seems to cause // crash on win http://trac.osgeo.org/qgis/ticket/2003 // disabled on win test it #if !defined(WIN32) Vect_close( &map ); #endif return list; } else if ( level < 1 ) { QgsDebugMsg( "Cannot open vector" ); QMessageBox::warning( 0, tr( "Warning" ), tr( "Cannot open vector %1 in mapset %2" ).arg( mapName ).arg( mapset ) ); return list; } QgsDebugMsg( "GRASS vector successfully opened" ); // Get layers int ncidx = Vect_cidx_get_num_fields( &map ); for ( int i = 0; i < ncidx; i++ ) { int field = Vect_cidx_get_field_number( &map, i ); QString fs; fs.sprintf( "%d", field ); QgsDebugMsg( QString( "i = %1 layer = %2" ).arg( i ).arg( field ) ); /* Points */ int npoints = Vect_cidx_get_type_count( &map, field, GV_POINT ); if ( npoints > 0 ) { QString l = fs + "_point"; list.append( l ); } /* Lines */ /* Lines without category appears in layer 0, but not boundaries */ int tp; if ( field == 0 ) tp = GV_LINE; else tp = GV_LINE | GV_BOUNDARY; int nlines = Vect_cidx_get_type_count( &map, field, tp ); if ( nlines > 0 ) { QString l = fs + "_line"; list.append( l ); } /* Polygons */ int nareas = Vect_cidx_get_type_count( &map, field, GV_AREA ); if ( nareas > 0 ) { QString l = fs + "_polygon"; list.append( l ); } } Vect_close( &map ); return list; }
OGRGRASSLayer::OGRGRASSLayer( int layerIndex, struct Map_info * map ) { CPLDebug ( "GRASS", "OGRGRASSLayer::OGRGRASSLayer layerIndex = %d", layerIndex ); iLayerIndex = layerIndex; poMap = map; poSRS = NULL; iNextId = 0; poPoints = Vect_new_line_struct(); poCats = Vect_new_cats_struct(); pszQuery = NULL; paQueryMatch = NULL; paSpatialMatch = NULL; iLayer = Vect_cidx_get_field_number ( poMap, iLayerIndex); CPLDebug ( "GRASS", "iLayer = %d", iLayer ); poLink = Vect_get_field ( poMap, iLayer ); // May be NULL if not defined // Layer name if ( poLink && poLink->name ) { pszName = CPLStrdup( poLink->name ); } else { char buf[20]; sprintf ( buf, "%d", iLayer ); pszName = CPLStrdup( buf ); } // Because we don't represent centroids as any simple feature, we have to scan // category index and create index of feature IDs pointing to category index nTotalCount = Vect_cidx_get_type_count(poMap,iLayer, GV_POINT|GV_LINES|GV_AREA); CPLDebug ( "GRASS", "nTotalCount = %d", nTotalCount ); paFeatureIndex = (int *) CPLMalloc ( nTotalCount * sizeof(int) ); int n = Vect_cidx_get_type_count(poMap,iLayer, GV_POINTS|GV_LINES|GV_AREA); int cnt = 0; for ( int i = 0; i < n; i++ ) { int cat,type, id; Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, i, &cat, &type, &id ); if ( !( type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue; paFeatureIndex[cnt++] = i; } poFeatureDefn = new OGRFeatureDefn( pszName ); poFeatureDefn->Reference(); // Get type definition int nTypes = Vect_cidx_get_num_types_by_index ( poMap, iLayerIndex ); int types = 0; for ( int i = 0; i < nTypes; i++ ) { int type, count; Vect_cidx_get_type_count_by_index ( poMap, iLayerIndex, i, &type, &count); if ( !(type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue; types |= type; CPLDebug ( "GRASS", "type = %d types = %d", type, types ); } OGRwkbGeometryType eGeomType = wkbUnknown; if ( types == GV_LINE || types == GV_BOUNDARY || types == GV_LINES ) { eGeomType = wkbLineString; } else if ( types == GV_POINT ) { eGeomType = wkbPoint; } else if ( types == GV_AREA ) { CPLDebug ( "GRASS", "set wkbPolygon" ); eGeomType = wkbPolygon; } if (Vect_is_3d(poMap)) poFeatureDefn->SetGeomType ( (OGRwkbGeometryType)(eGeomType | wkb25DBit) ); else poFeatureDefn->SetGeomType ( eGeomType ); // Get attributes definition poDbString = (dbString*) CPLMalloc ( sizeof(dbString) ); poCursor = (dbCursor*) CPLMalloc ( sizeof(dbCursor) ); bCursorOpened = FALSE; poDriver = NULL; bHaveAttributes = false; db_init_string ( poDbString ); if ( poLink ) { if ( StartDbDriver() ) { db_set_string ( poDbString, poLink->table ); dbTable *table; if ( db_describe_table ( poDriver, poDbString, &table) == DB_OK ) { nFields = db_get_table_number_of_columns ( table ); iCatField = -1; for ( int i = 0; i < nFields; i++) { dbColumn *column = db_get_table_column ( table, i ); int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) ); OGRFieldType ogrFtype = OFTInteger; switch ( ctype ) { case DB_C_TYPE_INT: ogrFtype = OFTInteger; break; case DB_C_TYPE_DOUBLE: ogrFtype = OFTReal; break; case DB_C_TYPE_STRING: ogrFtype = OFTString; break; case DB_C_TYPE_DATETIME: ogrFtype = OFTDateTime; break; } CPLDebug ( "GRASS", "column = %s type = %d", db_get_column_name(column), ctype ); OGRFieldDefn oField ( db_get_column_name(column), ogrFtype ); poFeatureDefn->AddFieldDefn( &oField ); if ( G_strcasecmp(db_get_column_name(column),poLink->key) == 0 ) { iCatField = i; } } if ( iCatField >= 0 ) { bHaveAttributes = true; } else { CPLError( CE_Failure, CPLE_AppDefined, "Cannot find key field" ); db_close_database_shutdown_driver ( poDriver ); poDriver = NULL; } } else { CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s", poLink->table ); } db_close_database_shutdown_driver ( poDriver ); poDriver = NULL; } } if ( !bHaveAttributes && iLayer > 0 ) // Because features in layer 0 have no cats { OGRFieldDefn oField("cat", OFTInteger); poFeatureDefn->AddFieldDefn( &oField ); } if ( getenv("GISBASE") ) // We have some projection info in GISBASE { struct Key_Value *projinfo, *projunits; // Note: we dont have to reset GISDBASE and LOCATION_NAME because // OGRGRASSLayer constructor is called from OGRGRASSDataSource::Open // where those variables are set projinfo = G_get_projinfo(); projunits = G_get_projunits(); char *srsWkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0); if ( srsWkt ) { poSRS = new OGRSpatialReference ( srsWkt ); CPLFree ( srsWkt ); } G_free_key_value(projinfo); G_free_key_value(projunits); } }
int main(int argc, char *argv[]) { struct Map_info In, Out; static struct line_pnts *Points; struct line_cats *Cats; struct field_info *Fi; struct cat_list *Clist; int i, j, ret, option, otype, type, with_z, step, id; int n_areas, centr, new_centr, nmodified; int open_level; double x, y; int cat, ocat, scat, *fields, nfields, field; struct GModule *module; struct Option *in_opt, *out_opt, *option_opt, *type_opt; struct Option *cat_opt, *field_opt, *step_opt, *id_opt; struct Flag *shell, *notab; FREPORT **freps; int nfreps, rtype, fld; char *desc; module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("category")); G_add_keyword(_("layer")); module->description = _("Attaches, deletes or reports vector categories to map geometry."); in_opt = G_define_standard_option(G_OPT_V_INPUT); field_opt = G_define_standard_option(G_OPT_V_FIELD); field_opt->multiple = YES; field_opt->guisection = _("Selection"); type_opt = G_define_standard_option(G_OPT_V3_TYPE); type_opt->answer = "point,line,centroid,face"; type_opt->guisection = _("Selection"); id_opt = G_define_standard_option(G_OPT_V_IDS); id_opt->label = _("Feature ids (by default all features are processed)"); id_opt->guisection = _("Selection"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = NO; option_opt = G_define_option(); option_opt->key = "option"; option_opt->type = TYPE_STRING; option_opt->required = YES; option_opt->multiple = NO; option_opt->options = "add,del,chlayer,sum,report,print,layers,transfer"; option_opt->description = _("Action to be done"); desc = NULL; G_asprintf(&desc, "add;%s;" "del;%s;" "chlayer;%s;" "sum;%s;" "transfer;%s;" "report;%s;" "print;%s;" "layers;%s", _("add a category to features without category in the given layer"), _("delete category (cat=-1 to delete all categories of given layer)"), _("change layer number (e.g. layer=3,1 changes layer 3 to layer 1)"), _("add the value specified by cat option to the current category value"), _("copy values from one layer to another (e.g. layer=1,2,3 copies values from layer 1 to layer 2 and 3)"), _("print report (statistics), in shell style: layer type count min max"), _("print category values, layers are separated by '|', more cats in the same layer are separated by '/'"), _("print only layer numbers")); option_opt->descriptions = desc; cat_opt = G_define_standard_option(G_OPT_V_CAT); cat_opt->answer = "1"; step_opt = G_define_option(); step_opt->key = "step"; step_opt->type = TYPE_INTEGER; step_opt->required = NO; step_opt->multiple = NO; step_opt->answer = "1"; step_opt->description = _("Category increment"); shell = G_define_flag(); shell->key = 'g'; shell->label = _("Shell script style, currently only for report"); shell->description = _("Format: layer type count min max"); notab = G_define_standard_flag(G_FLG_V_TABLE); notab->description = _("Do not copy attribute table(s)"); G_gisinit(argv[0]); if (G_parser(argc, argv)) exit(EXIT_FAILURE); /* read options */ option = 0; switch (option_opt->answer[0]) { case ('a'): option = O_ADD; break; case ('d'): option = O_DEL; break; case ('c'): option = O_CHFIELD; G_warning(_("Database connection and attribute tables for concerned layers are not changed")); break; case ('s'): option = O_SUM; break; case ('t'): option = O_TRANS; break; case ('r'): option = O_REP; break; case ('p'): option = O_PRN; break; case ('l'): option = O_LYR; break; } if (option == O_LYR) { /* print vector layer numbers */ /* open vector on level 2 head only, this is why this option * is processed here, all other options need (?) to fully open * the input vector */ Vect_set_open_level(2); if (Vect_open_old_head2(&In, in_opt->answer, "", field_opt->answer) < 2) { G_fatal_error(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), 2); } if (In.format == GV_FORMAT_NATIVE) { nfields = Vect_cidx_get_num_fields(&In); for (i = 0; i < nfields; i++) { if ((field = Vect_cidx_get_field_number(&In, i)) > 0) fprintf(stdout, "%d\n", field); } } else fprintf(stdout, "%s\n", field_opt->answer); Vect_close(&In); exit(EXIT_SUCCESS); } cat = atoi(cat_opt->answer); step = atoi(step_opt->answer); otype = Vect_option_to_types(type_opt); if (cat < 0 && option == O_ADD) G_fatal_error(_("Invalid category number (must be equal to or greater than 0). " "Normally category number starts at 1.")); /* collect ids */ if (id_opt->answer) { Clist = Vect_new_cat_list(); Clist->field = atoi(field_opt->answer); ret = Vect_str_to_cat_list(id_opt->answer, Clist); if (ret > 0) { G_warning(n_("%d error in id option", "%d errors in id option", ret), ret); } } else { Clist = NULL; } if ((option != O_REP) && (option != O_PRN) && (option != O_LYR)) { if (out_opt->answer == NULL) G_fatal_error(_("Output vector wasn't entered")); Vect_check_input_output_name(in_opt->answer, out_opt->answer, G_FATAL_EXIT); } Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* do we need topology ? */ if ((option == O_ADD && (otype & GV_AREA)) || (option == O_REP && (otype & GV_AREA)) || (option == O_TRANS) || /* topo for cidx check */ (option == O_LYR)) /* topo for cidx check */ open_level = 2; else open_level = 1; /* open input vector */ if (open_level > 1) { Vect_set_open_level(open_level); if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) { G_warning(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), open_level); open_level = 1; } } if (open_level == 1) { Vect_set_open_level(open_level); if (Vect_open_old2(&In, in_opt->answer, "", field_opt->answer) < open_level) { G_fatal_error(_("Unable to open vector map <%s> at topological level %d"), Vect_get_full_name(&In), open_level); } } /* read fields */ i = nfields = 0; while (field_opt->answers[i++]) nfields++; fields = (int *)G_malloc(nfields * sizeof(int)); i = 0; while (field_opt->answers[i]) { fields[i] = Vect_get_field_number(&In, field_opt->answers[i]); i++; } if (nfields > 1 && option != O_PRN && option != O_CHFIELD && option != O_TRANS) G_fatal_error(_("Too many layers for this operation")); if (nfields != 2 && option == O_CHFIELD) G_fatal_error(_("2 layers must be specified")); if (option == O_TRANS && open_level == 1 && nfields < 2) { G_fatal_error(_("2 layers must be specified")); } if (option == O_TRANS && open_level > 1) { /* check if field[>0] already exists */ if (nfields > 1) { for(i = 1; i < nfields; i++) { if (Vect_cidx_get_field_index(&In, fields[i]) != -1) G_warning(_("Categories already exist in layer %d"), fields[i]); } } /* find next free layer number */ else if (nfields == 1) { int max = -1; for (i = 0; i < Vect_cidx_get_num_fields(&In); i++) { if (max < Vect_cidx_get_field_number(&In, i)) max = Vect_cidx_get_field_number(&In, i); } max++; nfields++; fields = (int *)G_realloc(fields, nfields * sizeof(int)); fields[nfields - 1] = max; } } if (otype & GV_AREA && option == O_TRANS && !(otype & GV_CENTROID)) otype |= GV_CENTROID; /* open output vector if needed */ if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS) { with_z = Vect_is_3d(&In); if (0 > Vect_open_new(&Out, out_opt->answer, with_z)) { Vect_close(&In); exit(EXIT_FAILURE); } Vect_copy_head_data(&In, &Out); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); } id = 0; nmodified = 0; if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS) { G_message(_("Processing features...")); } switch (option) { case (O_ADD): /* Lines */ while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { if ((Vect_cat_get(Cats, fields[0], &ocat)) == 0) { if (ocat < 0) { if (Vect_cat_set(Cats, fields[0], cat) > 0) { nmodified++; } cat += step; } } } Vect_write_line(&Out, type, Points, Cats); } /* Areas */ if ((otype & GV_AREA) && open_level > 1) { n_areas = Vect_get_num_areas(&In); new_centr = 0; for (i = 1; i <= n_areas; i++) { centr = Vect_get_area_centroid(&In, i); if (centr > 0) continue; /* Centroid exists and may be processed as line */ ret = Vect_get_point_in_area(&In, i, &x, &y); if (ret < 0) { G_warning(_("Unable to calculate area centroid")); continue; } Vect_reset_line(Points); Vect_reset_cats(Cats); Vect_append_point(Points, x, y, 0.0); if (Vect_cat_set(Cats, fields[0], cat) > 0) { nmodified++; } cat += step; Vect_write_line(&Out, GV_CENTROID, Points, Cats); new_centr++; } if (new_centr > 0) G_message(n_("%d new centroid placed in output map", "%d new centroids placed in output map", new_centr), new_centr); } break; case (O_TRANS): /* Lines */ while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { int n = Cats->n_cats; scat = -1; for (i = 0; i < n; i++) { if (Cats->field[i] == fields[0]) { scat = Cats->cat[i]; for (j = 1; j < nfields; j++) { if (Vect_cat_set(Cats, fields[j], scat) > 0) { G_debug(4, "Copy cat %i of field %i to field %i", scat, fields[0], fields[j]); } } } } if (scat != -1) nmodified++; } Vect_write_line(&Out, type, Points, Cats); } break; case (O_DEL): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { ret = Vect_field_cat_del(Cats, fields[0], cat); if (ret > 0) { nmodified++; } } Vect_write_line(&Out, type, Points, Cats); } break; case (O_CHFIELD): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { i = 0; while (i < Cats->n_cats) { if (Cats->field[i] == fields[0]) { int found = -1; /* check if cat already exists in layer fields[1] */ for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[1] && Cats->cat[j] == Cats->cat[i]) { found = j; break; } } /* does not exist, change layer */ if (found < 0) { Cats->field[i] = fields[1]; i++; } /* exists already in fields[1], delete from fields[0] */ else Vect_field_cat_del(Cats, fields[0], Cats->cat[found]); nmodified++; } } } Vect_write_line(&Out, type, Points, Cats); } break; case (O_SUM): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (type & otype && (!Clist || (Clist && Vect_cat_in_cat_list(id, Clist) == TRUE))) { for (i = 0; i < Cats->n_cats; i++) { if (Cats->field[i] == fields[0]) { Cats->cat[i] += cat; } } nmodified++; } Vect_write_line(&Out, type, Points, Cats); } break; case (O_REP): nfreps = 0; freps = NULL; while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE) continue; switch (type) { case (GV_POINT): rtype = FR_POINT; break; case (GV_LINE): rtype = FR_LINE; break; case (GV_BOUNDARY): rtype = FR_BOUNDARY; break; case (GV_CENTROID): rtype = FR_CENTROID; break; case (GV_FACE): rtype = FR_FACE; break; case (GV_KERNEL): rtype = FR_KERNEL; break; default: rtype = FR_UNKNOWN; } for (i = 0; i < Cats->n_cats; i++) { field = Cats->field[i]; cat = Cats->cat[i]; ret = FALSE; for (j = 0; j < nfreps; j++) { if (freps[j]->field == field) { fld = j; ret = TRUE; break; } } if (!ret) { /* field report doesn't exist */ nfreps++; freps = (FREPORT **) G_realloc(freps, nfreps * sizeof(FREPORT *)); fld = nfreps - 1; freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT)); freps[fld]->field = field; for (j = 0; j < FRTYPES; j++) { /* cat '0' is valid category number */ freps[fld]->min[j] = -1; } if ((Fi = Vect_get_field(&In, field)) != NULL) { freps[fld]->table = G_store(Fi->table); } else { freps[fld]->table = '\0'; } } freps[fld]->count[rtype]++; freps[fld]->count[FR_ALL]++; if (freps[fld]->min[rtype] == -1 || freps[fld]->min[rtype] > cat) freps[fld]->min[rtype] = cat; if ((freps[fld]->max[rtype] == 0) || freps[fld]->max[rtype] < cat) freps[fld]->max[rtype] = cat; if (freps[fld]->min[FR_ALL] == -1 || freps[fld]->min[FR_ALL] > cat) freps[fld]->min[FR_ALL] = cat; if ((freps[fld]->max[FR_ALL] == 0) || freps[fld]->max[FR_ALL] < cat) freps[fld]->max[FR_ALL] = cat; } } /* Areas */ if ((otype & GV_AREA) && open_level > 1 && !Clist) { n_areas = Vect_get_num_areas(&In); for (i = 1; i <= n_areas; i++) { int k; centr = Vect_get_area_centroid(&In, i); if (centr <= 0) continue; /* Area without centroid */ Vect_read_line(&In, NULL, Cats, centr); for (j = 0; j < Cats->n_cats; j++) { field = Cats->field[j]; cat = Cats->cat[j]; ret = FALSE; for (k = 0; k < nfreps; k++) { if (freps[k]->field == field) { fld = k; ret = TRUE; break; } } if (!ret) { /* field report doesn't exist */ nfreps++; freps = (FREPORT **) G_realloc(freps, nfreps * sizeof(FREPORT *)); fld = nfreps - 1; freps[fld] = (FREPORT *) G_calloc(1, sizeof(FREPORT)); freps[fld]->field = field; for (j = 0; j < FRTYPES; j++) { /* cat '0' is valid category number */ freps[fld]->min[k] = -1; } if ((Fi = Vect_get_field(&In, field)) != NULL) { freps[fld]->table = G_store(Fi->table); } else { freps[fld]->table = '\0'; } } freps[fld]->count[FR_AREA]++; if (freps[fld]->min[FR_AREA] == -1 || freps[fld]->min[FR_AREA] > cat) freps[fld]->min[FR_AREA] = cat; if ((freps[fld]->max[FR_AREA] == 0) || freps[fld]->max[FR_AREA] < cat) freps[fld]->max[FR_AREA] = cat; } } } for (i = 0; i < nfreps; i++) { if (shell->answer) { if (freps[i]->count[FR_POINT] > 0) fprintf(stdout, "%d point %d %d %d\n", freps[i]->field, freps[i]->count[FR_POINT], (freps[i]->min[FR_POINT] < 0 ? 0 : freps[i]->min[FR_POINT]), freps[i]->max[FR_POINT]); if (freps[i]->count[FR_LINE] > 0) fprintf(stdout, "%d line %d %d %d\n", freps[i]->field, freps[i]->count[FR_LINE], (freps[i]->min[FR_LINE] < 0 ? 0 : freps[i]->min[FR_LINE]), freps[i]->max[FR_LINE]); if (freps[i]->count[FR_BOUNDARY] > 0) fprintf(stdout, "%d boundary %d %d %d\n", freps[i]->field, freps[i]->count[FR_BOUNDARY], (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]), freps[i]->max[FR_BOUNDARY]); if (freps[i]->count[FR_CENTROID] > 0) fprintf(stdout, "%d centroid %d %d %d\n", freps[i]->field, freps[i]->count[FR_CENTROID], (freps[i]->min[FR_BOUNDARY] < 0 ? 0 : freps[i]->min[FR_BOUNDARY]), freps[i]->max[FR_CENTROID]); if (freps[i]->count[FR_AREA] > 0) fprintf(stdout, "%d area %d %d %d\n", freps[i]->field, freps[i]->count[FR_AREA], (freps[i]->min[FR_AREA] < 0 ? 0 : freps[i]->min[FR_AREA]), freps[i]->max[FR_AREA]); if (freps[i]->count[FR_FACE] > 0) fprintf(stdout, "%d face %d %d %d\n", freps[i]->field, freps[i]->count[FR_FACE], (freps[i]->min[FR_FACE] < 0 ? 0 : freps[i]->min[FR_FACE]), freps[i]->max[FR_FACE]); if (freps[i]->count[FR_KERNEL] > 0) fprintf(stdout, "%d kernel %d %d %d\n", freps[i]->field, freps[i]->count[FR_KERNEL], (freps[i]->min[FR_KERNEL] < 0 ? 0 : freps[i]->min[FR_KERNEL]), freps[i]->max[FR_KERNEL]); if (freps[i]->count[FR_ALL] > 0) fprintf(stdout, "%d all %d %d %d\n", freps[i]->field, freps[i]->count[FR_ALL], (freps[i]->min[FR_ALL] < 0 ? 0 : freps[i]->min[FR_ALL]), freps[i]->max[FR_ALL]); } else { if (freps[i]->table != '\0') { fprintf(stdout, "%s: %d/%s\n", _("Layer/table"), freps[i]->field, freps[i]->table); } else { fprintf(stdout, "%s: %d\n", _("Layer"), freps[i]->field); } fprintf(stdout, _("type count min max\n")); fprintf(stdout, "%s %7d %10d %10d\n", _("point"), freps[i]->count[FR_POINT], (freps[i]->min[FR_POINT] < 0) ? 0 : freps[i]->min[FR_POINT], freps[i]->max[FR_POINT]); fprintf(stdout, "%s %7d %10d %10d\n", _("line"), freps[i]->count[FR_LINE], (freps[i]->min[FR_LINE] < 0) ? 0 : freps[i]->min[FR_LINE], freps[i]->max[FR_LINE]); fprintf(stdout, "%s %7d %10d %10d\n", _("boundary"), freps[i]->count[FR_BOUNDARY], (freps[i]->min[FR_BOUNDARY] < 0) ? 0 : freps[i]->min[FR_BOUNDARY], freps[i]->max[FR_BOUNDARY]); fprintf(stdout, "%s %7d %10d %10d\n", _("centroid"), freps[i]->count[FR_CENTROID], (freps[i]->min[FR_CENTROID] < 0) ? 0 : freps[i]->min[FR_CENTROID], freps[i]->max[FR_CENTROID]); fprintf(stdout, "%s %7d %10d %10d\n", _("area"), freps[i]->count[FR_AREA], (freps[i]->min[FR_AREA] < 0) ? 0 : freps[i]->min[FR_AREA], freps[i]->max[FR_AREA]); fprintf(stdout, "%s %7d %10d %10d\n", _("face"), freps[i]->count[FR_FACE], (freps[i]->min[FR_FACE] < 0) ? 0 : freps[i]->min[FR_FACE], freps[i]->max[FR_FACE]); fprintf(stdout, "%s %7d %10d %10d\n", _("kernel"), freps[i]->count[FR_KERNEL], (freps[i]->min[FR_KERNEL] < 0) ? 0 : freps[i]->min[FR_KERNEL], freps[i]->max[FR_KERNEL]); fprintf(stdout, "%s %7d %10d %10d\n", _("all"), freps[i]->count[FR_ALL], (freps[i]->min[FR_ALL] < 0) ? 0 : freps[i]->min[FR_ALL], freps[i]->max[FR_ALL]); } } break; case (O_PRN): while ((type = Vect_read_next_line(&In, Points, Cats)) > 0) { id++; int has = 0; if (!(type & otype)) continue; if (Clist && Vect_cat_in_cat_list(id, Clist) == FALSE) continue; /* Check if the line has at least one cat */ for (i = 0; i < nfields; i++) { for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[i]) { has = 1; break; } } } if (!has) continue; for (i = 0; i < nfields; i++) { int first = 1; if (i > 0) fprintf(stdout, "|"); for (j = 0; j < Cats->n_cats; j++) { if (Cats->field[j] == fields[i]) { if (!first) fprintf(stdout, "/"); fprintf(stdout, "%d", Cats->cat[j]); first = 0; } } } fprintf(stdout, "\n"); } break; } if (option == O_ADD || option == O_DEL || option == O_CHFIELD || option == O_SUM || option == O_TRANS){ if (!notab->answer){ G_message(_("Copying attribute table(s)...")); if (Vect_copy_tables(&In, &Out, 0)) G_warning(_("Failed to copy attribute table to output map")); } Vect_build(&Out); Vect_close(&Out); } if (option == O_TRANS && nmodified > 0) for(i = 1; i < nfields; i++) G_important_message(_("Categories copied from layer %d to layer %d"), fields[0], fields[i]); if (option != O_REP && option != O_PRN) G_done_msg(n_("%d feature modified.", "%d features modified.", nmodified), nmodified); Vect_close(&In); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int i; int **cats, *ncats, nfields, *fields; struct Flag *line_flag; /* struct Flag *all_flag; */ struct Option *in_opt, *out_opt; struct Flag *table_flag; struct GModule *module; struct line_pnts *Points; struct line_cats *Cats; int node, nnodes; COOR *coor; int ncoor, acoor; int line, nlines, type, ctype, area, nareas; int err_boundaries, err_centr_out, err_centr_dupl, err_nocentr; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("geometry")); G_add_keyword(_("triangulation")); module->description = _("Creates a Voronoi diagram from an input vector " "map containing points or centroids."); in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); /* all_flag = G_define_flag (); all_flag->key = 'a'; all_flag->description = _("Use all points (do not limit to current region)"); */ line_flag = G_define_flag(); line_flag->key = 'l'; line_flag->description = _("Output tessellation as a graph (lines), not areas"); table_flag = G_define_flag(); table_flag->key = 't'; table_flag->description = _("Do not create attribute table"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (line_flag->answer) Type = GV_LINE; else Type = GV_BOUNDARY; All = 0; Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); /* open files */ Vect_set_open_level(2); Vect_open_old(&In, in_opt->answer, ""); if (Vect_open_new(&Out, out_opt->answer, 0) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_copy(&In, &Out); Vect_hist_command(&Out); /* initialize working region */ G_get_window(&Window); Vect_region_box(&Window, &Box); Box.T = 0.5; Box.B = -0.5; freeinit(&sfl, sizeof(struct Site)); G_message(_("Reading sites...")); readsites(); siteidx = 0; geominit(); triangulate = 0; plot = 0; debug = 0; G_message(_("Voronoi triangulation...")); voronoi(triangulate, nextone); /* Close free ends by current region */ Vect_build_partial(&Out, GV_BUILD_BASE); ncoor = 0; acoor = 100; coor = (COOR *) G_malloc(sizeof(COOR) * acoor); nnodes = Vect_get_num_nodes(&Out); for (node = 1; node <= nnodes; node++) { double x, y; if (Vect_get_node_n_lines(&Out, node) < 2) { /* add coordinates */ Vect_get_node_coor(&Out, node, &x, &y, NULL); if (ncoor == acoor - 5) { /* always space for 5 region corners */ acoor += 100; coor = (COOR *) G_realloc(coor, sizeof(COOR) * acoor); } coor[ncoor].x = x; coor[ncoor].y = y; ncoor++; } } /* Add region corners */ coor[ncoor].x = Box.W; coor[ncoor].y = Box.S; ncoor++; coor[ncoor].x = Box.E; coor[ncoor].y = Box.S; ncoor++; coor[ncoor].x = Box.E; coor[ncoor].y = Box.N; ncoor++; coor[ncoor].x = Box.W; coor[ncoor].y = Box.N; ncoor++; /* Sort */ qsort(coor, ncoor, sizeof(COOR), (void *)cmp); /* add last (first corner) */ coor[ncoor].x = Box.W; coor[ncoor].y = Box.S; ncoor++; for (i = 1; i < ncoor; i++) { if (coor[i].x == coor[i - 1].x && coor[i].y == coor[i - 1].y) continue; /* duplicate */ Vect_reset_line(Points); Vect_append_point(Points, coor[i].x, coor[i].y, 0.0); Vect_append_point(Points, coor[i - 1].x, coor[i - 1].y, 0.0); Vect_write_line(&Out, Type, Points, Cats); } G_free(coor); /* Copy input points as centroids */ nfields = Vect_cidx_get_num_fields(&In); cats = (int **)G_malloc(nfields * sizeof(int *)); ncats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { ncats[i] = 0; cats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&In, i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(&In, i); } if (line_flag->answer) ctype = GV_POINT; else ctype = GV_CENTROID; nlines = Vect_get_num_lines(&In); G_message(_("Writing sites to output...")); for (line = 1; line <= nlines; line++) { G_percent(line, nlines, 2); type = Vect_read_line(&In, Points, Cats, line); if (!(type & GV_POINTS)) continue; if (!Vect_point_in_box(Points->x[0], Points->y[0], 0.0, &Box)) continue; Vect_write_line(&Out, ctype, Points, Cats); for (i = 0; i < Cats->n_cats; i++) { int f, j; f = -1; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == Cats->field[i]) { f = j; break; } } if (f > -1) { cats[f][ncats[f]] = Cats->cat[i]; ncats[f]++; } } } /* Copy tables */ if (!(table_flag->answer)) { int ttype, ntabs = 0; struct field_info *IFi, *OFi; /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(&In); i++) { int f, j; IFi = Vect_get_dblink(&In, i); f = -1; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (f > -1) { if (ncats[f] > 0) ntabs++; } } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; G_message(_("Layer %d"), fields[i]); /* Make a list of categories */ IFi = Vect_get_field(&In, fields[i]); if (!IFi) { /* no table */ G_message(_("No table")); continue; } OFi = Vect_default_field_info(&Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, &Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Cannot copy table")); } else { Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } } Vect_close(&In); /* cleaning part 1: count errors */ Vect_build_partial(&Out, GV_BUILD_CENTROIDS); err_boundaries = err_centr_out = err_centr_dupl = err_nocentr = 0; nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); if (left == 0 || right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); err_boundaries++; } } if (type == GV_CENTROID) { area = Vect_get_centroid_area(&Out, line); if (area == 0) err_centr_out++; else if (area < 0) err_centr_dupl++; } } err_nocentr = 0; nareas = Vect_get_num_areas(&Out); for (area = 1; area <= nareas; area++) { if (!Vect_area_alive(&Out, area)) continue; line = Vect_get_area_centroid(&Out, area); if (line == 0) err_nocentr++; } /* cleaning part 2: snap */ if (err_nocentr || err_centr_dupl || err_centr_out) { int nmod; G_important_message(_("Output needs topological cleaning")); Vect_snap_lines(&Out, GV_BOUNDARY, 1e-7, NULL); do { Vect_break_lines(&Out, GV_BOUNDARY, NULL); Vect_remove_duplicates(&Out, GV_BOUNDARY, NULL); nmod = Vect_clean_small_angles_at_nodes(&Out, GV_BOUNDARY, NULL); } while (nmod > 0); err_boundaries = 0; nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); if (left == 0 || right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); err_boundaries++; } } } } /* cleaning part 3: remove remaining incorrect boundaries */ if (err_boundaries) { G_important_message(_("Removing incorrect boundaries from output")); nlines = Vect_get_num_lines(&Out); for (line = 1; line <= nlines; line++) { if (!Vect_line_alive(&Out, line)) continue; type = Vect_get_line_type(&Out, line); if (type == GV_BOUNDARY) { int left, right; Vect_get_line_areas(&Out, line, &left, &right); /* &&, not ||, no typo */ if (left == 0 && right == 0) { G_debug(3, "line = %d left = %d right = %d", line, left, right); Vect_delete_line(&Out, line); } } } } /* build clean topology */ Vect_build_partial(&Out, GV_BUILD_NONE); Vect_build(&Out); Vect_close(&Out); G_done_msg(" "); exit(EXIT_SUCCESS); }
/* TODO: The collection of categories is horrible in current version! * Everything repeats many times. We need some data structure * implementing set! */ int copy_tables_by_cats(struct Map_info *In, struct Map_info *Out) { /* this is the (mostly) code from v.extract, it should be moved to * some vector library (probably) */ int nlines, line, nfields; int ttype, ntabs = 0; struct field_info *IFi, *OFi; struct line_cats *Cats; int **ocats, *nocats, *fields; int i; /* Collect list of output cats */ Cats = Vect_new_cats_struct(); nfields = Vect_cidx_get_num_fields(In); ocats = (int **)G_malloc(nfields * sizeof(int *)); nocats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { nocats[i] = 0; ocats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(In, i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(In, i); } nlines = Vect_get_num_lines(Out); for (line = 1; line <= nlines; line++) { Vect_read_line(Out, NULL, Cats, line); for (i = 0; i < Cats->n_cats; i++) { int f = 0, j; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == Cats->field[i]) { f = j; break; } } ocats[f][nocats[f]] = Cats->cat[i]; nocats[f]++; } } /* Copy tables */ G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(In); i++) { int j, f = -1; IFi = Vect_get_dblink(In, i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (f >= 0 && nocats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; if (nocats[i] == 0) continue; /* if ( fields[i] == field && new_cat != -1 ) continue; */ G_message(_("Layer %d"), fields[i]); /* Make a list of categories */ IFi = Vect_get_field(In, fields[i]); if (!IFi) { /* no table */ G_warning(_("Database connection not defined for layer %d"), fields[i]); continue; } OFi = Vect_default_field_info(Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, Out), OFi->table, IFi->key, ocats[i], nocats[i]); if (ret == DB_FAILED) { G_warning(_("Unable to copy table <%s>"), IFi->table); } else { Vect_map_add_dblink(Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } for (i = 0; i < nfields; i++) G_free(ocats[i]); G_free(ocats); G_free(nocats); G_free(fields); return 1; }
int main(int argc, char *argv[]) { int i, iopt; int operator; int aline, nalines, nskipped; int ltype, itype[2], ifield[2]; int **cats, *ncats, nfields, *fields; char *mapset[2], *pre[2]; struct GModule *module; struct GParm parm; struct GFlag flag; struct Map_info In[2], Out; struct field_info *IFi, *OFi; struct line_pnts *APoints, *BPoints; struct line_cats *ACats, *BCats; int *ALines; /* List of lines: 0 do not output, 1 - write to output */ struct ilist *List, *TmpList, *BoundList; G_gisinit(argv[0]); pre[0] = "a"; pre[1] = "b"; module = G_define_module(); module->keywords = _("vector, spatial query"); module->description = _("Selects features from vector map (A) by features from other vector map (B)."); parse_options(&parm, &flag); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (parm.operator->answer[0] == 'e') operator = OP_EQUALS; else if (parm.operator->answer[0] == 'd') { /* operator = OP_DISJOINT; */ operator = OP_INTERSECTS; flag.reverse->answer = YES; } else if (parm.operator->answer[0] == 'i') operator = OP_INTERSECTS; else if (parm.operator->answer[0] == 't') operator = OP_TOUCHES; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r') operator = OP_CROSSES; else if (parm.operator->answer[0] == 'w') operator = OP_WITHIN; else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o') operator = OP_CONTAINS; else if (parm.operator->answer[0] == 'o') { if (strcmp(parm.operator->answer, "overlaps") == 0) operator = OP_OVERLAPS; else operator = OP_OVERLAP; } else if (parm.operator->answer[0] == 'r') operator = OP_RELATE; else G_fatal_error(_("Unknown operator")); if (operator == OP_RELATE && !parm.relate->answer) { G_fatal_error(_("Required parameter <%s> not set"), parm.relate->key); } for (iopt = 0; iopt < 2; iopt++) { itype[iopt] = Vect_option_to_types(parm.type[iopt]); ifield[iopt] = atoi(parm.field[iopt]->answer); Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer, GV_FATAL_EXIT); if ((mapset[iopt] = G_find_vector2(parm.input[iopt]->answer, NULL)) == NULL) { G_fatal_error(_("Vector map <%s> not found"), parm.input[iopt]->answer); } Vect_set_open_level(2); Vect_open_old(&(In[iopt]), parm.input[iopt]->answer, mapset[iopt]); } /* Read field info */ IFi = Vect_get_field(&(In[0]), ifield[0]); APoints = Vect_new_line_struct(); BPoints = Vect_new_line_struct(); ACats = Vect_new_cats_struct(); BCats = Vect_new_cats_struct(); List = Vect_new_list(); TmpList = Vect_new_list(); BoundList = Vect_new_list(); /* Open output */ Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0]))); Vect_set_map_name(&Out, _("Output from v.select")); Vect_set_person(&Out, G_whoami()); Vect_copy_head_data(&(In[0]), &Out); Vect_hist_copy(&(In[0]), &Out); Vect_hist_command(&Out); nskipped = 0; nalines = Vect_get_num_lines(&(In[0])); #ifdef HAVE_GEOS initGEOS(G_message, G_fatal_error); GEOSGeometry *AGeom = NULL; #else void *AGeom = NULL; #endif /* Alloc space for input lines array */ ALines = (int *)G_calloc(nalines + 1, sizeof(int)); G_message(_("Building spatial index...")); Vect_build_spatial_index(&In[0]); Vect_build_spatial_index(&In[1]); /* Lines in A. Go through all lines and mark those that meets condition */ if (itype[0] & (GV_POINTS | GV_LINES)) { G_message(_("Processing features...")); for (aline = 1; aline <= nalines; aline++) { BOUND_BOX abox; G_debug(3, "aline = %d", aline); G_percent(aline, nalines, 2); /* must be before any continue */ /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[0]), aline, ifield[0]) < 0) { nskipped++; continue; } /* Read line and check type */ if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_line_geos(&(In[0]), aline, <ype); #endif if (!(ltype & (GV_POINT | GV_LINE))) continue; if (!AGeom) G_fatal_error(_("Unable to read line id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } else { ltype = Vect_read_line(&(In[0]), APoints, NULL, aline); } if (!(ltype & itype[0])) continue; Vect_get_line_box(&(In[0]), aline, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; /* Check if this line overlaps any feature in B */ /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { int i; int found = 0; /* Lines */ Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; G_debug(3, " bline = %d", bline); /* Check category */ if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { found = 1; break; } #endif } else { Vect_read_line(&(In[1]), BPoints, NULL, bline); if (Vect_line_check_intersection(APoints, BPoints, 0)) { found = 1; break; } } } if (found) { ALines[aline] = 1; continue; /* Go to next A line */ } } /* x Areas in B. */ if (itype[1] & GV_AREA) { int i; Vect_select_areas_by_box(&(In[1]), &abox, List); for (i = 0; i < List->n_values; i++) { int barea; barea = List->value[i]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { ALines[aline] = 1; break; } #endif } else { if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { ALines[aline] = 1; break; } } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } /* Areas in A. */ if (itype[0] & GV_AREA) { int aarea, naareas; G_message(_("Processing areas...")); naareas = Vect_get_num_areas(&(In[0])); for (aarea = 1; aarea <= naareas; aarea++) { BOUND_BOX abox; G_percent(aarea, naareas, 2); /* must be before any continue */ if (Vect_get_area_cat(&(In[0]), aarea, ifield[0]) < 0) { nskipped++; continue; } Vect_get_area_box(&(In[0]), aarea, &abox); abox.T = PORT_DOUBLE_MAX; abox.B = -PORT_DOUBLE_MAX; if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS AGeom = Vect_read_area_geos(&(In[0]), aarea); #endif if (!AGeom) G_fatal_error(_("Unable to read area id %d from vector map <%s>"), aline, Vect_get_full_name(&(In[0]))); } /* x Lines in B */ if (itype[1] & (GV_POINTS | GV_LINES)) { Vect_select_lines_by_box(&(In[1]), &abox, itype[1], List); for (i = 0; i < List->n_values; i++) { int bline; bline = List->value[i]; if (!flag.cat->answer && Vect_get_line_cat(&(In[1]), bline, ifield[1]) < 0) { nskipped++; continue; } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(line_relate_geos(&(In[1]), AGeom, bline, operator, parm.relate->answer)) { add_aarea(&(In[0]), aarea, ALines); break; } #endif } else { if (line_overlap_area(&(In[1]), bline, &(In[0]), aarea)) { add_aarea(&(In[0]), aarea, ALines); continue; } } } } /* x Areas in B */ if (itype[1] & GV_AREA) { int naisles; int found = 0; /* List of areas B */ /* Make a list of features forming area A */ Vect_reset_list(List); Vect_get_area_boundaries(&(In[0]), aarea, BoundList); for (i = 0; i < BoundList->n_values; i++) { Vect_list_append(List, abs(BoundList->value[i])); } naisles = Vect_get_area_num_isles(&(In[0]), aarea); for (i = 0; i < naisles; i++) { int j, aisle; aisle = Vect_get_area_isle(&(In[0]), aarea, i); Vect_get_isle_boundaries(&(In[0]), aisle, BoundList); for (j = 0; j < BoundList->n_values; j++) { Vect_list_append(List, BoundList->value[j]); } } Vect_select_areas_by_box(&(In[1]), &abox, TmpList); for (i = 0; i < List->n_values; i++) { int j, aline; aline = abs(List->value[i]); for (j = 0; j < TmpList->n_values; j++) { int barea, bcentroid; barea = TmpList->value[j]; G_debug(3, " barea = %d", barea); if (Vect_get_area_cat(&(In[1]), barea, ifield[1]) < 0) { nskipped++; continue; } /* Check if any centroid of area B is in area A. * This test is important in if area B is completely within area A */ bcentroid = Vect_get_area_centroid(&(In[1]), barea); Vect_read_line(&(In[1]), BPoints, NULL, bcentroid); if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS if(area_relate_geos(&(In[1]), AGeom, barea, operator, parm.relate->answer)) { found = 1; break; } #endif } else { if (Vect_point_in_area(&(In[0]), aarea, BPoints->x[0], BPoints->y[0])) { found = 1; break; } /* Check intersectin of lines from List with area B */ if (line_overlap_area(&(In[0]), aline, &(In[1]), barea)) { found = 1; break; } } } if (found) { add_aarea(&(In[0]), aarea, ALines); break; } } } if (operator != OP_OVERLAP) { #ifdef HAVE_GEOS GEOSGeom_destroy(AGeom); #endif AGeom = NULL; } } } Vect_close(&(In[1])); #ifdef HAVE_GEOS finishGEOS(); #endif /* Write lines */ nfields = Vect_cidx_get_num_fields(&(In[0])); cats = (int **)G_malloc(nfields * sizeof(int *)); ncats = (int *)G_malloc(nfields * sizeof(int)); fields = (int *)G_malloc(nfields * sizeof(int)); for (i = 0; i < nfields; i++) { ncats[i] = 0; cats[i] = (int *)G_malloc(Vect_cidx_get_num_cats_by_index(&(In[0]), i) * sizeof(int)); fields[i] = Vect_cidx_get_field_number(&(In[0]), i); } G_message(_("Writing selected features...")); for (aline = 1; aline <= nalines; aline++) { int atype; G_debug(4, "aline = %d ALines[aline] = %d", aline, ALines[aline]); G_percent(aline, nalines, 2); if ((!flag.reverse->answer && !(ALines[aline])) || (flag.reverse->answer && ALines[aline])) continue; atype = Vect_read_line(&(In[0]), APoints, ACats, aline); Vect_write_line(&Out, atype, APoints, ACats); if (!(flag.table->answer) && (IFi != NULL)) { for (i = 0; i < ACats->n_cats; i++) { int f, j; for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == ACats->field[i]) { f = j; break; } } cats[f][ncats[f]] = ACats->cat[i]; ncats[f]++; } } } /* Copy tables */ if (!(flag.table->answer)) { int ttype, ntabs = 0; G_message(_("Writing attributes...")); /* Number of output tabs */ for (i = 0; i < Vect_get_num_dblinks(&(In[0])); i++) { int f, j; IFi = Vect_get_dblink(&(In[0]), i); for (j = 0; j < nfields; j++) { /* find field */ if (fields[j] == IFi->number) { f = j; break; } } if (ncats[f] > 0) ntabs++; } if (ntabs > 1) ttype = GV_MTABLE; else ttype = GV_1TABLE; for (i = 0; i < nfields; i++) { int ret; if (fields[i] == 0) continue; /* Make a list of categories */ IFi = Vect_get_field(&(In[0]), fields[i]); if (!IFi) { /* no table */ G_warning(_("Layer %d - no table"), fields[i]); continue; } OFi = Vect_default_field_info(&Out, IFi->number, IFi->name, ttype); ret = db_copy_table_by_ints(IFi->driver, IFi->database, IFi->table, OFi->driver, Vect_subst_var(OFi->database, &Out), OFi->table, IFi->key, cats[i], ncats[i]); if (ret == DB_FAILED) { G_warning(_("Layer %d - unable to copy table"), fields[i]); } else { Vect_map_add_dblink(&Out, OFi->number, OFi->name, OFi->table, IFi->key, OFi->database, OFi->driver); } } } Vect_close(&(In[0])); Vect_build(&Out); Vect_close(&Out); if (nskipped > 0) { G_warning(_("%d features without category skipped"), nskipped); } G_done_msg(_("%d features written to output."), Vect_get_num_lines(&Out)); exit(EXIT_SUCCESS); }