[QGIS Commit] r12880 - in trunk/qgis/src: plugins/grass providers/grass

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Feb 4 16:25:36 EST 2010


Author: rblazek
Date: 2010-02-04 16:25:35 -0500 (Thu, 04 Feb 2010)
New Revision: 12880

Added:
   trunk/qgis/src/providers/grass/qgis.d.rast.c
   trunk/qgis/src/providers/grass/qgis.g.info.c
   trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp
   trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h
Modified:
   trunk/qgis/src/plugins/grass/qgsgrassplugin.cpp
   trunk/qgis/src/providers/grass/CMakeLists.txt
   trunk/qgis/src/providers/grass/qgsgrass.cpp
   trunk/qgis/src/providers/grass/qgsgrass.h
Log:
GRASS raster data provider

Modified: trunk/qgis/src/plugins/grass/qgsgrassplugin.cpp
===================================================================
--- trunk/qgis/src/plugins/grass/qgsgrassplugin.cpp	2010-02-04 21:23:12 UTC (rev 12879)
+++ trunk/qgis/src/plugins/grass/qgsgrassplugin.cpp	2010-02-04 21:25:35 UTC (rev 12880)
@@ -398,7 +398,9 @@
     QString name = uri.right( uri.length() - pos - 1 );
     name.replace( '/', ' ' );
 
-    qGisInterface->addRasterLayer( uri, sel->map );
+    //qGisInterface->addRasterLayer( uri, sel->map );
+    qGisInterface->addRasterLayer( uri, sel->map, "grassraster", QStringList(), QStringList(),
+                                   QString(), QString() );
   }
 }
 

Modified: trunk/qgis/src/providers/grass/CMakeLists.txt
===================================================================
--- trunk/qgis/src/providers/grass/CMakeLists.txt	2010-02-04 21:23:12 UTC (rev 12879)
+++ trunk/qgis/src/providers/grass/CMakeLists.txt	2010-02-04 21:25:35 UTC (rev 12880)
@@ -5,8 +5,14 @@
 
 SET(GRASS_PROVIDER_SRCS provider.cpp)
 
+SET(GRASS_RASTER_PROVIDER_SRCS qgsgrassrasterprovider.cpp)
+
 SET(GRASS_LIB_SRCS qgsgrassprovider.cpp qgsgrass.cpp)
 
+SET(QGIS_D_RAST_SRCS qgis.d.rast.c)
+
+SET(QGIS_G_INFO_SRCS qgis.g.info.c)
+
 ########################################################
 # Build
 
@@ -54,6 +60,32 @@
   qgisgrass
 )
 
+ADD_LIBRARY (grassrasterprovider MODULE ${GRASS_RASTER_PROVIDER_SRCS})
+
+IF (WIN32)
+  SET_TARGET_PROPERTIES(grassrasterprovider PROPERTIES COMPILE_FLAGS "\"-DGRASS_EXPORT=__declspec(dllimport)\"" )
+ELSE (WIN32)
+  SET_TARGET_PROPERTIES(grassrasterprovider PROPERTIES COMPILE_FLAGS "-DGRASS_EXPORT=" )
+ENDIF (WIN32)
+
+TARGET_LINK_LIBRARIES (grassrasterprovider
+  qgisgrass
+  qgis_core
+)
+
+ADD_EXECUTABLE(qgis.d.rast ${QGIS_D_RAST_SRCS})
+
+TARGET_LINK_LIBRARIES (qgis.d.rast
+  ${GRASS_LIBRARY_gis}
+)
+
+ADD_EXECUTABLE(qgis.g.info ${QGIS_G_INFO_SRCS})
+
+TARGET_LINK_LIBRARIES (qgis.g.info
+  ${GRASS_LIBRARY_gis}
+  ${GRASS_LIBRARY_gproj}
+)
+
 ########################################################
 # Install
 
