GRASS Programming Howto: Difference between revisions
(wikicode cleanup) |
mNo edit summary |
||
(27 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
* | * (Temporary solution here, becoming a Doxygen page in the source code.) | ||
* See also [http://grass.osgeo.org/programming7/ GRASS 7 Programmer's manual] | |||
== Introduction == | |||
HINT: this page origins from 2006 - outdated. | |||
The reason for starting this Howto is the fact that it's very hard to | The reason for starting this Howto is the fact that it's very hard to | ||
get a good overview on the | get a good overview on the GRASS code base, and documentation is | ||
sparse, lacking or not clear on many places. The aim of this Howto | sparse, lacking or not clear on many places. The aim of this Howto | ||
therefore, is to do something about that, so it will be easier to | therefore, is to do something about that, so it will be easier to | ||
contribute to, and better document the | contribute to, and better document the GRASS code base. I encourage | ||
everybody to submit changes, correct me where I'm wrong and add | everybody to submit changes, correct me where I'm wrong and add | ||
information on the places where I haven't been able to do so. For a | information on the places where I haven't been able to do so. For a | ||
start I've chosen to follow the outline of the Grass Programmer's | start I've chosen to follow the outline of the Grass Programmer's | ||
manual with some changes where needed. So let's start (26-01-2003) and | manual with some changes where needed. So let's start (26-01-2003) and | ||
make it more fun/ease to program for | make it more fun/ease to program for GRASS. | ||
Greetings | Greetings | ||
Line 23: | Line 23: | ||
The Netherlands | The Netherlands | ||
Update '''2018''': an initial overhaul has been done. | |||
== Tools == | == Tools == | ||
Line 31: | Line 32: | ||
on you're way (I luckily had a friend who could help me get started, | on you're way (I luckily had a friend who could help me get started, | ||
thanks C.W. de Gier). Also have a look at the Programmer's manuals | thanks C.W. de Gier). Also have a look at the Programmer's manuals | ||
(link: | (link: https://grass.osgeo.org/programming7). | ||
To get an impression of how the program/modules work there's a need to | To get an impression of how the program/modules work there's a need to | ||
Line 39: | Line 40: | ||
separate chapter with some screen shots. We'll see how to do this. | separate chapter with some screen shots. We'll see how to do this. | ||
To enable debug message up you have to give this command in the GRASS shell: | |||
g.gisenv set=DEBUG=#number | g.gisenv set="DEBUG=#number" | ||
where #number stands for the level. There are three levels, 1, 3, | where #number stands for the level. There are three levels, 1, 3, | ||
5. Play around with these to see the differences in output. If you | 5. Play around with these to see the differences in output. If you | ||
want output directed to a file it's necessary to edit you're .bashrc | want output directed to a file it's necessary to edit you're $HOME/.bashrc | ||
or .bash_profile and place a line like this: | or $HOME/.bash_profile and place a line like this: | ||
export | export GRASS_DEBUG_FILE=/whatever_path/debug.txt or any name you like | ||
You have to logout and login again to make it work. Then create | You have to logout and login again to make it work (i.e. open a new | ||
empty file with | terminal). Then create an empty file with a text editor or simply with | ||
the command: | |||
$touch / | $ touch /whatever_path/debug.txt | ||
To view some of the ouput while running Grass57 you can start a new | To view some of the ouput while running Grass57 you can start a new | ||
terminal or xterm and use this command: | terminal or xterm and use this command: | ||
$tail -f / | $ tail -f /whatever_path/debug.txt | ||
This file can | This file can grow very big quickly, so remove it once in a while. | ||
To re-enable logging, recreate an empty file. | |||
=== Emacs === | === Emacs === | ||
Some users use [http://www.gnu.org/software/emacs/ Emacs] as the main editor and viewer of the code. To get a | |||
overview, it's best to begin with making a TAGS file, which will make | overview, it's best to begin with making a TAGS file, which will make | ||
an overview of keywords (eg. function names, defines) and point to the | an overview of keywords (eg. function names, defines) and point to the | ||
Line 72: | Line 73: | ||
main directory of the Grass source code: | main directory of the Grass source code: | ||
$/Path_to_grass_source_code/find . -name '*.[ch]' -print |etags - | $ /Path_to_grass_source_code/find . -name '*.[ch]' -print |etags - | ||
Now you can start Emacs with <tt>emacs &</tt> from you're shell. For a | |||
Now you can start Emacs with | |||
complete reference read the Emacs manual, here are some of the | complete reference read the Emacs manual, here are some of the | ||
commands to search the TAGS file. | commands to search the TAGS file. Here is used the Emacs notation, | ||
mainly C-, push ctrl key, M- push meta or alt key. | mainly C-, push ctrl key, M- push meta or alt key. | ||
Line 91: | Line 91: | ||
Grass sources are. This however is you're main source of learning, | Grass sources are. This however is you're main source of learning, | ||
viewing and understanding what already has been coded. | viewing and understanding what already has been coded. | ||
See [https://bitbucket.org/tws/grass-mode.el grass-mode.el] posted by [http://lists.osgeo.org/pipermail/grass-user/2012-March/063991.html Tyler Smith]. | |||
;Various notes | |||
* to show tabs enter <tt>toggle-show-tabs-show-ws</tt> (install 'emacs-goodies-el' on Debian GNU/Linux), see more info at http://emacswiki.org/emacs/ShowWhiteSpace | |||
* don't use tabs <tt>(setq-default indent-tabs-mode nil)</tt> | |||
* type <tt>C-x h M-x untabify</tt> to remove all tabs in region | |||
=== QtCreator === | |||
See main article [[Using QtCreator for GRASS C development]]. | |||
=== Once you have the code (new one or fixed one) === | === Once you have the code (new one or fixed one) === | ||
Now if you decide to add or change something do this according to the | Now if you decide to add or change something do this according to the rules explained in the [https://trac.osgeo.org/grass/wiki/Submitting SUBMITTING] files (there is one for each programming language) and take a look at the "[http://www.gnu.org/prep/standards.html GNU Coding Standards]". Some other hints and needs for the GRASS programmer: | ||
rules explained in | |||
take a look at " | |||
http://www.gnu.org/prep/standards.html | |||
for the | |||
* Document you're new code well, and in browsing other code and gaining valuable insights, also document this either here, but especially in the code itself. | * Document you're new code well, and in browsing other code and gaining valuable insights, also document this either here, but especially in the code itself. | ||
* | |||
* | * Use G_debug() abundantly in new code as needed. | ||
* In library functions, use doxygen to extract the comments and documentation out of the source. So learn how to use this when submitting you're findings or changes. | |||
== Existing API Documentation == | == Existing API Documentation == | ||
Line 111: | Line 120: | ||
code so that documentation may be auto-generated at every update. | code so that documentation may be auto-generated at every update. | ||
The GRASS GIS html API documentation is locally produced in the html/ subdirectory by: | |||
make htmldocs | make htmldocs | ||
or | or | ||
make pdfdocs | make pdfdocs | ||
this will create the API documentation in the doxygenhtml directory | this will create the API documentation in the doxygenhtml directory | ||
just | just inside the GRASS source tree. | ||
== GIS programming in | == GIS programming in general == | ||
In GIS, from a user viewpoint, there's two main aspects in general to | In GIS, from a user viewpoint, there's two main aspects in general to | ||
Line 131: | Line 142: | ||
In Grass there's an addition to that in the form of sites. In my | In Grass there's an addition to that in the form of sites. In my | ||
understanding this will be changed to either a cell file for raster | understanding this will be changed to either a cell file for raster | ||
(already a fact), a definition of point structure for vectors | (already a fact), a definition of point structure for vectors. | ||
So in the end this will be not be there anymore as a | |||
separate structure. | separate structure. | ||
In | In GRASS GIS, vector to attribute links are done through a database connection, | ||
either directly or via odbc. There's the possibility to add more data then cat(egory) | |||
and an attribute label to a map. | |||
or via odbc. | |||
and label to a map | |||
Now for the programming part, we'll all have to think about how we can | Now for the programming part, we'll all have to think about how we can | ||
provide a structure which will ease all the tasks needed to do | provide a structure which will ease all the tasks needed to do | ||
this. In general we should consider most probably that we have the | this. In general we should consider most probably that we have the | ||
main | main GRASS program environment, which will be responsible for things | ||
like display, i/o handling etc, and modules for specific tasks (eg | like display, i/o handling etc, and modules for specific tasks (eg | ||
digitize new map). | digitize new map). | ||
== Libraries == | == Libraries == | ||
Line 174: | Line 166: | ||
<pre> | <pre> | ||
GIS | Core libraries: | ||
Raster library ( | gis: GRASS GIS General Library (aka GIS Library) | ||
raster: GRASS Raster Library | |||
vector: GRASS Vector Library | |||
Raster | Temporal GIS API: See http://grass.osgeo.org/grass75/manuals/libpython/temporal_framework.html | ||
Further libraries | |||
Segment Library ( | (the name refers to the directory name in lib/ in the source code) | ||
Display Libraries and Drivers | |||
display: GRASS Display Library (general display library) | |||
cairodriver: GRASS Cairo Display Driver | |||
OpenGL gsurf Library ( | driver: Graphics monitor driver | ||
htmldriver: htmldriverlib (HTML graphics driver) | |||
pngdriver: GRASS GIS PNG Display Driver Library | |||
psdriver: GRASS Postscript Display Driver Library | |||
Math and Statistics Libraries | |||
arraystats: GRASS Array Statistics Library (library of statistics for arrays of doubles) | |||
cdhc: GRASS testing normality & exponentiality Library | |||
gmath: GRASS Numerical math interface (generic mathematical functions and BLAS/LAPACK library wrapper) | |||
gpde: GRASS Partial differential equations Library (GPDE) | |||
Raster Libraries | |||
raster: GRASS Raster Library (2D raster library) | |||
raster3d: GRASS 3D Raster Volume Library (3D raster aka voxels or volumes) | |||
rowio: GRASS Row Input/Output Library (library for reading/writing raster rows) | |||
rst: GRASS Library for interpolation with regularized splines with tension (library for interpolation with regularized splines with tension) | |||
segment: GRASS Segment Library (segment library for segmented raster reading) | |||
stats: statslib (statistics library) | |||
Imagery Libraries (image processing) | |||
cluster: GRASS Cluster analysis statistics Library (library for k-means style of cluster analysis processing) | |||
imagery: GRASS Imagery Library (library for image processing) | |||
Vector Libraries | |||
vector: GRASS Vector Library (architecture description) | |||
dglib: GRASS Directed Graph Library | |||
vedit: GRASS Vedit Library (vector editing library) | |||
neta: GRASS Network Analysis Library | |||
rtree: rtree.h (R search tree library) | |||
Search tree libraries | |||
btree: btree.h | |||
btree2: btree2 library | |||
rtree: rtree.h (R search tree library) | |||
Database Management Libraries | |||
db: GRASS DataBase Management Interface | |||
OpenGL Libraries and friends | |||
ogsf: GRASS GIS OGSF Library (OpenGL (R) ported gsurf library (required for NVIZ)) | |||
nviz: GRASS Nviz Library (used by wxGUI Nviz extension and CLI-based Nviz module) | |||
Python API | |||
python: See GRASS GIS Python library (http://grass.osgeo.org/grass75/manuals/libpython/) | |||
Projection Libraries | |||
proj: GRASS and the PROJ4 projection library (wrapper to PROJ4 projection library) | |||
Miscellaneous Libraries | |||
datetime: datetime (DateTime library) | |||
external: external (External libraries from other projects such as shapelib and CCMATH mathematics library source code) | |||
fonts: fonts (GRASS fonts library) | |||
init: Library Initialization (GRASS initialization code + scripts) | |||
iostream: iostream (fast I/O library) | |||
lidar: lidar.h (LiDAR data related library) | |||
linkm: linkm (linked list memory manager) | |||
manage: GRASS Data Elements Manage Library | |||
symbol: symbol (Drawing symbols for point vector data library) | |||
</pre> | </pre> | ||
Not really a library but it could be is the following: | |||
<pre> | |||
GUI programming | GUI programming | ||
</pre> | |||
The main idea is to provide good documentation for functions in each | The main idea is to provide good documentation for functions in each | ||
Line 204: | Line 262: | ||
=== GIS library === | === GIS library === | ||
Info and functions explained will come here: | Info and functions explained will come here: | ||
https://grass.osgeo.org/programming7/gislib.html | |||
=== Directory Make === | === Directory include/Make === | ||
Compile.make | |||
DB.make | |||
Dir.make | Dir.make | ||
Grass.make. | Docs.make | ||
Doxyfile_arch_html.in | |||
Doxyfile_arch_latex.in | |||
Doxygen.make | |||
Etc.make | |||
Grass.make | |||
GuiScript.make | |||
Html.make | |||
HtmlRules.make | |||
Install.make | |||
Lib.make | Lib.make | ||
Module.make | Module.make | ||
Multi.make | |||
NoHtml.make | |||
Other.make | |||
Platform.make.in | Platform.make.in | ||
Python.make | |||
Rules.make | Rules.make | ||
Script.make | Script.make | ||
ScriptRules.make | |||
Shlib.make | Shlib.make | ||
ShScript.make | |||
ShScriptRules.make | |||
Sphinx.make | |||
Stlib.make | Stlib.make | ||
Vars.make | |||
=== Raster library === | === Raster library === | ||
Used for | Used for raster map programming. | ||
=== Vector library === | === Vector library === | ||
Info and functions explained see next | |||
=== VectLib === | === VectLib === | ||
Vector library consists in fact of 5 libraries. Here's a list: | Vector library lib/vector/ consists in fact of 5 libraries. Here's a list: | ||
dgLib the Directed Graph Library for network analysis | |||
digLib lower level functions | |||
neta vector network library | |||
rtree spatial index for lower level functions | |||
vedit vector editing | |||
Vlib higher level functions, intended for programming modules | Vlib higher level functions, intended for programming modules | ||
=== Imagery library === | === Imagery library === | ||
Info and functions explained will come here: ImgLib | Info and functions explained will come here: ImgLib | ||
=== Display Graphics Library === | === Display Graphics Library === | ||
Info and functions explained will come here: DisplGraphicsLib | Info and functions explained will come here: DisplGraphicsLib | ||
=== Rowio Library === | === Rowio Library === | ||
Info and functions explained will come here: RowioLib | Info and functions explained will come here: RowioLib | ||
=== Segment Library === | === Segment Library === | ||
Info and functions explained will come here: SegLib | Info and functions explained will come here: SegLib | ||
=== Vask Library === | === Vask Library === | ||
Info and functions explained will come here: VaskLib | Info and functions explained will come here: VaskLib | ||
=== Projection and Datum Libraries === | === Projection and Datum Libraries === | ||
Info and functions explained will come here: ProjLib | Info and functions explained will come here: ProjLib | ||
=== Grid3D Library === | === Grid3D Library === | ||
Info and functions explained will come here: Grd3dLib | Info and functions explained will come here: Grd3dLib | ||
=== DateTime Library === | === DateTime Library === | ||
Info and functions explained will come here: DateTimeLib | Info and functions explained will come here: DateTimeLib | ||
=== OpenGL gsurf Library === | === OpenGL gsurf Library === | ||
Info and functions explained will come here: OpenglLib | Info and functions explained will come here: OpenglLib | ||
=== GMath numerical Library === | === GMath numerical Library === | ||
Info and functions explained will come here: GMathLib | Info and functions explained will come here: GMathLib | ||
=== Bitmap Library === | === Bitmap Library === | ||
Info and functions explained will come here: BitmapLib | Info and functions explained will come here: BitmapLib | ||
== Database Structure == | == Database Structure == | ||
Everything related to internal Grass Database structure | Everything related to internal Grass Database structure | ||
[[Vector Database Management]] | |||
== Raster Modules == | == Raster Modules == | ||
Everything related to Raster Modules (make list in progress) | Everything related to Raster Modules (make list in progress) | ||
Example of raster module source code and Makefile: | |||
{{src|doc/raster/r.example/}} | |||
List of commands: {{cmd|raster.html}} | |||
=== Raster Module Programming === | === Raster Module Programming === | ||
Line 413: | Line 386: | ||
G_check_input_output_name(input_name, output_name, GR_FATAL_EXIT); | G_check_input_output_name(input_name, output_name, GR_FATAL_EXIT); | ||
== Vector Modules == | == Vector Modules == | ||
Everything related to vector modules | Everything related to vector modules | ||
Example of vector module source code and Makefile: | Example of vector module source code and Makefile: | ||
{{src|doc/vector/v.example/}} | |||
The vector model, API introduction and example module source code is in | |||
https://grass.osgeo.org/programming7/vectorlib.html | |||
=== Vector module list === | |||
Vector module source code is in $grass_source_home/vector/ | |||
List of commands: {{cmd|vector.html}} | |||
==== Vector Module Programming ==== | ==== Vector Module Programming ==== | ||
Line 450: | Line 410: | ||
Well first try on description of a module in a almost dummy way. As | Well first try on description of a module in a almost dummy way. As | ||
I'm new to programming please try to help me out, I'm bound to make | I'm new to programming please try to help me out, I'm bound to make | ||
mistakes. I'll assume that you have a basic understanding of | mistakes. I'll assume that you have a basic understanding of C and are | ||
familiar with pointers, arrays and structs. As I do often not have a | familiar with pointers, arrays and structs. As I do often not have a | ||
nice picture in my head containing a array of structs, I often do to | nice picture in my head containing a array of structs, I often do to | ||
Line 457: | Line 417: | ||
This module has 1 file main.c and a makefile. I'll begin with main.c | This module has 1 file main.c and a makefile. I'll begin with main.c | ||
and the function main as this seems the most logical place to | and the function main as this seems the most logical place to | ||
start. In | start. In GRASS modules almost behave like a standalone program as | ||
they have standard arguments found in c programs in general. The main | they have standard arguments found in c programs in general. The main | ||
thing where there is a difference to a standalone program is the | thing where there is a difference to a standalone program is the GRASS | ||
parser. Let's take a look at standard command line arguments. | parser. Let's take a look at standard command line arguments. | ||
Line 624: | Line 584: | ||
Vect_hist_command ( &Out ); /* actual write see VliB HisT.c */ | Vect_hist_command ( &Out ); /* actual write see VliB HisT.c */ | ||
</pre> | </pre> | ||
(below notes are from 2006) | |||
I'm wondering, haven't figured it out yet, if some of these aspects | I'm wondering, haven't figured it out yet, if some of these aspects | ||
Line 1,192: | Line 1,154: | ||
referral must be thought of. I'm thinking of numbering everything like | referral must be thought of. I'm thinking of numbering everything like | ||
VliB 1.1 (1.= e.g AreA.c & .1 = first function declared) etc. | VliB 1.1 (1.= e.g AreA.c & .1 = first function declared) etc. | ||
== Image Data Modules == | == Image Data Modules == | ||
Everything related to Image Data Modules | Everything related to Image Data Modules | ||
List of commands: {{cmd|imagery.html}} | |||
== Region and Mask Modules == | == Region and Mask Modules == | ||
Line 1,205: | Line 1,165: | ||
Everything related to Region and Mask Modules | Everything related to Region and Mask Modules | ||
{{cmd|g.region.html}}, {{cmd|r.mask.html}} | |||
== Environment Variables == | |||
Everything related to Environment Variables | |||
List: {{cmd|variables.html}} | |||
== Display Symbols == | == Display Symbols == | ||
Line 1,218: | Line 1,177: | ||
For user contributed symbols see the [[IconSymbols]] wiki page. | For user contributed symbols see the [[IconSymbols]] wiki page. | ||
To see custom symbols in the GUI, you need to make a thumbnail image with ps.map and | |||
inkscape. See [https://trac.osgeo.org/grass/browser/grass/trunk/gui/images/symbols/README gui/images/symbols/README] | |||
in the grass source code for more instructions and a [https://trac.osgeo.org/grass/browser/grass/trunk/tools/symbol_to_img.sh script] to do that. | |||
Put the resulting pngs in the same ./gui/images/symbols/ directory structure. | |||
=== File format description === | |||
<pre> | <pre> | ||
Symbol drawing commands are stored in a text file (one file for each symbol) | Symbol drawing commands are stored in a text file (one file for each symbol) | ||
which are located in $GISBASE/etc/symbol/group/name or | which are located in $GISBASE/etc/symbol/group/name or $MAPSET/symbol/group/name | ||
S_read() searches first in mapsets and then in $GISBASE (symbol names in | S_read() searches first in mapsets and then in $GISBASE (symbol names in | ||
Line 1,239: | Line 1,204: | ||
ends with a new line or 'END'. Some objects may contain other objects. | ends with a new line or 'END'. Some objects may contain other objects. | ||
* Drawing is composed of POLYGONS and STRINGS. | |||
* POLYGONS are composed of RINGS. The first ring is outer (clockwise for now), | |||
following rings are inner (counter clockwise currently). | following rings are inner (counter clockwise currently). | ||
* STRINGS and RINGS are composed of LINES and ARCS. | |||
POLYGONS and STRINGS are drawn using the default color and fill color | POLYGONS and STRINGS are drawn using the default color and fill color | ||
Line 1,289: | Line 1,254: | ||
with a straight chord-line from the start/end points on the circle | with a straight chord-line from the start/end points on the circle | ||
as defined by the two angles. | as defined by the two angles. | ||
STRING | STRING | ||
Line 1,322: | Line 1,286: | ||
Internal structure: | Internal structure: | ||
A symbol read into memory is stored in structure SYMBOL containing an array | A symbol read into memory is stored in structure SYMBOL containing an array | ||
of parts (SYMBPART). Each part may be of type S_STRING or S_POLYGON, and | of parts (SYMBPART). Each part may be of type S_STRING or S_POLYGON, and | ||
Line 1,327: | Line 1,292: | ||
stored. One chain contains an array of elements (SYMBEL). | stored. One chain contains an array of elements (SYMBEL). | ||
</pre> | </pre> | ||
== wxGUI Programming Howto == | |||
See main article [[wxGUI Programming Howto]]. | |||
== Compiling and Installing == | == Compiling and Installing == | ||
Line 1,335: | Line 1,304: | ||
* [[Compile_and_Install|Click here]]. | * [[Compile_and_Install|Click here]]. | ||
== | == Numerical math interface == | ||
arraystats: https://grass.osgeo.org/programming7/arraystatslib.html (library of statistics for arrays of doubles) | |||
cdhc: https://grass.osgeo.org/programming7/cdhclib.html (GRASS testing normality & exponentiality Library) | |||
gmath: https://grass.osgeo.org/programming7/gmathlib.html (GRASS Numerical math interface - generic mathematical functions and BLAS/LAPACK library wrapper) | |||
gpde: https://grass.osgeo.org/programming7/gpdelib.html (GRASS Partial differential equations Library (GPDE)) | |||
[[Category: Development|Programming Howto]] | [[Category: Development|Programming Howto]] |
Latest revision as of 17:12, 9 February 2018
- (Temporary solution here, becoming a Doxygen page in the source code.)
- See also GRASS 7 Programmer's manual
Introduction
HINT: this page origins from 2006 - outdated.
The reason for starting this Howto is the fact that it's very hard to get a good overview on the GRASS code base, and documentation is sparse, lacking or not clear on many places. The aim of this Howto therefore, is to do something about that, so it will be easier to contribute to, and better document the GRASS code base. I encourage everybody to submit changes, correct me where I'm wrong and add information on the places where I haven't been able to do so. For a start I've chosen to follow the outline of the Grass Programmer's manual with some changes where needed. So let's start (26-01-2003) and make it more fun/ease to program for GRASS.
Greetings
J.c.m van der Kwast (aka Sjors) Bsc Tropical Agriculture, Plant Production. The Netherlands
Update 2018: an initial overhaul has been done.
Tools
If you are new to programming I suggest that you start looking at a few tutorials on c, which are widely available on the internet. Also try to find somebody who has some experience and get them to help you on you're way (I luckily had a friend who could help me get started, thanks C.W. de Gier). Also have a look at the Programmer's manuals (link: https://grass.osgeo.org/programming7).
To get an impression of how the program/modules work there's a need to help you see which functions are called when, from which place and what it is they pass etc. To do this you'll have to us a debugger like DDD and GDB, here's a link to some debugging hints. This could be a separate chapter with some screen shots. We'll see how to do this.
To enable debug message up you have to give this command in the GRASS shell:
g.gisenv set="DEBUG=#number"
where #number stands for the level. There are three levels, 1, 3, 5. Play around with these to see the differences in output. If you want output directed to a file it's necessary to edit you're $HOME/.bashrc or $HOME/.bash_profile and place a line like this:
export GRASS_DEBUG_FILE=/whatever_path/debug.txt or any name you like
You have to logout and login again to make it work (i.e. open a new terminal). Then create an empty file with a text editor or simply with the command:
$ touch /whatever_path/debug.txt
To view some of the ouput while running Grass57 you can start a new terminal or xterm and use this command:
$ tail -f /whatever_path/debug.txt
This file can grow very big quickly, so remove it once in a while. To re-enable logging, recreate an empty file.
Emacs
Some users use Emacs as the main editor and viewer of the code. To get a overview, it's best to begin with making a TAGS file, which will make an overview of keywords (eg. function names, defines) and point to the places where it's used. To set this up use a command like this in the main directory of the Grass source code:
$ /Path_to_grass_source_code/find . -name '*.[ch]' -print |etags -
Now you can start Emacs with emacs & from you're shell. For a complete reference read the Emacs manual, here are some of the commands to search the TAGS file. Here is used the Emacs notation, mainly C-, push ctrl key, M- push meta or alt key.
For DEFINES and Functions, this will point to the code of the DEFINE or function:
'M-.' then type search string etc
For references of functions, this will point to any file where a function is used:
'M-x tags-search' then type search string etc
Now get handy with the tools and notice how incredibly complex the Grass sources are. This however is you're main source of learning, viewing and understanding what already has been coded.
See grass-mode.el posted by Tyler Smith.
- Various notes
- to show tabs enter toggle-show-tabs-show-ws (install 'emacs-goodies-el' on Debian GNU/Linux), see more info at http://emacswiki.org/emacs/ShowWhiteSpace
- don't use tabs (setq-default indent-tabs-mode nil)
- type C-x h M-x untabify to remove all tabs in region
QtCreator
See main article Using QtCreator for GRASS C development.
Once you have the code (new one or fixed one)
Now if you decide to add or change something do this according to the rules explained in the SUBMITTING files (there is one for each programming language) and take a look at the "GNU Coding Standards". Some other hints and needs for the GRASS programmer:
- Document you're new code well, and in browsing other code and gaining valuable insights, also document this either here, but especially in the code itself.
- Use G_debug() abundantly in new code as needed.
- In library functions, use doxygen to extract the comments and documentation out of the source. So learn how to use this when submitting you're findings or changes.
Existing API Documentation
In order to get quick documentation on functions structures while programming there are tools designed for extracting documentation directly from the source code so that documentation may be auto-generated at every update.
The GRASS GIS html API documentation is locally produced in the html/ subdirectory by:
make htmldocs
or
make pdfdocs
this will create the API documentation in the doxygenhtml directory just inside the GRASS source tree.
GIS programming in general
In GIS, from a user viewpoint, there's two main aspects in general to deal with. The geographical aspect (coordinates/location) and data we want tie to this position, in order to calculate, combine, interpolate (data and/or coordinates), or whatever it is you want to do with these two aspects. Then there are two main ways of presentation of these aspects, in the form of raster and vector maps. In Grass there's an addition to that in the form of sites. In my understanding this will be changed to either a cell file for raster (already a fact), a definition of point structure for vectors. So in the end this will be not be there anymore as a separate structure.
In GRASS GIS, vector to attribute links are done through a database connection, either directly or via odbc. There's the possibility to add more data then cat(egory) and an attribute label to a map.
Now for the programming part, we'll all have to think about how we can provide a structure which will ease all the tasks needed to do this. In general we should consider most probably that we have the main GRASS program environment, which will be responsible for things like display, i/o handling etc, and modules for specific tasks (eg digitize new map).
Libraries
To gain a insight here look at the directory in $Path_to_grass_source_code/lib/, where all the library code is placed. A division is made according to the several distinctions in tasks these libraries perform. Here's a list of the main libraries so far:
Core libraries: gis: GRASS GIS General Library (aka GIS Library) raster: GRASS Raster Library vector: GRASS Vector Library Temporal GIS API: See http://grass.osgeo.org/grass75/manuals/libpython/temporal_framework.html Further libraries (the name refers to the directory name in lib/ in the source code) Display Libraries and Drivers display: GRASS Display Library (general display library) cairodriver: GRASS Cairo Display Driver driver: Graphics monitor driver htmldriver: htmldriverlib (HTML graphics driver) pngdriver: GRASS GIS PNG Display Driver Library psdriver: GRASS Postscript Display Driver Library Math and Statistics Libraries arraystats: GRASS Array Statistics Library (library of statistics for arrays of doubles) cdhc: GRASS testing normality & exponentiality Library gmath: GRASS Numerical math interface (generic mathematical functions and BLAS/LAPACK library wrapper) gpde: GRASS Partial differential equations Library (GPDE) Raster Libraries raster: GRASS Raster Library (2D raster library) raster3d: GRASS 3D Raster Volume Library (3D raster aka voxels or volumes) rowio: GRASS Row Input/Output Library (library for reading/writing raster rows) rst: GRASS Library for interpolation with regularized splines with tension (library for interpolation with regularized splines with tension) segment: GRASS Segment Library (segment library for segmented raster reading) stats: statslib (statistics library) Imagery Libraries (image processing) cluster: GRASS Cluster analysis statistics Library (library for k-means style of cluster analysis processing) imagery: GRASS Imagery Library (library for image processing) Vector Libraries vector: GRASS Vector Library (architecture description) dglib: GRASS Directed Graph Library vedit: GRASS Vedit Library (vector editing library) neta: GRASS Network Analysis Library rtree: rtree.h (R search tree library) Search tree libraries btree: btree.h btree2: btree2 library rtree: rtree.h (R search tree library) Database Management Libraries db: GRASS DataBase Management Interface OpenGL Libraries and friends ogsf: GRASS GIS OGSF Library (OpenGL (R) ported gsurf library (required for NVIZ)) nviz: GRASS Nviz Library (used by wxGUI Nviz extension and CLI-based Nviz module) Python API python: See GRASS GIS Python library (http://grass.osgeo.org/grass75/manuals/libpython/) Projection Libraries proj: GRASS and the PROJ4 projection library (wrapper to PROJ4 projection library) Miscellaneous Libraries datetime: datetime (DateTime library) external: external (External libraries from other projects such as shapelib and CCMATH mathematics library source code) fonts: fonts (GRASS fonts library) init: Library Initialization (GRASS initialization code + scripts) iostream: iostream (fast I/O library) lidar: lidar.h (LiDAR data related library) linkm: linkm (linked list memory manager) manage: GRASS Data Elements Manage Library symbol: symbol (Drawing symbols for point vector data library)
Not really a library but it could be is the following:
GUI programming
The main idea is to provide good documentation for functions in each library in the next paragraphs, and add usable examples of how to use and implement functions. Basically there's a need for a good overview, creating and/or explaining API's etc.
GIS library
Info and functions explained will come here:
https://grass.osgeo.org/programming7/gislib.html
Directory include/Make
Compile.make DB.make Dir.make Docs.make Doxyfile_arch_html.in Doxyfile_arch_latex.in Doxygen.make Etc.make Grass.make GuiScript.make Html.make HtmlRules.make Install.make Lib.make Module.make Multi.make NoHtml.make Other.make Platform.make.in Python.make Rules.make Script.make ScriptRules.make Shlib.make ShScript.make ShScriptRules.make Sphinx.make Stlib.make Vars.make
Raster library
Used for raster map programming.
Vector library
Info and functions explained see next
VectLib
Vector library lib/vector/ consists in fact of 5 libraries. Here's a list:
dgLib the Directed Graph Library for network analysis digLib lower level functions neta vector network library rtree spatial index for lower level functions vedit vector editing Vlib higher level functions, intended for programming modules
Imagery library
Info and functions explained will come here: ImgLib
Display Graphics Library
Info and functions explained will come here: DisplGraphicsLib
Rowio Library
Info and functions explained will come here: RowioLib
Segment Library
Info and functions explained will come here: SegLib
Vask Library
Info and functions explained will come here: VaskLib
Projection and Datum Libraries
Info and functions explained will come here: ProjLib
Grid3D Library
Info and functions explained will come here: Grd3dLib
DateTime Library
Info and functions explained will come here: DateTimeLib
OpenGL gsurf Library
Info and functions explained will come here: OpenglLib
GMath numerical Library
Info and functions explained will come here: GMathLib
Bitmap Library
Info and functions explained will come here: BitmapLib
Database Structure
Everything related to internal Grass Database structure
Raster Modules
Everything related to Raster Modules (make list in progress)
Example of raster module source code and Makefile: doc/raster/r.example/
List of commands: raster.html
Raster Module Programming
After running G_parse(), input and output file names should be checked to make sure that the input file exists, the output file is not the input file, and the output filename is legal. The third argument can be one of the following:
- GR_FATAL_EXIT - Prints error and exits program
- GR_FATAL_PRINT - Prints warning and returns error code
- GR_FATAL_RETURN - Returns error code
G_check_input_output_name(input_name, output_name, GR_FATAL_EXIT);
Vector Modules
Everything related to vector modules
Example of vector module source code and Makefile: doc/vector/v.example/
The vector model, API introduction and example module source code is in
https://grass.osgeo.org/programming7/vectorlib.html
Vector module list
Vector module source code is in $grass_source_home/vector/
List of commands: vector.html
Vector Module Programming
v.buffer: An Example
Well first try on description of a module in a almost dummy way. As I'm new to programming please try to help me out, I'm bound to make mistakes. I'll assume that you have a basic understanding of C and are familiar with pointers, arrays and structs. As I do often not have a nice picture in my head containing a array of structs, I often do to some extend know what's happening. Maybe in time we could visualize some of this in a nice way. This module has 1 file main.c and a makefile. I'll begin with main.c and the function main as this seems the most logical place to start. In GRASS modules almost behave like a standalone program as they have standard arguments found in c programs in general. The main thing where there is a difference to a standalone program is the GRASS parser. Let's take a look at standard command line arguments.
v.buffer help
Prints help.
v.buffer input=map output=buffer type=line buffer=100 tolerance=1 debug=clean
Arguments debug and tolerance are a bit unclear but the rest is self explanatory, this draws a 100 map units buffer around lines in "map", output it to "buffer" with a tolerance of 1 (default).
Now lets take a look at function main() in main.c which has to receive this and do something with it.
int Main(int argc, char *argv[]); /* with argc number of arguments including program name and argv a pointer to a arguments array, normal C form */
Variables depicting arguments for commands are always structured like this (I commented on this):
{ struct Map_info In, Out; /* info on map format */ struct line_pnts *Points, *BPoints; /* Structures to hold line *Points (old map) *Bpoints (buffer map) see Dig_Structs.h */ struct line_cats *Cats; /* structure to hold Cats see Dig_Structs.h*/ char *mapset; /* pointer to mapset */ struct GModule *module; /* Simple description of module see GiS.h */ struct Option *in_opt, *out_opt, *type_opt, *buffer_opt, *tolerance_opt, *debug_opt; /* pointers to program arguments */ double buffer, tolerance; /* declaration to hold answer you give to option arguments */ int type, debug; /* declaration to hold answer you give to option arguments */ int ret, nareas, area, nlines, line; /* declaration to hold answers to function calls */ char *Areas, *Lines; /* declaration to hold answer you give to option arguments */
There seems two are always be defined, being struct GModule * and struct Option *. GModule is for outputting a description of the module and what it does. Next function therefore always assigned to pointer
- module:
module=G_define_module() /* in GisLib ParseR.c */ module->description = "description"
Option refers usually to input and/or output map and other arguments. To have a better understanding see GiS.h as it also provides a way to define flags. So here also assigning to pointers, although some standard options have been constructed (vector map in/out etc).
in_opt = G_define_standard_option(G_OPT_V_INPUT); out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
snip see source code
debug_opt = G_define_option(); /* assign new (not standard) option see GiS.h and GisLib ParseR.c */ debug_opt->key = "debug"; debug_opt->type = TYPE_STRING; debug_opt->required = NO; debug_opt->options = "buffer,clean"; debug_opt->description = "Stop the process in certain stage.";
This last option shows the main items of a Option structure. Key is argument given on the command line, type indicates what kind of answer is to be expected (string, int etc), required tells is an answer must be given in order to process command, options is to compare the answer given where multiple answers are possible, description is self explanatory.
Also Map_info could be considered as standard, see dig_structs.h as it gives info on all supported vector formats.
After declaring all variables to arguments the next function is:
G_gisinit(argv[0]) /* I'm not sure, seems some initialization with the argument being program name see GisLib GisInit.c */
And then most important the call to parser:
if (G_parser (argc, argv)) /* parsing everything and also provides a call to go interactively in shell or Gui IF no arguments are given and if its possible for given module in GiSlib ParseR.c, test if argc is same as argv*/ exit(EXIT_FAILURE); /* if not error code */
Input and output file names should be checked to make sure that the input file exists, the output file is not the input file, and the output filename is legal. The third argument can be one of the following:
- GR_FATAL_EXIT - Prints error and exits program
- GR_FATAL_PRINT - Prints warning and returns error code
- GR_FATAL_RETURN - Returns error code
Vect_check_input_output_name(input_name, output_name, GR_FATAL_EXIT);
Now passing answers to to options before doing the work:
type = Vect_option_to_types ( type_opt ); /* get type see VliB TypE.c here type refers to point, line, area etc */ buffer = abs ( atof( buffer_opt->answer ) ); /* get buffer answer and convert to float */ tolerance = atof( tolerance_opt->answer ); /* get tolerance answer and convert to float */ debug = DEBUG_NONE; if ( debug_opt->answer ) { if ( debug_opt->answer[0] == 'b' ) debug = DEBUG_BUFFER; else if ( debug_opt->answer[0] == 'c' ) debug = DEBUG_CLEAN; } /* decide if option debug and what kind of debug */ Points = Vect_new_line_struct (); /* assign to pointer (link to VliB line.c) */ BPoints = Vect_new_line_struct (); /* assign to pointer (link to VliB line.c) */ Cats = Vect_new_cats_struct (); /* assign to pointer (link to VliB cats.c) */
This all being done open the vector map
/* open input vector */ if ((mapset = G_find_vector2 (in_opt->answer, "")) == NULL) { G_fatal_error ( "Could not find input map <%s>\n", in_opt->answer); } /* see GisLib Find_Vect.c */ Vect_set_open_level (2); /* determine level 1 or 2 see VliB OpeN.c */ Vect_open_old (&In, in_opt->answer, mapset); /* Open map, take a good look at &In dealing with reference? see VliB OpeN.c */ Vect_set_fatal_error (GV_FATAL_PRINT); /* error code see VliB ErroR.c */ if (0 > Vect_open_new (&Out, out_opt->answer, 0) ) { Vect_close (&In); exit (EXIT_FAILURE); } /* open new map for buffer if error close all see VliB OpeN.c and VliB ClosE.c */
Some housekeeping: copying of header and history data
Vect_copy_head_data (&In, &Out); /* see VliB Init_Head.c */ Vect_hist_copy (&In, &Out); /* copy see VliB HisT.c */ Vect_hist_command ( &Out ); /* actual write see VliB HisT.c */
(below notes are from 2006)
I'm wondering, haven't figured it out yet, if some of these aspects can be hidden better. Take the history and header part, can we not provide for one command which does it all? Also defining options, flags etc seems unnecessary difficult, or am I thinking to OO (object orientated)? Maybe a good template with strict names for all elementary components should be constructed, look at difference for type, it refers to
- type of variable, eg string int etc
- or type of feature, eg point, line, string.
Could be changed to typeVar and typeFea? Comments please.
Now finally we get to the actual work, making the buffer.
/* Create buffers' boundaries */ /* Lines */ if ( (type & GV_POINTS) || (type & GV_LINES) ) { int nlines, line, ltype; /* declaring number of, line itself and line type. somehow for points or lines? */ nlines = Vect_get_num_lines ( &In ); /* see VliB Level_Two.c */ fprintf ( stderr, "Lines buffers ... "); for ( line = 1; line <= nlines; line++ ) { G_debug ( 3, "line = %d", line ); /* precious system debug see GisLib DebuG.c */ G_percent ( line, nlines, 2 ); /* give percentage see GisLib PercenT.c */ ltype = Vect_read_line (&In, Points, NULL, line); /* reading line see VliB ReaD.c if ( !(ltype & type ) ) continue; /* comparing type instructed (option argument) and actual line type */ Vect_line_buffer ( Points, buffer, tolerance, BPoints ); /* perform the math see VliB BuffeR.c */ Vect_write_line ( &Out, GV_BOUNDARY, BPoints, Cats ); /* write the line to output map see Vlib WritE.c */ } fprintf ( stderr, "\n"); /* print newline */ }
Continuing with areas, same procedure in basis, just other variables and functions
if ( type & GV_AREA ) { int i, nareas, area, centroid, nisles, isle; /* declare counter i, number of areas, area itself, centroid, number of isle, isle itself. this is strictly areas */ nareas = Vect_get_num_areas ( &In ); /* see VliB Level_Two.c */ fprintf ( stderr, "Areas buffers ... "); for ( area = 1; area <= nareas; area++ ) { G_percent ( area, nareas, 2 ); /* give percentage see GisLib PercenT.c */ centroid = Vect_get_area_centroid ( &In, area ); */ get centroid for given area see VliB Level_Two.c */ if ( centroid == 0 ) continue; /* first found? */ /* outer ring */ Vect_get_area_points ( &In, area, Points ); /* see Vlib area.c */ Vect_line_buffer ( Points, buffer, tolerance, BPoints ); /* perform the math see VliB BuffeR.c */ Vect_write_line ( &Out, GV_BOUNDARY, BPoints, Cats ); /* write the line to output map see VliB WritE.c */ /* islands */ nisles = Vect_get_area_num_isles (&In, area); /* see VliB AreA.c */ for ( i = 0; i < nisles; i++ ) { isle = Vect_get_area_isle (&In, area, i); /* see VliB AreA.c */ Vect_get_isle_points ( &In, isle, Points ); /* get the points see VliB AreA.c */ Vect_line_buffer ( Points, buffer, tolerance, BPoints ); */ perform the math see VliB BuffeR.c */ Vect_write_line ( &Out, GV_BOUNDARY, BPoints, Cats ); /* write the line to output map see Vlib WritE.c */ } } fprintf ( stderr, "\n"); } if ( debug == DEBUG_BUFFER ) { stop ( &In, &Out ); exit (EXIT_SUCCESS); } /* if defined debug stop */
Now some after work must be done before writing and building the map. Radim has put some thoughts here, so see if they make sense. It's mainly to do with building a new topology, a mystery to most. In general in grass vector handling there are two levels of interaction. One that deals with simple geometry (level 1) and one with geometry and topology (level 2). This not being documented well and discussed lately on grass list (Jan,Feb 2004), is still confusing especially when dealing with code. Clearly new common boundaries have to be defined and duplicates deleted etc, and some issues with snapping. The point being that all buffer areas are now new areas, so the new map has old areas and new buffer areas.
/* Create areas */ /* Break lines */ fprintf (stderr, "Building parts of topology ...\n" ); Vect_build_partial ( &Out, GV_BUILD_BASE, stderr ); /* Partial Building the map for main area not isles?, I'm still confused, see VliB BuilD.c */ /* Warning: snapping must be done, otherwise collinear boundaries are not broken and * topology cannot be built (the same angle). But snapping distance must be very, very * small, otherwise counterclockwise boundaries can appear in areas outside the buffer. * I have done some tests on real data (projected) and threshold 1e-8 was not enough, * Snapping threshold 1e-7 seems to work. Don't increase until we find example * where it is not sufficient. */ /* TODO: look at snapping threshold better, calculate some theoretical value to avoid * the same angles of lines at nodes, don't forget about LongLat data, probably * calculate different threshold for each map, depending on map's bounding box */ fprintf ( stderr, "Snapping boundaries ...\n" ); Vect_snap_lines ( &Out, GV_BOUNDARY, 1e-7, NULL, stderr ); /* see VliB SnaP.c */ fprintf ( stderr, "Breaking boundaries ...\n" ); Vect_break_lines ( &Out, GV_BOUNDARY, NULL, stderr ); /* see VliB Break_Lines.c */ fprintf ( stderr, "Removing duplicates ...\n" ); Vect_remove_duplicates ( &Out, GV_BOUNDARY, NULL, stderr ); /* defining new common boundaries and removing duplicates?, see VliB Remove_Duplicates.c */
More thoughts and dealing with Isles
/* Dangles and bridges don't seem to be necessary if snapping is small enough. */ fprintf ( stderr, "Removing dangles ...\n" ); Vect_remove_dangles ( &Out, GV_BOUNDARY, -1, NULL, stderr ); /* see VliB DangleS.c */ fprintf ( stderr, "Removing bridges ...\n" ); Vect_remove_bridges ( &Out, NULL, stderr ); /* see VliB BridgeS.c */ fprintf ( stderr, "Attaching islands ...\n" ); Vect_build_partial ( &Out, GV_BUILD_ATTACH_ISLES, stderr ); /* again build partial now for Isle see VliB BuilD.c */ /* Calculate new centroids for all areas */ nareas = Vect_get_num_areas ( &Out ); /* see VliB AreA.c */ Areas = (char *) G_calloc ( nareas+1, sizeof(char) ); /* dealing with memory for first time why necessary here? see GisLib alloc.c */ for ( area = 1; area <= nareas; area++ ) { G_debug ( 3, "area = %d", area ); /* see GisLib DebuG.c */ ret = area_in_buffer ( &In, &Out, area, type, buffer, tolerance ); /* Function in main.c of v.buffer, is not yet explained but checking if area in output map is in buffer */ if ( ret ) { G_debug ( 3, " -> in buffer"); /* see GisLib DebuG.c */ Areas[area] = 1; } /* if in buffer (valid) assign 1 */ /* Write out centroid (before check if correct, so that it is visible for debug option argument) */ if ( debug == DEBUG_CLEAN ) { double x, y; ret = Vect_get_point_in_area ( &Out, area, &x, &y ); /* new centroid see VliB PolY.c */ if ( ret < 0 ) { G_warning ("Cannot calculate area centroid" ); continue; } /* Checking again */ Vect_reset_cats ( Cats ); /* see VliB CatS.c */ if ( Areas[area] ) Vect_cat_set (Cats, 1, 1 ); /* see VliB CatS.c */ Vect_reset_line ( Points ); /* some reset? see VliB LinE.c */ Vect_append_point ( Points, x, y, 0 ); /* append points for writing to new map see VliB LinE.c */ Vect_write_line ( &Out, GV_CENTROID, Points, Cats ); /* write centroids to file see VliB WritE.c */ } } if ( debug == DEBUG_CLEAN ) { stop ( &In, &Out ); exit (EXIT_SUCCESS); } /* again something for Option debug argument */ /* Make a list of boundaries to be deleted (both sides inside) */ nlines = Vect_get_num_lines ( &Out ); /* see Vlib Level_Two.c */ G_debug ( 3, "nlines = %d", nlines ); /* see GisLib DebuG.c */ Lines = (char *) G_calloc ( nlines+1, sizeof(char) ); /* again allocating memory is beyond me now */ for ( line = 1; line <= nlines; line++ ) { int j, side[2], areas[2]; G_debug ( 3, "line = %d", line ); /* see GisLib DebuG.c */ if ( !Vect_line_alive ( &Out, line ) ) continue; /* check for validness, see VliB ReaD.c */ Vect_get_line_areas ( &Out, line, &side[0], &side[1] ); /* checking for number of areas or isle on right or left side of lines see VliB Level_Two */ for ( j = 0; j < 2; j++ ) { if ( side[j] == 0 ) { /* area/isle not build */ areas[j] = 0; } else if ( side[j] > 0 ) { /* area */ areas[j] = side[j]; } else { /* < 0 -> island */ areas[j] = Vect_get_isle_area ( &Out, abs ( side[j] ) ); */ not null, not area, must be isle see VliB AreA.c */ } } G_debug ( 3, " areas = %d , %d -> Areas = %d, %d", areas[0], areas[1], Areas[areas[0]], Areas[areas[1]] ); /* see GisLib DebuG.c */ if ( Areas[areas[0]] && Areas[areas[1]] ) Lines[line] = 1; /* assign lines for deletion */ } G_free( Areas ); /* release memory see GisLib AlloC.c */ /* Delete boundaries */ for ( line = 1; line <= nlines; line++ ) { if ( Lines[line] ) { G_debug ( 3, " delete line %d", line ); /* see GisLib DebuG.c */ Vect_delete_line ( &Out, line ); /* see VliB WritE.c */ } } G_free( Lines ); /* release memory see GisLib AlloC.c */ /* Create new centroids */ Vect_reset_cats ( Cats ); /* some resetting see VliB CatS.c */ Vect_cat_set (Cats, 1, 1 ); /* writing cats see VliB CatS.c */ nareas = Vect_get_num_areas ( &Out ); /* See VliB AreA.c */ for ( area = 1; area <= nareas; area++ ) { double x, y; G_debug ( 3, "area = %d", area ); /* see GisLib DebuG.c */ if ( !Vect_area_alive ( &Out, area ) ) continue; /* see VliB ReaD.c */ ret = area_in_buffer ( &In, &Out, area, type, buffer, tolerance ); /* check areas in output map is in buffer see main.c in v.buffer */ if ( ret ) { ret = Vect_get_point_in_area ( &Out, area, &x, &y ); /* get centroid in area not in isle see Vlib poly.c */ if ( ret < 0 ) { G_warning ("Cannot calculate area centroid." ); /* see LibGis ErroR.c continue; } Vect_reset_line ( Points ); /* see Vlib LinE.c */ Vect_append_point ( Points, x, y, 0 ); /* see Vlib LinE.c */ Vect_write_line ( &Out, GV_CENTROID, Points, Cats ); /* write the centroids see Vlib WritE.c } fprintf ( stderr, "Attaching centroids ...\n" ); Vect_build_partial ( &Out, GV_BUILD_CENTROIDS, stderr ); /* again build partial topology but now for centroids, still confusing, is everything build now? */ stop ( &In, &Out ); /* defined in main.c of v.buffer */ exit(EXIT_SUCCESS); /* exit program */ }
The workings of the main function should at least be somewhat clear now. Most functions are in the gis or vector library, however there remain the new functions of the module itself being area_in_buffer() to check whether area in output map is in buffer. Basically compare area in input map with output map. This function will also call another function input_distance() being defined in main.c of v.buffer and has something to do with defining the distance from a point of an area in the output map to the nearest feature in the input map. I'm myself not quite sure I understand what is happening, if you do add you're insights. If I understand it's defining the distance to the nearest feature in the buffer and if none are found outside the buffer. If I try to rationalize this, it makes a little more sense. Let's take a look at this:
+ - + + - + + - + + - + A + - + B + - + + - + + - + + - + + = buffer - = borderline area = centroid
A centroid may fall into buffer but the area as a whole doesn't have to be. So distance to centroid can be smaller than buffer or bigger. That's I believe the main rationale for these functions. Again we'll walk through the code starting with area_in_buffer()
/* * Test if area in Out is in buffer. * Return: 1 in buffer * 0 outside buffer */ int area_in_buffer ( struct Map_info *In, struct Map_info *Out, int area, int type, double buffer, double tolerance ) /* taking arguments which should by now mean something */ { double dist; /* think declaration for something returned by function input_distance */ int ret, i; /* seen before, declaration for return value and counter */ static struct ilist *List = NULL; /* declaration of list of integers see Dig_Struct.h */ static struct line_pnts *Points = NULL; /* setting point structure to NULL see Dig_Struct.h */ double x, y; /* declaring as double x and y coordinates? */ G_debug ( 3, " area_in_buffer(): area = %d", area ); /* see GisLib DebuG.c */ if ( List == NULL ) List = Vect_new_list (); /* make new list see VliB LisT.c */ if ( Points == NULL ) Points = Vect_new_line_struct (); /* new line structure see Vlib LinE.c */ /* Warning: because of tolerance, centroid in area calculated by Vect_get_point_in_area() * may fall into buffer (arc interpolated by polygon) even if area is outside!!! */ /* Because of finite number of decimal places in double representation, RET is used. */ /* Test1: Centroid (the only reliable, I think). * There are 3 possible cases for the distance of centroid to nearest input feature: * 1) < (buffer - tolerance) => area inside the buffer * 2) > buffer => area outside the buffer * 3) > (buffer - tolerance) and < buffer (that means within the tolerance) => uncertain */ ret = Vect_get_point_in_area ( Out, area, &x, &y ); /* get coordinates for a point in an area in output map see VliB PolY.c */ if ( ret == 0 ) { /* centroid OK */ /* test the distance to nearest input feature */ dist = input_distance ( In, type, buffer, x, y); /* this function is in main.c of v.buffer explained later */ G_debug ( 3, " centroid %f, %f dist = %f", x, y, dist ); /* see GisLib DebuG.c */ if ( dist < (buffer - tolerance - RET) ) { G_debug ( 3, " centroid in buffer -> area in buffer"); /* see GisLib DebuG.c */ return 1; } else if ( dist > (buffer + RET) ) { G_debug ( 3, "centroid outside buffer -> area outside buffer"); /* see GisLib DebuG.c */ return 0; } /* testing for case 1 as described above by Radim */ /* Test2: counterclockwise (ccw) boundary * Boundaries around features are written in ccw order, that means area inside buffer is on the * left side. Area boundaries are listed in cw order (ccw boundaries as negative). * So if any boundary in area list is negative, i.e. in cww order, i.e. buffer inside area, * whole area _must_ be in buffer. But, also areas without such boundary may be in buffer, * see below. */ /* TODO: The problem!!!: unfortunately it is not true. After snap, break and remove duplicate * it may happen that ccw line appears in the area outside the buffer!!! */ Vect_get_area_boundaries ( Out, area, List ); /* get boundaries of areas of in output map and put in list plus assign an integer id number for looping through them see VliB AreA.c */ for ( i = 0; i < List->n_values; i++ ) { if ( List->value[i] < 0 ) { G_debug ( 3, " negative boundary -> area in buffer"); /* see GisLib DebuG.c */ return 1; } } /* looping through the list to find negative areas */ /* Test3: Input feature within area. * I believe, that if no negative boundary was found and area is in buffer, * the distance of the nearest input feature for at least one area vertex must be < (buffer- tolerance) * This test is left as last because it is slow (check each vertex). */ Vect_get_area_points ( Out, area, Points ); /* get the points=vertex of line see VliB AreA.c */ for ( i = 0; i < Points->n_points - 1; i++ ) { dist = input_distance ( In, type, buffer, Points->x[i], Points->y[i]); G_debug ( 3, " vertex dist = %f", dist ); /* see GisLib DebuG.c */ if ( dist < (buffer - tolerance - RET) ) { G_debug ( 3, " vertex in buffer -> area in buffer"); /* see GisLib DebuG.c */ return 1; } } /* looping though the list and doing the math */ /* Test4?: It may be that that Test3 does not cover all possible cases. If so, somebody must * find such example and send it to me */ G_debug ( 3, " -> area outside buffer"); /* see GisLib DebuG.c */ return 0; } void stop ( struct Map_info *In, struct Map_info *Out ) /* function stop called in main() */ { Vect_close (In); /* see VliB ClosE.c */ fprintf ( stderr, "Rebuilding topology ...\n" ); Vect_build_partial ( Out, GV_BUILD_NONE, NULL ); /* see VliB BuilD.c */ Vect_build (Out, stderr); /* see VliB BuilD.c */ Vect_close (Out); /* see VliB ClosE.c */ } /* closing the input map and building and closing the output map */ Ok now for the last function which support the last one described. Though I do not fully understand, it has to with topology and the distance of the a point to a other feature in the map. double input_distance ( struct Map_info *In, int type, double buffer, double x, double y ) { int i; /* for looping */ static struct ilist *List = NULL; /* setting the list to null */ static struct line_pnts *Points = NULL; /* setting the list of line points to null */ double current_distance; /* declaration of */ BOUND_BOX box; /* see Dig_Structs.h assigning name box */ if ( List == NULL ) List = Vect_new_list (); /* See Vlib LisT.c */ else Vect_reset_list ( List ); if ( Points == NULL ) Points = Vect_new_line_struct (); /* See Vlib LinE.c */ /* Inside area ? */ if ( type & GV_AREA) { int area, centroid; /* inside */ area = Vect_find_area ( In, x, y ); /* find a point in an area see Vlib find.c */ centroid = 0; if ( area ) centroid = Vect_get_area_centroid ( In, area ); /* get the centroid of that area see VLiB AreA.c */ G_debug ( 3, "area = %d centroid = %d", area, centroid ); /* see GisLib DebuG.c */ if ( centroid ) return 0.0; } /* find the area and the centroid, if none return 0.0 */ /* outside area, within buffer? */ /* The centroid is in buffer if at least one point/line/boundary is in buffer distance */ box.E = x + buffer; box.W = x - buffer; box.N = y + buffer; box.S = y - buffer; box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX; /* defining the bounding box see Dig_Structs.h */ Vect_select_lines_by_box ( In, &box, GV_POINTS | GV_LINES, List ); /* see Vlib SelecT.c */ G_debug ( 3, " %d lines selected by box", List->n_values ); /* see GisLib DebuG.c */ current_distance = 2*buffer; /* defining the the distance as 2* buffer */ for ( i = 0; i < List->n_values; i++) { int line, ltype; /* declare line and line type */ double dist; /* declare distance */ line = List->value[i]; /* make line addressable in list by a number */ G_debug ( 3, " line[%d] = %d", i, line ); /* see GisLib DebuG.c */ ltype = Vect_read_line (In, Points, NULL, line); /* get line types in input map see VliB ReaD.c */ Vect_line_distance ( Points, x, y, 0, 0, NULL, NULL, NULL, &dist, NULL, NULL); /* distance of a line? see VliB line.c */ G_debug ( 3, " dist = %f", dist ); /* see GisLib DebuG.c */ if ( dist > buffer ) continue; /* lines */ if ( type & ltype ) { if ( dist < current_distance ) current_distance = dist; } /* test for initial distance if greater than buffer or smaller */ /* Areas */ if ( (type & GV_AREA) && ltype == GV_BOUNDARY ) { int j, side[2], centr[2], area_in; Vect_get_line_areas ( In, line, &side[0], &side[1] ); /* getting the lines for an area see VliB Level_Two.c */ for ( j = 0; j < 2; j++ ) { centr[j] = 0; if ( side[j] > 0 ) area_in = side[j]; else /* island */ area_in = Vect_get_isle_area ( In, abs ( side[j] ) ); /* testing for isles see VliB AreA.c */ if ( area_in > 0 ) centr[j] = Vect_get_area_centroid ( In, area_in ); /* get centroid see VliB AreA.c */ } if ( centr[0] || centr[1] ) { if ( dist < current_distance ) current_distance = dist; } } } return current_distance; }
OK we should be able now to at least have a little understanding of what is happening now. Only thing we did not take a look at are the defines:
#include <stdlib.h> /* standard lib unixsystem */ #include <string.h> /* standard string lib unixsystem */ #include "gis.h" /* include gis.h standard Grass system for all the structs we've seen */ #include "Vect.h" /*vect.h standard Grass system for all the structs we've seen */ #define DEBUG_NONE 0 /* for the option debug */ #define DEBUG_BUFFER 1 /* for the option debug */ #define DEBUG_CLEAN 2 /* for the option debug */ /* TODO: look at RET value and use, is it OK? */ #define RET 0.000000001 /* Representation error tolerance */ /* for the math if the area centroid is in or outside buffer */
Well that's it for now. I'll hope you get the grasp and help out a little because it's by no means perfect now. Also a better system of referral must be thought of. I'm thinking of numbering everything like VliB 1.1 (1.= e.g AreA.c & .1 = first function declared) etc.
Image Data Modules
Everything related to Image Data Modules
List of commands: imagery.html
Region and Mask Modules
Everything related to Region and Mask Modules
Environment Variables
Everything related to Environment Variables
List: variables.html
Display Symbols
For user contributed symbols see the IconSymbols wiki page.
To see custom symbols in the GUI, you need to make a thumbnail image with ps.map and inkscape. See gui/images/symbols/README in the grass source code for more instructions and a script to do that. Put the resulting pngs in the same ./gui/images/symbols/ directory structure.
File format description
Symbol drawing commands are stored in a text file (one file for each symbol) which are located in $GISBASE/etc/symbol/group/name or $MAPSET/symbol/group/name S_read() searches first in mapsets and then in $GISBASE (symbol names in $GISBASE may be overidden by symbols of the same group/name in mapset). File format example: VERSION 1.0 BOX -10 -10 10 10 STRING LINE 0 -10 0 10 END END A symbol file is composed of objects, each object starts with a keyword and ends with a new line or 'END'. Some objects may contain other objects. * Drawing is composed of POLYGONS and STRINGS. * POLYGONS are composed of RINGS. The first ring is outer (clockwise for now), following rings are inner (counter clockwise currently). * STRINGS and RINGS are composed of LINES and ARCS. POLYGONS and STRINGS are drawn using the default color and fill color (specified in module options such as 'd.vect color='). This color may be overwritten by using the COLOR and FCOLOR keywords. ---- DESCRIPTION OF OBJECTS ---- In the following descriptions these variables are used: N - integer number R G B - RGB color as 3 numbers ranging 0-255 X,Y - coordinates (double precision floating point) Keywords: VERSION N.N Version number BOX X Y X Y Bounding box. Lower left and upper right corner. Larger side of box is taken as 1 for symbol scaling. That means that if size of box is 10 x 5, and scale in application is 2, all geometry will be multiplied by: 2 / 10. Origin of symbol is 0,0. COLOR NONE | R G B Color used for string or outline of polygon. If NONE is used, then the polygon outline is not drawn. FCOLOR NONE | R G B Fill color used for polygon. If NONE is used, then the polygon is not filled. LINE X Y X Y [X Y] END Line constructed from coordinate pairs. ARC X Y R A1 A2 [C] Arc specified by center (X Y), radius (R), start/end angle in degrees (A1/A2) and optionaly direction (C for clockwise, default counter clockwise) Note degrees are polar theta not navigational, i.e. 0 is east and values increase counter-clockwise from there. Reducing the angle from a full circle does not make it draw like a pacman but rather with a straight chord-line from the start/end points on the circle as defined by the two angles. STRING [COLOR R G B] LINE | ARC [LINE | ARC] END String composed of any number of lines and/or arcs. RING LINE | ARC [LINE | ARC] END Ring composed of any number of lines and/or arcs. A ring is automatically closed with a line from last point to first point. POLYGON [COLOR R G B] [FCOLOR R G B] RING [RING] END A polygon is composed of any number of rings. The first ring is outer (clockwise) and others are inner (counter-clockwise). ------------------------------------ Note: restriction for clockwise/counter clockwise rings should be removed later and replaced by reordering in symbol library. Order is required by ps.map because PS uses even-odd rule for polygon filling. Internal structure: A symbol read into memory is stored in structure SYMBOL containing an array of parts (SYMBPART). Each part may be of type S_STRING or S_POLYGON, and contain an array of chains (SYMBCHAIN) where both STRING or POLYGONS are stored. One chain contains an array of elements (SYMBEL).
wxGUI Programming Howto
See main article wxGUI Programming Howto.
Compiling and Installing
Everything related to Compiling and Installing. Makefiles, configure files etc.
Numerical math interface
arraystats: https://grass.osgeo.org/programming7/arraystatslib.html (library of statistics for arrays of doubles)
cdhc: https://grass.osgeo.org/programming7/cdhclib.html (GRASS testing normality & exponentiality Library)
gmath: https://grass.osgeo.org/programming7/gmathlib.html (GRASS Numerical math interface - generic mathematical functions and BLAS/LAPACK library wrapper)
gpde: https://grass.osgeo.org/programming7/gpdelib.html (GRASS Partial differential equations Library (GPDE))