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; }
// 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" ); } }
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); } }