@@ -64,3 +96,12 @@
 INSTALL(TARGETS grassprovider
   RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
   LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
+
+INSTALL(TARGETS grassrasterprovider
+  RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
+  LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
+
+INSTALL(TARGETS qgis.d.rast qgis.g.info
+        RUNTIME DESTINATION ${QGIS_DATA_DIR}/grass/modules 
+        PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)

Added: trunk/qgis/src/providers/grass/qgis.d.rast.c
===================================================================
--- trunk/qgis/src/providers/grass/qgis.d.rast.c	                        (rev 0)
+++ trunk/qgis/src/providers/grass/qgis.d.rast.c	2010-02-04 21:25:35 UTC (rev 12880)
@@ -0,0 +1,171 @@
+/****************************************************************************
+ * 
+ * MODULE:       qgis.d.rast
+ * AUTHOR(S):    Radim Blazek <radim.blazek gmail.com>
+ *               using d.rast from GRASS
+ * PURPOSE:      display raster maps in active graphics display
+ * COPYRIGHT:    (C) 2010 by Radim Blazek 
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2).
+ *
+ *****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/display.h>
+#include <grass/glocale.h>
+
+int display(char *name, char *mapset, RASTER_MAP_TYPE data_type);
+
+int main(int argc, char **argv)
+{
+    char *mapset;
+    char *name;
+    int fp;
+    int cols, rows;
+    struct GModule *module;
+    struct Option *map;
+    struct Option *win;
+    struct Flag *flag_o;
+    struct Flag *flag_i;
+    struct Flag *flag_x;
+    struct Cell_head window;
+
+    /* Initialize the GIS calls */
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->keywords = _("display, raster");
+    module->description = _("Output raster map layers in a format suitable for display in QGIS");
+
+    map = G_define_standard_option(G_OPT_R_MAP);
+    map->description = _("Raster map to be displayed");
+
+    win = G_define_option();
+    win->key = "window";
+    win->type = TYPE_DOUBLE;
+    win->multiple = YES;
+    win->description = "xmin,ymin,xmax,ymax,ncols,nrows";
+     
+    if (G_parser(argc, argv))
+	exit(EXIT_FAILURE);
+
+    name = map->answer;
+
+    G_get_window(&window);
+    window.west = atof(win->answers[0]);
+    window.south = atof(win->answers[1]);
+    window.east = atof(win->answers[2]);
+    window.north = atof(win->answers[3]);
+    window.cols = atoi(win->answers[4]);
+    window.rows = atoi(win->answers[5]);
+    G_adjust_Cell_head(&window,1,1);
+    G_set_window(&window);
+
+    /* Make sure map is available */
+    mapset = G_find_cell2(name, "");
+    if (mapset == NULL)
+	G_fatal_error(_("Raster map <%s> not found"), name);
+
+
+    fp = G_raster_map_is_fp(name, mapset);
+
+    /* use DCELL even if the map is FCELL */
+    if (fp)
+	display(name, mapset, DCELL_TYPE );
+    else
+	display(name, mapset, CELL_TYPE );
+
+    exit(EXIT_SUCCESS);
+}
+
+static int cell_draw(char *, char *, struct Colors *, RASTER_MAP_TYPE);
+
+int display(char *name,
+	    char *mapset,
+	    RASTER_MAP_TYPE data_type)
+{
+    struct Colors colors;
+    int r, g, b;
+
+    if (G_read_colors(name, mapset, &colors) == -1)
+	G_fatal_error(_("Color file for <%s> not available"), name);
+
+    //G_set_null_value_color(r, g, b, &colors);
+
+    /* Go draw the raster map */
+    cell_draw(name, mapset, &colors, data_type);
+
+    /* release the colors now */
+    G_free_colors(&colors);
+
+    return 0;
+}
+
+static int cell_draw(char *name,
+		     char *mapset,
+		     struct Colors *colors,
+		     RASTER_MAP_TYPE data_type)
+{
+    int cellfile;
+    void *xarray;
+    int row;
+    int t, b, l, r;
+    int ncols, nrows;
+    static unsigned char *red, *grn, *blu, *set;
+    int i;
+    void *ptr;
+    int big_endian;
+    long one= 1;
+
+    big_endian = !(*((char *)(&one)));
+
+    ncols = G_window_cols();
+    nrows = G_window_rows();
+
+    /* Make sure map is available */
+    if ((cellfile = G_open_cell_old(name, mapset)) == -1)
+	G_fatal_error(_("Unable to open raster map <%s>"), name);
+
+    /* Allocate space for cell buffer */
+    xarray = G_allocate_raster_buf(data_type);
+    red = G_malloc(ncols);
+    grn = G_malloc(ncols);
+    blu = G_malloc(ncols);
+    set = G_malloc(ncols);
+    
+    /* loop for array rows */
+    for ( row = 0; row < nrows; row++ ) {
+	G_get_raster_row(cellfile, xarray, row, data_type);
+        ptr = xarray;
+
+        G_lookup_raster_colors(xarray, red, grn, blu, set, ncols, colors,
+                                data_type);
+
+        for (i = 0; i < ncols; i++) { 
+            unsigned char alpha = 255;
+            if ( G_is_null_value(ptr, data_type) ) {
+                alpha = 0;
+            }
+            ptr = G_incr_void_ptr(ptr, G_raster_size(data_type));
+            
+
+            // We need data suitable for QImage 32-bpp
+            // the data are stored in QImage as QRgb which is unsigned int.
+            // Because it depends on byte order of the platform we have to 
+            // consider byte order (well, middle endian ignored)
+            if ( big_endian ) {
+                // I have never tested this 
+                fprintf(stdout, "%c%c%c%c", alpha, red[i],grn[i],blu[i]);
+            } else {
+                fprintf(stdout, "%c%c%c%c", blu[i],grn[i],red[i],alpha);
+            }
+        }
+    }
+
+    G_close_cell(cellfile);
+    return (0);
+}

Added: trunk/qgis/src/providers/grass/qgis.g.info.c
===================================================================
--- trunk/qgis/src/providers/grass/qgis.g.info.c	                        (rev 0)
+++ trunk/qgis/src/providers/grass/qgis.g.info.c	2010-02-04 21:25:35 UTC (rev 12880)
@@ -0,0 +1,135 @@
+/****************************************************************************
+ * 
+ * MODULE:       qgis.g.info
+ * AUTHOR(S):    Radim Blazek <radim.blazek gmail.com>
+ *               using various GRASS modules 
+ * PURPOSE:      get informations about locations,mapsets,maps
+ * COPYRIGHT:    (C) 2010 by Radim Blazek 
+ *
+ *               This program is free software under the GNU General Public
+ *               License (>=v2).
+ *
+ *****************************************************************************/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/raster.h>
+#include <grass/display.h>
+#include <grass/glocale.h>
+#include <grass/gprojects.h>
+
+int main(int argc, char **argv)
+{
+    char *mapset;
+    char *name;
+    struct GModule *module;
+    struct Option *info_opt, *rast_opt, *vect_opt, *coor_opt;
+    struct Cell_head window;
+    
+    /* Initialize the GIS calls */
+    G_gisinit(argv[0]);
+
+    module = G_define_module();
+    module->description = _("Get info about locations,mapsets,maps");
+
+    info_opt = G_define_option();
+    info_opt->key = "info";
+    info_opt->type = TYPE_STRING;
+    info_opt->description = "info key";
+    info_opt->options = "proj,window,query";
+
+    rast_opt = G_define_standard_option(G_OPT_R_INPUT);
+    rast_opt->key = "rast";
+    rast_opt->required = NO;
+
+    vect_opt = G_define_standard_option(G_OPT_V_INPUT);
+    vect_opt->key = "vect";
+    vect_opt->required = NO;
+
+    coor_opt = G_define_option();
+    coor_opt->key = "coor";
+    coor_opt->type = TYPE_DOUBLE;
+    coor_opt->multiple = YES;
+     
+    if (G_parser(argc, argv))
+        exit(EXIT_FAILURE);
+
+
+    if ( strcmp("proj",info_opt->answer) == 0 ) 
+    {
+        G_get_window(&window);
+        /* code from g.proj */
+        if (window.proj != PROJECTION_XY) {
+            struct Key_Value *projinfo, *projunits;
+            char *wkt;
+            projinfo = G_get_projinfo();
+            projunits = G_get_projunits();
+            wkt = GPJ_grass_to_wkt( projinfo, projunits,  0, 0 );
+            fprintf (stdout, "%s", wkt);
+        }
+    }
+    else if ( strcmp("window",info_opt->answer) == 0 ) 
+    {
+        if ( rast_opt->answer ) 
+        {
+          G_get_cellhd( rast_opt->answer, "", &window);
+          fprintf (stdout, "%f,%f,%f,%f", window.west, window.south,window.east,window.north );
+        }
+        else if ( vect_opt->answer )
+        {
+          G_fatal_error ("Not yet supported");
+        }
+    }
+    else if ( strcmp("query",info_opt->answer) == 0 ) 
+    {
+        double x, y;
+        int row, col;
+        x = atof ( coor_opt->answers[0] );
+        y = atof ( coor_opt->answers[1] );
+        if ( rast_opt->answer ) 
+        {
+          int fd;
+          RASTER_MAP_TYPE rast_type;
+          DCELL *dcell;
+          CELL *cell;
+          G_get_cellhd( rast_opt->answer, "", &window);
+          G_set_window(&window);
+          fd = G_open_cell_old( rast_opt->answer, "");
+          col = G_easting_to_col( x, &window);
+          row = G_northing_to_row( y, &window);
+          if (col == window.cols) col--;
+          if (row == window.rows) row--;
+
+          rast_type = G_get_raster_map_type(fd);
+          cell = G_allocate_c_raster_buf();
+          dcell = G_allocate_d_raster_buf();
+
+          if (rast_type == CELL_TYPE) 
+          {
+            if (G_get_c_raster_row(fd, cell, row) < 0) 
+            {
+              G_fatal_error(_("Unable to read raster map <%s> row %d"),
+                                    rast_opt->answer, row);
+            }
+            fprintf (stdout, "value:%d\n", cell[col] );
+          } 
+          else 
+          { 
+            if (G_get_d_raster_row(fd, dcell, row) < 0) 
+            {
+              G_fatal_error(_("Unable to read raster map <%s> row %d"),
+                                    rast_opt->answer, row);
+            }
+            fprintf (stdout, "value:%f\n", dcell[col] );
+          }
+        }
+        else if ( vect_opt->answer )
+        {
+          G_fatal_error ("Not yet supported");
+        }
+    }
+
+    exit(EXIT_SUCCESS);
+}
+

Modified: trunk/qgis/src/providers/grass/qgsgrass.cpp
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrass.cpp	2010-02-04 21:23:12 UTC (rev 12879)
+++ trunk/qgis/src/providers/grass/qgsgrass.cpp	2010-02-04 21:25:35 UTC (rev 12880)
@@ -19,12 +19,15 @@
 
 #include "qgslogger.h"
 #include "qgsapplication.h"
+#include "qgscoordinatereferencesystem.h"
+#include "qgsrectangle.h"
 
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QProcess>
 #include <QSettings>
 #include <QTextStream>
+#include <QTemporaryFile>
 
 #include <QTextCodec>
 
@@ -1029,6 +1032,157 @@
   return true;
 }
 
