
	Standalone GRASS Database Access Library - libgrass
	===================================================

Overview
--------

The libgrass package consists of the majority of the GRASS libgis, and
libdatetime library build as a standalone shared library suitable for use
by non-GRASS applications wishing to read and write GRASS databases.  Some
additional functions have been added to simplify library initialization and
data access by non-GRASS applications.  

While libgrass is currently only suitable for accessing GRASS raster cells,
and associated support files, it is hoped that future revisions will include
support for vector files, and other data elements stored within the GRASS
database.


New Versions
------------

The temporary libgrass web page is at:
 
  http://gdal.velocet.ca/projects/grass/index.html

The source for libgrass can be found in the "libgrass" tree on the grass
CVS server. 

  http://grass.itc.it/grasscvs.html


Building
--------

The INSTALL file addresses generic build, and installation issues.  The
libgrass package uses configure, and libtool to simplify building in 
different environments.  Libgrass has no noteworthy dependencies, but is
unlikely to work in a non-Unix environment.

By default the install target should put libgrass.so and libgrass.a in 
/usr/local/lib, and several include files in /usr/local/include.  

Building On Windows
-------------------

It is possible to build using the latest Cygwin environment (ie. 1.1.x):

  http://sources.redhat.com/cygwin/

It is also necessary to install "sun rpc" support to provide access to 
XDR functions.  A pre-built version (to be untarred over /usr) can
be found at:

  http://gdal.velocet.ca/projects/grass/sunrpc-4_0_cygwin1_bin_tar.gz


Usage
-----

A sample program is "samples/grassinfo". Do use this software on a GRASS
raster map, specify the map name within the cellhd/ directory (full path).
The information about LOCATION, MAPSET and DATABASE are read from
$HOME/.grassrc5

Example:

samples/grassinfo $HOME/grassdata5/ambergau/ambergau/cellhd/dgm25
 
Cell dgm25
data type = float (FCELL)
bytes per pixel = 0
compressed = 0
rows, cols = 180x200
proj = 99
zone = 0
ew_res = 25.000000
ns_res = 25.000000
north = 5767500.000000
south = 5763000.000000
east = 3574000.000000
west = 3569000.000000
PROJ.4 Definition = +proj=tmerc +ellps=bessel +a=6377397.1550000003
+es=0.0066743720 +lat_0=0.0000000000 +lon_0=9.0000000000 +k=1.0000000000
+x_0=3500000.0000000000 +to_meter=1.0


Usage within MapServer
----------------------

To read GRASS location directly from MapServer (http://mapserver.gis.umn.edu)
the libgrass has to be compiled into GDAL library
(http://www.remotesensing.org/gdal/) and made available to MapServer. 

The information about LOCATION, MAPSET and DATABASE are read from
$DOCUMENT_ROOT/.grassrc5 instead of $HOME/.grassrc5 when the
$SERVER_SOFTWARE variable is defined (Apache Server will do that, it is an
Apache build-in variable).



Programmer Documentation
------------------------

All the standard libgis GRASS functions are documented in the GRASS 5 
Programmers Manual, available from:

  http://grass.itc.it/grassdevel.html

The following functions have been implemented custom to libgrass, though some
of them may move into the GRASS core in time.  The libgrass extensions can
be accessed by #include'ing "libgrass.h" normally stored in 
/usr/local/include. 

In general a standalone application needing to read, or write the GRASS
database should:

 1) Call g_gisinit_2(program_name, NULL, NULL, NULL) to intialize the 
    library.  If a $HOME/.grassrc5 file exists, it will be read and used
    to default the database, mapset and location. 

 2) Use G_check_cell() to test if a particular path is a valid GRASS raster
    cell.  Note that if it is, G_check_cell() will make that cells mapset the
    current mapset.

 3) It may be necessary to set the active window before accessing a 
    cell with G_open_cell_old_2(), in particular if the cell has a different
    projection than the raster.  The cells window can be fetched with 
    G_get_cellhd(), after G_check_cell() has succeeded and set with 
    G_set_window().  Use the mapset, and cellname returned by G_check_cell(). 

 3) Use G_open_cell_old_2() to open a raster cell.  It understands direct
    paths as well as current mapset names like G_check_cell(). 

 4) Use normal GRASS calls like G_set_window(), G_get_raster_row(), and
    G_get_cellhd() to access the database.  Don't forget to close the cell
    with G_close_cell(). 

The new entry points are listed here:

/***************************************************************************
 *  char **G_gisinit_2(pgm, gisdbase, location, mapset );
 *
 *      char *pgm	 name of the program for error reporting.
 *      char *gisdbase   path to database, or NULL to use GISDBASE environment
 *                       variable, or contents of ~/.grassrc file.
 *      char *location   location within database, or NULL to use environment
 *                       variable LOCATION_NAME or ~/.grassrc file.
 *      char *mapset     mapset within location, or NULL to use environment
 *                       variable MAPSET or ~/.grassrc.
 *                         
 * Library initialization similar to G_gisinit(), but giving the 
 * calling application some control over what database, location and
 * mapset is used. 
 *
 * If the initialization fails (because no valid mapset was given,
 * nor determinable) the function will return a non-zero error, otherwise
 * zero is returned.   
 *
 * Note that this will potentially modify the programs environment 
 * with G_setenv() to record the database, location and mapset selected.
 *
 * ------------------------------------------------------------------------
 * FIXME: I am currently using G_setenv() to override environment variables
 *        which results in the .grassrc file being rewritten.  This isn't
 *        really desirable.   I would prefer the effects to be "in memory"
 *        only.
 *************************************************************************/

/**********************************************************************
 *  char **G_fetch_list_element (element, mapset)
 *
 *      char *element    database element (eg, "cell", "cellhd", etc)
 *      char *mapset     mapset to be listed.
 *                       NULL to list all mapsets in mapset search list
 *                       "." will list current mapset
 *
 *   Fetches a list of all the files in the indicated element in the
 *   indicated mapsets.  The returned list is a NULL terminated array
 *   of strings that should be deallocated with G_free().
 *********************************************************************/

/**********************************************************************
 *  char **G_fetch_list_locations( gisdbase )
 *
 *      char *gisdbase	Database to selection locations from, or 
 *                      NULL to use the default database.
 *
 * Returns a NULL terminated list of location names, which can be
 * freed with G_free_list() when no longer needed.
 *********************************************************************/

/**********************************************************************
 *  char **G_fetch_list_mapsets( location_path )
 *
 *      char *location_path	full path to location to list mapsets for,
 *                              or NULL to use the default.
 *
 * Returns a NULL terminated list of mapset names, which can be
 * freed with G_free_list() when no longer needed.
 *********************************************************************/

/**********************************************************************
 *  void G_free_list( list )
 *
 *      char **list	NULL terminated list of strings to be freed with
 *                      G_free(), as returned by the various G_fetch_list*()
 *                      functions.
 *********************************************************************/

/***************************************************************************
 *  int G_check_cell( full_name, ret_mapset, ret_cellname );
 *
 *      char *full_name  Name of cell to open.  This may be just the cell name,
 *                       in which case it will be interpreted relative to the
 *                       current mapset, or it may be a relative or absolute
 *                       path to a cellhd file.
 *
 *      char **ret_mapset 
 *			 Location in which to return the mapset name, or NULL
 *                       if not requested.  Mapset name should be freed with
 *                       G_free() when no longer needed.
 *                         
 *      char **ret_cellname
 *			 Location in which to return the cell name, or NULL
 *                       if not requested.  Cell name should be freed with
 *                       G_free() when no longer needed.
 *                         
 * Returns 0 if the passed name does not appear to be a valid cell name, or
 * 1 otherwise.   If this functions returns 1, then the cell_name should
 * be suitable for G_open_cell_old_2() (but might not work with 
 * G_open_cell_old().  This function may call G_gisinit_2() if the cell
 * if fully qualified and in a different location or database than the current
 * one. 
 *
 * Applications should have called G_gisinit(), or G_gisinit_2() before
 * calling this function; however, this doesn't require that the 
 * initialization successfully identified a current grass mapset. 
 *************************************************************************/

/***************************************************************************
 *  int G_open_cell_old_2( cell_name );
 *
 *      char *cell_name  Name of cell to open.  This may be just the cell name,
 *                       in which case it will be interpreted relative to the
 *                       current mapset, or it may be a relative or absolute
 *                       path to a cellhd file.
 *                         
 * Returns -1 if the open fails, or the file descriptor for the cell otherwise.
 * Applications should have called G_gisinit(), or G_gisinit_2() before
 * calling this function; however, this doesn't require that the 
 * initialization successfully identified a current grass mapset.  After
 * a successful return, the current database, location and mapset will have
 * been set suitably for the given cell.
 *************************************************************************/