+QByteArray GRASS_EXPORT QgsGrass::runModule(  QString gisdbase, QString location, 
+                                      QString module, QStringList arguments )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+
+#ifdef WIN32
+  module += ".exe";
+#endif
+
+  // We have to set GISRC file, uff
+  QTemporaryFile gisrcFile;
+  if ( !gisrcFile.open() ) 
+  {
+    // TODO Exception
+    return QByteArray();
+  }
+ 
+  QTextStream out(&gisrcFile);
+  out << "GISDBASE: " << gisdbase << "\n";
+  out << "LOCATION_NAME: " << location << "\n";
+  out << "MAPSET: PERMANENT\n";
+  out.flush ();
+  QgsDebugMsg( gisrcFile.fileName() );
+
+  QStringList environment = QProcess::systemEnvironment();
+  environment.append("GISRC=" + gisrcFile.fileName() );
+
+  QProcess process;
+  process.setEnvironment( environment );
+
+  QgsDebugMsg( module + " " + arguments.join (" ") );
+  process.start( module, arguments );
+  if ( !process.waitForFinished()
+       || ( process.exitCode() != 0 && process.exitCode() != 255 ) )
+  {
+    QgsDebugMsg( "process.exitCode() = " + QString::number( process.exitCode() ) );
+/*
+    QMessageBox::warning( 0, QObject::tr( "Warning" ),
+                          QObject::tr( "Cannot start module" )
+                          + QObject::tr( "<br>command: %1 %2<br>%3<br>%4" )
+                          .arg( module ).arg( arguments.join( " " ) )
+                          .arg( process.readAllStandardOutput().constData() )
+                          .arg( process.readAllStandardError().constData() ) );
+*/
+    throw QgsGrass::Exception( QObject::tr( "Cannot start module" ) + "\n"
+                          + QObject::tr( "command: %1 %2<br>%3<br>%4" )
+                          .arg( module ).arg( arguments.join( " " ) )
+                          .arg( process.readAllStandardOutput().constData() )
+                          .arg( process.readAllStandardError().constData() ) );
+  }
+  QByteArray data = process.readAllStandardOutput();
+
+  return data;
+}
+
+QString GRASS_EXPORT QgsGrass::getInfo(  QString info, QString gisdbase, QString location, 
+                                      QString mapset, QString map, MapType type, double x, double y)
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+
+  QStringList arguments; 
+
+  QString cmd = QgsApplication::pkgDataPath() + "/grass/modules/qgis.g.info";
+  
+  arguments.append( "info=" + info );
+  if ( !map.isNull() ) 
+  { 
+      QString opt;
+      switch (type)
+      {
+        case Raster:
+          opt = "rast";
+          break;
+        case Vector:
+          opt = "vect";
+          break;
+      }
+      arguments.append( opt + "=" +  map + "@" + mapset );
+  }
+  if ( info == "query" ) 
+  {
+    arguments.append( QString("coor=%1,%2").arg(x).arg(y) );
+  }
+  
+  QByteArray data =  QgsGrass::runModule ( gisdbase, location, cmd, arguments );
+  QgsDebugMsg( data );
+  return QString( data );
+}
+
+QgsCoordinateReferenceSystem GRASS_EXPORT QgsGrass::crs(  QString gisdbase, QString location )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+  QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem();
+  try 
+  {
+    QString wkt = QgsGrass::getInfo ( "proj", gisdbase, location );
+    crs.createFromWkt( wkt );
+
+  } 
+  catch ( QgsException &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), 
+        QObject::tr( "Cannot get projection " ) + "\n"+ e.what() );
+  }
+
+  return crs;
+}
+
+QgsRectangle GRASS_EXPORT QgsGrass::extent(  QString gisdbase, QString location, QString mapset, QString map, MapType type )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+
+  try 
+  {
+    QString str = QgsGrass::getInfo ( "window", gisdbase, location, mapset, map, type );
+    QStringList list = str.split(",");
+    if ( list.size() != 4 ) {
+      throw QgsGrass::Exception( "Cannot parse GRASS map extent: " + str );
+    }
+    return QgsRectangle ( list[0].toDouble(), list[1].toDouble(), list[2].toDouble(), list[3].toDouble() ) ;
+  }
+  catch ( QgsException &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), 
+        QObject::tr( "Cannot get raster extent" ) + "\n"+ e.what() );
+  }
+  return QgsRectangle( 0, 0, 0, 0 );
+}
+
+QMap<QString, QString> GRASS_EXPORT QgsGrass::query (  QString gisdbase, QString location, QString mapset, QString map, MapType type, double x, double y )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+
+  QMap<QString, QString> result;
+  // TODO: multiple values (more rows)
+  try 
+  {
+    QString str = QgsGrass::getInfo ( "query", gisdbase, location, mapset, map, type, x, y  );
+    QStringList list = str.trimmed().split(":");
+    if ( list.size() == 2 ) {
+      result[list[0]] = list[1];
+    }
+  }
+  catch ( QgsException &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), 
+        QObject::tr( "Cannot query raster " ) + "\n"+ e.what() );
+  }
+  return result;
+}
+
 // GRASS version constants have been changed on 26.4.2007
 // http://freegis.org/cgi-bin/viewcvs.cgi/grass6/include/version.h.in.diff?r1=1.4&r2=1.5
 // The following lines workaround this change