/**********************************************************************
 * int G_make_location( location_name, wind, proj_info, proj_units, 
 *                      report_file )
 *
 * This function creates a new location in the current database,
 * initializes the projection, default window and current window.  
 *
 * char * location_name
 *                      The name of the new location.  Should not include
 *                      the full path, the location will be created within
 *                      the current database.
 * struct Cell_head *wind
 *                      Contains the default window setting for the
 *                      new location.  All fields should be set in this
 *                      structure, and care should be taken to ensure that
 *                      the proj/zone fields match the definition in the
 *                      proj_info parameter (see G_set_cellhd_from_projinfo()).
 *
 * struct Key_Value *proj_info
 *                      Projection definition suitable to write to the
 *                      PROJ_INFO file, or NULL for PROJECTION_XY.
 *
 * struct Key_Value *proj_units
 *                      Projection units suitable to write to the PROJ_UNITS
 *                      file, or NULL.
 *
 * FILE *report_file 
 *                      File to which creation information should be written
 *                      (can be stdout).  Currently not used.
 *
 * Returns 0 on success, or generates a fatal error on failure.  
 * The G__make_location() function operates the same, but returns a
 * non-zero error code on failure, instead of terminating. 
 *********************************************************************/

/**********************************************************************
 * void G_set_cellhd_from_projinfo( cellhd, proj_info )
 *
 * This function will set the proj and zone fields in a cell header 
 * structure based on the projection defined in the proj_list keyword
 * list.  The proj_info keyword list may be read using G_get_projinfo().
 * This function is most often used to initialize the wind parameter to
 * G_make_location().  Note that no fields in the cell header other than
 * proj and zone are modified.
 * 
 * struct Cell_head *cellhd
 *                      Structure in which the proj, and zone fields should
 *                      be set.
 *
 * struct Key_Value *proj_info
 *                      Keyword list from the PROJ_INFO file from which the
 *                      projection and zone should be derived.  May be NULL
 *                      for PROJECTION_XY.
 *********************************************************************/

/**********************************************************************
 * int G_compare_projections( proj_info1, proj_units1, 
 *                            proj_info2, proj_units2 )
 *
 * This function compares two projection/units definitions, and returns
 * 1 if they are equivelent, or 0 if they differ.  Currently the 
 * is inexact ... some differences will be missed, but it will be
 * improved in the future. 
 *
 * struct Key_Value *proj_info1
 *                         First projection definition as would be read
 *                         from the PROJ_INFO file (or NULL).
 * struct Key_Value *proj_units1
 *                         First units definition as would be read from the
 *                         PROJ_UNITS file (or NULL).
 * struct Key_Value *proj_info2
 *                         Second projection definition as would be read
 *                         from the PROJ_INFO file (or NULL).
 * struct Key_Value *proj_units2
 *                         Second units definition as would be read from the
 *                         PROJ_UNITS file (or NULL).
 *
 * Returns 0 if they differ, or 1 if the appear to be equivelent.
 */

Hints and Tips for Programmers
------------------------------

 o libgrass can be used to open GRASS cells (rasters) with just the name of
   the cell (as opposed to a whole path to the cell header file) if there is
   a $HOME/.grassrc5 file with a valid database, location and mapset set.  

 o Any GRASS cell can be access by giving a full path to the cell header file.
   This might look something like:

    /u/data/grassdb/global/PERMANENT/cellhd/soil.f 

   Note that the path must include the grass database, location, mapset and
   cellhd components.  If a relative path is used without all these components
   the access will not work properly. 

 o As of the first revision, directly accessing a raster cell with a path will
   result in the $HOME/.grassrc5 being updating with that cell's mapset, 
   location and database being current.

 o There is currently no support for preventing concurrent access or update to
   the grass database (unlike GRASS itself which avoids multiple users
   operating on the same mapset). 

 o G_open_cell_old_2(), and G_check_cell() may call G_gisinit_2() internally
   potentially resulting in confusion of access to existing open grass cells.

 o Many GRASS functions treat a failure as a fatal error, and will call
   exit() via G_fatal_error() without returning.  This can be a problem if
   the master program would prefer to recover from the error. :-)

   The G_gisinit_2(), G_check_cell(), and G_open_cell_2() functions have
   been "cleansed" to avoid this problem.  Care should be taken to avoid
   calling other functions in situations where they may fail. 

   It may be possible to avoid this by installing a custom error handler
   with G_set_error_routine(), and careful use of setjmp(), and longjmp() to
   return to application level code without giving the GRASS library an
   opportunity to call exit(). 

 o Sample code demonstrating use of libgrass can be found in the samples
   directory, as well as in the GRASS drivers of GDAL and OSSIM. 
   
   http://www.remotesensing.org/cgi-bin/cvsweb.cgi/osrs/ossim/src/util/image_proc/formats/grass/GrassTileSource.cc?rev=1.1

   http://www.remotesensing.org/cgi-bin/cvsweb.cgi/osrs/gdal/frmts/grass/grassdataset.cpp?rev=1.1

 o Sample code demonstrating use of libgrass to write a new cell can be
   found at in the samples/ppm2grass.c file.