Modified: trunk/qgis/src/providers/grass/qgsgrass.h
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrass.h	2010-02-04 21:23:12 UTC (rev 12879)
+++ trunk/qgis/src/providers/grass/qgsgrass.h	2010-02-04 21:25:35 UTC (rev 12880)
@@ -25,6 +25,9 @@
 
 #include "qgsexception.h"
 #include <QString>
+#include <QMap>
+class QgsCoordinateReferenceSystem;
+class QgsRectangle;
 
 /*!
    Methods for C library initialization and error handling.
@@ -74,7 +77,7 @@
               };
 
     //! Map type
-    enum MapType { Raster, Vector, Region };
+    enum MapType { None, Raster, Vector, Region };
 
     //! Reset error code (to OK). Call this before a piece of code where an error is expected
     static GRASS_EXPORT void resetError( void );  // reset error status
@@ -157,6 +160,24 @@
     // ! Get the lock file
     static GRASS_EXPORT QString lockFilePath();
 
+    // ! Run a GRASS module in any gisdbase/location
+    static GRASS_EXPORT QByteArray runModule( QString gisdbase, QString location, QString module, QStringList arguments );
+
+    // ! Get info string from qgis.g.info module
+    static GRASS_EXPORT QString getInfo( QString info, QString gisdbase, 
+                            QString location, QString mapset=0, QString map=0, MapType type = None, double x=0, double y=0 );
+
+    // ! Get location projection 
+    static GRASS_EXPORT QgsCoordinateReferenceSystem crs( QString gisdbase, QString location);
+
+    // ! Get map extent
+   static GRASS_EXPORT QgsRectangle extent( QString gisdbase, QString location, 
+                      QString mapset, QString map, MapType type = None );
+
+    // ! Get map value / feautre info
+   static GRASS_EXPORT QMap<QString, QString> query( QString gisdbase, QString location, 
+                      QString mapset, QString map, MapType type, double x, double y);
+
     //! Library version
     static GRASS_EXPORT int versionMajor();
     static GRASS_EXPORT int versionMinor();

Added: trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp	                        (rev 0)
+++ trunk/qgis/src/providers/grass/qgsgrassrasterprovider.cpp	2010-02-04 21:25:35 UTC (rev 12880)
@@ -0,0 +1,215 @@
+/***************************************************************************
+  qgsgrassrasterprovider.cpp  -  QGIS Data provider for
+                           GRASS rasters
+                             -------------------
+    begin                : 16 Jan, 2010
+    copyright            : (C) 2010 by Radim Blazek
+    email                : radim dot blazek at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+/* $Id: qgsgrassrasterprovider.cpp 11522 2009-08-28 14:49:22Z jef $ */
+
+#include "qgslogger.h"
+#include "qgsgrass.h"
+#include "qgsgrassrasterprovider.h"
+
+#include <math.h>
+
+#include "qgsapplication.h"
+#include "qgscoordinatetransform.h"
+#include "qgsrectangle.h"
+#include "qgscoordinatereferencesystem.h"
+
+#include <QImage>
+#include <QSettings>
+#include <QColor>
+#include <QProcess>
+#include <QMessageBox>
+#include <QDir>
+#include <QFileInfo>
+#include <QFile>
+
+static QString PROVIDER_KEY = "grassraster";
+static QString PROVIDER_DESCRIPTION = "GRASS raster provider";
+
+QgsGrassRasterProvider::QgsGrassRasterProvider( QString const & uri )
+    : QgsRasterDataProvider( uri ), mValid(true)
+{
+  QgsDebugMsg( "QgsGrassRasterProvider: constructing with uri '" + uri + "'." );
+
+  // Parse URI, it is the same like using GDAL, i.e. path to raster cellhd, i.e.
+  // /path/to/gisdbase/location/mapset/cellhd/map
+  QFileInfo fileInfo ( uri );
+  mValid = fileInfo.exists(); // then we keep it valid forever
+  mMapName = fileInfo.fileName();
+  QDir dir = fileInfo.dir();
+  QString element = dir.dirName();
+  if ( element != "cellhd" ) 
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), 
+      QObject::tr( "Groups not yet supported" ) + " (GRASS " + uri + ")"  );
+
+    mValid = false;
+    return;
+  }
+  dir.cdUp(); // skip cellhd
+  mMapset = dir.dirName();
+  dir.cdUp();
+  mLocation = dir.dirName();
+  dir.cdUp();
+  mGisdbase = dir.path();
+
+  QgsDebugMsg( QString( "gisdbase: %1" ).arg( mGisdbase ) );
+  QgsDebugMsg( QString( "location: %1" ).arg( mLocation ) );
+  QgsDebugMsg( QString( "mapset: %1" ).arg( mMapset ) );
+  QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) );
+  
+  mCrs = QgsGrass::crs ( mGisdbase, mLocation );
+}
+
+QgsGrassRasterProvider::~QgsGrassRasterProvider()
+{
+  QgsDebugMsg( "QgsGrassRasterProvider: deconstructing." );
+}
+
+QImage* QgsGrassRasterProvider::draw( QgsRectangle  const & viewExtent, int pixelWidth, int pixelHeight )
+{
+  QgsDebugMsg( "pixelWidth = "  + QString::number( pixelWidth ) );
+  QgsDebugMsg( "pixelHeight = "  + QString::number( pixelHeight ) );
+  QgsDebugMsg( "viewExtent: " + viewExtent.toString() );
+
+  QImage *image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
+  image->fill ( QColor(Qt::gray).rgb() );
+
+  QStringList arguments;
+  arguments.append( "map=" +  mMapName + "@" + mMapset );
+  
+  arguments.append( (QString("window=%1,%2,%3,%4,%5,%6")
+                    .arg(viewExtent.xMinimum()).arg(viewExtent.yMinimum())
+                    .arg(viewExtent.xMaximum()).arg(viewExtent.yMaximum())
+                    .arg(pixelWidth).arg(pixelHeight)) );
+  QProcess process( this );
+  QString cmd = QgsApplication::pkgDataPath() + "/grass/modules/qgis.d.rast";
+  QByteArray data;
+  try 
+  {
+    data = QgsGrass::runModule ( mGisdbase, mLocation, cmd, arguments );
+  }
+  //catch ( QgsGrass::Exception &e ) // does not work
+  catch ( QgsException &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot draw raster" ) + "\n"
+                              + e.what() );
+
+    // We dont set mValid to false, because the raster can be recreated and work next time
+    return image;
+  }
+  QgsDebugMsg( QString("%1 bytes read from modules stdout").arg(data.size()) );
+  uchar * ptr = image->bits( ) ;
+  // byteCount() in Qt >= 4.6
+  //int size = image->byteCount() < data.size() ? image->byteCount() : data.size();
+  int size = pixelWidth*pixelHeight*4 < data.size() ? pixelWidth*pixelHeight*4 : data.size();
+  memcpy ( ptr, data.data(), size ); 
+  
+  return image;
+}
+
+QgsCoordinateReferenceSystem QgsGrassRasterProvider::crs()
+{
+  QgsDebugMsg( "Entered" );
+  return mCrs;
+}
+
+QgsRectangle QgsGrassRasterProvider::extent()
+{
+  // The extend can change of course so we get always fresh, to avoid running always the module
+  // we should save mExtent and mLastModified and check if the map was modified
+
+  QgsRectangle rect;
+  rect = QgsGrass::extent ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
+  return rect;
+}
+
+bool QgsGrassRasterProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>& theResults )
+{
+  QgsDebugMsg( "Entered" );
+  //theResults["Error"] = tr( "Out of extent" );
+  theResults = QgsGrass::query ( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster, thePoint.x(), thePoint.y() );
+  return true;
+}
+
+int QgsGrassRasterProvider::capabilities() const
+{
+  int capability = QgsRasterDataProvider::Identify;
+  return capability;
+}
+
+bool QgsGrassRasterProvider::isValid()
+{
+  return mValid;
+}
+
+QString QgsGrassRasterProvider::identifyAsText( const QgsPoint& point )
+{
+  return  QString ("Not implemented");
+}
+
+QString QgsGrassRasterProvider::lastErrorTitle()
+{
+  return  QString ("Not implemented");
+}
+
+QString QgsGrassRasterProvider::lastError()
+{
+  return  QString ("Not implemented");
+}
+
+QString  QgsGrassRasterProvider::name() const
+{
+  return PROVIDER_KEY;
+} 
+
+QString  QgsGrassRasterProvider::description() const
+{
+  return PROVIDER_DESCRIPTION;
+}
+
+/**
+ * Class factory to return a pointer to a newly created
+ * QgsGrassRasterProvider object
+ */
+QGISEXTERN QgsGrassRasterProvider * classFactory( const QString *uri )
+{
+  return new QgsGrassRasterProvider( *uri );
+}
+/** Required key function (used to map the plugin to a data store type)
+*/
+QGISEXTERN QString providerKey()
+{
+  return PROVIDER_KEY;
+}
+/**
+ * Required description function
+ */
+QGISEXTERN QString description()
+{
+  return PROVIDER_DESCRIPTION;
+}
+/**
+ * Required isProvider function. Used to determine if this shared library
+ * is a data provider plugin
+ */
+QGISEXTERN bool isProvider()
+{
+  return true;
+}
+

Added: trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h	                        (rev 0)
+++ trunk/qgis/src/providers/grass/qgsgrassrasterprovider.h	2010-02-04 21:25:35 UTC (rev 12880)
@@ -0,0 +1,186 @@
+/***************************************************************************
+      qgsgrassrasterprovider.h  -  QGIS Data provider for
+                           GRASS rasters
+                             -------------------
+    begin                : 16 Jan, 2010
+    copyright            : (C) 2010 by Radim Blazek
+    email                : radim dot blazek at gmail dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+/* $Id: qgsgrassrasterprovider.h 12528 2009-12-20 12:29:07Z jef $ */
+
+#ifndef QGSWMSPROVIDER_H
+#define QGSWMSPROVIDER_H
+
+#include "qgscoordinatereferencesystem.h"
+#include "qgsrasterdataprovider.h"
+#include "qgsrectangle.h"
+
+#include <QString>
+#include <QStringList>
+#include <QDomElement>
+#include <QMap>
+#include <QVector>
+
+class QgsCoordinateTransform;
+
+/**
+
+  \brief Data provider for OGC WMS layers.
+
+  This provider implements the
+  interface defined in the QgsDataProvider class to provide access to spatial
+  data residing in a OGC Web Map Service.
+
+*/
+class QgsGrassRasterProvider : public QgsRasterDataProvider
+{
+    //Q_OBJECT
+
+  public:
+    /**
+    * Constructor for the provider.
+    *
+    * \param   uri   HTTP URL of the Web Server.  If needed a proxy will be used
+    *                otherwise we contact the host directly.
+    *
+    */
+    QgsGrassRasterProvider( QString const & uri = 0 );
+
+    //! Destructor
+    ~QgsGrassRasterProvider();
+
+    /** \brief   Renders the layer as an image
+     */
+    QImage* draw( QgsRectangle  const & viewExtent, int pixelWidth, int pixelHeight );
+
+    /** return a provider name
+
+    Essentially just returns the provider key.  Should be used to build file
+    dialogs so that providers can be shown with their supported types. Thus
+    if more than one provider supports a given format, the user is able to
+    select a specific provider to open that file.
+
+    @note
+
+    Instead of being pure virtual, might be better to generalize this
+    behavior and presume that none of the sub-classes are going to do
+    anything strange with regards to their name or description?
+
+    */
+    QString name() const;
+
+
+    /** return description
+
+    Return a terse string describing what the provider is.
+
+    @note
+
+    Instead of being pure virtual, might be better to generalize this
+    behavior and presume that none of the sub-classes are going to do
+    anything strange with regards to their name or description?
+
+    */
+    QString description() const;
+
+    /*! Get the QgsCoordinateReferenceSystem for this layer
+     * @note Must be reimplemented by each provider.
+     * If the provider isn't capable of returning
+     * its projection an empty srs will be return, ti will return 0
+     */
+    virtual QgsCoordinateReferenceSystem crs();
+
+    /** Return the extent for this data layer
+    */
+    virtual QgsRectangle extent();
+
+    /**Returns true if layer is valid
+    */
+    bool isValid();
+
+    /** \brief Identify raster value(s) found on the point position */
+    bool identify( const QgsPoint & point, QMap<QString, QString>& results );
+
+    /**
+     * \brief Identify details from a WMS Server from the last screen update
+     *
+     * \param point[in]  The pixel coordinate (as it was displayed locally on screen)
+     *
+     * \return  A text document containing the return from the WMS server
+     *
+     * \note WMS Servers prefer to receive coordinates in image space, therefore
+     *       this function expects coordinates in that format.
+     *
+     * \note  The arbitraryness of the returned document is enforced by WMS standards
+     *        up to at least v1.3.0
+     */
+    QString identifyAsText( const QgsPoint& point );
+
+    /**
+     * \brief   Returns the caption error text for the last error in this provider
+     *
+     * If an operation returns 0 (e.g. draw()), this function
+     * returns the text of the error associated with the failure.
+     * Interactive users of this provider can then, for example,
+     * call a QMessageBox to display the contents.
+     */
+    QString lastErrorTitle();
+
+    /**
+     * \brief   Returns the verbose error text for the last error in this provider
+     *
+     * If an operation returns 0 (e.g. draw()), this function
+     * returns the text of the error associated with the failure.
+     * Interactive users of this provider can then, for example,
+     * call a QMessageBox to display the contents.
+     */
+
+    QString lastError();
+
+    /** Returns a bitmask containing the supported capabilities
+        Note, some capabilities may change depending on which
+        sublayers are visible on this provider, so it may
+        be prudent to check this value per intended operation.
+      */
+    int capabilities() const;
+
+    /**
+     * Get metadata in a format suitable for feeding directly
+     * into a subset of the GUI raster properties "Metadata" tab.
+     */
+    QString metadata() { return QString(); }
+
+    // Following methods specific for  WMS are not used at all in this provider and should be removed IMO from qgsdataprovider.h 
+    void addLayers( QStringList const &  layers, QStringList const &  styles = QStringList() ) {}
+    QStringList supportedImageEncodings() { return QStringList();} 
+    QString imageEncoding() const { return QString(); }
+    void setImageEncoding( QString const & mimeType ) {}
+    void setImageCrs( QString const & crs ) {} 
+
+  private:
+
+    /**
+    * Flag indicating if the layer data source is a valid WMS layer
+    */
+    bool mValid;
+
+    QString mGisdbase;      // map gisdabase
+    QString mLocation;      // map location name (not path!)
+    QString mMapset;        // map mapset
+    QString mMapName;       // map name 
+   
+    QgsCoordinateReferenceSystem mCrs;
+};
+
+#endif
+



More information about the QGIS-commit mailing list